text: /**********************************************************************
   *
   * 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.
           */
  #if 1
          remainder ^= (REFLECT_DATA (message [byte]) << (WIDTH - 8));
  #endif
  
          /*
           * 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() */
  