You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
2.1 KiB
119 lines
2.1 KiB
/* |
|
* crc.c - reference CRC implementations and LUT generator |
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <stdint.h> |
|
|
|
/* |
|
* CRC-16-IBM -- reversed reciprocal representation |
|
* https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations_of_cyclic_redundancy_checks |
|
*/ |
|
#define CRCPOLY (0xc002) |
|
|
|
static uint16_t crc16_lut[256] = { 0x0000 }; |
|
|
|
uint16_t crc16(uint8_t *data, uint32_t len); |
|
void crc16_gen(); |
|
uint16_t crc16_ref(uint8_t *Pkt, uint32_t PktCnt); |
|
|
|
int main() |
|
{ |
|
uint8_t i; |
|
uint8_t golden_packet[32] = { |
|
0xf2, 0x22, 0x22, 0x22, |
|
0x20, 0x00, 0x00, 0x00, |
|
0x78, 0x56, 0x34, 0x12, |
|
0xd2, 0xc3, 0xb4, 0xa5, |
|
0x10, 0x00, 0x00, 0x00, |
|
0x01, 0x5a, 0x00, 0x00, |
|
0x42, 0x43, 0x44, 0x45, |
|
0x46, 0x47, 0x00, 0x00 |
|
}; |
|
|
|
/* generate lookup table */ |
|
crc16_gen(); |
|
|
|
/* print out the table (for embedding into code data sections) */ |
|
printf("CRC byte lookup table:\n0x0000"); |
|
for(i = 0; i < 255; i++) |
|
{ |
|
printf(",%s0x%04x", |
|
(i && !((i + 1) % 8)) ? "\n" : " ", |
|
crc16_lut[i + 1]); |
|
} |
|
printf("\n\n"); |
|
|
|
/* compute the golden checksum using the LUT and a reference algorithm */ |
|
printf("Golden Checksum: 0x%04x\n", crc16(golden_packet, 32)); |
|
printf("Reference Golden Checksum: 0x%04x\n", crc16_ref(golden_packet, 32)); |
|
|
|
return(0); |
|
} |
|
|
|
/* fast CRC calculation using LUT */ |
|
uint16_t crc16(uint8_t *data, uint32_t len) |
|
{ |
|
uint32_t i; |
|
uint16_t rem = 0; |
|
|
|
for (i = 0; i < len; i++) |
|
{ |
|
rem = (rem >> 8) ^ crc16_lut[data[i] ^ (rem & 0xff)]; |
|
} |
|
|
|
return(rem); |
|
} |
|
|
|
/* fast CRC LUT generation */ |
|
void crc16_gen() |
|
{ |
|
uint16_t crc = 1; |
|
uint8_t i; |
|
uint16_t j; |
|
|
|
for(i = 0x80; i > 0; i >>= 1) |
|
{ |
|
if(crc & 1) |
|
{ |
|
crc = (crc >> 1) ^ CRCPOLY; |
|
} |
|
else |
|
{ |
|
crc >>= 1; |
|
} |
|
|
|
for(j = 0; j < 256; j += 2 * i) |
|
{ |
|
crc16_lut[i + j] = crc ^ crc16_lut[j]; |
|
} |
|
} |
|
} |
|
|
|
/* reference CRC implementation */ |
|
uint16_t crc16_ref(uint8_t *buf, uint32_t len) |
|
{ |
|
uint16_t rem = 0; |
|
uint16_t dat; |
|
uint16_t tmp; |
|
uint32_t i, j; |
|
|
|
for(i = 0; i < len; i++) |
|
{ |
|
dat = buf[i]; |
|
for(j = 0; j < 8; j++) |
|
{ |
|
tmp = (rem ^ dat) & 0x0001; |
|
|
|
rem >>= 1; |
|
dat >>= 1; |
|
|
|
if(tmp) |
|
{ |
|
rem ^= CRCPOLY; |
|
} |
|
} |
|
} |
|
|
|
return(rem); |
|
}
|
|
|