Thread: XOR checksum calculation of 6 variables

  1. #1
    Registered User
    Join Date
    Jan 2019
    Posts
    6

    XOR checksum calculation of 6 variables

    A program to calculate the checksum of one variable is here below (source: http://forum.arduino.cc/index.php?topic=488003.0).

    However, I need a program (based on this below if possible) that calculates this checksum for 3 floats, 2 integers and one ASCII character. These variables are individually available.

    In reverse, the same calculation needs to be done at the receiving end where the data is available as string characters separated by commas. For example: 43.25,28.25,11.20,33,28,A. (the dot after A is included).
    So at the receiving end the same values as at the transmitting side are available but separated with commas.

    Code:
    String dataToParse;
    void setup()
    {
      // put your setup code here, to run once:
      Serial.begin(115200);
    }
    
    void loop()
    {
      // put your main code here, to run repeatedly:
    
       if (Serial.available() > 0)
          {           
          dataToParse = Serial.readString();
          Serial.print("ToCheckSum.:");
          Serial.println(dataToParse);
          Serial.print("");
          Serial.print("ToCheckLength.:");
          Serial.println(dataToParse.length());
          Serial.print("");
          char toCheck[dataToParse.length()];
          Serial.print("Size ToCheck.:");
          Serial.println(sizeof(toCheck));
          dataToParse.toCharArray(toCheck,dataToParse.length());
          byte aaa = getCheckSum(toCheck);
          Serial.print("CheckSum HEX.:");
          Serial.println(aaa,HEX);
          Serial.print("CheckSum DEC.:");
          Serial.println(aaa,DEC);
          Serial.print("");     
          dataToParse ="";
         } 
    }
    uint8_t getCheckSum(char *string)
    {
      int XOR = 0; 
      for (int i = 0; string[i] != '\0';  i+= 2) // <-- increment by 2
      {
        Serial.print("i.:");
        Serial.println(string[i]);
        Serial.print("");
    
        // make single byte value out of 2 characters from the string...
        byte b1,b2,b;
    
        // First byte: hex to bin
        b1 = string[i];
        if (b1 >= 'a')
          b1 = b1 - 'a' + 10;
        else if (b1 >= 'A')
          b1 = b1 - 'A' + 10;
        else
          b1 -= '0';
    
        // Second byte: hex to bin
        b2 = string[i + 1];
        if (b2 >= 'a')
          b2 = b2 - 'a' + 10;
        else if (b2 >= 'A')
          b2 = b2 - 'A' + 10;
        else
          b2 -= '0';
    
        // Combine the two
        b = 0x10 * b1 + b2;
    
        XOR = XOR ^ b;
      }
    
      return XOR; 
    }

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    You can treat a float and an integer as arrays of bytes. That way, you could create their checksum by simply passing a uint8_t array (with all their values, serialized) and its size to getCheckSum().

    You could use a struct for that, but be careful about possible alignment issues.
    Devoted my life to programming...

  3. #3
    Registered User
    Join Date
    Jan 2019
    Posts
    6
    Quote Originally Posted by GReaper View Post
    You can treat a float and an integer as arrays of bytes. That way, you could create their checksum by simply passing a uint8_t array (with all their values, serialized) and its size to getCheckSum().

    You could use a struct for that, but be careful about possible alignment issues.
    Ok, thanks for that input.
    I declared two variables as string and added the variables inside (not yet used for calculations, just to verify if this addition works):
    Code:
    float cyclevalue = 40.43;
    float temp1 = 50.21;
    float battVolt = 12.21;
    int time1 = 12;
    int time2 = 20;
    char C = "X";
    String checksumCheck1;
    String checksumCheck2;
    void setup()
    {
      Serial.begin(115200);
    }
    void loop()
    {
      if (Serial.available() > 0)
      {
        dataToParse = Serial.readString();
        checksumCheck1 = cyclevalue;
        checksumCheck2 = checksumCheck1 + "," + temp1 + "," + battVolt + "," + time1 + "," + time2 + "," + "C" + ".";
        Serial.print("checksumCheck2 : ");
        Serial.println(checksumCheck2);
    // rest of the code per my first post.
    Next is to add this cchecksum to the data to be transmitted.

    However, at the receiver I now get a packet including this checksum which I have to remove before calculating the checksum again, now on the receiver side.

    At the receiver I have an array which used to contain (prior to using the checksum): 3 floats, two integers and one character, separated by commas. For example: 43.65,27.25,11.0 0,33,37,C.
    The C has a dot after it, and that is it.
    Now there will be a checksum value preceding these values, also separated by a comma from the first float.
    Question: how can I extract this checksum from this array?

    The array at the receiver is defined as char receivedChars[32];
    Last edited by brice3010; 01-20-2019 at 01:25 PM.

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    I was thinking raw binary data, but your way is better because it avoids many common pitfalls.

    If you receive the whole thing as a string, you need to parse it. I don't know, doesn't the Arduino language have something similar to sscanf()? If not, you'll need to make your own simplified version.
    Devoted my life to programming...

  5. #5
    Registered User
    Join Date
    Jan 2019
    Posts
    6
    I receive the data in a char array (size 32), not a string (I had edited my message after posting).
    I am not familiar enough with Arduino language to know. But since the data is in a cha array I assume/hope/think/.. that it should not be too hard to extract the first characters and the first comma from this array. I just don't know enough of C how to do this.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    So, the 32 char array is not null terminated?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Jan 2019
    Posts
    6
    No. Just the values as shown in my initial post.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ah. It seems to me that you have two options:
    • Parse the char array "manually". This means looping over the characters of the array until either all the items have been tokenised (presumably by looking for the next ',' character) and parsed, or all 32 characters have been processed.
    • Copy the char array to another char array of 33 characters, and append a null character after the last valid character. After doing this, you can then use standard C functions like sscanf to parse the null terminated string, or strtok to tokenise it based on the commas and then you parse the individual tokens yourself.

    If you have space to spare (it is only another 33 characters, so 36 bytes at most for alignment) and the standard library string functions are available, I would recommend the second approach.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jan 2019
    Posts
    6
    Quote Originally Posted by laserlight View Post
    Ah. It seems to me that you have two options:
    • Parse the char array "manually". This means looping over the characters of the array until either all the items have been tokenised (presumably by looking for the next ',' character) and parsed, or all 32 characters have been processed.
    • Copy the char array to another char array of 33 characters, and append a null character after the last valid character. After doing this, you can then use standard C functions like sscanf to parse the null terminated string, or strtok to tokenise it based on the commas and then you parse the individual tokens yourself.

    If you have space to spare (it is only another 33 characters, so 36 bytes at most for alignment) and the standard library string functions are available, I would recommend the second approach.
    Parsing is done separately. A transmitter sends about 24 bytes at 1200 baud; a startmarker < and an endmarker > are included around three floats, two integers and one character (identifier: A, or B or C or D) plus a dot. Floats, integers and identifier are separated by a comma.
    At TX a XOR checksum is performed (2 hex characters) and inserted after the < and the first float, separated by a comma.

    At RX these two hex characters and the first comma need to be extracted (ie as in "removed") and used to be compared with the same XOR checksum calculation of the received characters (excluding the < and the > and the hex characters. Both XOR calculations then are compared to verify integrity of the received character array.

    So, in this case, my question is how to remove the 2 hex characters and the first comma from the received array. And store the 2 hex characters for further use.

    Parsing is done separately in a different function, with the received character array excluding the 2 hex characters and excluding the first comma behind the 2 hex characters.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brice3010
    So, in this case, my question is how to remove the 2 hex characters and the first comma from the received array. And store the 2 hex characters for further use.
    That would be even easier since you basically have two goals:
    • Extract the checksum.
    • Obtain a pointer to the actual data, i.e., a pointer to the first character in the array after the comma that denotes the end of the checksum.

    This can be done in one of two ways, depending on the format of the input:
    • If you know for sure that the checksum will be exactly two hex digit characters followed by a comma, then to extract it you just need to extract the first two characters, e.g., whether you compute the integer checksum from the hex characters, or just copy the two characters to another array. The pointer to the actual data is trivial since it is just char_array + 3.
    • Otherwise, you need to loop to find the first comma. Once you do so, the portion of the array before that comma is the checksum, and you just need to +1 to the pointer to that comma to get the pointer to the actual data.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Jan 2019
    Posts
    6
    Quote Originally Posted by laserlight View Post
    That would be even easier since you basically have two goals:
    • Extract the checksum.
    • Obtain a pointer to the actual data, i.e., a pointer to the first character in the array after the comma that denotes the end of the checksum.

    This can be done in one of two ways, depending on the format of the input:
    • If you know for sure that the checksum will be exactly two hex digit characters followed by a comma, then to extract it you just need to extract the first two characters, e.g., whether you compute the integer checksum from the hex characters, or just copy the two characters to another array. The pointer to the actual data is trivial since it is just char_array + 3.
    • Otherwise, you need to loop to find the first comma. Once you do so, the portion of the array before that comma is the checksum, and you just need to +1 to the pointer to that comma to get the pointer to the actual data.
    To extract/remove the first three characters (2 hex characters and a comma) I think of using strtol(); and store as hex data
    Is that your idea to, or something else? How to write this command in my case?

    The checksum can then be performed on the remainder in the char array.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by brice3010
    To extract/remove the first three characters (2 hex characters and a comma) I think of using strtol(); and store as hex data
    If you use strtol, you won't be storing as "hex data"; you will be storing the integer that is represented by those two hex digits.

    Quote Originally Posted by brice3010
    Is that your idea to, or something else?
    I didn't have any particulat specific idea in mind, but yes, strtol will work as it has a parameter to specify the number base.

    Quote Originally Posted by brice3010
    How to write this command in my case?
    I suggest replacing the comma (i.e., the character at index 2) with a null character. This way, the first two hex digits become part of a string of length 2. You can then pass the array of char to strtol and it will work since the embedded null character means that strtol will not examine the portion of the array that contains the actual data, and hence will convert the checksum alone correctly.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checksum generate
    By yazixchi in forum C Programming
    Replies: 8
    Last Post: 05-29-2011, 10:55 PM
  2. checksum calculation
    By karthigayan in forum C Programming
    Replies: 3
    Last Post: 06-29-2009, 03:18 AM
  3. Making of checksum using XOR
    By Subsonics in forum C Programming
    Replies: 4
    Last Post: 02-20-2009, 01:19 PM
  4. CheckSum help
    By remoir in forum C Programming
    Replies: 13
    Last Post: 02-01-2009, 10:19 PM
  5. CRC / checksum
    By Zoltarc in forum C++ Programming
    Replies: 0
    Last Post: 11-30-2002, 11:05 PM

Tags for this Thread