commit
531b2e8f52
2 changed files with 126 additions and 0 deletions
@ -0,0 +1,9 @@ |
|||||||
|
CC=gcc
|
||||||
|
OBJ=crc.o
|
||||||
|
CFLAGS=-Wall -Wextra -Werror -pedantic
|
||||||
|
|
||||||
|
%.o: %.c $(DEPS) |
||||||
|
$(CC) -c -o $@ $< $(CFLAGS)
|
||||||
|
|
||||||
|
crc: $(OBJ) |
||||||
|
$(CC) -o $@ $^ $(CFLAGS)
|
@ -0,0 +1,117 @@ |
|||||||
|
/*
|
||||||
|
* 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(", 0x%04x", 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); |
||||||
|
} |
Loading…
Reference in new issue