Skip to content

Instantly share code, notes, and snippets.

@ganindu7
Last active April 9, 2021 20:50
Show Gist options
  • Save ganindu7/30326a54cd1982221191a2d7d8d1bee8 to your computer and use it in GitHub Desktop.
Save ganindu7/30326a54cd1982221191a2d7d8d1bee8 to your computer and use it in GitHub Desktop.
Understanding CRC16
//function 1
uint16_t crc16(uint8_t const *data, size_t size)
{
/**
* Author: Mark Alder
* stackoverflow.com/users/1180620/mark-adler
*/
uint16_t crc = 0xFFFF; // I also tried with 0x0000 too - Ganindu
while (size--)
{
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
}
return crc >> 8 | crc << 8; //Edit I made to swap bytes - Ganindu
}
// function 2
uint16_t gen_crc16(const uint8_t *data, int16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
uint16_t crc = 0;
if(data == NULL)
return 0;
while(size > 0)
{
// printf("processing at top of loop %02X size %d \n", (uint8_t)((*data) & 0xFF), size);
/**
* bit flag is the msb of out
*/
bit_flag = out >> 15;
/**
* shift the out to the left by 1
* making lsb of out = 0
*/
out <<= 1;
/**
* shift data by bits_read -> puts next bit to bit 0
* check if that is 1
* append to out
*/
out |= (*data >> bits_read) & 0x01;
bits_read++;
/**
* if a byte is read,
* - reset bits_read
* - increment the byte reference to the start of the next byte in the payload
* - decrement the remaining byte count to work on by 1
*/
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/**
* for the condition to satisfy the msb of out must be 1
*/
if(bit_flag)
out ^= CRC16;
}
/**
* now we have at most two bytes that were not XORed
* so we push the last 16 bits
*
*/
int i;
for(i = 0; i < 16; ++i){
bit_flag = out >> 15;
out <<= 1;
if(bit_flag)
out ^= CRC16;
}
/**
* now we reverse the bits to match the protocol
*/
i = 0x8000;
int j = 0x0001;
for(; i != 0; i >>=1, j<<=1){
if(i & out)
crc |= j;
}
return crc;
}
//Test patterns
unsigned char pattern1[8] = {0x01, 0x03, 0x00, 0x32, 0x00, 0x24, 0xE4, 0x1E};
unsigned char pattern2[8] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x0A, 0x94, 0x0D};
uint8_t crc_1 = gen_crc16(pattern1, 8);
printf("crc_ = 0x%02X 0x%02X\n", (uint8_t)(crc_1 >> 8) , (uint8_t)(crc_1 & 0X00FF));
// this one gives 0x00 0x00 (works)
uint16_t crc = crc16(pattern1, 8);
printf("crc2 = 0x%02X 0x%02X\n", (uint8_t)(crc >> 8) , (uint8_t)(crc & 0X00FF));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment