Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to calculate 8-bit Checksum (2’s complement)?

How to calculate 8-bit Checksum (2’s complement)?

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 7.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    ahsan737
    wrote on 22 May 2020, 00:45 last edited by ahsan737
    #1

    Greetings,

    I am receiving data via Bluetooth, and I want to calculate 8-bit Checksum (2’s complement) for incoming data (Hex format).
    what is the simplest approach for this calculation?

    I am using the following code for incoming data interpretation:

        while (socket->bytesAvailable())
        {
               QByteArray receivedBytes = socket->readAll();
                hexString.append(receivedBytes.toHex(0));
    
                char hex[hexString.size()];
                strcpy(hex, hexString); 
                QByteArray data=QByteArray::fromHex(hex);
                QDataStream stream(data);
                stream.setByteOrder(QDataStream::BigEndian);
    
                uint8_t bn, nb, esc, s, cs;
                uint16_t d1,d2,d3,d4;
    
                stream>>bn>>nb>>esc>>s;
                stream>>d1>>d2>>d3>>d4;
                stream>>cs;
       }
    

    Looking forward to your kind responses.

    J 1 Reply Last reply 22 May 2020, 05:42
    0
    • A ahsan737
      22 May 2020, 00:45

      Greetings,

      I am receiving data via Bluetooth, and I want to calculate 8-bit Checksum (2’s complement) for incoming data (Hex format).
      what is the simplest approach for this calculation?

      I am using the following code for incoming data interpretation:

          while (socket->bytesAvailable())
          {
                 QByteArray receivedBytes = socket->readAll();
                  hexString.append(receivedBytes.toHex(0));
      
                  char hex[hexString.size()];
                  strcpy(hex, hexString); 
                  QByteArray data=QByteArray::fromHex(hex);
                  QDataStream stream(data);
                  stream.setByteOrder(QDataStream::BigEndian);
      
                  uint8_t bn, nb, esc, s, cs;
                  uint16_t d1,d2,d3,d4;
      
                  stream>>bn>>nb>>esc>>s;
                  stream>>d1>>d2>>d3>>d4;
                  stream>>cs;
         }
      

      Looking forward to your kind responses.

      J Offline
      J Offline
      JonB
      wrote on 22 May 2020, 05:42 last edited by JonB
      #2

      @ahsan737
      You'll have to be more specific about just what you mean. "Hex format" is not relevant, as per your code you'll convert any strings into the actual numbers and do the math on that. 8-bit checksum is often just sum() % 255 or (uint8_t)sum(), perhaps you want a ~ in front of it for your "2’s complement". See maybe https://stackoverflow.com/questions/31151032/writing-an-8-bit-checksum-in-c or https://stackoverflow.com/questions/27505240/computing-a-8-bit-checksum-in-c.

      Your current

                  char hex[hexString.size()];
                  strcpy(hex, hexString); 
                  QByteArray data=QByteArray::fromHex(hex);
      

      is simply a waste of time & space, you can just QByteArray::fromHex(hexString);. Worse that that, you are actually copying one more character (the terminating \0) from hexString than the size you have allocated for stack variable hex, so you're lucky if this does not corrupt your stack....

      As a side note your, code is assuming that socket->readAll() inside socket->bytesAvailable() will read all bytes, sufficient for all your expected variables (and no more than that). This is dangerous, readAll() only returns however many happen to be there at the instant you call bytesAvailable(), which may not yet be all sent (or could even be more than for one structure, depending on your protocol). You should buffer your input till you have enough for your structure, you could look at QDataStream::startTransaction().

      A 1 Reply Last reply 22 May 2020, 06:05
      1
      • J JonB
        22 May 2020, 05:42

        @ahsan737
        You'll have to be more specific about just what you mean. "Hex format" is not relevant, as per your code you'll convert any strings into the actual numbers and do the math on that. 8-bit checksum is often just sum() % 255 or (uint8_t)sum(), perhaps you want a ~ in front of it for your "2’s complement". See maybe https://stackoverflow.com/questions/31151032/writing-an-8-bit-checksum-in-c or https://stackoverflow.com/questions/27505240/computing-a-8-bit-checksum-in-c.

        Your current

                    char hex[hexString.size()];
                    strcpy(hex, hexString); 
                    QByteArray data=QByteArray::fromHex(hex);
        

        is simply a waste of time & space, you can just QByteArray::fromHex(hexString);. Worse that that, you are actually copying one more character (the terminating \0) from hexString than the size you have allocated for stack variable hex, so you're lucky if this does not corrupt your stack....

        As a side note your, code is assuming that socket->readAll() inside socket->bytesAvailable() will read all bytes, sufficient for all your expected variables (and no more than that). This is dangerous, readAll() only returns however many happen to be there at the instant you call bytesAvailable(), which may not yet be all sent (or could even be more than for one structure, depending on your protocol). You should buffer your input till you have enough for your structure, you could look at QDataStream::startTransaction().

        A Offline
        A Offline
        ahsan737
        wrote on 22 May 2020, 06:05 last edited by
        #3

        @JonB
        Thank you so much for pointing out mistakes.
        for checksum: I have to calculate checksum for given data and make comparison with the checksum reference value.

        checksum.JPG

        J 1 Reply Last reply 22 May 2020, 06:21
        0
        • A ahsan737
          22 May 2020, 06:05

          @JonB
          Thank you so much for pointing out mistakes.
          for checksum: I have to calculate checksum for given data and make comparison with the checksum reference value.

          checksum.JPG

          J Offline
          J Offline
          JonB
          wrote on 22 May 2020, 06:21 last edited by JonB
          #4

          @ahsan737
          You haven't said how that 36 is calculated from the input bytes. I already suggested to you

          is often just sum() % 255 or (uint8_t)sum(), perhaps you want a ~ in front of it for your "2’s complement".

          You can do it from here, I'm not going to figure how you come up with your checksum number or do the C++ for you.

          A 1 Reply Last reply 22 May 2020, 06:28
          0
          • H Offline
            H Offline
            hskoglund
            wrote on 22 May 2020, 06:24 last edited by
            #5

            Hi, should be something like this:

            QByteArray receivedBytes = socket->readAll();
            
            char c = 0;
            for (auto b : receivedBytes)
                c += b;
            
            c = 256 - c;
            qDebug() << QString::number(c,16);
            

            (I got 36 when i tested with

             QByteArray receivedBytes = QByteArray::fromHex("D4 0A 1B 73 0F 3A 0F 41 00 A7 0A 14")
            
            J A 2 Replies Last reply 22 May 2020, 06:31
            3
            • J JonB
              22 May 2020, 06:21

              @ahsan737
              You haven't said how that 36 is calculated from the input bytes. I already suggested to you

              is often just sum() % 255 or (uint8_t)sum(), perhaps you want a ~ in front of it for your "2’s complement".

              You can do it from here, I'm not going to figure how you come up with your checksum number or do the C++ for you.

              A Offline
              A Offline
              ahsan737
              wrote on 22 May 2020, 06:28 last edited by
              #6

              @JonB Thanks, got your point. And I have already mentioned checksum type twice (question title, and description).

              1 Reply Last reply
              0
              • H hskoglund
                22 May 2020, 06:24

                Hi, should be something like this:

                QByteArray receivedBytes = socket->readAll();
                
                char c = 0;
                for (auto b : receivedBytes)
                    c += b;
                
                c = 256 - c;
                qDebug() << QString::number(c,16);
                

                (I got 36 when i tested with

                 QByteArray receivedBytes = QByteArray::fromHex("D4 0A 1B 73 0F 3A 0F 41 00 A7 0A 14")
                
                J Offline
                J Offline
                JonB
                wrote on 22 May 2020, 06:31 last edited by JonB
                #7

                @hskoglund said in How to calculate 8-bit Checksum (2’s complement)?:

                c = 256 - c;
                qDebug() << QString::number(c,16);

                Slight correction: This generates a number in range 1--256. Isn't the checksum supposed to be a byte 0--255 (uint8_t cs)? Yet you say you did get 36 on the data, so perhaps not, but surprises me....

                H 1 Reply Last reply 22 May 2020, 06:40
                0
                • H hskoglund
                  22 May 2020, 06:24

                  Hi, should be something like this:

                  QByteArray receivedBytes = socket->readAll();
                  
                  char c = 0;
                  for (auto b : receivedBytes)
                      c += b;
                  
                  c = 256 - c;
                  qDebug() << QString::number(c,16);
                  

                  (I got 36 when i tested with

                   QByteArray receivedBytes = QByteArray::fromHex("D4 0A 1B 73 0F 3A 0F 41 00 A7 0A 14")
                  
                  A Offline
                  A Offline
                  ahsan737
                  wrote on 22 May 2020, 06:39 last edited by
                  #8

                  @hskoglund
                  thank you for such a detailed response. It holds true for other data strings that I have tested.

                  1 Reply Last reply
                  1
                  • J JonB
                    22 May 2020, 06:31

                    @hskoglund said in How to calculate 8-bit Checksum (2’s complement)?:

                    c = 256 - c;
                    qDebug() << QString::number(c,16);

                    Slight correction: This generates a number in range 1--256. Isn't the checksum supposed to be a byte 0--255 (uint8_t cs)? Yet you say you did get 36 on the data, so perhaps not, but surprises me....

                    H Offline
                    H Offline
                    hskoglund
                    wrote on 22 May 2020, 06:40 last edited by
                    #9

                    @JonB No worries, a char has only 8 bits so the value 256 will be truncated to 0, i.e. the range will still be 0..255.
                    Basically you're translating from signed arithmetic to unsigned d:o using 2's-complement.

                    J 1 Reply Last reply 22 May 2020, 06:50
                    0
                    • H hskoglund
                      22 May 2020, 06:40

                      @JonB No worries, a char has only 8 bits so the value 256 will be truncated to 0, i.e. the range will still be 0..255.
                      Basically you're translating from signed arithmetic to unsigned d:o using 2's-complement.

                      J Offline
                      J Offline
                      JonB
                      wrote on 22 May 2020, 06:50 last edited by JonB
                      #10

                      @hskoglund
                      Yes I know that (bits, signed, overflow wrapping), I thought the result would be wrong. E.g. if there is, say, just 1 byte with value 0, then 256 - c will generate 256 == char(0) == 0x00 for the checksum. I expected that to need to be 255 - c => 255 == char(255) == 0xFF for the 2's complement? So I don't get it. But since your answer matches what the OP expects, there you are....

                      EDIT OK, I looked up https://en.wikipedia.org/wiki/Two's_complement

                      The two's complement is calculated by inverting the digits and adding one

                      I didn't know about the "adding one"! :) I thought it was just ~number, got it now!

                      M 1 Reply Last reply 22 May 2020, 12:02
                      1
                      • J JonB
                        22 May 2020, 06:50

                        @hskoglund
                        Yes I know that (bits, signed, overflow wrapping), I thought the result would be wrong. E.g. if there is, say, just 1 byte with value 0, then 256 - c will generate 256 == char(0) == 0x00 for the checksum. I expected that to need to be 255 - c => 255 == char(255) == 0xFF for the 2's complement? So I don't get it. But since your answer matches what the OP expects, there you are....

                        EDIT OK, I looked up https://en.wikipedia.org/wiki/Two's_complement

                        The two's complement is calculated by inverting the digits and adding one

                        I didn't know about the "adding one"! :) I thought it was just ~number, got it now!

                        M Offline
                        M Offline
                        mpergand
                        wrote on 22 May 2020, 12:02 last edited by mpergand
                        #11

                        @JonB response is correct.

                        From the code I posted earlier, you can add:

                        // checksum = 36h 54d
                        uint8_t c=0;
                        for(uint8_t v : data) c+=v;
                        c-=cs;  // remove the checksum value
                        c=~c;   // 1's complement
                        c++;    // 2's complement
                        
                        if(c != cs)
                            {
                            qDebug()<<"checksum error";
                            }
                        
                        A 1 Reply Last reply 25 May 2020, 06:07
                        2
                        • M mpergand
                          22 May 2020, 12:02

                          @JonB response is correct.

                          From the code I posted earlier, you can add:

                          // checksum = 36h 54d
                          uint8_t c=0;
                          for(uint8_t v : data) c+=v;
                          c-=cs;  // remove the checksum value
                          c=~c;   // 1's complement
                          c++;    // 2's complement
                          
                          if(c != cs)
                              {
                              qDebug()<<"checksum error";
                              }
                          
                          A Offline
                          A Offline
                          ahsan737
                          wrote on 25 May 2020, 06:07 last edited by
                          #12

                          @mpergand
                          thank you very much.

                          1 Reply Last reply
                          0

                          4/12

                          22 May 2020, 06:21

                          topic:navigator.unread, 8
                          • Login

                          • Login or register to search.
                          4 out of 12
                          • First post
                            4/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved