cscの作法 その46 intelHEX

#概要

cscの作法、調べてみた。
intelHEXやってみた。

#参考にしたページ

http://nanoappli.com/blog/archives/3655


#サンプルコード


```

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

public class HexFileParser {
	class HexFileData {
		private int offset;
		public int Offset {
			get { 
				return offset; 
			}
			set { 
				offset = value; 
			}
		}
		private int length;
		public int Length {
			get { 
				return length; 
			}
			set { 
				length = value; 
			}
		}
		private string recType;
		public string RecType {
			get { 
				return recType; 
			}
			set { 
				recType = value; 
			}
		}
		// レコード種別 2byte
		// 00 データレコード
		// 01 ファイル終了レコード
		// 02 拡張セグメントアドレスレコード
		// 03 スタートセグメントアドレスレコード
		// 04 拡張リニアアドレスレコード
		// 05 スタートリニアアドレスレコード
		private string data;
		public string Data {
			get { 
				return data; 
			}
			set { 
				data = value; 
			}
		}
	}
	public int StartAddr {
		get {
			return startAddr;
		}
	}
	public int EndAddr {
		get {
			return endAddr;
		}
	}
	public List<string>ParseErrorInfo {
		get {
			return parseErrorInfo;
		}
	}
	private string defaultValue;
	public string DefaultValue {
		get { 
			return defaultValue; 
		}
		set { 
			defaultValue = value; 
		}
	}
	private int startAddr;
	private int endAddr;
	private List<HexFileData> hexFileList = new List<HexFileData>();
	private List<string> parseErrorInfo = new List<string>();
	public HexFileParser() {
		DefaultValue = "00";
		clearParseInfo();
	}
	public void clearParseInfo() {
		startAddr = 0xFFFF;
		endAddr = 0x0000;
		parseErrorInfo.Clear();
		hexFileList.Clear();
	}
	public void parseLine(int lineNo, string inData) {
		string startMark;
	 	// 1byte	スタートマーク(":"固定)
		string byteCount;
	 	// 2byte	データ長
		string offsetAddress;
	 	// 4byte	データオフセット(開始位置)
		string recType;
		// 2byte	レコード種別 00:データ
		string data;
		// variable データ
		string checkSum;
		// 2byte	チェックサム
		if (inData.Length < 11)
		{
			parseErrorInfo.Add("行:" + lineNo + " レコード長が不正です");
			return;
		}
		startMark = inData.Substring(0, 1);
		byteCount = inData.Substring(1, 2);
		offsetAddress = inData.Substring(3, 4);
		recType = inData.Substring(7, 2);
		data = inData.Substring(9, inData.Length - 11);
		checkSum = inData.Substring(inData.Length - 2);
		if (!startMark.Equals(":"))
		{
			parseErrorInfo.Add("行:" + lineNo + " スタートマークが':'では有りません[data=" + startMark + "]");
			return;
		}
		if (!isHexaDecimal(byteCount))
		{
			parseErrorInfo.Add("行:" + lineNo + " バイトカウントが16進文字列では有りません[data=" + byteCount + "]");
			return;
		}
		if (!isHexaDecimal(offsetAddress))
		{
			parseErrorInfo.Add("行:" + lineNo + " オフセットアドレスが16進文字列では有りません[data=" + offsetAddress + "]");
			return;
		}
		if (!isHexaDecimal(recType))
		{
			parseErrorInfo.Add("行:" + lineNo + " レコード種別が16進文字列では有りません[data=" + recType + "]");
			return;
		}
		if (!recType.Equals("00") && !recType.Equals("01") && !recType.Equals("02") && !recType.Equals("03") && !recType.Equals("04") && !recType.Equals("05"))
		{
			parseErrorInfo.Add("行:" + lineNo + " レコード種別が00～05以外の値です[data=" + recType + "]");
			return;
		}
		if (!isHexaDecimal(data))
		{
			parseErrorInfo.Add("行:" + lineNo + " データが16進文字列では有りません[data=" + data + "]");
			return;
		}
		if (!isHexaDecimal(checkSum))
		{
			parseErrorInfo.Add("行:" + lineNo + " チェックサムが16進文字列では有りません[data=" + checkSum + "]");
			return;
		}
		uint calcValue = 0;
		for (int loop = 1; loop < inData.Length - 2; loop +=2)
		{
			string curValue = inData.Substring(loop, 2);
			calcValue += (uint) Convert.ToInt32(curValue, 16);
		}
		calcValue = (~calcValue) + 1;
		// 2の補数を取る
		calcValue &= 0x000000FF;
	 	// 下位16ビット分だけを抽出
		if (Convert.ToInt32(checkSum, 16) != calcValue)
		{
			parseErrorInfo.Add("行:" + lineNo + " チェックサムが一致しません[calc=" + calcValue.ToString() + ", data=" + checkSum + "]");
			return;
		}
		int start = Convert.ToInt32(offsetAddress, 16);
		int len = Convert.ToInt32(byteCount, 16);
		storeValue(start, len, recType, data);
	}
	public string getValue(int address) {
		HexFileData targetData = null;
		foreach (HexFileData curData in hexFileList)
		{
			if (curData.Offset <= address && curData.Offset + curData.Length > address)
			{
				targetData = curData;
				break;
			}
		}
		if (targetData == null)
		{
			int wordLen = DefaultValue.Length / 2;
			// １ワードの長さを求める
			int wordPos = address % wordLen;
			// 要求されたアドレスが、ワード中のどこにあたるかかのoffsetを求める
			return DefaultValue.Substring(wordPos * 2, 2);
		}
		int pos = address - targetData.Offset;
		return targetData.Data.Substring(pos * 2, 2);
	}
	private void storeValue(int start, int len, string recType, string data) {
		if (!recType.Equals("00"))
		{
			 return;
		}
		if (start < startAddr)
		{
			startAddr = start;
		}
		if (start + len > endAddr)
		{
			endAddr = start + len;
		}
		HexFileData hexFileData = new HexFileData();
		hexFileData.Offset = start;
		hexFileData.Length = len;
		hexFileData.RecType = recType;
		hexFileData.Data = data;
		hexFileList.Add(hexFileData);
	}
	private bool isHexaDecimal(string inData) {
		foreach (Char data in inData)
		{
			if ((data >= '0' && data <= '9') || (data >= 'A' && data <= 'F'))
			{
				continue;
			}
			return false;
		}
		return true;
	}
}
public class Hex0 {
	static void Main() {
		string fileName = "c:\\avr\\a0.hex";
		HexFileParser parser = new HexFileParser();
		//parser.DefaultValue = "FF3F";
		using (StreamReader reader = new StreamReader(fileName)) {
			int lineNo = 0;
			while (true)
			{
				string line = reader.ReadLine();
				if (line == null)
				{
					break;
				}
				parser.parseLine(lineNo, line);
				Console.WriteLine(line + Environment.NewLine);
				lineNo++;
			}
		}
		//txtHexDump.Text = "";
		int loopCol = 0;
		int startAddr = parser.StartAddr;
		int endAddr = parser.EndAddr;
		for (int curAddr = startAddr; curAddr < endAddr; curAddr++)
		{
			string mCode = parser.getValue(curAddr);
			Console.WriteLine(mCode + " ");
			if (loopCol++ >= 16)
			{
				loopCol = 0;
				Console.WriteLine(Environment.NewLine);
			}
		}
	}
}




```

以上。