Go Down

Topic: Checksum Nightmare! (Read 1 time) previous topic - next topic

SystemsGuy

Aug 05, 2012, 02:02 am Last Edit: Aug 06, 2012, 12:14 am by SystemsGuy Reason: 1
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: [Select]
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: [Select]
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!

retrolefty

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.  ;)
Good luck;
Lefty

SystemsGuy

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!

Tom Carpenter

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.
~Tom~

el_supremo

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

PeterH

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.
I only provide help via the forum - please do not contact me for private consultancy.

Tom Carpenter

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.
~Tom~

SystemsGuy

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! :P


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

Code: [Select]
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: [Select]

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: [Select]

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!

MarkT

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.
[ I won't respond to messages, use the forum please ]

Nick Gammon


I have a old display controller ...


The model / device number? Link? Any manuals? Documentation?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

SystemsGuy



I have a old display controller ...


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


Nothing helpful - proprietary CANBUS device with no published documentation.

Tom Carpenter

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?
~Tom~

SystemsGuy

#12
Aug 05, 2012, 09:28 pm Last Edit: Aug 05, 2012, 09:36 pm by SystemsGuy Reason: 1

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: [Select]
// 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: [Select]

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

cwrose

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

PeterH

Or, go through the rigmarole I suggested to find out which bits affect the CRC value.
I only provide help via the forum - please do not contact me for private consultancy.

Go Up