Search code examples
crccrc16

OWI_ComputeCRC16 returning value 0


I am checking out this function OWI_ComputeCRC16() and when I test the function with OWI_ComputeCRC16(0 >> 8, 0), the return value is 0.

/**
* @brief    Compute the CRC16 value of a data set.
* @details  This function will compute the CRC16 of inData using seed as inital value for the CRC.
* @note     Setting seed to 0 computes the crc16 of the inData.
* @note     Constantly passing the return value of this function as the seed argument computes the CRC16 value of a longer string of data.
* @bug      N/A
* @warning  N/A
* @param    unsigned char inData: One byte of data to compute CRC from.
* @param    unsigned short seed: The starting value of the CRC.
* @return   The CRC16 of inData with seed as initial value.
*/
unsigned short OWI_ComputeCRC16(unsigned char inData, unsigned short seed)
{
    unsigned char bitsLeft;
    unsigned char temp;

    for (bitsLeft = 8; bitsLeft > 0; bitsLeft--)
    {
        temp = ((seed ^ inData) & 0x01);
        if (temp == 0)
        {
            seed >>= 1;
        }
        else
        {
            seed ^= 0x4002;
            seed >>= 1;
            seed |= 0x8000;
        }
        inData >>= 1;
    }
    return seed;
}

This is making some problems in legacy code that I have to solve, where this function is also used with parameters 0, 0 and then SUM of calculated CRC values is used.

Example:

a) I have some data on example position = 0 with key = 0 ... => OWI_ComputeCRC16(0 >> 8, 0) returns 0.

b) I have some data on example position = 0 with key = 0 ... crc = 0. And I have another data record on example position = 1 with key = 1 ... OWI_ComputeCRC16(1 >> 8, 1) returns 49345.

If I do SUM on this returned CRC values, I will not know, if data from position 0 is included or not.

Ok, I think this is logical error and I can solve it.

The question is: is it ok for function, that should calculate and return CRC value, to return value 0 (for any possible given input values)?

p.s.: this is my first question on stackoverflow, so if I did something wrong or not understandable, please let me know. Thanks.


Solution

  • The question is: is it ok for function, that should calculate and return CRC value, to return value 0 (for any possible given input values)?

    Not for any, but for some sequences of bytes you will get a zero return value. In fact for a 16-bit CRC, you should expect to get a zero CRC for, on average, one out of every 65536 random sequences you try.

    This particular CRC, with no pre or post conditioning, will give a zero CRC for the empty sequence and any sequence of zeros.

    By the way, that is an odd implementation with a lot more operations than needed. It should be replaced by this:

    unsigned short OWI_ComputeCRC16(unsigned char inData, unsigned short seed)
    {
        seed ^= inData;
        for (int k = 0; k < 8; k++)
            seed = seed & 1 ? (seed >> 1) ^ 0xa001 : seed >> 1;
        return seed;
    }
    

    That also doesn't obfuscate the CRC polynomial, where in this version is the familiar (reflected) 0xa001 or (not reflected) polynomial 0x8005, which is x16+x15+x2+1. Faster still would be a byte-wise or word-wise table-driven version. See crcany.c for examples.