Help understanding a Checksum

pmcmahon
2019-04-11
2019-04-23
  • pmcmahon

    pmcmahon - 2019-04-11

    CoDeSys v2.3 on an IFM CR0403 basic controller

    I'm working with J1939 message TSC1 with validates the data with a checksum and message counter in the 8th data byte. Here is the description of the checksum.

    Zitat:
    The message checksum is calculated using the first 7 data bytes, the message counter and the bytes of the message identifier. It is calculated as follows:
    Checksum = (Byte1 + Byte2 + Byte3 + Byte4 + Byte5 + Byte6 + Byte7 + (message counter & 0Fh) + message ID low byte + message ID mid low byte + message ID mid high byte + message ID high byte)
    Message Checksum = (((Checksum >> 6) & 03h) + (Checksum >>3) + Checksum) & 07h

    I was given code for CodeSys of that checksum to be

    Zitat:
    dwCheckSum :=abPGN0[1]+abPGN0[2]+abPGN0[3]+abPGN0[4]+abPGN0[5]+abPGN0[6]+abPGN0[7]+ (bMessageCounter AND 16#0F) + 16#11 + 16#00 + 16#00 + 16#0C;

    bMessageCheckSum := DWORD_TO_BYTE((((SHR(dwCheckSum,6)) AND 16#03) + (SHR(dwCheckSum,3)) + dwCheckSum) AND 16#07);

    abPGN0[8] := SHL(bMessageCheckSum,4) + bMessageCounter;

    I'd would like to actually understand the code I am using however. So the parts I get. abPGN0 is my 8 byte data array that makes up the data field of the message. The message counter is a rotating 0-7 decimal that will be 3 bits. That will have an AND mask with the 16#0F number (0000 1111). Which i think just ends up adding a leading 1 to the 3 bit number and will make it a 4 bit number? After that i'm quite lost. I don't understand the terminology of of ID low byte and mid low byte. How does that translate into the 16#11, 16#00, and 16#0C numbers? I'm also totally lost on the whole bMessageCheckSum line. Why are we shifting the numbers right and what does this do? Help please!

     
  • john-hedges-ifm

    john-hedges-ifm - 2019-04-23

    Hi there,

    The checksum code you have was developed based on documentation from Deutz for their new Stage V engine. The documentation is very misleading in places and so I cannot say for sure that the following solution is correct - however, it appears to work well based on testing with an engine on site.

    The '&' signs were replaced with '+' as the statement "& 16#03" is not valid.

    The last part of the checksum line where the 4 parts of the message ID are added together can be exampled as follows:



    The shifting of data after addition is something that is requested by the Deutz documentation and so I cannot explain why this is required, but it is necessary. The last shift function 'SHR(bMessageCheckSum, 4)' is to move the checksum into the low nibble of 'abPGN0[8]'.

    Finally, you must be careful when adding the Checksum to the message counter. Because the Checksum and counter are separated into the low nibble and high nibble of the 8th byte respectively, you must add them in a binary fashion. Example:



    If I remember rightly, the counter must not exceed 7 according to the Deutz document - worth checking this too.

    Hope this helps.

    Regards,
    John

     

Log in to post a comment.