123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- /**********************************************************************
- *
- * Filename: crc.c
- *
- * Description: Slow and fast implementations of the CRC standards.
- *
- * Notes: The parameters for each supported CRC standard are
- * defined in the header file crc.h. The implementations
- * here should stand up to further additions to that list.
- *
- *
- * Copyright (c) 2000 by Michael Barr. This software is placed into
- * the public domain and may be used for any purpose. However, this
- * notice must not be changed or removed and no warranty is either
- * expressed or implied by its publication or distribution.
- **********************************************************************/
-
- #include "crc.h"
- /*
- * Derive parameters from the standard-specific parameters in crc.h.
- */
- #define WIDTH (8 * sizeof(crc))
- #define TOPBIT (1 << (WIDTH - 1))
- #if (REFLECT_DATA == TRUE)
- #undef REFLECT_DATA
- #define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))
- #else
- #undef REFLECT_DATA
- #define REFLECT_DATA(X) (X)
- #endif
- #if (REFLECT_REMAINDER == TRUE)
- #undef REFLECT_REMAINDER
- #define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))
- #else
- #undef REFLECT_REMAINDER
- #define REFLECT_REMAINDER(X) (X)
- #endif
- /*********************************************************************
- *
- * Function: reflect()
- *
- * Description: Reorder the bits of a binary sequence, by reflecting
- * them about the middle position.
- *
- * Notes: No checking is done that nBits <= 32.
- *
- * Returns: The reflection of the original data.
- *
- *********************************************************************/
- static unsigned long
- reflect(unsigned long data, unsigned char nBits)
- {
- unsigned long reflection = 0x00000000;
- unsigned char bit;
- /*
- * Reflect the data about the center bit.
- */
- for (bit = 0; bit < nBits; ++bit)
- {
- /*
- * If the LSB bit is set, set the reflection of it.
- */
- if (data & 0x01)
- {
- reflection |= (1 << ((nBits - 1) - bit));
- }
- data = (data >> 1);
- }
- return (reflection);
- } /* reflect() */
- /*********************************************************************
- *
- * Function: crcSlow()
- *
- * Description: Compute the CRC of a given message.
- *
- * Notes:
- *
- * Returns: The CRC of the message.
- *
- *********************************************************************/
- crc
- crcSlow(unsigned char const message[], int nBytes)
- {
- crc remainder = INITIAL_REMAINDER;
- int byte;
- unsigned char bit;
- /*
- * Perform modulo-2 division, a byte at a time.
- */
- for (byte = 0; byte < nBytes; ++byte)
- {
- /*
- * Bring the next byte into the remainder.
- */
- remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));
- /*
- * Perform modulo-2 division, a bit at a time.
- */
- for (bit = 8; bit > 0; --bit)
- {
- /*
- * Try to divide the current data bit.
- */
- if (remainder & TOPBIT)
- {
- remainder = (remainder << 1) ^ POLYNOMIAL;
- }
- else
- {
- remainder = (remainder << 1);
- }
- }
- }
- /*
- * The final remainder is the CRC result.
- */
- return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
- } /* crcSlow() */
- crc crcTable[256];
- /*********************************************************************
- *
- * Function: crcInit()
- *
- * Description: Populate the partial CRC lookup table.
- *
- * Notes: This function must be rerun any time the CRC standard
- * is changed. If desired, it can be run "offline" and
- * the table results stored in an embedded system's ROM.
- *
- * Returns: None defined.
- *
- *********************************************************************/
- void
- crcInit(void)
- {
- crc remainder;
- int dividend;
- unsigned char bit;
- /*
- * Compute the remainder of each possible dividend.
- */
- for (dividend = 0; dividend < 256; ++dividend)
- {
- /*
- * Start with the dividend followed by zeros.
- */
- remainder = dividend << (WIDTH - 8);
- /*
- * Perform modulo-2 division, a bit at a time.
- */
- for (bit = 8; bit > 0; --bit)
- {
- /*
- * Try to divide the current data bit.
- */
- if (remainder & TOPBIT)
- {
- remainder = (remainder << 1) ^ POLYNOMIAL;
- }
- else
- {
- remainder = (remainder << 1);
- }
- }
- /*
- * Store the result into the table.
- */
- crcTable[dividend] = remainder;
- }
- } /* crcInit() */
- /*********************************************************************
- *
- * Function: crcFast()
- *
- * Description: Compute the CRC of a given message.
- *
- * Notes: crcInit() must be called first.
- *
- * Returns: The CRC of the message.
- *
- *********************************************************************/
- crc
- crcFast(unsigned char const message[], int nBytes)
- {
- crc remainder = INITIAL_REMAINDER;
- unsigned char data;
- int byte;
- /*
- * Divide the message by the polynomial, a byte at a time.
- */
- for (byte = 0; byte < nBytes; ++byte)
- {
- data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8));
- remainder = crcTable[data] ^ (remainder << 8);
- }
- /*
- * The final remainder is the CRC.
- */
- return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
- } /* crcFast() */
|