Calculating checksums for serial communication (yuk!)

hax

New Member
OK coffee out and head scratching begin. This is a tough one, and I would really appreciate any feedback at all.


I'm trying to get my head around getting the picaxe to calculate checksums for a bit of hardware I am designing.

The Picaxe will be controlling an observatory dome and will be sending and receiving information to/from a PC. The hardware isn't the issue.

The PC has ASCOM software installed. ASCOM is an industry standard that allows many types of astronomy "software" to communicate with generic astronomy "hardware".

So I thought it would be logical to get the Picaxe to talk through ASCOM to the PC.

An example serial ASCOM message is as follows:

In DECIMAL:

016 002 001 000 252 002 016 003 000

The same string in ASCII:

DLE STX SOH NUL ü STX DLE ETX NUL


Now quoting from the serial protocol document:

Each of these segments is defined as follows:
<start> - Two character start sequence consisting of ASCII DLE and STX.
<addr> - One byte address ranging from 0 to 255.
<control> - One byte of control information.
<data> - 0 to 250 bytes of data.
<checksum> - Two bytes of checksum information.
<end> - Two character end sequence consisting of ASCII DLE and ETX.

So in the above example serial string (which I captured using Docklight), <addr> is 001, <control> is 000, data doesn't exist, and the two bytes of checksum data are in Decimal 252 002. There is also 000 at the end, which appears in the captured data, but does not exist in the documentation, so its probably an added on bit of data that doesnt conform to the official standard, and would be ignored by most programs.


Now the big question: I don't get how to calculate these two checksum decimal numbers from the message. 252 and 002.

The documentation states:


MNCP uses the two byte Fletcher's checksum to check data integrity. The checksum includes all data bytes and the address and control bytes. The checksum does not include the DLE characters added during character stuffing.
The checksum is calculated by the following procedure:

sum1 = 0;
sum2 = 0;
for (i = 0; i < length; i++) {
sum1 = (sum1 + message) % 255;
sum2 = (sum2 + sum1) % 255;
}

c1 = 255 - ((sum1 + sum2) % 255;
c2 = 255 - ((sum1 + c1) % 255;

c1 and c2 are then appended to the message. On the other end, the check is made by adding all of the message bytes and the two checksum bytes modulo 255. If the result is 0, the data is valid.



Thats where I get lost. I try to step through the calculation using the serial string I captured, but I never get 252 and 002 as the checksums. Any help appreciated.
 

Milos

Member
Dear Haxby,

I have done the counting manually (according your C program) and my results are c1 = 4 and c2 = 214 ($D6).
I have written my PICAXE code with the same results.

Code:
#picaxe	28X2

symbol sum1        = w0
symbol sum2        = w1
symbol c1            = w2
symbol c2            = w3
symbol counter     = b8
symbol message_i	 = b9

TABLE	0,(16,2,1,0,252,2,16,3,0)

sum1 = 0
sum2 = 0

for counter = 0 to 8
	readtable counter,message_i
	sum1 = sum1 + message_i
	sum1 = sum1 % 255
	sum2 = sum2 + sum1
	sum2 = sum2 % 255
next counter

c1 = sum1 + sum2
c1 = c1 % 255
c1 = 255 - c1
c2 = sum1 + c1
c2 = c2 % 255
c2 = 255 - c2

end
I cannot get your wanted results - 252 and 2.

I hope it can help you.
 

hippy

Technical Support
Staff member
016 002 001 000 252 002 016 003 000

Just do the checksum calculation on the packet payload, not the framing, then it works, just the "001 000" part.

In Milos's code change "for counter = 0 to 8" to "for counter = 2 to 3".
 

hippy

Technical Support
Staff member
Also ...

c1 and c2 are then appended to the message. On the other end, the check is made by adding all of the message bytes and the two checksum bytes modulo 255. If the result is 0, the data is valid.

It's important to study exactly what is written. The above ( modified Milos code ) calculates the checksum, c1 and c2. It doesn't verify the checksum. As the above describes, verification is easier, done on payload data plus checksum "001 000 252 002" ...

#picaxe 28X2

symbol sum1 = w0

TABLE 0,(16,2,1,0,252,2,16,3,0)

sum1 = 0

for counter = 2 to 5
readtable counter,message_i
sum1 = sum1 + message_i
next counter

sum1 = sum1 % 255

If sum1 = 0 Then
sertxd(#sum1, " - PASS")
Else
sertxd(#sum1, " - FAIL")
end if

end
 

Milos

Member
I modified my code a bit. Now c1 = c2 = 255 at the end.

Code:
#picaxe	28X2

symbol sum1	= w0
symbol sum2	= w1
symbol c1		= w2
symbol c2		=	w3
symbol counter		= b8
symbol message_i	= b9

TABLE	0,(1,0,252,2)

sum1 = 0
sum2 = 0

for counter = 0 to 3
	readtable counter,message_i
	sum1 = sum1 + message_i
	sum1 = sum1 % 255
	sum2 = sum2 + sum1
	sum2 = sum2 % 255
next counter

c1 = sum1 + sum2
c1 = c1 % 255
c1 = 255 - c1
c2 = sum1 + c1
c2 = c2 % 255
c2 = 255 - c2

end
I think that it is OK. You should omit the strings "c1 = 255 - c1" and "c2 = 255 - c2" when you are checking the summ to get zeroes. Or, you can treat 255 as the correct result.
 

Milos

Member
It is even simpler. You can forget about c1 and c2 when checking the summ.
This is my final code:

Code:
#picaxe 28X2

symbol sum1 = w0
symbol sum2 = w1
symbol c1 = w2
symbol c2 = w3
symbol counter = b8
symbol message_i = b9

; 6 bytes of data
; the last two are the summ
TABLE	0,(1,0,25,2,56,11,180,235)

; counting
sum1 = 0
sum2 = 0

for counter = 0 to 5 ; data only
	readtable counter,message_i
	sum1 = sum1 + message_i
	sum1 = sum1 % 255
	sum2 = sum2 + sum1
	sum2 = sum2 % 255
next counter

c1 = sum1 + sum2
c1 = c1 % 255
c1 = 255 - c1 ; c1 = 180
c2 = sum1 + c1
c2 = c2 % 255
c2 = 255 - c2 ; c2 = 235

; checking
sum1 = 0
sum2 = 0

for counter = 0 to 7 ; data + summ
	readtable counter,message_i
	sum1 = sum1 + message_i
	sum1 = sum1 % 255
	sum2 = sum2 + sum1
	sum2 = sum2 % 255
next counter

; sum1 = sum2 = 0
end
 
Top