/*************************************** *******************************
*
* Filename: main. c
*
* Description: A simple test program for the CRC implementations.
*
* Notes: To test a different CRC standard, modify crc. h.
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed
* 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 <stdio. h>
# Include <string. h>
# Include "crc. h"
Void
Main (void)
{
Unsigned char test [] = "123456789 ";
/*
* Print the check value for the selected CRC algorithm.
*/
Printf ("The check value for the % s standard is 0x % X \ n", CRC_NAME,
CHECK_VALUE );
/*
* Compute the CRC of the test message, slowly.
*/
*/
Printf ("The crcSlow () of \" 123456789 \ "is 0x % X \ n", crcSlow (test,
Strlen (test )));
/*
* Compute the CRC of the test message, more efficiently.
*/
CrcInit ();
Printf ("The crcFast () of \" 123456789 \ "is 0x % X \ n", crcFast (test,
Strlen (test )));
}/* Main ()*/
/*************************************** *******************************
*
* Filename: crc. h
*
* Description: A header file describing the various CRC standards.
*
* Notes:
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed
* 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.
**************************************** ******************************/
# Ifndef _ crc_h
# Define _ crc_h
# Define FALSE 0
# Define TRUE! FALSE
/*
* Select the CRC standard from the list that follows.
*/
# Define CRC_CCITT
# If defined (CRC_CCITT)
Typedef unsigned short crc;
# Define CRC_NAME "CRC-CCITT"
# Define POLYNOMIAL 0x1021
# Define INITIAL_REMAINDER 0 xFFFF
# Define final_xoracle _value 0x0000
# Define REFLECT_DATA FALSE
# Define REFLECT_REMAINDER FALSE
# Define CHECK_VALUE 0x29B1
# Elif defined (CRC16)
Typedef unsigned short crc;
# Define CRC_NAME "CRC-16"
# Define POLYNOMIAL 0x8005
# Define INITIAL_REMAINDER 0x0000
# Define final_xoracle _value 0x0000
# Define REFLECT_DATA TRUE
# Define REFLECT_REMAINDER TRUE
# Define CHECK_VALUE 0xBB3D
# Elif defined (CRC32)
Typedef unsigned long crc;
# Define CRC_NAME "CRC-32"
# Define POLYNOMIAL 0x04C11DB7
# Define INITIAL_REMAINDER 0 xFFFFFFFF
# Define FINAL_XOR_VALUE 0 xFFFFFFFF
# Define REFLECT_DATA TRUE
# Define REFLECT_REMAINDER TRUE
# Define CHECK_VALUE 0xCBF43926
# Else
# Error "One of CRC_CCITT, CRC16, or CRC32 must be # define 'd ."
# Endif
Void crcInit (void );
Crc crcSlow (unsigned char const message [], int nBytes );
Crc crcFast (unsigned char const message [], int nBytes );
# Endif/* _ crc_h */
/*************************************** *******************************
*
* 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 implementtations
* Here shoshould stand up to further additions to thaat list.
*
*
* Copyright (c) 2000 by Michael Barr. This software is placed
* 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"
# 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)
# Endif
# If (REFLECT_REMAINDER = TRUE)
# Undef REFLECT_REMAINDER
# Define REFLECT_REMAINDER (X) (crc) reflect (X), WIDTH ))
# Else
# Undef REFLECT_REMAINDER
# Define REFLECT_REMAINDER (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 'ss 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;
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 ()*/