C++/CLI Conversions and the Intel Hex file
Last updated 27 July 2012
Introduction
Discusses the Intel Hex file plus some implementations to read and extract data from Intel Hex files. Also some data type conversion methods.
The Intel Hex File Format
Recently had to write some code that reads data from Intel Hex files. Doing this I came accross quite a few pitfalls re type conversions. A good overview of the Intel Hex file format can be had at Wiki: Intel hex files, especially useful is the little example image at the bottom of this page.
The Intel hex file is simply a text file that holds hex values. So each char in the text file holds one half of a hex value. E.g. 2 consecutive values may be '5' and 'D', which will translate to 0x5D which converts to the character ']'
Read Hex file into a buffer
In order to work on an Intel Hex file, it may be useful to store the file into a buffer. Following implementation doesn't show the checksum matching algorithm.
FileStream ^ fs = gcnew FileStream(filename, FileMode::Open); BinaryReader^ br = gcnew BinaryReader(fs); array<char>^ buffer = gcnew array<char>((int)(br->BaseStream->Length)); int i = 0; while(br->BaseStream->Position < br->BaseStream->Length){ buffer[i++] = br->ReadChar(); }
Create data-only buffer
If you want a buffer that holds the data only (as you do when you need to work on the data), you have to eliminate all the overhead that the Intel file has. Again, I'm skipping the part of the implementation that ensures that the checksum matches.
// declare buffer to hold data only array<char> ^dataBuffer = gcnew array<char>((int)(br->BaseStream->Length)); System::Array::Clear(dataBuffer, 0, br->BaseStream->Length); int counter = 0; // read each intel hex line in turn for(int i = 0; i<br->BaseStream->Length;i++){ if(buffer[i] == ':'){ // new intel hex line encountered //next byte (2 hex digits) determines number of bytes of data in this line int numbytes = ConvertToInt(buffer,i+1); // skip over bytecount, address and record type bytes and copy the data only for(int j = 0; j<(numbytes*2); j++){ // 2 characters for each byte dataBuffer[counter] = buffer[j+i+9]; counter++; } } }
// get hex value from 2 chars and converts to int private: int ConvertToInt(array<char>^ buff, int startIndex) { String^ tempstr = gcnew String(String::Concat(Char::ToString(buff[startIndex]), Char::ToString(buff[startIndex+1]))); int temp = System::Int32::Parse(tempstr, System::Globalization::NumberStyles::HexNumber); return temp; }
Convert char to managed string
The problem is this: say you have char c = 'a', then c->ToString() will be "65", but what do you do if you want a string that represents the ASCII-character 'a'?
Answer 1
String ^ str = gcnew String('D'); // char to managed string
Answer 2
Char::ToString('D') // char to managed string
Convert string containing hex value to char
Here we have a string like "5D", we want to convert this to the char ']' As fas as I know there is no one step solution to do this, one way is as follows.
String^ sHex = gcnew String(String::Concat(Char::ToString('5'), Char::ToString('D')); // string with hex value Byte newByte = Byte::Parse(sHex, System::Globalization::NumberStyles::HexNumber); // convert string to byte int i = Convert::ToInt32(newByte.ToString()); // convert byte to int return Convert::ToChar(i); // convert int to char