KFDtool/sw/control/KFDtool.BSL430/BinaryTextFileParser.cs

147 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KFDtool.BSL430
{
public class BinaryTextFileParser
{
/*
* This class takes in input a text file containing the binary
* code to be uploaded to the MSP430. It generates a list of
* CodeSection instances, each containg a portion of the code to be
* loaded.
*/
private const int RVECTOR = 0xFFFE;
// Outputs
public List<CodeSection> sections = new List<CodeSection>();
// After parsing, if file is indeed a program code, returns true. False otherwise.
private bool formatCorrect = true;
public bool IsFileFormatConform()
{
if (!formatCorrect)
return false;
if (sections.Count <= 0)
return false;
foreach (CodeSection section in sections)
{
if (section.binaryCode.Count() <= 0)
return false;
}
return true;
}
public BinaryTextFileParser(string text)
{
try
{
StringReader strReader = new StringReader(text);
string line = strReader.ReadLine();
while (line != null)
{
// End of the text read
if (line.Contains("q"))
return;
else if (line.Contains("@"))
{
// Read the line
int address = readAddressLine(line);
// Create a new code section
sections.Add(new CodeSection());
sections.Last().StartAddress = address;
}
else
{
// Read the binary code
byte[] bLine = readBinaryCodeLine(line);
// Add this to the section
sections.Last().AppendBinaryCode(bLine);
}
line = strReader.ReadLine();
}
}
catch
{
formatCorrect = false;
}
}
public static BinaryTextFileParser FromTextFile(string filename)
{
string str = File.ReadAllText(filename);
return new BinaryTextFileParser(str);
}
// Returns the address (if found) of the program reset, contained in Reset Vector (0xFFFE)
public int ResetAddress()
{
foreach (CodeSection section in sections)
{
// If the section contains the reset vector
if (section.StartAddress <= RVECTOR &&
section.StartAddress + section.binaryCode.Length >= RVECTOR + 1)
{
byte[] address = new byte[4];
int i = RVECTOR - section.StartAddress;
address[0] = 0;
address[1] = 0;
address[2] = section.binaryCode[i + 1];
address[3] = section.binaryCode[i];
if (BitConverter.IsLittleEndian)
Array.Reverse(address);
return BitConverter.ToInt32(address, 0);
}
}
return 0;
}
private byte[] readBinaryCodeLine(string line)
{
return StringToByteArray(line.Replace(" ", ""));
}
private int readAddressLine(string line)
{
string addressText = line.Replace("@", string.Empty);
int nbAdditionalCharacters = 8 - addressText.Length;
int i;
for (i = 0; i < nbAdditionalCharacters; i++)
addressText = "0" + addressText;
byte[] byteAddress = StringToByteArray(addressText);
if (BitConverter.IsLittleEndian)
Array.Reverse(byteAddress);
i = BitConverter.ToInt32(byteAddress, 0);
return i;
}
private static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
}
}