Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

intel hex record 1

Status
Not open for further replies.

bc819

Programmer
Jan 27, 2006
9
US
Does anyone know how to write a perl script to do a checksum calculation of an intel hex record?
The intel hex record format is:
:BBAAAATTDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDCC
where
BB = 2 digit byte count
AAAA = 4 digit hex address
TT = 2 digit hex record type
DD = 2 digit hex data byte
CC = 2 digit checksum byte
The checksum is calculated by summing the values of all hexadecimal digit pairs in the record and taking the two's complement.
for example:
intel record:
:1000F000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3F10
sum of all hex bytes except the checksum:
10+00+F0+00+FF+3F+...+FF+3F = AF0
2's compliment of F0 is 10

Thanks.
 
Thanks, KevinADC.
However, the script i'm looking for is not that complicated. All I need is to convert 2 char in the string to hex and then add them all up, then negate the number and add 1 to it. Take the LSB and put it back to the end of the string. That is it.
I'm reading the Perl Cookbook right now. Hope i'll come up with somethng soon.
 
I'm sure there's a great way to use unpack to deal with your string of hex characters, but I don't know how; so it's a regex instead. This code will calculate the sum of that string.
Code:
my $str = '1000F000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3F10';
my $check = substr($str,length($str)-2,2, ""); #Strip Checksum
my $sum;
$sum += hex($_) for $str =~ /(.{2})/gc;
printf '%i - %x', ($sum) x 2
I'm still working on the 2's complement bit.
 
This is kind of ugly looking, but it appears to work.
Code:
my $str = '1000F000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3F10';
my $check = substr($str,length($str)-2,2, ""); #Strip Checksum
my $sum;
$sum += $_ for unpack('C*', pack("H*", $str));
my $hex_sum = sprintf "%x", $sum;
print "$sum - $hex_sum\n";
print "Check: $check - ", two_comp(), "\n";

# Calculates 2's complement for last 2 characters of hex string
sub two_comp {
    my $hex = substr $_[0], length($_[0]) - 2, 2;
    my $bin = unpack('B*', pack("H*", $hex));
    $bin =~ s/(.)/($1 xor 1) || 0/ge;
    my $dec = unpack('C*', pack("B*", $bin));
    $dec++;
    return unpack('H*', pack('C*', $dec));
}
 
I don't know what the heck I wa thinking but rharsh bailed me out, thanks mate. A star is in order.
 
I know the feeling Kevin, when I read this post at first I said to myself "it supposed to do what?!" There probably is a module to do something similar, but reinventing the wheel every once in a while can be fun.

I do have a question for you, bc819 - what is the 2's complement function supposed to return if you pass in '00'? Following the algorithm you gave above:

Invert the bits: 0000 0000 becomes 1111 1111 (FF)

Add one: Well, you end up with 0000 0001 0000 0000 (100)

Since the definition of your hex record is that there's only one hex value to use as a checksum - so, again, what is &two_comp('00') supposed to return?
 
&two_comp('00') should return (00). rharsh, thanks for the srcipt.
 
rharsh, please take a look at my mod on your code, I used the xor to compute 2's complement.
Thanks again for your effort.


my $str = '1000F000FF3FFF3FFF3FFF3FFF3FFF3FFF3FFF3F10';
my $check = substr($str,length($str)-2,2, ""); #Strip Checksum
my $sum;
$sum += $_ for unpack('C*', pack("H*", $str));
my $hex_sum = sprintf "%x", $sum;
print "$sum - $hex_sum\n";
$hex_sum = substr($hex_sum, -2); # just save the last byte of sum
$chksum = (hex($hex_sum) ^ 0xFF) + 1; # 2's complement of hex_sum
print "chksum is $chksum\n";
$chksum = sprintf("%2x",$chksum); # convert checksum to string
my $str = $str.$chksum; # put is back to the end of string, done
print"$str\n";


 
help...
$chksum = sprintf("%2x",$chksum); works fine when chksum is greater than 0x0f. If it's less than 0x10, the leading 0 does not show up in the string, only a space and the digit is appended at the end of the string. Any idea how to correct this problem?
Thanks
 
problem fixed:
added a line:
$chksum =~ s/ /0/g;
before append it to $str
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top