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

/*
* 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);
}