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.
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
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!
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.
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.
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!
What I have at hand - if you want three examples - is as follows :
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.
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..
// 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.
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
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.
retrolefty:
So again I will ask, is this topic discussing a CRC algorithm or a simple checksum algorithm?
Sorry lefty - subject updated - didn't realize I could fix that! It's a CRC.
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
Hey Will - See below :
Frame.data[0] = Frame ID - Seems to be irrelevant to CRC, but can't be changed. Sequence starts with "10", ACK'd, responses are "21, 22, 23...."
Frame.data[1] = Length of data - excludes Frame Sequence numbers (see above).
In the first frame, the are a couple of data bytes that represent the location and style of text - these are all included in the checksum.
In the remaining frames, frame.data[0] is the sequence number, all the rest is data up to the checksum.
PeterH:
Or, go through the rigmarole I suggested to find out which bits affect the CRC value.
Peter - that's exactly what I did, and how I discovered that the frame length - Frame.data[1] - has a different impact on the CRC - see the table I posted earlier.
Each Frame of "X" bytes has a consistent CRC - if you change a byte from "00" to "01", the CRC decreases by 1.
If I change the data length, the CRC "jumps" as described in the table below -
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
Here are some example frames, 2 frames, so sequence 10 and 21, length 0x09 -
|First Frame, Sequence #10
|
| | Length, excluding Sequence Bytes
| | | Second Frame, Sequence #21
| | | | CRC - since length is 9, it is 9 bytes from length
| | | | byte excluding the Frame sequence bytes
data[] ={0x10,0x9,0x3,0x00,0xFF,0xFF,0xFF,0xFF,0x21,0xFF,0xFF,0xE6};
data[] ={0x10,0x9,0x3,0x00,0x00,0xFF,0xFF,0xFF,0x21,0xFF,0xFF,0xE5};
data[] ={0x10,0x9,0x3,0x00,0x00,0x00,0xFF,0xFF,0x21,0xFF,0xFF,0xE4};
data[] ={0x10,0x9,0x3,0x00,0x00,0x00,0x00,0xFF,0x21,0xFF,0xFF,0xE3};
data[] ={0x10,0x9,0x3,0x00,0x00,0x00,0x00,0x00,0x21,0xFF,0xFF,0xE2};
data[] ={0x10,0x9,0x3,0x26,0x00,0x00,0x00,0x00,0x21,0xFF,0xFF,0xBC};
data[] ={0x10,0x9,0x3,0x24,0x00,0x00,0x00,0x00,0x21,0xFF,0xFF,0xBE};
Some more example frames of different lengths, show CRC jump
Sorry, I may have missed where you explained this earlier, but I'm having trouble figuring out what all that data means.
Is each frame processed independently? There are several places where you seem to have several frames in the same buffer and I'm not clear how those relate to the messaging structure.
Do you understand the overall structure of a frame i.e. where the sequence number, length and CRC are for any frame?
Do you understand which bits and bytes within that frame affect the CRC?
If so, what you really need is examples of values of the bits/bytes that affect the CRC, and what the corresponding CRC value is.
Perhaps you already gave us that, but I haven't been able to figure that out from your preceding posts.
Hey Peter - sorry, guess I'm not doing well explaining. The frames are CAN BUS messages.
A message is made up of one or more frames of up to 8 bytes. In the situation I'm in, there is always more than one frame in a message. Messages are sent with a "frame sequence number" in byte 0.
The first frame is special, in that it contains the length of the data being sent, then the destination, and some formatting info. This first frame's "sequence number" in byte 0 is always "10". Byte 1 is the length of the message being sent, EXCLUDING the frame sequence numbers.
So frame one starts with "10", then the length, and 6 other data bytes. As nearly as I can tell, all data in Frame 10 is used in the checksum, including the length - but as I posted earlier, the length has a different impact on the crc than the data fields.
Example of frame 1 , where the length is 0x18 and the destination is 0x03 :
0x10,0x18,0x3,0x26,0x0,0x0,0x0,0x0
Following frames carry the data up to the data length, and then the checksum :
Example of frame 2
0x21,0x0,0x0,0x0,0x0,0x0,0x0,0x0
to make the length of 0x18, takes another frame. I was playing, and added the data byte "1" at position 5.
0x22,0x0,0x0,0x0,0x0,0x1,0x0,0x0
And finally, the last frame, which also holds the CRC at position 4. This is 0x18 bytes from the length value in frame 1, excluding the frame sequence bytes.