Here's my code:
set data
\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
LogToScreen "Checksum: cksum"
set cks [cksum($data)]
LogToScreen $cks
LogToScreen "Checksum: crc::sum"
set crcsum [crc::sum -format 0x%X $data]
LogToScreen $crcsum
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
1111 0101 0100 1110
4. Convert back to hex
F54E
5. Show low byte first and then high byte
4EF5
Checksum = 4EF5
don't do that tcl is not C
what about:
% package require crc16
% set data
"\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"
% ::crc::crc16 $data
6800
G!
uwe
Unless you've stored the name of the command in an array named cksum,
that should probably be:
set cks [crc::cksum $data]
You might need to add "package require cksum" to your code as well. It's
unfortunate that you need to do "package require cksum" but the commands
actually live in the crc namespace.
Out of curiosity, what's the point of this exercise? Is it homework?
I'm trying to get a network operations software package called Priisms
to display alarm messages on an LED marquee. The command to change
the text on the sign is a series of hex numbers with a 16-bit checksum
at the end.
you need the "crc16" package which is a part of tcllib
( there is also a crc32 and some other crc types )
as in :
package require crc16
assumed the chars to chksumm are in the variable "data"
the command to generate crc16 is
set chksum [ ::crc::crc16 $data ]
see my previous post
uwe
What is the procedure for adding the crc16 library to TCL?
source "d:/priisms/crc16.tcl"
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:
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
Here is my attempt, the numbers don't work out the
same as your example... but I think what I have done
is correct.
Please note: your problem description was not very precise:
"Sum up all the numbers" is not a complete description,
a better description would be "16 bits sum of each BYTE"
set data
"\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"
proc checksum data {
set sum 0
for { set i 0 } { $i < [ string length $data ] } { incr i } {
binary scan $data "@${i}c" int
incr sum $int
puts "[format "%x, %x" $sum $int ]"
}
puts "[format %x $sum]"
set sum [ expr { ( (~$sum << 8 ) & 0xff00 ) | (( ~$sum >> 8 ) &
0x00ff ) } ]
return $sum
}
puts "Checksum is [ format %x [ checksum $data ] ]"
And the output is
set data
"\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"
proc checksum data {
set sum 0
for { set i 0 } { $i < [ string length $data ] } { incr i } {
binary scan $data "@${i}c" int
incr sum $int
puts "[format "%x, %x" $sum $int ]"
}
puts "[format %x $sum]"
set sum [ expr { ( (~$sum << 8 ) & 0xff00 ) | (( ~$sum >> 8 ) &
0x00ff ) } ]
return $sum
}
puts "Checksum is [ format %x [ checksum $data ] ]"
Regards
Paul
Here is my attempt, the numbers don't work out the
same as your example... but I think what I have done
is correct.
Please note: your problem description was not very precise:
"Sum up all the numbers" is not a complete description,
a better description would be
"Add the value of each 8-bit value to a 16 bit sum"
set data
"\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"
proc checksum data {
set sum 0
for { set i 0 } { $i < [ string length $data ] } { incr i } {
binary scan $data "@${i}c" int
incr sum $int
puts "[format "%x, %x" $sum $int ]"
}
puts "[format %x $sum]"
set sum [ expr { ( (~$sum << 8 ) & 0xff00 ) | (( ~$sum >> 8 ) &
0x00ff ) } ]
return $sum
}
puts "Checksum is [ format %x [ checksum $data ] ]"
And the output is
0, 0
4d, 4d
8e, 41
d7, 49
125, 4e
125, 0
125, 0
125, 0
125, 0
14b, 26
14b, 0
14f, 4
154, 5
163, f
16c, 9
16d, 1
173, 6
162, ffffffef
154, fffffff2
155, 1
147, fffffff2
13a, fffffff3
13b, 1
12e, fffffff3
182, 54
1e7, 65
25a, 73
2ce, 74
337, 69
3a5, 6e
40c, 67
42c, 20
45d, 31
48f, 32
4c2, 33
4b1, ffffffef
4b1
Checksum is 4efb
Regards
Paul
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)?
--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
<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.
* simple communication protocols that use a simple "check sum" like
this. Often in embedded processors with limited processing power/resources.
The bad thing about such algorithms is that they are not that
good at detecting anything other than a single bit error.
Regards
Paul
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
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.
> 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
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.
Jeff