static unsigned int  CRC16_LookupHigh[16];
static unsigned int  CRC16_LookupLow[16];

static unsigned int  GenCRC16TableEntry(const unsigned int  index,
                                        const short         numBits,
                                        const unsigned int  genPoly )
{
	// Prepare the initial setup of the register so the index is at the
	// top most bits.
	unsigned int  crc = index & (0xFFFF >> (16 - numBits));
	int           i   = numBits;

	for(i = numBits; i; i--)
    {
		if(crc & 1)
        {
			crc = (crc >> 1) ^ genPoly;
        }
		else
        {
			crc >>= 1;
        }
	}
	
	return crc;
}


/*
 * The following Defines are used to configure the table generator
 */
#define NUM_BITS 4 // Width of message chunk each iteration of the CRC algorithm

void  initCRC4Bit(unsigned int  genPoly)
{
	unsigned int  i;
	unsigned int  Count = 1 << NUM_BITS; // Number of entries in the table

	// Generate the HIGH byte table
	for(i = 0; i < Count; i++)
    {
		CRC16_LookupHigh[i] = GenCRC16TableEntry(i, NUM_BITS, genPoly) & 0xFF;
	}

	// Generate the LOW byte table
	for(i = 0; i < Count; i++)
    {
		CRC16_LookupLow[i] = GenCRC16TableEntry(i, NUM_BITS, genPoly) >> 8;
	}

}


/*
 * Process 4 bits of the message to update the CRC Value.
 *
 * Note that the data must be in the low nibble of newData.
 */
static unsigned int CRC16_Update4Bits(unsigned char  newData,
                                      unsigned int   oldCRC)
{
    unsigned char  CRC16_High = oldCRC & 0xFF;
    unsigned char  CRC16_Low  = oldCRC >> 8;
	unsigned char  t;

	// Step one, extract the Most significant 4 bits of the CRC register
	t = CRC16_High & 0xF;

	// XOR in the Message Data into the extracted bits
	t = t ^ newData;

	// Shift the CRC Register right 4 bits
	CRC16_High = (CRC16_High >> 4) | (CRC16_Low << 4);
	CRC16_Low  = CRC16_Low >> 4;

	// Do the table lookups and XOR the result into the CRC Tables
	CRC16_High = CRC16_High ^ CRC16_LookupHigh[t];
	CRC16_Low  = CRC16_Low ^ CRC16_LookupLow[t];

    oldCRC = CRC16_Low;
    oldCRC = CRC16_High | (oldCRC << 8);

    return  oldCRC;
}


/*
 * Process one Message Byte to update the current CRC Value
 */
unsigned int  add2CRC4Bit(unsigned char  newData, unsigned int  oldCRC)
{
	oldCRC = CRC16_Update4Bits(newData & 0xF, oldCRC); // High nibble first
	oldCRC = CRC16_Update4Bits(newData >> 4, oldCRC); // Low nibble

    return  oldCRC;
}
