#! 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); }