Pages: [1] 2 3   Go Down
Author Topic: Checksum Nightmare!  (Read 1662 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So I've been looking at this problem too long.  I have a old display controller that I can send a message to, but it require a checksum to "accept" the message.  Checksum is a 2 byte value 1 byte value, and the controller is kind enough to "brute force" the checksum since it sends back a "bad checksum" message.

What I know is
1] The checksum is not byte position dependent - so I can swap bytes in the message with no change in the checksum.
2] The checksum is decremented when the data value is incremented - so if I change a data value from "00" to "01" the checksum is one less.

Complicating the matter a bit is that there is framing data that I do not believe is included in the calculation - but I've experimented enough to "think" I know what bytes are included an which are excluded.

Code:
MenuFrames[4].data[0] = 0x10;
MenuFrames[4].data[1] = 0x14;
MenuFrames[4].data[2] = 0x03;
MenuFrames[4].data[3] = 0x26;
MenuFrames[4].data[4] = 0x01;
MenuFrames[4].data[5] = 0x00;
MenuFrames[4].data[6] = 0x01;
MenuFrames[4].data[7] = 0x00;
MenuFrames[4].data[8] = 0x21;
MenuFrames[4].data[9] = 0x22;

The checksum of the frame above is 0x29.  I *think* that data[1] and data[2] as well as [8] and [9] are excluded, but not 100% positive.  

If I change one byte as follows :
Code:
MenuFrames[4].data[0] = 0x10;
MenuFrames[4].data[1] = 0x14;
MenuFrames[4].data[2] = 0x03;
MenuFrames[4].data[3] = 0x26;
MenuFrames[4].data[4] = 0x01;
MenuFrames[4].data[5] = 0x00;
MenuFrames[4].data[6] = 0x00;
MenuFrames[4].data[7] = 0x00;
MenuFrames[4].data[8] = 0x21;
MenuFrames[4].data[9] = 0x22;

The checksum is now 0x2A as data[6] changed.

Suggestions as to what type of checksum formula is being used, or advise as to how to figure it out would be greatly appreciated!
« Last Edit: August 05, 2012, 05:14:28 pm by SystemsGuy » Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17301
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The use of CRC in the title is misleading as CRC stands for cyclic redundancy code, a much more rigorous error detection method then simple checksum totals. There are several 'standard' CRC standards, but when one gets to simple checksum methods I don't think there are standards to go by. What the starting value of the checksum variable should be is one factor I would think. Also which characters in the specific message format to include or exclude in the checksum calc is also germain. The only file format I've used that uses simple checksums is the the 'Intel HEX' format that the arduino platform uses to save the compiled AVR binary output.

Perhaps what you have posted is enough to allow some of your software gurus to figure out for you, but that's not me.  smiley-wink
Good luck;
Lefty
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Lefty - good point, as you say, it's a simply checksum - I hope!   Thanks for responding - I've still not stopped looking at it - probably need to take a break, as it's starting to do my head in!
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1729
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you know what each of your 10 bytes represent? Also, can you try some more random combinations of data and see what the display wants the checksum to be for each of those combinations.
Logged

~Tom~

Offline Offline
Edison Member
*
Karma: 49
Posts: 1670
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

At first you say:
Quote
Checksum is a 2 byte value
but then you say
Quote
The checksum of the frame above is 0x29
which is one byte.
Which is it?
I agree with Tom Carpenter that testing it with some random data to get more checksums might help.

Pete
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What I'd do is write a method to determine the checksum of a given frame by submitting it with each possible checksum in turn until it is accepted.

Then call that with a frame of zero bytes and set each byte to 0xFF in turn and see which bytes affect the checksum.

Once you know which bytes affect the checksum, I'd hope to be able to decide the checksum algorithm by toggling a few bits and see how that affected the checksum.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1729
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Its more helpful initially to have a number of different know valid frames (as in, at least 3, preferably more), and then work from their.
Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Told ya - been looking at this too long!

The checksum is 1 byte.  I can generate as many frames as I like and find the valid checksum from the display controller - right now that's what I'm doing to send it messages - generating the message, brute forcing the checksum, and then saving that into my frame data.  Great for static frames, useless if I want to generate dynamic frames without brute forcing every time.

The methodology you are suggesting is to send an "all zeros" message, get the valid checksum, and then do the same with an "all FF" message?  I can try that - I've not used an "FF" in the frame before - probably set my display into some really weird mode! smiley-razz


What I have at hand - if you want three examples - is as follows :

Code:
MenuFrames[0].data[0] = 0x10;  // frame #
MenuFrames[0].data[1] = 0x1B;  // data length
MenuFrames[0].data[2] = 0x03;
MenuFrames[0].data[3] = 0x24;
MenuFrames[0].data[4] = 0x02;
MenuFrames[0].data[5] = 0x00;
MenuFrames[0].data[6] = 0x01;
MenuFrames[0].data[7] = 0x01;


MenuFrames[1].data[0] = 0x21; // frame #
MenuFrames[1].data[1] = 0x00;
MenuFrames[1].data[2] = 0x00;
MenuFrames[1].data[3] = 0x00;
MenuFrames[1].data[4] = 0x12;
MenuFrames[1].data[5] = 0x09;
MenuFrames[1].data[6] = 0x01;
MenuFrames[1].data[7] = 0x00;


MenuFrames[2].data[0] = 0x22; // frame #
MenuFrames[2].data[1] = 0x02;
MenuFrames[2].data[2] = 0x00;
MenuFrames[2].data[3] = 0x65;
MenuFrames[2].data[4] = 0x42;
MenuFrames[2].data[5] = 0x72;
MenuFrames[2].data[6] = 0x61;
MenuFrames[2].data[7] = 0x6b;


MenuFrames[3].data[0] = 0x23; // frame #
MenuFrames[3].data[1] = 0x65;
MenuFrames[3].data[2] = 0x20;
MenuFrames[3].data[3] = 0x4D;
MenuFrames[3].data[4] = 0x6F;
MenuFrames[3].data[5] = 0x64;
MenuFrames[3].data[6] = 0x00;
MenuFrames[3].data[7] = 0xE7; // checksum


and

Code:
MenuFrames[4].data[0] = 0x10; // frame #
MenuFrames[4].data[1] = 0x14; // data length
MenuFrames[4].data[2] = 0x03;
MenuFrames[4].data[3] = 0x26;
MenuFrames[4].data[4] = 0x01;
MenuFrames[4].data[5] = 0x00;
MenuFrames[4].data[6] = 0x01;
MenuFrames[4].data[7] = 0x14;

MenuFrames[5].data[0] = 0x21; // Frame #
MenuFrames[5].data[1] = 0x10;
MenuFrames[5].data[2] = 0x53;
MenuFrames[5].data[3] = 0x79;
MenuFrames[5].data[4] = 0x73;
MenuFrames[5].data[5] = 0x74;
MenuFrames[5].data[6] = 0x65;
MenuFrames[5].data[7] = 0x6D;

MenuFrames[6].data[0] = 0x22; // Frame #
MenuFrames[6].data[1] = 0x20;
MenuFrames[6].data[2] = 0x4F;
MenuFrames[6].data[3] = 0x4E;
MenuFrames[6].data[4] = 0x20;
MenuFrames[6].data[5] = 0x20;
MenuFrames[6].data[6] = 0x00;
MenuFrames[6].data[7] = 0x83; // Checksum

and

Code:
MenuFrames[4].data[0] = 0x10; // Frame Header
MenuFrames[4].data[1] = 0x14; // Data Length
MenuFrames[4].data[2] = 0x03;
MenuFrames[4].data[3] = 0x26;
MenuFrames[4].data[4] = 0x01;
MenuFrames[4].data[5] = 0x00;
MenuFrames[4].data[6] = 0x01;
MenuFrames[4].data[7] = 0x14;

MenuFrames[5].data[0] = 0x21; // Frame #
MenuFrames[5].data[1] = 0x10;
MenuFrames[5].data[2] = 0x53;
MenuFrames[5].data[3] = 0x79;
MenuFrames[5].data[4] = 0x73;
MenuFrames[5].data[5] = 0x74;
MenuFrames[5].data[6] = 0x65;
MenuFrames[5].data[7] = 0x6D;

MenuFrames[7].data[0] = 0x22; // Frame #
MenuFrames[7].data[1] = 0x20;
MenuFrames[7].data[2] = 0x4F;
MenuFrames[7].data[3] = 0x46;
MenuFrames[7].data[4] = 0x46;
MenuFrames[7].data[5] = 0x20;
MenuFrames[7].data[6] = 0x00;
MenuFrames[7].data[7] = 0x65; // Checksum


(Examples 2 & 3 are correct - 2 is composed of frames 4,5 & 6, 3 is frames 4,5 & 7)

Mucho appreciate any and all advice!
Logged

0
Offline Offline
Shannon Member
****
Karma: 215
Posts: 12467
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So if you start with 0x00 and subtract each checksummed byte from it, does that work?  You said incrementing a byte decrements the result and that swapping bytes makes no difference - if that's true it must be subtracting each byte.

On reception you are probably meant to sum all the relevant bytes in the message _including the checksum_ to yield a fixed value which validates the checksum.

And yes its a checksum, not a CRC code.
Logged

[ I won't respond to messages, use the forum please ]

Global Moderator
Online Online
Brattain Member
*****
Karma: 499
Posts: 19070
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a old display controller ...

The model / device number? Link? Any manuals? Documentation?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a old display controller ...

The model / device number? Link? Any manuals? Documentation?

Nothing helpful - proprietary CANBUS device with no published documentation.
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1729
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I notice the three examples you just posted are a totally different layout to the the ones in the post before?

Also, you say 2 and 3 are correct, what about 1?
Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I notice the three examples you just posted are a totally different layout to the the ones in the post before?

Also, you say 2 and 3 are correct, what about 1?

In the post above - they are all correct - I was just not very clear.  You hit it on the head, though - didn't notice it last night, but did this morning.  I could easily run the data sequences, but when I changed the data length, I kept screwing up my results.  I could easily calculate the checksum with a set of frames of fixed data length, but when I changed the length, was never right!

So - to complicate things, the checksum also is effected by the data length. Remind me to slow down on the tasty beverage consumption.

Data's in a different format, just for ease of me playing with it.. 

Code:
// trying to see if the length byte is part of the checksum
// joy, it is.  Not same as changing data. Naturally
data = {0x10,0x07,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0xC7,0x00,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x08,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0xC1,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x09,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0xBA,0x00,0x00,0x00,0x0}
data = {0x10,0x0A,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0xB2,0x00,0x00,0x0}
data = {0x10,0x0B,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0xA9,0x00,0x0}
data = {0x10,0x0C,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x9F,0x0}
data = {0x10,0x0D,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x94}
data = {0x10,0x0E,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x88,0x00,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x0F,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x7B,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x10,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x6D,0x00,0x00,0x00,0x0}
data = {0x10,0x11,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x5E,0x00,0x00,0x0}
data = {0x10,0x12,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x4E,0x00,0x0}
data = {0x10,0x13,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x3D,0x0}
data = {0x10,0x14,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x2B}
data = {0x10,0x15,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x18,0x00,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x16,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x4,0x00,0x00,0x00,0x00,0x0}
data = {0x10,0x17,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0xEF,0x00,0x00,0x00,0x0}
data = {0x10,0x18,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0xD9,0x00,0x00,0x0}
data = {0x10,0x19,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0xC2,0x00,0x00,
data = {0x10,0x1A,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0xAA,0x0}
data = {0x10,0x1B,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x91}

// Sanity check - changing (add) one bit, regardless of position, decreases checksum
data = {0x10,0x1B,0x03,0x26,0x00,0x00,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x90}
data = {0x10,0x1B,0x03,0x26,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x90}


Here's the same in tabular format, just the length, checksum, and difference.

Code:
Data Length Checksum Diff
7 C7 6
8 C1 7
9 BA 8
A B2 9
B A9 A
C 9F B
D 94 C
E 88 D
F 7B E
10 6D F
11 5E 10
12 4E 11
13 3D 12
14 2B 13
15 18 14
16 4 15
17 EF 16
18 D9 17
19 C2 18
1A AA 19
1B 91
« Last Edit: August 05, 2012, 02:36:25 pm by SystemsGuy » Logged

Offline Offline
Jr. Member
**
Karma: 1
Posts: 55
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The crc is almost certainly an XOR of the relevant bytes, but it's difficult to
see which bytes are relevant, since in the examples you give the fields
vary widely in length and description.

If you can work out the packet structure,  ie. what the various bytes are
used for, then it might be easier to see which are likely to be used as part
of the CRC.

Will
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or, go through the rigmarole I suggested to find out which bits affect the CRC value.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: [1] 2 3   Go Up
Jump to: