/* * calculate ccitt cyclic redundancy codes * * actual Crc16 = x ^ 16 + x ^ 12 + x ^ 5 + 1 * * inverse Crc32 = x ^ 32 + x ^ 31 + x ^ 30 + * x ^ 28 + x ^ 27 + x ^ 25 + x ^ 24 + * x ^ 22 + x ^ 21 + x ^ 20 + x ^ 16 + * x ^ 10 + x ^ 9 + x ^ 6 + 1 * * n.b. standard ANSI X3.66 crc-32 polynomial: * x^0 + x^1 + x^2 + x^4 + x^5 + x^7 + x^8 + x^10 + * x^11 + x^12 + x^16 + x^22 + x^23 + x^26 + x^32 * * Tables constructed so that entry 0x80 = inverse polynomial */ unsigned short Crc16[] = { 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387, 0x8408, 0x9489, 0xa50a, 0xb58b, 0xc60c, 0xd68d, 0xe70e, 0xf78f }; unsigned long Crc32[] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; unsigned short crc16_calc (unsigned char *ptr, unsigned cnt, unsigned short crc) { while( cnt-- ) { crc = ( crc >> 4 ) ^ Crc16[(crc & 0xf) ^ (*ptr & 0xf)]; crc = ( crc >> 4 ) ^ Crc16[(crc & 0xf) ^ (*ptr++ >> 4)]; } return crc; } unsigned long crc32_calc (unsigned char *ptr, unsigned cnt, unsigned long crc) { while( cnt-- ) { crc = ( crc >> 4 ) ^ Crc32[(crc & 0xf) ^ (*ptr & 0xf)]; crc = ( crc >> 4 ) ^ Crc32[(crc & 0xf) ^ (*ptr++ >> 4)]; } return crc; } #ifdef STANDALONE #include <stdio.h> int main (int argc, char **argv) { int len = strlen(argv[1]), idx; unsigned char msg[128]; unsigned short v16; unsigned long v32; if( len > sizeof(msg) - sizeof(unsigned long) ) len = sizeof(msg) - sizeof(unsigned); memcpy (msg, argv[1], len); // CRC32 test: v32 = ~crc32_calc (msg, len, ~0U); printf("32 bit CRC: %08lx", v32); // append the inverted the crc and recompute for( idx = 0; idx < sizeof(unsigned long); idx++ ) msg[len + idx] = v32 >> idx * 8; v32 = crc32_calc (msg, len + sizeof(unsigned), ~0UL); // this should yield the well known CRC32 residue value: // 0xdebb20e3 printf(" RESIDUE: %08lx\n", v32); // CRC16 test: v16 = ~crc16_calc (msg, len, ~0U); printf("16 bit CRC: %04lx ", v16); for( idx = 0; idx < sizeof(unsigned short); idx++ ) msg[len + idx] = v16 >> idx * 8; v16 = crc16_calc (msg, len + sizeof(unsigned short), 0xffff); // this should yield the well known CRC16 residue value: // 0xf0b8 printf(" RESIDUE: %04lx\n", v16); } #endif