#! perl -slw
use strict;
sub checksum {
my( $string ) = @_;
my $chk_sum = 0;
$chk_sum += $_ for unpack 'C*', substr $string, 0, -5;
my $twos_comp = hex( substr $string, -5, 4 );
return ( ( $chk_sum + $twos_comp ) & 0xFFFF ) ? 1 : 0;
}
print "$_ : ", checksum $_ for "\x019999FF1B\x03", "\x019998FF1B\x03";
__END__
P:\test>283701
?9999FF1B? : 0
?9998FF1B? : 1
####
9999 = 57 + 57 + 57 + 57 = 228.
~ 228 = -229 decimal = FF1B hex (16-bit)
Add the header and trailer characters = 9999FF1B
####
1 + 57 + 57 + 57 + 57 = 229
####
FF1B = 65307
####
(65307 + 229) = 65536
65536 & 65535 = 0x10000 & 0xFFFF = 0
####
sub build_string {
my( $string ) = @_;
my $chksum = 0;
$chksum += $_ for map{ $_ & 0x7F } unpack 'C*', $string;
$chksum = (~$chksum & 0xFFFF);
return chr(1) . $string . sprintf( '%4x', $chksum ) . chr(3);
}