/* * crc.c - reference CRC implementations and LUT generator */ #include #include /* * 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); }