I'm trying to implement a 10-bit CRC with a polynomial of 0x633. I've scoured through countless pages but not much is written on CRC-10.
I've written some sample code that seems to calculate it just fine. I can run some test data through to get a CRC then run the data + CRC back through to get 0, which is expect. The problem is that we're testing it against this calculator and getting incongruent results: http://www.ghsi.de/pages/subpages/Online%20CRC%20Calculation/indexDetails.php?Polynom=11000110011&Message=1f+ff+30+04+05+34+a7. This includes the poly and test data. The result from this calculator is "0x10e" while mine is "0x3b1".
Here is the code, modified from https://cs.fit.edu/code/svn/cse2410f13team7/wireshark/wsutil/crc10.c:
#include <stdio.h>
#include <stdint.h>
uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size);
static const uint16_t byte_crc10_table[256] = {
0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1
};
/* update the data block's CRC-10 remainder one byte at a time */
uint16_t GetCRC10(uint16_t crc10, const uint8_t *data_blk_ptr, int data_blk_size)
{
register int i;
uint16_t crc10_accum = 0;
for (i = 0; i < data_blk_size; i++) {
crc10_accum = ((crc10_accum << 8) & 0x3ff)
^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
^ *data_blk_ptr++;
}
crc10_accum = ((crc10_accum << 8) & 0x3ff)
^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
^ (crc10>>2);
crc10_accum = ((crc10_accum << 8) & 0x3ff)
^ byte_crc10_table[( crc10_accum >> 2) & 0xff]
^ ((crc10<<6) & 0xFF);
return crc10_accum;
}
#define TEST_DATA_SIZE 9
void main()
{
uint8_t test_input_data[TEST_DATA_SIZE] = {0x1f, 0xff, 0x30, 0x4, 0x5, 0x34, 0xa7, 0x0, 0x0};
uint16_t crc;
uint16_t crc_final;
GenerateCRC10Table();
crc = GetCRC10(0, test_input_data, TEST_DATA_SIZE-2);
test_input_data[TEST_DATA_SIZE-2] ^= crc >> 8;
test_input_data[TEST_DATA_SIZE-1] ^= crc & 0xFF;
printf("%x\n", crc); // Error here. This crc doesn't match with the calculator.
crc_final = GetCRC10(0, test_input_data, TEST_DATA_SIZE);
if (crc_final == 0)
{
printf("Success");
}
}
This is the function used to produce the lookup table:
#define POLYNOMIAL 0x633
static uint16_t byte_crc10_table[256];
void gen_byte_crc10_table(void)
/* generate the table of CRC-10 remainders for all possible bytes */
{
register int i, j;
register unsigned short crc10_accum;
for ( i = 0; i < 256; i++ )
{
crc10_accum = ((unsigned short) i << 2);
for ( j = 0; j < 8; j++ )
{
if ((crc10_accum <<= 1) & 0x400) crc10_accum ^= POLYNOMIAL;
}
byte_crc10_table[i] = crc10_accum;
}
return;
}
I've tried this with the 0x233 normal polynomial form as well.
Is this even possible? In essence, I'm tying to bitwise operations on a complete array of bytes. I suspect the problem is that the calculator does it bit-by-bit and mine is byte-by-byte. Since the poly is 10 bits wide, it doesn't work cleanly with uint8s. I'd really appreciate some feedback. Thanks.
Does it make sense that the calculator CRC and my CRC are different because of the 10 bit polynomial and 8 bit data difference?