Hi all other monks,
I'm trying to write a hex to binary converter and found what I thought were the needed code nuggets towards the bottom of "perldoc perlpacktut" documentation in the Intel Hex section. It seemed fairly straightforward, but I found that when processing bytes of data that the upper nibble is being dropped during the conversion. The discovery only came by reverse-conversion of the binary output string. The data length is reported as being correct; the first data line has 16 bytes, and the second contains 14 bytes - note this format has 4 bytes of info at the beginning of the line and a checksum byte at the end.
Here is my test code:
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
#=====================================================================
+==========
# Set to "1" for additional debugging print statements.
#=====================================================================
+==========
my $debug= 1;
#=====================================================================
+==========
# Standard input while loop
#=====================================================================
+==========
my $line;
# Retrieve a line
while ($line = <DATA>) {
# chomp line
chomp $line;
# Does line begin with ":"?
if (($line !~ /^\:/) || ($line =~ /^\$/)) {
print "INVALID LINE, SKIPPING : $line\n" if $debug;
next
} else {
# convert line to hex (and strip off ":")
my $hexrec = pack( 'H*', substr( $line, 1 ) );
# calculate checksum, if error, die.
my $chksum = unpack( "%C*", $hexrec );
print "checksum = $chksum\n" if $debug;
die unless unpack( "%8C*", $hexrec ) == 0;
#
# process the line. get bytecount, address, record type, and d
+ata
#
my( $bytecount, $address, $recordtype, $data ) = unpack( "C n
+C X4 C x3 /a", $hexrec );
# note: no reason to print data, since it results in special,
+unprintable chars
printf ("bytecount = %d, address = %d, recordtype = %d\n", $by
+tecount, $address, $recordtype) if $debug;
#
# terminator line
#
if ($recordtype == 1) {
print "Conversion complete\n";
exit;
}
#
# real data line
#
elsif ($recordtype == 0) {
my $binarycount = $bytecount*8;
my $datlength = length($data);
print "Data length (should match bytecount) = $datlength\n
+";
# convert to binary
my $binaryval = unpack("B$binarycount", pack("H$bytecount"
+, $data));
print "binary = $binaryval\n" if $debug;
}
}
} # end of while
__DATA__
:1004D0000A95E1F7E0E0F8E000E40BBF00E81791CF
:0E04E0001D930A95E1F74CCE00E10883FDCE96
:00000001FF
__END__
The results of running the Perl code is this:
checksum = 2816
bytecount = 16, address = 1232, recordtype = 0
Data length (should match bytecount) = 16
binary = 1010010100010111000000001000000000000100101111110000100001110
+001
checksum = 2304
+
bytecount = 14, address = 1248, recordtype = 0
+
Data length (should match bytecount) = 14
+
binary = 11010011101001010001011101011110000000011000001111011110
+
checksum = 256
+
bytecount = 0, address = 0, recordtype = 1
+
Conversion complete
If someone can shed some light on this and help me to understand pack/unpack a tiny bit better, it would be much appreciated.
Thanks,
Joe