Dirk Bertels

The greatest malfunction of spirit
is to believe things (Louis Pasteur)

C++/CLI Conversions and the Intel Hex file

Last updated 27 July 2012


Index

Introduction
The Intel Hex File Format
Read Hex file into a buffer
Create data-only buffer
Convert char to managed string
Convert string containing hex value to char
Links

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

Links


Comments