crc16

CRC-16 polynomial notation


In the CRC-16 calculation what is the difference (if any) between polynomial (x16 + x15 + x2 + x0) and (x16 + x15 + x2 + 1)?

Are the same (any number raised to zero is equal to one)?

Can someone explain me how get the hex number from this notation?

I don't understand because these polynomial seems to be 17 bits long:

0x18005 or 0b11000000000000101


Solution

  • No, there is no difference.

    The correct way to write those is with superscripts, representing "to the power of":

    x16 + x15 + x2 + x0

    and:

    x16 + x15 + x2 + 1

    As you noted, anything raised to the zero power is one.

    A 16-bit CRC uses a polynomial of degree 16. That means there must be an x16 term. You have the correct hexadecimal notation 0x18005. However in writing code to implement the CRC, you can do it with 16-bit operations and don't need the high 1. In the code you will see an exclusive-or with 0x8005. The high 1 is in fact being taken into account in the conditional that decides whether or not to exclusive-or with 0x8005.

    Here is an example in C:

    uint16_t crc16umts(uint16_t crc, uint8_t const *data, size_t len) {
        for (size_t i = 0; i < len; i++) {
            crc ^= (uint16_t)data[i] << 8;
            for (unsigned k = 0; k < 8; k++)
                crc = crc & 0x8000 ? (crc << 1) ^ 0x8005 : crc << 1;
        }
        return crc;
    }
    

    The crc & 0x8000 is checking the high bit of crc which is about to be shifted up and out, before it is shifted out, to decide whether or not to exclusive-or with 0x8005 after the shift. That is the same as doing it in a 32-bit register instead, doing the shift first, and if the 16th bit (0x10000) is one, then exclusive-oring with 0x18005 to effect the polynomial remainder operation. So that innermost line of code could have been, with a uint32_t crc:

                crc <<= 1;
                if (crc & 0x10000)
                    crc ^= 0x18005;