From: Gerald W. Lester on
Paul Whitfield wrote:
> Gerald W. Lester wrote:
>> Jeff Waite wrote:
>>> I'm still having a problem with creating a 16-bit checksum. I've
>>> tried using cksum, sum, and crc but they all produce values that are
>>> significantly different than what I need. I suppose they may be
>>> computing the checksum differently.
>>
>> Yes they each have their documented algorithms -- and none of them
>> match the one you (rather imprecisely describe below).
>>
>>> Below is an example of how I need
>>> to compute the checksum.
>>>
>>> I suspect that I'm going to have to build my own algorithm. Does
>>> anyone know which TCL commands I can use to do the following:
>>
>> Sure: expr, binary scan, foreach, string range, format, set, and maybe
>> proc and return.
>
> <SNIP> Worked example removed </SNIP>
>
>> BTW, this is a rather strange algorithm would you care to share
>> what/where it is being used (just to satisfy my curiosity)?
>
> Examples where I have seen this "type" of checksum include:
>
> * motorola S-record file, that is an ASCII file format that is used for
> storing binary file.

Ok, did not know about that one.

> * simple communication protocols that use a simple "check sum" like
> this. Often in embedded processors with limited processing power/resources.

I have not seen a check sum like this used since the `70s -- I thought
everyone had either switched over to CRC-32 of dropped check sums since they
were running their protocol on top of Tcp/IP.


Sorry for the typo you pointed out in your other message -- cut, paste and
clean up error that happened late at night.


--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
From: Uwe Klein on
Gerald W. Lester wrote:

> I have not seen a check sum like this used since the `70s -- I thought
> everyone had either switched over to CRC-32 of dropped check sums since
> they were running their protocol on top of Tcp/IP.

you will find 8bit checksums in Intel HEX type files.

> http://www.cs.net/lucid/intel.htm

jedec fusemaps have 16Bit but on the asciis not the bytevalues:
> The transmission checksum is the 16 bit sum (that is, modulo 65,535) of all
> ASCII characters transmitted between and including the STX and ETX. The
> parity bit is excluded in the calculation.

there is some format were the chksum is not modulo something
instead the overflow is folded into chksumlength

i.e.
set chksum [ expr [ join $bytes + ] ]
while {$chksum > 0x0ffff } {
set chksum [ expr ( $chksum & 0x0ffff ) + ( $chksum >>16 ) ]
}

uwe
From: Donal K. Fellows on
Gerald W. Lester wrote:
> I have not seen a check sum like this used since the `70s -- I thought
> everyone had either switched over to CRC-32 of dropped check sums since
> they were running their protocol on top of Tcp/IP.

FWIW, important stuff actually uses either:
1) error-correcting codes instead of checksums, so that minor errors
are restored automatically, or
2) cryptographic hashes, so that even malicious changes are impractical

Donal.
From: Jeff Waite on

That works. Thanks for your help.

Jeff

Paul Whitfield wrote:
> Gerald W. Lester wrote:
> > Jeff Waite wrote:
> >> I'm still having a problem with creating a 16-bit checksum. I've
> >> tried using cksum, sum, and crc but they all produce values that are
> >> significantly different than what I need. I suppose they may be
> >> computing the checksum differently.
> >
> > Yes they each have their documented algorithms -- and none of them match
> > the one you (rather imprecisely describe below).
> >
> >> Below is an example of how I need
> >> to compute the checksum.
> >>
> >> I suspect that I'm going to have to build my own algorithm. Does
> >> anyone know which TCL commands I can use to do the following:
> >
> > Sure: expr, binary scan, foreach, string range, format, set, and maybe
> > proc and return.
> >
> >>
> >> 1. Sum a series of hex numbers
> >> 2. Perform a bit flip (binary complement)
> >>
> >> FYI, I'm trying to create a checksum for a series of hex numbers. For
> >> example:
> >>
> >> Input:
> >>
> >> \x00\x4d\x41\x49\x4e\x00\x00\x00\x00\x26\x00\x04\x05\x0f\x09\x01\x06\xef\xf2\x01\xf2\xf3\x01\xf3\x54\x65\x73\x74\x69\x6e\x67\x20\x31\x32\x33\xef
> >>
> >>
> >> 1. Sum up all the numbers
> >>
> >> Sum = 0AB1
> >>
> >> 2. Convert to binary
> >>
> >> 0000 1010 1011 0001
> >>
> >> 3. Take the complement (bit flip)
> >>
> >> 1111 0101 0100 1110
> >>
> >> 4. Convert back to hex
> >>
> >> F54E
> >>
> >> 5. Show low byte first and then high byte
> >>
> >> 4EF5
> >>
> >> Checksum = 4EF5
> >>
> >
> > Try:
> > proc checksum {str} {
> > binary scan $str c* byteList
> > set sum 0
> > foreach bye $byteList {
> > set sum [expr {($sum + $bye & 0xff}) & 0xffff}]
> > }
> > set sumStr [format {%4.4x} [expr {~$sum & 0xffff}]]
> > return [string range $sumStr 2 3][string range $sumStr 0 1]
> > }
> >
> > BTW, this is a rather strange algorithm would you care to share
> > what/where it is being used (just to satisfy my curiosity)?
>
> There is a typo in this example, the bracing in the expr are wrong
> and it does not give the correct result.. BUT
>
> ...it made me see the mistake in my earlier attempt, I needed to
> force the bytes to be unsigned by masking with 0xff:
>
> Here is a fixed version of my code that give the correct result,
> using a better scan format cribbed from Gerald ...
>
> proc checksum data {
> set sum 0
> binary scan $data "c*" bytes
> foreach int $bytes {
> set sum [ expr { $sum + ( $int & 0xff ) } ]
> }
> set sum [ expr { ( (~$sum << 8 ) & 0xff00 ) | (( ~$sum >> 8 ) &
> 0x00ff) } ]
> return $sum
> }
>
> Hope that helps
>
> Paul