[SOLVED] CRC function doesnt produce expected result!

Hi,

I am trying to calculate an 8-bit CRC -WCDMA byte:

// Define the polynomial for CRC-8-WCDMA
#define CRC8_WCDMA_POLY 0x9B

  uint8_t cmd[25] = {
    0x40, 0x00 ,0x10 ,0x00 ,0x00 ,0x61 ,0x01 ,0x16 ,0x00 ,0x31 ,0x00 ,0x3A ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x82 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80   };

// Function to calculate CRC-8-WCDMA
uint8_t calculateCRC8_WCDMA(uint8_t* data, size_t length) {
  uint8_t crc = 0x00; // Initial CRC value

  for (size_t i = 0; i < length; i++) {
    crc ^= data[i]; // XOR byte into the current CRC

    // Process each bit
    for (uint8_t bit = 0; bit < 8; bit++) {
      if (crc & 0x80) { // If the MSB is 1
        crc = (crc << 1) ^ CRC8_WCDMA_POLY; // Shift and XOR with the polynomial
      } else {
        crc <<= 1; // Just shift if MSB is 0
      }
    }
  }

  return crc; // Return the final CRC value
}

void setup() {
  Serial.begin(9600);

  
}

void loop() {

   uint8_t crc = calculateCRC8_WCDMA(cmd, 23);
    // Print the result
  Serial.print("CRC-8-WCDMA: 0x");
  Serial.println(crc, HEX);

  delay (10000);
}

The above results in CRC = 0X08

However, when checked with an online tool like this , the result is 0xD5 !

Can anyone please spot whats wrong ?

Where you found this code?

I don't know much about CRC calculations, but I think that this constant should be used somewhere in your code.

Well it was, but I have now replaced it with the actual value here :

crc = (crc << 1) ^ 0x9B; 

Now replaced with original Define to avoid confusion

What are you using the CRC for? If for error checking then what matters is that the CRC you calculate at the beginning of whatever you are doing matches the one at the end when you want to check for errors. The actual number doesn't matter.

Hi. I understand what you are saying but unfortunately its not as simple as that.
Am trying to talk / control an HAV system which uses the above CRC check, so its important to get it right! :slight_smile:

1 Like

looks OK to me if you are expecting 0x08 (0x8):

Here is the hex string I pasted in:

0x40 0x00 0x10 0x00 0x00 0x61 0x01 0x16 0x00 0x31 0x00 0x3A 0x00 0x00 0x00 0x00 0x00 0x82 0x00 0x00 0x00 0x00 0x80 

Now i am even more Confused!
I am expecting 0xD5. This is what the online tool i linked gjves and, more importantly, this is what the system i wanna talk to you gives as well!

Edit: You didn't select CRC -WCDMA from drop down list at tge top

Perhaps your code is also not a CRC -WCDMA ? It would explain the result...

You didn't answer, where you found this code.

Sorry for not answering..it was in stackexchange.

Your code does not implement input/output reflection :

1 Like

do you have a link?

That must be it then!

Byte reflection i guess just means mirroring the bits before each byte enters the code?

I ll try find it again

This code produces the expected value of 0xD5:

// Function to reflect (mirror) a byte
uint8_t reflect_byte(uint8_t byte) 
{
    uint8_t reflected = 0;

    for (int i = 0; i < 8; i++) {
        // Shift the existing bits of `reflected` to the left
        reflected <<= 1;
        // Add the least significant bit of `byte` to `reflected`
        reflected |= (byte & 1);
        // Shift the original `byte` to the right to process the next bit
        byte >>= 1;
    }

    return reflected;
}

// Define the polynomial for CRC-8-WCDMA
#define CRC8_WCDMA_POLY 0x9B

uint8_t cmd[25] = {
  0x40, 0x00 ,0x10 ,0x00 ,0x00 ,0x61 ,0x01 ,0x16 ,0x00 ,0x31 ,0x00 ,0x3A ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x82 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80 };

// Function to calculate CRC-8-WCDMA
uint8_t calculateCRC8_WCDMA(uint8_t* data, size_t length) {
    uint8_t crc = 0x00; // Initial CRC value

    for (size_t i = 0; i < length; i++) {
        crc ^= reflect_byte(data[i]); // XOR byte into the current CRC

        // Process each bit
        for (uint8_t bit = 0; bit < 8; bit++) {
            if (crc & 0x80) { // If the MSB is 1
                crc = (crc << 1) ^ CRC8_WCDMA_POLY; // Shift and XOR with the polynomial
            }
            else {
                crc <<= 1; // Just shift if MSB is 0
            }
        }
    }

    return reflect_byte(crc); // Return the final CRC value
}

Full disclosure : the reflect_byte() function is AI generated.

2 Likes

There are better ways, no doubt.

One would be to use a lookup table.

Here's another from the entertaining

https://graphics.stanford.edu/~seander/bithacks.html


//Reverse the bits in a byte with 7 operations (no 64-bit):

b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 

/*
Make sure you assign or cast the result to an unsigned char to remove garbage in the higher bits. Devised by Sean Anderson, July 13, 2001. Typo spotted and correction supplied by Mike Keith, January 3, 2002.
*/

Which would be fastest must be tested, I would have to test anyway - modern compilers seem to be very good at making code.

Guessing and placing money on the lookup table.

HTH

a7

That works indeed! Thanks very much!

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.