I was hoping someone might be able to shed some light on why my CRC-16 implementation does not seem to run correctly on Visual Studio? I got the algorithm from a manual for a specific device, and wrote the int main() myself. There are always 'type' errors when I try to pass the arguments to the function, so I suspect there is something wrong with the format? This is the info that came with the code:
CRC Name : CRC-16
Width : 16 Bits
Polynomial Used : 1189 (hex)
Seed Value : FFFF (hex)
Reflected Input/Output : No
Exclusive OR Output : No
Test CRC for string "123456789" : 5502 (hex)
#include <stdio.h>
unsigned int crctable[256] =
{
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x0919, 0x1890, 0x2A0B, 0x3B82, 0x4F3D, 0x5EB4, 0x6C2F, 0x7DA6,
0x8551, 0x94D8, 0xA643, 0xB7CA, 0xC375, 0xD2FC, 0xE067, 0xF1EE,
0x1232, 0x03BB, 0x3120, 0x20A9, 0x5416, 0x459F, 0x7704, 0x668D,
0x9E7A, 0x8FF3, 0xBD68, 0xACE1, 0xD85E, 0xC9D7, 0xFB4C, 0xEAC5,
0x1B2B, 0x0AA2, 0x3839, 0x29B0, 0x5D0F, 0x4C86, 0x7E1D, 0x6F94,
0x9763, 0x86EA, 0xB471, 0xA5F8, 0xD147, 0xC0CE, 0xF255, 0xE3DC,
0x2464, 0x35ED, 0x0776, 0x16FF, 0x6240, 0x73C9, 0x4152, 0x50DB,
0xA82C, 0xB9A5, 0x8B3E, 0x9AB7, 0xEE08, 0xFF81, 0xCD1A, 0xDC93,
0x2D7D, 0x3CF4, 0x0E6F, 0x1FE6, 0x6B59, 0x7AD0, 0x484B, 0x59C2,
0xA135, 0xB0BC, 0x8227, 0x93AE, 0xE711, 0xF698, 0xC403, 0xD58A,
0x3656, 0x27DF, 0x1544, 0x04CD, 0x7072, 0x61FB, 0x5360, 0x42E9,
0xBA1E, 0xAB97, 0x990C, 0x8885, 0xFC3A, 0xEDB3, 0xDF28, 0xCEA1,
0x3F4F, 0x2EC6, 0x1C5D, 0x0DD4, 0x796B, 0x68E2, 0x5A79, 0x4BF0,
0xB307, 0xA28E, 0x9015, 0x819C, 0xF523, 0xE4AA, 0xD631, 0xC7B8,
0x48C8, 0x5941, 0x6BDA, 0x7A53, 0x0EEC, 0x1F65, 0x2DFE, 0x3C77,
0xC480, 0xD509, 0xE792, 0xF61B, 0x82A4, 0x932D, 0xA1B6, 0xB03F,
0x41D1, 0x5058, 0x62C3, 0x734A, 0x07F5, 0x167C, 0x24E7, 0x356E,
0xCD99, 0xDC10, 0xEE8B, 0xFF02, 0x8BBD, 0x9A34, 0xA8AF, 0xB926,
0x5AFA, 0x4B73, 0x79E8, 0x6861, 0x1CDE, 0x0D57, 0x3FCC, 0x2E45,
0xD6B2, 0xC73B, 0xF5A0, 0xE429, 0x9096, 0x811F, 0xB384, 0xA20D,
0x53E3, 0x426A, 0x70F1, 0x6178, 0x15C7, 0x044E, 0x36D5, 0x275C,
0xDFAB, 0xCE22, 0xFCB9, 0xED30, 0x998F, 0x8806, 0xBA9D, 0xAB14,
0x6CAC, 0x7D25, 0x4FBE, 0x5E37, 0x2A88, 0x3B01, 0x099A, 0x1813,
0xE0E4, 0xF16D, 0xC3F6, 0xD27F, 0xA6C0, 0xB749, 0x85D2, 0x945B,
0x65B5, 0x743C, 0x46A7, 0x572E, 0x2391, 0x3218, 0x0083, 0x110A,
0xE9FD, 0xF874, 0xCAEF, 0xDB66, 0xAFD9, 0xBE50, 0x8CCB, 0x9D42,
0x7E9E, 0x6F17, 0x5D8C, 0x4C05, 0x38BA, 0x2933, 0x1BA8, 0x0A21,
0xF2D6, 0xE35F, 0xD1C4, 0xC04D, 0xB4F2, 0xA57B, 0x97E0, 0x8669,
0x7787, 0x660E, 0x5495, 0x451C, 0x31A3, 0x202A, 0x12B1, 0x0338,
0xFBCF, 0xEA46, 0xD8DD, 0xC954, 0xBDEB, 0xAC62, 0x9EF9, 0x8F70
};
unsigned int // Returns Calculated CRC value
CalculateCRC16(
unsigned int crc_seed, // Seed for CRC calculation
void *c_ptr, // Pointer to byte array to perform CRC on
unsigned int len) // Number of bytes to CRC
{
unsigned char *c = c_ptr;
unsigned int crc = crc_seed;
while (len--){
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
printf("%d", crc);
}
return (crc);
}
int main(){
printf("%d", CalculateCRC16(0xFFFF, "123456789", 2));
return 0;
}
All cleaned up and ready to go:
#include <stdio.h>
#include <stdint.h>
static const uint16_t crctable[256] =
{
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x0919, 0x1890, 0x2A0B, 0x3B82, 0x4F3D, 0x5EB4, 0x6C2F, 0x7DA6,
0x8551, 0x94D8, 0xA643, 0xB7CA, 0xC375, 0xD2FC, 0xE067, 0xF1EE,
0x1232, 0x03BB, 0x3120, 0x20A9, 0x5416, 0x459F, 0x7704, 0x668D,
0x9E7A, 0x8FF3, 0xBD68, 0xACE1, 0xD85E, 0xC9D7, 0xFB4C, 0xEAC5,
0x1B2B, 0x0AA2, 0x3839, 0x29B0, 0x5D0F, 0x4C86, 0x7E1D, 0x6F94,
0x9763, 0x86EA, 0xB471, 0xA5F8, 0xD147, 0xC0CE, 0xF255, 0xE3DC,
0x2464, 0x35ED, 0x0776, 0x16FF, 0x6240, 0x73C9, 0x4152, 0x50DB,
0xA82C, 0xB9A5, 0x8B3E, 0x9AB7, 0xEE08, 0xFF81, 0xCD1A, 0xDC93,
0x2D7D, 0x3CF4, 0x0E6F, 0x1FE6, 0x6B59, 0x7AD0, 0x484B, 0x59C2,
0xA135, 0xB0BC, 0x8227, 0x93AE, 0xE711, 0xF698, 0xC403, 0xD58A,
0x3656, 0x27DF, 0x1544, 0x04CD, 0x7072, 0x61FB, 0x5360, 0x42E9,
0xBA1E, 0xAB97, 0x990C, 0x8885, 0xFC3A, 0xEDB3, 0xDF28, 0xCEA1,
0x3F4F, 0x2EC6, 0x1C5D, 0x0DD4, 0x796B, 0x68E2, 0x5A79, 0x4BF0,
0xB307, 0xA28E, 0x9015, 0x819C, 0xF523, 0xE4AA, 0xD631, 0xC7B8,
0x48C8, 0x5941, 0x6BDA, 0x7A53, 0x0EEC, 0x1F65, 0x2DFE, 0x3C77,
0xC480, 0xD509, 0xE792, 0xF61B, 0x82A4, 0x932D, 0xA1B6, 0xB03F,
0x41D1, 0x5058, 0x62C3, 0x734A, 0x07F5, 0x167C, 0x24E7, 0x356E,
0xCD99, 0xDC10, 0xEE8B, 0xFF02, 0x8BBD, 0x9A34, 0xA8AF, 0xB926,
0x5AFA, 0x4B73, 0x79E8, 0x6861, 0x1CDE, 0x0D57, 0x3FCC, 0x2E45,
0xD6B2, 0xC73B, 0xF5A0, 0xE429, 0x9096, 0x811F, 0xB384, 0xA20D,
0x53E3, 0x426A, 0x70F1, 0x6178, 0x15C7, 0x044E, 0x36D5, 0x275C,
0xDFAB, 0xCE22, 0xFCB9, 0xED30, 0x998F, 0x8806, 0xBA9D, 0xAB14,
0x6CAC, 0x7D25, 0x4FBE, 0x5E37, 0x2A88, 0x3B01, 0x099A, 0x1813,
0xE0E4, 0xF16D, 0xC3F6, 0xD27F, 0xA6C0, 0xB749, 0x85D2, 0x945B,
0x65B5, 0x743C, 0x46A7, 0x572E, 0x2391, 0x3218, 0x0083, 0x110A,
0xE9FD, 0xF874, 0xCAEF, 0xDB66, 0xAFD9, 0xBE50, 0x8CCB, 0x9D42,
0x7E9E, 0x6F17, 0x5D8C, 0x4C05, 0x38BA, 0x2933, 0x1BA8, 0x0A21,
0xF2D6, 0xE35F, 0xD1C4, 0xC04D, 0xB4F2, 0xA57B, 0x97E0, 0x8669,
0x7787, 0x660E, 0x5495, 0x451C, 0x31A3, 0x202A, 0x12B1, 0x0338,
0xFBCF, 0xEA46, 0xD8DD, 0xC954, 0xBDEB, 0xAC62, 0x9EF9, 0x8F70
};
uint16_t // Returns Calculated CRC value
CalculateCRC16(
uint16_t crc, // Seed for CRC calculation
const void *c_ptr, // Pointer to byte array to perform CRC on
size_t len) // Number of bytes to CRC
{
const uint8_t *c = c_ptr;
while (len--)
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
return crc;
}
int main()
{
printf("%04x\n", CalculateCRC16(0xFFFF, "123456789", 9));
return 0;
}
there is not a computer near me now. Just a try:
crc = (crc << 8) ^ crctable[(unsigned char)(crc >> 8) ^ *c++];
On this line
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
the result of ((crc >> 8) ^ *c++) can become > 255, and cause an access violation. Just make sure the result is always 0.255 by masking the index into crctable
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++) & 0x00FF];
// but you will need to clean up the result as its upper 16 bits
// are not guaranteed to be all 0
return crc & 0xffff;
or better, the resulting crc value as it ensures that crc will never contain a value > 0x0000ffff
crc = ( (crc << 8) ^ crctable[((crc >> 8) ^ *c++)] ) & 0xffff;
and you'll be all set. The base of the issue is that the original code seems to be 16 bits code (where int was 16 bits), and you are using a 32 bits compiler.
The table you are using appears to be incorrectly generated. The first sixteen entries are correct, but it diverges after that. I don't think you will have much luck decoding CCITT CRC-16 with it.
See CRC for cross platform applications for an example of the correctly-generated table.
I have used the same CRC checks and in your code you need to change only the following line:
crc = (crc >> 8) ^ crctable[(crc^(*c++))&0xFF];
that table lists the powers of the polynomial, to avoid errors in the table calculate the powers during the calculation, and make the polynomial an entry as well as the initial value. Use Dartpad to simulate it: https://dartpad.dev/?null_safety=true
void main() {
final int polynomial = 0x1189;
final int initialValue = 0xFFFF;
String crc16(String expression, int polynomial, int initialValue) {
int checkSum = initialValue;
for (int i = 0; i < expression.length; i++) {
checkSum ^= (expression.codeUnitAt(i) << 8);
for (int j = 0; j < 8; j++) {
if (((checkSum <<= 1) & 0x10000) == 0x10000) checkSum ^= polynomial;
checkSum &= 0xFFFF;
}
}
return checkSum.toRadixString(16).toUpperCase();
}
print(crc16('123456789', polynomial, initialValue));
}
To be compliant to CRC16 CCITT you should use polynomial=0x1021 and initial value = 0xFFFF.
https://www.gatevidyalay.com/cyclic-redundancy-check-crc-error-detection/ has a good explanation about CRC.
I'm working on a library to provide simple reliable communication over an RS232 or RS485 connection. Part of this code involves using a CRC16 checksum on the data to detect corruption from line noise. I've created a function to calculate a CRC16 checksum, but it doesn't seem to be outputting correct values.
The relevant code I've written is below (it can also be found here).
#include <stdint.h>
#define CRC16 0x8005
uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
/* Sanity check: */
if(data == NULL)
return 0;
while(size > 0)
{
bit_flag = out >> 15;
/* Get next bit: */
out <<= 1;
out |= (*data >> (7 - bits_read)) & 1;
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
return out;
}
I'm checking my output against this online CRC calculator.
I've come to the conclusion that either my understanding of how to calculate a CRC16 is wrong, or the online calculator is wrong (the former seems more likely). Can someone tell me where I might be going wrong?
There are several details you need to 'match up' with for a particular CRC implementation - even using the same polynomial there can be different results because of minor differences in how data bits are handled, using a particular initial value for the CRC (sometimes it's zero, sometimes 0xffff), and/or inverting the bits of the CRC. For example, sometimes one implementation will work from the low order bits of the data bytes up, while sometimes they'll work from the high order bits down (as yours currently does).
Also, you need to 'push out' the last bits of the CRC after you've run all the data bits through.
Keep in mind that CRC algorithms were designed to be implemented in hardware, so some of how bit ordering is handled may not make so much sense from a software point of view.
If you want to match the CRC16 with polynomial 0x8005 as shown on the lammertbies.nl CRC calculator page, you need to make the following changes to your CRC function:
a) run the data bits through the CRC loop starting from the least significant bit instead of from the most significant bit
b) push the last 16 bits of the CRC out of the CRC register after you've finished with the input data
c) reverse the CRC bits (I'm guessing this bit is a carry over from hardware implementations)
So, your function might look like:
#define CRC16 0x8005
uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;
/* Sanity check: */
if(data == NULL)
return 0;
while(size > 0)
{
bit_flag = out >> 15;
/* Get next bit: */
out <<= 1;
out |= (*data >> bits_read) & 1; // item a) work from the least significant bits
/* Increment bit counter: */
bits_read++;
if(bits_read > 7)
{
bits_read = 0;
data++;
size--;
}
/* Cycle check: */
if(bit_flag)
out ^= CRC16;
}
// item b) "push out" the last 16 bits
int i;
for (i = 0; i < 16; ++i) {
bit_flag = out >> 15;
out <<= 1;
if(bit_flag)
out ^= CRC16;
}
// item c) reverse the bits
uint16_t crc = 0;
i = 0x8000;
int j = 0x0001;
for (; i != 0; i >>=1, j <<= 1) {
if (i & out) crc |= j;
}
return crc;
}
That function returns 0xbb3d for me when I pass in "123456789".
Here follows a working code to calculate crc16 CCITT. I tested it and the results matched with those provided by http://www.lammertbies.nl/comm/info/crc-calculation.html.
unsigned short crc16(const unsigned char* data_p, unsigned char length){
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--){
x = crc >> 8 ^ *data_p++;
x ^= x>>4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
}
return crc;
}
crcany will generate efficient C code for any CRC, and includes a library of over one hundred known CRC definitions.
Efficient CRC code uses tables instead of bit-wise calculations. crcany generates both byte-wise routines and word-wise routines, the latter tuned to the architecture they are generated on. Word-wise is the fastest. Byte-wise is still much faster than bit-wise, but the implementation is more easily portable over architectures.
You do not seem to have a protocol definition with a specific CRC definition that you need to match. In this case, you can pick any 16-bit CRC in the catalog, and you will get good performance.
If you have a relatively low bit error rate, e.g. single digit number of errors per packet, and you want to maximize your error detection performance, you would need to look at the packet size you are applying the CRC to, assuming that that is constant or bounded, and look at the performance of the best polynomials in Philip Koopman's extensive research. The classic CRCs, such as the CCITT/Kermit 16-bit CRC or the X.25 16-bit CRC are not the best performers.
One of the good 16-bit performers in Koopman's tables that is also in the catalog of CRCs used in practice is CRC-16/DNP. It has very good performance detecting up to 6-bit errors in a packet. Following is the code generated by crcany for that CRC definition. This code assumes a little-endian architecture for the word-wise calculation, e.g. Intel x86 and x86-64, and it assumes that uintmax_t is 64 bits. crcany can be used to generate alternative code for big-endian and other word sizes.
crc16dnp.h:
// The _bit, _byte, and _word routines return the CRC of the len bytes at mem,
// applied to the previous CRC value, crc. If mem is NULL, then the other
// arguments are ignored, and the initial CRC, i.e. the CRC of zero bytes, is
// returned. Those routines will all return the same result, differing only in
// speed and code complexity. The _rem routine returns the CRC of the remaining
// bits in the last byte, for when the number of bits in the message is not a
// multiple of eight. The low bits bits of the low byte of val are applied to
// crc. bits must be in 0..8.
#include <stddef.h>
// Compute the CRC a bit at a time.
unsigned crc16dnp_bit(unsigned crc, void const *mem, size_t len);
// Compute the CRC of the low bits bits in val.
unsigned crc16dnp_rem(unsigned crc, unsigned val, unsigned bits);
// Compute the CRC a byte at a time.
unsigned crc16dnp_byte(unsigned crc, void const *mem, size_t len);
// Compute the CRC a word at a time.
unsigned crc16dnp_word(unsigned crc, void const *mem, size_t len);
crc16dnp.c:
#include <stdint.h>
#include "crc16dnp.h"
// This code assumes that unsigned is 4 bytes.
unsigned crc16dnp_bit(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffff;
crc = ~crc;
crc &= 0xffff;
while (len--) {
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0xa6bc : crc >> 1;
}
crc ^= 0xffff;
return crc;
}
unsigned crc16dnp_rem(unsigned crc, unsigned val, unsigned bits) {
crc = ~crc;
crc &= 0xffff;
val &= (1U << bits) - 1;
crc ^= val;
while (bits--)
crc = crc & 1 ? (crc >> 1) ^ 0xa6bc : crc >> 1;
crc ^= 0xffff;
return crc;
}
#define table_byte table_word[0]
static unsigned short const table_word[][256] = {
{0xed35, 0xdb6b, 0x8189, 0xb7d7, 0x344d, 0x0213, 0x58f1, 0x6eaf, 0x12bc, 0x24e2,
0x7e00, 0x485e, 0xcbc4, 0xfd9a, 0xa778, 0x9126, 0x5f5e, 0x6900, 0x33e2, 0x05bc,
0x8626, 0xb078, 0xea9a, 0xdcc4, 0xa0d7, 0x9689, 0xcc6b, 0xfa35, 0x79af, 0x4ff1,
0x1513, 0x234d, 0xc49a, 0xf2c4, 0xa826, 0x9e78, 0x1de2, 0x2bbc, 0x715e, 0x4700,
0x3b13, 0x0d4d, 0x57af, 0x61f1, 0xe26b, 0xd435, 0x8ed7, 0xb889, 0x76f1, 0x40af,
0x1a4d, 0x2c13, 0xaf89, 0x99d7, 0xc335, 0xf56b, 0x8978, 0xbf26, 0xe5c4, 0xd39a,
0x5000, 0x665e, 0x3cbc, 0x0ae2, 0xbe6b, 0x8835, 0xd2d7, 0xe489, 0x6713, 0x514d,
0x0baf, 0x3df1, 0x41e2, 0x77bc, 0x2d5e, 0x1b00, 0x989a, 0xaec4, 0xf426, 0xc278,
0x0c00, 0x3a5e, 0x60bc, 0x56e2, 0xd578, 0xe326, 0xb9c4, 0x8f9a, 0xf389, 0xc5d7,
0x9f35, 0xa96b, 0x2af1, 0x1caf, 0x464d, 0x7013, 0x97c4, 0xa19a, 0xfb78, 0xcd26,
0x4ebc, 0x78e2, 0x2200, 0x145e, 0x684d, 0x5e13, 0x04f1, 0x32af, 0xb135, 0x876b,
0xdd89, 0xebd7, 0x25af, 0x13f1, 0x4913, 0x7f4d, 0xfcd7, 0xca89, 0x906b, 0xa635,
0xda26, 0xec78, 0xb69a, 0x80c4, 0x035e, 0x3500, 0x6fe2, 0x59bc, 0x4b89, 0x7dd7,
0x2735, 0x116b, 0x92f1, 0xa4af, 0xfe4d, 0xc813, 0xb400, 0x825e, 0xd8bc, 0xeee2,
0x6d78, 0x5b26, 0x01c4, 0x379a, 0xf9e2, 0xcfbc, 0x955e, 0xa300, 0x209a, 0x16c4,
0x4c26, 0x7a78, 0x066b, 0x3035, 0x6ad7, 0x5c89, 0xdf13, 0xe94d, 0xb3af, 0x85f1,
0x6226, 0x5478, 0x0e9a, 0x38c4, 0xbb5e, 0x8d00, 0xd7e2, 0xe1bc, 0x9daf, 0xabf1,
0xf113, 0xc74d, 0x44d7, 0x7289, 0x286b, 0x1e35, 0xd04d, 0xe613, 0xbcf1, 0x8aaf,
0x0935, 0x3f6b, 0x6589, 0x53d7, 0x2fc4, 0x199a, 0x4378, 0x7526, 0xf6bc, 0xc0e2,
0x9a00, 0xac5e, 0x18d7, 0x2e89, 0x746b, 0x4235, 0xc1af, 0xf7f1, 0xad13, 0x9b4d,
0xe75e, 0xd100, 0x8be2, 0xbdbc, 0x3e26, 0x0878, 0x529a, 0x64c4, 0xaabc, 0x9ce2,
0xc600, 0xf05e, 0x73c4, 0x459a, 0x1f78, 0x2926, 0x5535, 0x636b, 0x3989, 0x0fd7,
0x8c4d, 0xba13, 0xe0f1, 0xd6af, 0x3178, 0x0726, 0x5dc4, 0x6b9a, 0xe800, 0xde5e,
0x84bc, 0xb2e2, 0xcef1, 0xf8af, 0xa24d, 0x9413, 0x1789, 0x21d7, 0x7b35, 0x4d6b,
0x8313, 0xb54d, 0xefaf, 0xd9f1, 0x5a6b, 0x6c35, 0x36d7, 0x0089, 0x7c9a, 0x4ac4,
0x1026, 0x2678, 0xa5e2, 0x93bc, 0xc95e, 0xff00},
{0x740f, 0xdf41, 0x6fea, 0xc4a4, 0x43c5, 0xe88b, 0x5820, 0xf36e, 0x1b9b, 0xb0d5,
0x007e, 0xab30, 0x2c51, 0x871f, 0x37b4, 0x9cfa, 0xab27, 0x0069, 0xb0c2, 0x1b8c,
0x9ced, 0x37a3, 0x8708, 0x2c46, 0xc4b3, 0x6ffd, 0xdf56, 0x7418, 0xf379, 0x5837,
0xe89c, 0x43d2, 0x8726, 0x2c68, 0x9cc3, 0x378d, 0xb0ec, 0x1ba2, 0xab09, 0x0047,
0xe8b2, 0x43fc, 0xf357, 0x5819, 0xdf78, 0x7436, 0xc49d, 0x6fd3, 0x580e, 0xf340,
0x43eb, 0xe8a5, 0x6fc4, 0xc48a, 0x7421, 0xdf6f, 0x379a, 0x9cd4, 0x2c7f, 0x8731,
0x0050, 0xab1e, 0x1bb5, 0xb0fb, 0xdf24, 0x746a, 0xc4c1, 0x6f8f, 0xe8ee, 0x43a0,
0xf30b, 0x5845, 0xb0b0, 0x1bfe, 0xab55, 0x001b, 0x877a, 0x2c34, 0x9c9f, 0x37d1,
0x000c, 0xab42, 0x1be9, 0xb0a7, 0x37c6, 0x9c88, 0x2c23, 0x876d, 0x6f98, 0xc4d6,
0x747d, 0xdf33, 0x5852, 0xf31c, 0x43b7, 0xe8f9, 0x2c0d, 0x8743, 0x37e8, 0x9ca6,
0x1bc7, 0xb089, 0x0022, 0xab6c, 0x4399, 0xe8d7, 0x587c, 0xf332, 0x7453, 0xdf1d,
0x6fb6, 0xc4f8, 0xf325, 0x586b, 0xe8c0, 0x438e, 0xc4ef, 0x6fa1, 0xdf0a, 0x7444,
0x9cb1, 0x37ff, 0x8754, 0x2c1a, 0xab7b, 0x0035, 0xb09e, 0x1bd0, 0x6f20, 0xc46e,
0x74c5, 0xdf8b, 0x58ea, 0xf3a4, 0x430f, 0xe841, 0x00b4, 0xabfa, 0x1b51, 0xb01f,
0x377e, 0x9c30, 0x2c9b, 0x87d5, 0xb008, 0x1b46, 0xabed, 0x00a3, 0x87c2, 0x2c8c,
0x9c27, 0x3769, 0xdf9c, 0x74d2, 0xc479, 0x6f37, 0xe856, 0x4318, 0xf3b3, 0x58fd,
0x9c09, 0x3747, 0x87ec, 0x2ca2, 0xabc3, 0x008d, 0xb026, 0x1b68, 0xf39d, 0x58d3,
0xe878, 0x4336, 0xc457, 0x6f19, 0xdfb2, 0x74fc, 0x4321, 0xe86f, 0x58c4, 0xf38a,
0x74eb, 0xdfa5, 0x6f0e, 0xc440, 0x2cb5, 0x87fb, 0x3750, 0x9c1e, 0x1b7f, 0xb031,
0x009a, 0xabd4, 0xc40b, 0x6f45, 0xdfee, 0x74a0, 0xf3c1, 0x588f, 0xe824, 0x436a,
0xab9f, 0x00d1, 0xb07a, 0x1b34, 0x9c55, 0x371b, 0x87b0, 0x2cfe, 0x1b23, 0xb06d,
0x00c6, 0xab88, 0x2ce9, 0x87a7, 0x370c, 0x9c42, 0x74b7, 0xdff9, 0x6f52, 0xc41c,
0x437d, 0xe833, 0x5898, 0xf3d6, 0x3722, 0x9c6c, 0x2cc7, 0x8789, 0x00e8, 0xaba6,
0x1b0d, 0xb043, 0x58b6, 0xf3f8, 0x4353, 0xe81d, 0x6f7c, 0xc432, 0x7499, 0xdfd7,
0xe80a, 0x4344, 0xf3ef, 0x58a1, 0xdfc0, 0x748e, 0xc425, 0x6f6b, 0x879e, 0x2cd0,
0x9c7b, 0x3735, 0xb054, 0x1b1a, 0xabb1, 0x00ff},
{0x7c67, 0x65df, 0x4f17, 0x56af, 0x1a87, 0x033f, 0x29f7, 0x304f, 0xb1a7, 0xa81f,
0x82d7, 0x9b6f, 0xd747, 0xceff, 0xe437, 0xfd8f, 0xaa9e, 0xb326, 0x99ee, 0x8056,
0xcc7e, 0xd5c6, 0xff0e, 0xe6b6, 0x675e, 0x7ee6, 0x542e, 0x4d96, 0x01be, 0x1806,
0x32ce, 0x2b76, 0x9cec, 0x8554, 0xaf9c, 0xb624, 0xfa0c, 0xe3b4, 0xc97c, 0xd0c4,
0x512c, 0x4894, 0x625c, 0x7be4, 0x37cc, 0x2e74, 0x04bc, 0x1d04, 0x4a15, 0x53ad,
0x7965, 0x60dd, 0x2cf5, 0x354d, 0x1f85, 0x063d, 0x87d5, 0x9e6d, 0xb4a5, 0xad1d,
0xe135, 0xf88d, 0xd245, 0xcbfd, 0xf008, 0xe9b0, 0xc378, 0xdac0, 0x96e8, 0x8f50,
0xa598, 0xbc20, 0x3dc8, 0x2470, 0x0eb8, 0x1700, 0x5b28, 0x4290, 0x6858, 0x71e0,
0x26f1, 0x3f49, 0x1581, 0x0c39, 0x4011, 0x59a9, 0x7361, 0x6ad9, 0xeb31, 0xf289,
0xd841, 0xc1f9, 0x8dd1, 0x9469, 0xbea1, 0xa719, 0x1083, 0x093b, 0x23f3, 0x3a4b,
0x7663, 0x6fdb, 0x4513, 0x5cab, 0xdd43, 0xc4fb, 0xee33, 0xf78b, 0xbba3, 0xa21b,
0x88d3, 0x916b, 0xc67a, 0xdfc2, 0xf50a, 0xecb2, 0xa09a, 0xb922, 0x93ea, 0x8a52,
0x0bba, 0x1202, 0x38ca, 0x2172, 0x6d5a, 0x74e2, 0x5e2a, 0x4792, 0x29c0, 0x3078,
0x1ab0, 0x0308, 0x4f20, 0x5698, 0x7c50, 0x65e8, 0xe400, 0xfdb8, 0xd770, 0xcec8,
0x82e0, 0x9b58, 0xb190, 0xa828, 0xff39, 0xe681, 0xcc49, 0xd5f1, 0x99d9, 0x8061,
0xaaa9, 0xb311, 0x32f9, 0x2b41, 0x0189, 0x1831, 0x5419, 0x4da1, 0x6769, 0x7ed1,
0xc94b, 0xd0f3, 0xfa3b, 0xe383, 0xafab, 0xb613, 0x9cdb, 0x8563, 0x048b, 0x1d33,
0x37fb, 0x2e43, 0x626b, 0x7bd3, 0x511b, 0x48a3, 0x1fb2, 0x060a, 0x2cc2, 0x357a,
0x7952, 0x60ea, 0x4a22, 0x539a, 0xd272, 0xcbca, 0xe102, 0xf8ba, 0xb492, 0xad2a,
0x87e2, 0x9e5a, 0xa5af, 0xbc17, 0x96df, 0x8f67, 0xc34f, 0xdaf7, 0xf03f, 0xe987,
0x686f, 0x71d7, 0x5b1f, 0x42a7, 0x0e8f, 0x1737, 0x3dff, 0x2447, 0x7356, 0x6aee,
0x4026, 0x599e, 0x15b6, 0x0c0e, 0x26c6, 0x3f7e, 0xbe96, 0xa72e, 0x8de6, 0x945e,
0xd876, 0xc1ce, 0xeb06, 0xf2be, 0x4524, 0x5c9c, 0x7654, 0x6fec, 0x23c4, 0x3a7c,
0x10b4, 0x090c, 0x88e4, 0x915c, 0xbb94, 0xa22c, 0xee04, 0xf7bc, 0xdd74, 0xc4cc,
0x93dd, 0x8a65, 0xa0ad, 0xb915, 0xf53d, 0xec85, 0xc64d, 0xdff5, 0x5e1d, 0x47a5,
0x6d6d, 0x74d5, 0x38fd, 0x2145, 0x0b8d, 0x1235},
{0xf917, 0x3bff, 0x31be, 0xf356, 0x253c, 0xe7d4, 0xed95, 0x2f7d, 0x0c38, 0xced0,
0xc491, 0x0679, 0xd013, 0x12fb, 0x18ba, 0xda52, 0x5e30, 0x9cd8, 0x9699, 0x5471,
0x821b, 0x40f3, 0x4ab2, 0x885a, 0xab1f, 0x69f7, 0x63b6, 0xa15e, 0x7734, 0xb5dc,
0xbf9d, 0x7d75, 0xfa20, 0x38c8, 0x3289, 0xf061, 0x260b, 0xe4e3, 0xeea2, 0x2c4a,
0x0f0f, 0xcde7, 0xc7a6, 0x054e, 0xd324, 0x11cc, 0x1b8d, 0xd965, 0x5d07, 0x9fef,
0x95ae, 0x5746, 0x812c, 0x43c4, 0x4985, 0x8b6d, 0xa828, 0x6ac0, 0x6081, 0xa269,
0x7403, 0xb6eb, 0xbcaa, 0x7e42, 0xff79, 0x3d91, 0x37d0, 0xf538, 0x2352, 0xe1ba,
0xebfb, 0x2913, 0x0a56, 0xc8be, 0xc2ff, 0x0017, 0xd67d, 0x1495, 0x1ed4, 0xdc3c,
0x585e, 0x9ab6, 0x90f7, 0x521f, 0x8475, 0x469d, 0x4cdc, 0x8e34, 0xad71, 0x6f99,
0x65d8, 0xa730, 0x715a, 0xb3b2, 0xb9f3, 0x7b1b, 0xfc4e, 0x3ea6, 0x34e7, 0xf60f,
0x2065, 0xe28d, 0xe8cc, 0x2a24, 0x0961, 0xcb89, 0xc1c8, 0x0320, 0xd54a, 0x17a2,
0x1de3, 0xdf0b, 0x5b69, 0x9981, 0x93c0, 0x5128, 0x8742, 0x45aa, 0x4feb, 0x8d03,
0xae46, 0x6cae, 0x66ef, 0xa407, 0x726d, 0xb085, 0xbac4, 0x782c, 0xf5cb, 0x3723,
0x3d62, 0xff8a, 0x29e0, 0xeb08, 0xe149, 0x23a1, 0x00e4, 0xc20c, 0xc84d, 0x0aa5,
0xdccf, 0x1e27, 0x1466, 0xd68e, 0x52ec, 0x9004, 0x9a45, 0x58ad, 0x8ec7, 0x4c2f,
0x466e, 0x8486, 0xa7c3, 0x652b, 0x6f6a, 0xad82, 0x7be8, 0xb900, 0xb341, 0x71a9,
0xf6fc, 0x3414, 0x3e55, 0xfcbd, 0x2ad7, 0xe83f, 0xe27e, 0x2096, 0x03d3, 0xc13b,
0xcb7a, 0x0992, 0xdff8, 0x1d10, 0x1751, 0xd5b9, 0x51db, 0x9333, 0x9972, 0x5b9a,
0x8df0, 0x4f18, 0x4559, 0x87b1, 0xa4f4, 0x661c, 0x6c5d, 0xaeb5, 0x78df, 0xba37,
0xb076, 0x729e, 0xf3a5, 0x314d, 0x3b0c, 0xf9e4, 0x2f8e, 0xed66, 0xe727, 0x25cf,
0x068a, 0xc462, 0xce23, 0x0ccb, 0xdaa1, 0x1849, 0x1208, 0xd0e0, 0x5482, 0x966a,
0x9c2b, 0x5ec3, 0x88a9, 0x4a41, 0x4000, 0x82e8, 0xa1ad, 0x6345, 0x6904, 0xabec,
0x7d86, 0xbf6e, 0xb52f, 0x77c7, 0xf092, 0x327a, 0x383b, 0xfad3, 0x2cb9, 0xee51,
0xe410, 0x26f8, 0x05bd, 0xc755, 0xcd14, 0x0ffc, 0xd996, 0x1b7e, 0x113f, 0xd3d7,
0x57b5, 0x955d, 0x9f1c, 0x5df4, 0x8b9e, 0x4976, 0x4337, 0x81df, 0xa29a, 0x6072,
0x6a33, 0xa8db, 0x7eb1, 0xbc59, 0xb618, 0x74f0},
{0x3108, 0x120e, 0x7704, 0x5402, 0xbd10, 0x9e16, 0xfb1c, 0xd81a, 0x6441, 0x4747,
0x224d, 0x014b, 0xe859, 0xcb5f, 0xae55, 0x8d53, 0x9b9a, 0xb89c, 0xdd96, 0xfe90,
0x1782, 0x3484, 0x518e, 0x7288, 0xced3, 0xedd5, 0x88df, 0xabd9, 0x42cb, 0x61cd,
0x04c7, 0x27c1, 0x2955, 0x0a53, 0x6f59, 0x4c5f, 0xa54d, 0x864b, 0xe341, 0xc047,
0x7c1c, 0x5f1a, 0x3a10, 0x1916, 0xf004, 0xd302, 0xb608, 0x950e, 0x83c7, 0xa0c1,
0xc5cb, 0xe6cd, 0x0fdf, 0x2cd9, 0x49d3, 0x6ad5, 0xd68e, 0xf588, 0x9082, 0xb384,
0x5a96, 0x7990, 0x1c9a, 0x3f9c, 0x01b2, 0x22b4, 0x47be, 0x64b8, 0x8daa, 0xaeac,
0xcba6, 0xe8a0, 0x54fb, 0x77fd, 0x12f7, 0x31f1, 0xd8e3, 0xfbe5, 0x9eef, 0xbde9,
0xab20, 0x8826, 0xed2c, 0xce2a, 0x2738, 0x043e, 0x6134, 0x4232, 0xfe69, 0xdd6f,
0xb865, 0x9b63, 0x7271, 0x5177, 0x347d, 0x177b, 0x19ef, 0x3ae9, 0x5fe3, 0x7ce5,
0x95f7, 0xb6f1, 0xd3fb, 0xf0fd, 0x4ca6, 0x6fa0, 0x0aaa, 0x29ac, 0xc0be, 0xe3b8,
0x86b2, 0xa5b4, 0xb37d, 0x907b, 0xf571, 0xd677, 0x3f65, 0x1c63, 0x7969, 0x5a6f,
0xe634, 0xc532, 0xa038, 0x833e, 0x6a2c, 0x492a, 0x2c20, 0x0f26, 0x507c, 0x737a,
0x1670, 0x3576, 0xdc64, 0xff62, 0x9a68, 0xb96e, 0x0535, 0x2633, 0x4339, 0x603f,
0x892d, 0xaa2b, 0xcf21, 0xec27, 0xfaee, 0xd9e8, 0xbce2, 0x9fe4, 0x76f6, 0x55f0,
0x30fa, 0x13fc, 0xafa7, 0x8ca1, 0xe9ab, 0xcaad, 0x23bf, 0x00b9, 0x65b3, 0x46b5,
0x4821, 0x6b27, 0x0e2d, 0x2d2b, 0xc439, 0xe73f, 0x8235, 0xa133, 0x1d68, 0x3e6e,
0x5b64, 0x7862, 0x9170, 0xb276, 0xd77c, 0xf47a, 0xe2b3, 0xc1b5, 0xa4bf, 0x87b9,
0x6eab, 0x4dad, 0x28a7, 0x0ba1, 0xb7fa, 0x94fc, 0xf1f6, 0xd2f0, 0x3be2, 0x18e4,
0x7dee, 0x5ee8, 0x60c6, 0x43c0, 0x26ca, 0x05cc, 0xecde, 0xcfd8, 0xaad2, 0x89d4,
0x358f, 0x1689, 0x7383, 0x5085, 0xb997, 0x9a91, 0xff9b, 0xdc9d, 0xca54, 0xe952,
0x8c58, 0xaf5e, 0x464c, 0x654a, 0x0040, 0x2346, 0x9f1d, 0xbc1b, 0xd911, 0xfa17,
0x1305, 0x3003, 0x5509, 0x760f, 0x789b, 0x5b9d, 0x3e97, 0x1d91, 0xf483, 0xd785,
0xb28f, 0x9189, 0x2dd2, 0x0ed4, 0x6bde, 0x48d8, 0xa1ca, 0x82cc, 0xe7c6, 0xc4c0,
0xd209, 0xf10f, 0x9405, 0xb703, 0x5e11, 0x7d17, 0x181d, 0x3b1b, 0x8740, 0xa446,
0xc14c, 0xe24a, 0x0b58, 0x285e, 0x4d54, 0x6e52},
{0xffb8, 0x4a5f, 0xd90f, 0x6ce8, 0xb2d6, 0x0731, 0x9461, 0x2186, 0x6564, 0xd083,
0x43d3, 0xf634, 0x280a, 0x9ded, 0x0ebd, 0xbb5a, 0x8779, 0x329e, 0xa1ce, 0x1429,
0xca17, 0x7ff0, 0xeca0, 0x5947, 0x1da5, 0xa842, 0x3b12, 0x8ef5, 0x50cb, 0xe52c,
0x767c, 0xc39b, 0x0e3a, 0xbbdd, 0x288d, 0x9d6a, 0x4354, 0xf6b3, 0x65e3, 0xd004,
0x94e6, 0x2101, 0xb251, 0x07b6, 0xd988, 0x6c6f, 0xff3f, 0x4ad8, 0x76fb, 0xc31c,
0x504c, 0xe5ab, 0x3b95, 0x8e72, 0x1d22, 0xa8c5, 0xec27, 0x59c0, 0xca90, 0x7f77,
0xa149, 0x14ae, 0x87fe, 0x3219, 0x51c5, 0xe422, 0x7772, 0xc295, 0x1cab, 0xa94c,
0x3a1c, 0x8ffb, 0xcb19, 0x7efe, 0xedae, 0x5849, 0x8677, 0x3390, 0xa0c0, 0x1527,
0x2904, 0x9ce3, 0x0fb3, 0xba54, 0x646a, 0xd18d, 0x42dd, 0xf73a, 0xb3d8, 0x063f,
0x956f, 0x2088, 0xfeb6, 0x4b51, 0xd801, 0x6de6, 0xa047, 0x15a0, 0x86f0, 0x3317,
0xed29, 0x58ce, 0xcb9e, 0x7e79, 0x3a9b, 0x8f7c, 0x1c2c, 0xa9cb, 0x77f5, 0xc212,
0x5142, 0xe4a5, 0xd886, 0x6d61, 0xfe31, 0x4bd6, 0x95e8, 0x200f, 0xb35f, 0x06b8,
0x425a, 0xf7bd, 0x64ed, 0xd10a, 0x0f34, 0xbad3, 0x2983, 0x9c64, 0xee3b, 0x5bdc,
0xc88c, 0x7d6b, 0xa355, 0x16b2, 0x85e2, 0x3005, 0x74e7, 0xc100, 0x5250, 0xe7b7,
0x3989, 0x8c6e, 0x1f3e, 0xaad9, 0x96fa, 0x231d, 0xb04d, 0x05aa, 0xdb94, 0x6e73,
0xfd23, 0x48c4, 0x0c26, 0xb9c1, 0x2a91, 0x9f76, 0x4148, 0xf4af, 0x67ff, 0xd218,
0x1fb9, 0xaa5e, 0x390e, 0x8ce9, 0x52d7, 0xe730, 0x7460, 0xc187, 0x8565, 0x3082,
0xa3d2, 0x1635, 0xc80b, 0x7dec, 0xeebc, 0x5b5b, 0x6778, 0xd29f, 0x41cf, 0xf428,
0x2a16, 0x9ff1, 0x0ca1, 0xb946, 0xfda4, 0x4843, 0xdb13, 0x6ef4, 0xb0ca, 0x052d,
0x967d, 0x239a, 0x4046, 0xf5a1, 0x66f1, 0xd316, 0x0d28, 0xb8cf, 0x2b9f, 0x9e78,
0xda9a, 0x6f7d, 0xfc2d, 0x49ca, 0x97f4, 0x2213, 0xb143, 0x04a4, 0x3887, 0x8d60,
0x1e30, 0xabd7, 0x75e9, 0xc00e, 0x535e, 0xe6b9, 0xa25b, 0x17bc, 0x84ec, 0x310b,
0xef35, 0x5ad2, 0xc982, 0x7c65, 0xb1c4, 0x0423, 0x9773, 0x2294, 0xfcaa, 0x494d,
0xda1d, 0x6ffa, 0x2b18, 0x9eff, 0x0daf, 0xb848, 0x6676, 0xd391, 0x40c1, 0xf526,
0xc905, 0x7ce2, 0xefb2, 0x5a55, 0x846b, 0x318c, 0xa2dc, 0x173b, 0x53d9, 0xe63e,
0x756e, 0xc089, 0x1eb7, 0xab50, 0x3800, 0x8de7},
{0xc20e, 0x9d6c, 0x7cca, 0x23a8, 0xf2ff, 0xad9d, 0x4c3b, 0x1359, 0xa3ec, 0xfc8e,
0x1d28, 0x424a, 0x931d, 0xcc7f, 0x2dd9, 0x72bb, 0x01ca, 0x5ea8, 0xbf0e, 0xe06c,
0x313b, 0x6e59, 0x8fff, 0xd09d, 0x6028, 0x3f4a, 0xdeec, 0x818e, 0x50d9, 0x0fbb,
0xee1d, 0xb17f, 0x08ff, 0x579d, 0xb63b, 0xe959, 0x380e, 0x676c, 0x86ca, 0xd9a8,
0x691d, 0x367f, 0xd7d9, 0x88bb, 0x59ec, 0x068e, 0xe728, 0xb84a, 0xcb3b, 0x9459,
0x75ff, 0x2a9d, 0xfbca, 0xa4a8, 0x450e, 0x1a6c, 0xaad9, 0xf5bb, 0x141d, 0x4b7f,
0x9a28, 0xc54a, 0x24ec, 0x7b8e, 0x1a95, 0x45f7, 0xa451, 0xfb33, 0x2a64, 0x7506,
0x94a0, 0xcbc2, 0x7b77, 0x2415, 0xc5b3, 0x9ad1, 0x4b86, 0x14e4, 0xf542, 0xaa20,
0xd951, 0x8633, 0x6795, 0x38f7, 0xe9a0, 0xb6c2, 0x5764, 0x0806, 0xb8b3, 0xe7d1,
0x0677, 0x5915, 0x8842, 0xd720, 0x3686, 0x69e4, 0xd064, 0x8f06, 0x6ea0, 0x31c2,
0xe095, 0xbff7, 0x5e51, 0x0133, 0xb186, 0xeee4, 0x0f42, 0x5020, 0x8177, 0xde15,
0x3fb3, 0x60d1, 0x13a0, 0x4cc2, 0xad64, 0xf206, 0x2351, 0x7c33, 0x9d95, 0xc2f7,
0x7242, 0x2d20, 0xcc86, 0x93e4, 0x42b3, 0x1dd1, 0xfc77, 0xa315, 0x3e41, 0x6123,
0x8085, 0xdfe7, 0x0eb0, 0x51d2, 0xb074, 0xef16, 0x5fa3, 0x00c1, 0xe167, 0xbe05,
0x6f52, 0x3030, 0xd196, 0x8ef4, 0xfd85, 0xa2e7, 0x4341, 0x1c23, 0xcd74, 0x9216,
0x73b0, 0x2cd2, 0x9c67, 0xc305, 0x22a3, 0x7dc1, 0xac96, 0xf3f4, 0x1252, 0x4d30,
0xf4b0, 0xabd2, 0x4a74, 0x1516, 0xc441, 0x9b23, 0x7a85, 0x25e7, 0x9552, 0xca30,
0x2b96, 0x74f4, 0xa5a3, 0xfac1, 0x1b67, 0x4405, 0x3774, 0x6816, 0x89b0, 0xd6d2,
0x0785, 0x58e7, 0xb941, 0xe623, 0x5696, 0x09f4, 0xe852, 0xb730, 0x6667, 0x3905,
0xd8a3, 0x87c1, 0xe6da, 0xb9b8, 0x581e, 0x077c, 0xd62b, 0x8949, 0x68ef, 0x378d,
0x8738, 0xd85a, 0x39fc, 0x669e, 0xb7c9, 0xe8ab, 0x090d, 0x566f, 0x251e, 0x7a7c,
0x9bda, 0xc4b8, 0x15ef, 0x4a8d, 0xab2b, 0xf449, 0x44fc, 0x1b9e, 0xfa38, 0xa55a,
0x740d, 0x2b6f, 0xcac9, 0x95ab, 0x2c2b, 0x7349, 0x92ef, 0xcd8d, 0x1cda, 0x43b8,
0xa21e, 0xfd7c, 0x4dc9, 0x12ab, 0xf30d, 0xac6f, 0x7d38, 0x225a, 0xc3fc, 0x9c9e,
0xefef, 0xb08d, 0x512b, 0x0e49, 0xdf1e, 0x807c, 0x61da, 0x3eb8, 0x8e0d, 0xd16f,
0x30c9, 0x6fab, 0xbefc, 0xe19e, 0x0038, 0x5f5a},
{0x4a8f, 0x5c9d, 0x66ab, 0x70b9, 0x12c7, 0x04d5, 0x3ee3, 0x28f1, 0xfa1f, 0xec0d,
0xd63b, 0xc029, 0xa257, 0xb445, 0x8e73, 0x9861, 0x66d6, 0x70c4, 0x4af2, 0x5ce0,
0x3e9e, 0x288c, 0x12ba, 0x04a8, 0xd646, 0xc054, 0xfa62, 0xec70, 0x8e0e, 0x981c,
0xa22a, 0xb438, 0x123d, 0x042f, 0x3e19, 0x280b, 0x4a75, 0x5c67, 0x6651, 0x7043,
0xa2ad, 0xb4bf, 0x8e89, 0x989b, 0xfae5, 0xecf7, 0xd6c1, 0xc0d3, 0x3e64, 0x2876,
0x1240, 0x0452, 0x662c, 0x703e, 0x4a08, 0x5c1a, 0x8ef4, 0x98e6, 0xa2d0, 0xb4c2,
0xd6bc, 0xc0ae, 0xfa98, 0xec8a, 0xfbeb, 0xedf9, 0xd7cf, 0xc1dd, 0xa3a3, 0xb5b1,
0x8f87, 0x9995, 0x4b7b, 0x5d69, 0x675f, 0x714d, 0x1333, 0x0521, 0x3f17, 0x2905,
0xd7b2, 0xc1a0, 0xfb96, 0xed84, 0x8ffa, 0x99e8, 0xa3de, 0xb5cc, 0x6722, 0x7130,
0x4b06, 0x5d14, 0x3f6a, 0x2978, 0x134e, 0x055c, 0xa359, 0xb54b, 0x8f7d, 0x996f,
0xfb11, 0xed03, 0xd735, 0xc127, 0x13c9, 0x05db, 0x3fed, 0x29ff, 0x4b81, 0x5d93,
0x67a5, 0x71b7, 0x8f00, 0x9912, 0xa324, 0xb536, 0xd748, 0xc15a, 0xfb6c, 0xed7e,
0x3f90, 0x2982, 0x13b4, 0x05a6, 0x67d8, 0x71ca, 0x4bfc, 0x5dee, 0x653e, 0x732c,
0x491a, 0x5f08, 0x3d76, 0x2b64, 0x1152, 0x0740, 0xd5ae, 0xc3bc, 0xf98a, 0xef98,
0x8de6, 0x9bf4, 0xa1c2, 0xb7d0, 0x4967, 0x5f75, 0x6543, 0x7351, 0x112f, 0x073d,
0x3d0b, 0x2b19, 0xf9f7, 0xefe5, 0xd5d3, 0xc3c1, 0xa1bf, 0xb7ad, 0x8d9b, 0x9b89,
0x3d8c, 0x2b9e, 0x11a8, 0x07ba, 0x65c4, 0x73d6, 0x49e0, 0x5ff2, 0x8d1c, 0x9b0e,
0xa138, 0xb72a, 0xd554, 0xc346, 0xf970, 0xef62, 0x11d5, 0x07c7, 0x3df1, 0x2be3,
0x499d, 0x5f8f, 0x65b9, 0x73ab, 0xa145, 0xb757, 0x8d61, 0x9b73, 0xf90d, 0xef1f,
0xd529, 0xc33b, 0xd45a, 0xc248, 0xf87e, 0xee6c, 0x8c12, 0x9a00, 0xa036, 0xb624,
0x64ca, 0x72d8, 0x48ee, 0x5efc, 0x3c82, 0x2a90, 0x10a6, 0x06b4, 0xf803, 0xee11,
0xd427, 0xc235, 0xa04b, 0xb659, 0x8c6f, 0x9a7d, 0x4893, 0x5e81, 0x64b7, 0x72a5,
0x10db, 0x06c9, 0x3cff, 0x2aed, 0x8ce8, 0x9afa, 0xa0cc, 0xb6de, 0xd4a0, 0xc2b2,
0xf884, 0xee96, 0x3c78, 0x2a6a, 0x105c, 0x064e, 0x6430, 0x7222, 0x4814, 0x5e06,
0xa0b1, 0xb6a3, 0x8c95, 0x9a87, 0xf8f9, 0xeeeb, 0xd4dd, 0xc2cf, 0x1021, 0x0633,
0x3c05, 0x2a17, 0x4869, 0x5e7b, 0x644d, 0x725f}
};
unsigned crc16dnp_byte(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffff;
crc &= 0xffff;
while (len--)
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
return crc;
}
// This code assumes that integers are stored little-endian.
unsigned crc16dnp_word(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffff;
crc &= 0xffff;
while (len && ((ptrdiff_t)data & 0x7)) {
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
len--;
}
if (len >= 8) {
do {
uintmax_t word = crc ^ *(uintmax_t const *)data;
crc = table_word[7][word & 0xff] ^
table_word[6][(word >> 8) & 0xff] ^
table_word[5][(word >> 16) & 0xff] ^
table_word[4][(word >> 24) & 0xff] ^
table_word[3][(word >> 32) & 0xff] ^
table_word[2][(word >> 40) & 0xff] ^
table_word[1][(word >> 48) & 0xff] ^
table_word[0][word >> 56];
data += 8;
len -= 8;
} while (len >= 8);
}
while (len--)
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
return crc;
}
There are several different varieties of CRC-16. See wiki page.
Every of those will return different results from the same input.
So you must carefully select correct one for your program.
for (pos = 0; pos < len; pos++) {
crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
for (i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // Shift right and XOR 0xA001
crc ^= CRC16;
} else { // Else LSB is not set
crc >>= 1; // Just shift right
}
}
}
return crc;
I used the code example from:
http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch5
And also this utility to verify:
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
This function works for CRC-16 Modbus version. Not for CRC-16