Last active
April 9, 2021 20:50
-
-
Save ganindu7/30326a54cd1982221191a2d7d8d1bee8 to your computer and use it in GitHub Desktop.
Understanding CRC16
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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