/// <summary>
/// Motorola S/EXORciser/EXORmacs/32位格式 S-Record
/// 解析 EXORciser-S19 EXORmacs-S28 32位-S37 文件使用
/// 作者只使用过 S37文件验证过
/// </summary>
public class SRecord //
{
public enum Header { S0, S1, S2, S3, S4, S5, S6, S7, S8, S9 } // 文件开始
public enum Type { S19, S28, S37 }
public byte[] address;
public byte len = 0x0;
public byte[] data;
public byte cs = 0x0;
public List<byte> read = new List<byte>();
public UInt32 headAddress { get; set; }
public UInt32 execAddress { get; set; }
public Type type = Type.S37;
public bool firstLine = false;
public void genFile(byte[] content, UInt32 address, UInt32 execAddress, string filePath)
{
List<string> list = new List<string>();
int len = 32; //<=32 字节
byte[] buf = System.Text.Encoding.Default.GetBytes(filePath);
Header header = Header.S0;
int pStart = 0;
//address 累加 buf循环 长度
this.execAddress = execAddress;
list.Add(genRecord(0x0, buf, Header.S0)); //开始S0 开始
buf = new byte[len];
//循环 内容
while (pStart < content.Length)
{
if (pStart + len <= content.Length)
{
Array.Copy(content, pStart, buf, 0, len);
}
else
{
len = content.Length - pStart;
buf = new byte[len];
Array.Copy(content, pStart, buf, 0, len);
}
list.Add(genRecord(address, buf, Header.S3));
address = address + (uint)len;
pStart = pStart + len;
}
list.Add(genRecord(execAddress, new byte[0], Header.S7)); //最后结束
//保存文件
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8);
foreach (string str in list)
{ sw.WriteLine(str); }
sw.Flush();
sw.Close();
fs.Close();
}
private string genRecord(UInt32 address, byte[] buf, Header header)
{
//int len = 0;
string str = "";
data = new byte[buf.Length];
Array.Copy(buf, 0, data, 0, buf.Length);
if (header == Header.S0)
{
this.address = new byte[] { 0x0, 0x0 };
}
else if (header == Header.S3)
{
this.address = Common.uInt32ToByte(address); //转地址
}
else if (header == Header.S7)
{
this.address = Common.uInt32ToByte(address);
}
len = (byte)(buf.Length + 1 + this.address.Length);
genCheckSum();
Array.Reverse(this.address);
str += header.ToString() + len.ToString("X2") + Common.byte2HexStr(this.address).Replace(" ", "")
+ Common.byte2HexStr(buf).Replace(" ", "") + cs.ToString("X2");
return str;
}
private void genCheckSum()
{
ushort sum = 0;
sum += len;
for (int i = 0; i < address.Length; i++)
{
sum += address[i];
}
for (int i = 0; i < data.Length; i++)
{
sum += data[i];
}
cs = (byte)(sum & 0xff);
cs = (byte)~cs;
}
public bool readRecord(string filePath, out string errorMsg)
{
string[] lines = System.IO.File.ReadAllLines(filePath, System.Text.Encoding.Default);
errorMsg = "";
bool result = true;
for (int i = 0; i < lines.Length; i++)
{
anaysisRecord(lines[i], out errorMsg);
if (errorMsg != "")
{
result = false;
break;
}
}
return result;
}
private void anaysisRecord(string line, out string errorMsg)
{
errorMsg = "";
if (line == "") { return; }
if (line.Length < 2) { errorMsg = "this line is too little"; }
string headStr = line.Substring(0, 2);
byte[] buf = Common.hexStr2Bytes(line.Substring(2));
//S325AF07FFE0000000000000000000000000000000000000000000000000000000000000000045
if (buf[0] != buf.Length - 1) { errorMsg = "this line data_len area do not match line length "; }
if (headStr == "S0")
{
//头行 没有实际内容
}
else if (headStr == "S2")
{
type = Type.S28;
// 等等 后续开发
}
else if (headStr == "S3")
{
address = new byte[4];
Array.Copy(buf, 1, address, 0, 4);
//Array.Reverse(address);
if (firstLine == false)
{
firstLine = true;
type = Type.S37;
headAddress = Common.byteToUInt(address);
}
for (int i = 0; i < buf.Length - 4 - 1 - 1; i++) //buf - 长度区域(1)- 地址区域(4)-校验和(1)
{
read.Add(buf[1 + 4 + i]); // 演示 demo 第一个字节 长度 然后4个字节地址 是第五个字节
}
}
else if (headStr == "S7")
{
address = new byte[4];
Array.Copy(buf, 1, address, 0, 4);
execAddress = Common.byteToUInt(address);
}
}
}