Computing CRC16 with reflected / bit reversed input in C - c
I want to compute the reflected CRC16 of the CCITT polynomial 0x1021 starting from 0xC6C6 (no XOR at end, also known as CRC16-A on this page https://crccalc.com) in two different ways with (embedded) C.
For the two alternatives, I want to use the polynomial 0x1021 starting with 0xC6C6 as well as the reflected polynomial 0x8408 starting from 0x6363 (= reflect(0xC6C6)).
Assume I have a lookup-table for each polynomial:
static const UINT16 au16Table1021[256u]
and
static const UINT16 au16Table8408[256u]
and a reflect function that reverses the bit order of a byte (e.g. based on
In C/C++ what's the simplest way to reverse the order of bits in a byte?)
From the accepted answer of How to configure calculation of CRC table I expected that I would get the same result by reflecting the input, the starting CRC (wOldCRC = 0xC6C6), shifting the CRC calculation in the opposed direction and finally reflecting the resulting CRC. However, the second option I tried does not yield the expected result. What am I doing wrong?
Minimal (more or less) working example with incorrect CRC for option 2:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
static const uint16_t crcTable1021[256u] = {
0x0000u, 0x17CEu, 0x0FDFu, 0x1811u, 0x1FBEu, 0x0870u, 0x1061u, 0x07AFu,
0x1F3Fu, 0x08F1u, 0x10E0u, 0x072Eu, 0x0081u, 0x174Fu, 0x0F5Eu, 0x1890u,
0x1E3Du, 0x09F3u, 0x11E2u, 0x062Cu, 0x0183u, 0x164Du, 0x0E5Cu, 0x1992u,
0x0102u, 0x16CCu, 0x0EDDu, 0x1913u, 0x1EBCu, 0x0972u, 0x1163u, 0x06ADu,
0x1C39u, 0x0BF7u, 0x13E6u, 0x0428u, 0x0387u, 0x1449u, 0x0C58u, 0x1B96u,
0x0306u, 0x14C8u, 0x0CD9u, 0x1B17u, 0x1CB8u, 0x0B76u, 0x1367u, 0x04A9u,
0x0204u, 0x15CAu, 0x0DDBu, 0x1A15u, 0x1DBAu, 0x0A74u, 0x1265u, 0x05ABu,
0x1D3Bu, 0x0AF5u, 0x12E4u, 0x052Au, 0x0285u, 0x154Bu, 0x0D5Au, 0x1A94u,
0x1831u, 0x0FFFu, 0x17EEu, 0x0020u, 0x078Fu, 0x1041u, 0x0850u, 0x1F9Eu,
0x070Eu, 0x10C0u, 0x08D1u, 0x1F1Fu, 0x18B0u, 0x0F7Eu, 0x176Fu, 0x00A1u,
0x060Cu, 0x11C2u, 0x09D3u, 0x1E1Du, 0x19B2u, 0x0E7Cu, 0x166Du, 0x01A3u,
0x1933u, 0x0EFDu, 0x16ECu, 0x0122u, 0x068Du, 0x1143u, 0x0952u, 0x1E9Cu,
0x0408u, 0x13C6u, 0x0BD7u, 0x1C19u, 0x1BB6u, 0x0C78u, 0x1469u, 0x03A7u,
0x1B37u, 0x0CF9u, 0x14E8u, 0x0326u, 0x0489u, 0x1347u, 0x0B56u, 0x1C98u,
0x1A35u, 0x0DFBu, 0x15EAu, 0x0224u, 0x058Bu, 0x1245u, 0x0A54u, 0x1D9Au,
0x050Au, 0x12C4u, 0x0AD5u, 0x1D1Bu, 0x1AB4u, 0x0D7Au, 0x156Bu, 0x02A5u,
0x1021u, 0x07EFu, 0x1FFEu, 0x0830u, 0x0F9Fu, 0x1851u, 0x0040u, 0x178Eu,
0x0F1Eu, 0x18D0u, 0x00C1u, 0x170Fu, 0x10A0u, 0x076Eu, 0x1F7Fu, 0x08B1u,
0x0E1Cu, 0x19D2u, 0x01C3u, 0x160Du, 0x11A2u, 0x066Cu, 0x1E7Du, 0x09B3u,
0x1123u, 0x06EDu, 0x1EFCu, 0x0932u, 0x0E9Du, 0x1953u, 0x0142u, 0x168Cu,
0x0C18u, 0x1BD6u, 0x03C7u, 0x1409u, 0x13A6u, 0x0468u, 0x1C79u, 0x0BB7u,
0x1327u, 0x04E9u, 0x1CF8u, 0x0B36u, 0x0C99u, 0x1B57u, 0x0346u, 0x1488u,
0x1225u, 0x05EBu, 0x1DFAu, 0x0A34u, 0x0D9Bu, 0x1A55u, 0x0244u, 0x158Au,
0x0D1Au, 0x1AD4u, 0x02C5u, 0x150Bu, 0x12A4u, 0x056Au, 0x1D7Bu, 0x0AB5u,
0x0810u, 0x1FDEu, 0x07CFu, 0x1001u, 0x17AEu, 0x0060u, 0x1871u, 0x0FBFu,
0x172Fu, 0x00E1u, 0x18F0u, 0x0F3Eu, 0x0891u, 0x1F5Fu, 0x074Eu, 0x1080u,
0x162Du, 0x01E3u, 0x19F2u, 0x0E3Cu, 0x0993u, 0x1E5Du, 0x064Cu, 0x1182u,
0x0912u, 0x1EDCu, 0x06CDu, 0x1103u, 0x16ACu, 0x0162u, 0x1973u, 0x0EBDu,
0x1429u, 0x03E7u, 0x1BF6u, 0x0C38u, 0x0B97u, 0x1C59u, 0x0448u, 0x1386u,
0x0B16u, 0x1CD8u, 0x04C9u, 0x1307u, 0x14A8u, 0x0366u, 0x1B77u, 0x0CB9u,
0x0A14u, 0x1DDAu, 0x05CBu, 0x1205u, 0x15AAu, 0x0264u, 0x1A75u, 0x0DBBu,
0x152Bu, 0x02E5u, 0x1AF4u, 0x0D3Au, 0x0A95u, 0x1D5Bu, 0x054Au, 0x1284u,
};
static const uint16_t crcTable8408[256u] = {
0x0000u, 0x1189u, 0x2312u, 0x329Bu, 0x4624u, 0x57ADu, 0x6536u, 0x74BFu,
0x8C48u, 0x9DC1u, 0xAF5Au, 0xBED3u, 0xCA6Cu, 0xDBE5u, 0xE97Eu, 0xF8F7u,
0x1081u, 0x0108u, 0x3393u, 0x221Au, 0x56A5u, 0x472Cu, 0x75B7u, 0x643Eu,
0x9CC9u, 0x8D40u, 0xBFDBu, 0xAE52u, 0xDAEDu, 0xCB64u, 0xF9FFu, 0xE876u,
0x2102u, 0x308Bu, 0x0210u, 0x1399u, 0x6726u, 0x76AFu, 0x4434u, 0x55BDu,
0xAD4Au, 0xBCC3u, 0x8E58u, 0x9FD1u, 0xEB6Eu, 0xFAE7u, 0xC87Cu, 0xD9F5u,
0x3183u, 0x200Au, 0x1291u, 0x0318u, 0x77A7u, 0x662Eu, 0x54B5u, 0x453Cu,
0xBDCBu, 0xAC42u, 0x9ED9u, 0x8F50u, 0xFBEFu, 0xEA66u, 0xD8FDu, 0xC974u,
0x4204u, 0x538Du, 0x6116u, 0x709Fu, 0x0420u, 0x15A9u, 0x2732u, 0x36BBu,
0xCE4Cu, 0xDFC5u, 0xED5Eu, 0xFCD7u, 0x8868u, 0x99E1u, 0xAB7Au, 0xBAF3u,
0x5285u, 0x430Cu, 0x7197u, 0x601Eu, 0x14A1u, 0x0528u, 0x37B3u, 0x263Au,
0xDECDu, 0xCF44u, 0xFDDFu, 0xEC56u, 0x98E9u, 0x8960u, 0xBBFBu, 0xAA72u,
0x6306u, 0x728Fu, 0x4014u, 0x519Du, 0x2522u, 0x34ABu, 0x0630u, 0x17B9u,
0xEF4Eu, 0xFEC7u, 0xCC5Cu, 0xDDD5u, 0xA96Au, 0xB8E3u, 0x8A78u, 0x9BF1u,
0x7387u, 0x620Eu, 0x5095u, 0x411Cu, 0x35A3u, 0x242Au, 0x16B1u, 0x0738u,
0xFFCFu, 0xEE46u, 0xDCDDu, 0xCD54u, 0xB9EBu, 0xA862u, 0x9AF9u, 0x8B70u,
0x8408u, 0x9581u, 0xA71Au, 0xB693u, 0xC22Cu, 0xD3A5u, 0xE13Eu, 0xF0B7u,
0x0840u, 0x19C9u, 0x2B52u, 0x3ADBu, 0x4E64u, 0x5FEDu, 0x6D76u, 0x7CFFu,
0x9489u, 0x8500u, 0xB79Bu, 0xA612u, 0xD2ADu, 0xC324u, 0xF1BFu, 0xE036u,
0x18C1u, 0x0948u, 0x3BD3u, 0x2A5Au, 0x5EE5u, 0x4F6Cu, 0x7DF7u, 0x6C7Eu,
0xA50Au, 0xB483u, 0x8618u, 0x9791u, 0xE32Eu, 0xF2A7u, 0xC03Cu, 0xD1B5u,
0x2942u, 0x38CBu, 0x0A50u, 0x1BD9u, 0x6F66u, 0x7EEFu, 0x4C74u, 0x5DFDu,
0xB58Bu, 0xA402u, 0x9699u, 0x8710u, 0xF3AFu, 0xE226u, 0xD0BDu, 0xC134u,
0x39C3u, 0x284Au, 0x1AD1u, 0x0B58u, 0x7FE7u, 0x6E6Eu, 0x5CF5u, 0x4D7Cu,
0xC60Cu, 0xD785u, 0xE51Eu, 0xF497u, 0x8028u, 0x91A1u, 0xA33Au, 0xB2B3u,
0x4A44u, 0x5BCDu, 0x6956u, 0x78DFu, 0x0C60u, 0x1DE9u, 0x2F72u, 0x3EFBu,
0xD68Du, 0xC704u, 0xF59Fu, 0xE416u, 0x90A9u, 0x8120u, 0xB3BBu, 0xA232u,
0x5AC5u, 0x4B4Cu, 0x79D7u, 0x685Eu, 0x1CE1u, 0x0D68u, 0x3FF3u, 0x2E7Au,
0xE70Eu, 0xF687u, 0xC41Cu, 0xD595u, 0xA12Au, 0xB0A3u, 0x8238u, 0x93B1u,
0x6B46u, 0x7ACFu, 0x4854u, 0x59DDu, 0x2D62u, 0x3CEBu, 0x0E70u, 0x1FF9u,
0xF78Fu, 0xE606u, 0xD49Du, 0xC514u, 0xB1ABu, 0xA022u, 0x92B9u, 0x8330u,
0x7BC7u, 0x6A4Eu, 0x58D5u, 0x495Cu, 0x3DE3u, 0x2C6Au, 0x1EF1u, 0x0F78u,
};
static uint8_t reverse(uint8_t n) {
static uint8_t lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
uint8_t result;
result = lookup[n & 0xF] << 4 | lookup[n>>4];
return result;
}
static uint16_t reverse16(uint16_t n) {
return reverse(n & 0xFF) << 8 | reverse(n >> 8);
}
uint16_t Calculate(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC;
for (int byte = 0; byte < nBytes; ++byte) {
data = message[byte] ^ remainder;
remainder = crcTable8408[data] ^ (remainder >> 8);
}
return remainder;
}
uint16_t CalculateInv(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC; //already reversed in function call
for (int byte = nBytes; byte > 0; --byte) {
data = reverse(message[byte-1]) ^ remainder;
remainder = crcTable1021[data] ^ (remainder << 8);
}
return reverse16(remainder);
}
int main(void) {
uint16_t expected = 0x4167;
uint8_t pattern[] = "Hello World!";
uint16_t result = Calculate(pattern, 12, 0x6363);
printf("CRC option 1: 0x%04x, expected 0x%04x\n", result, expected);
result = CalculateInv(pattern, 12, 0xC6C6);
printf("CRC option 2: 0x%04X, expected 0x%04X\n", result, expected);
return EXIT_SUCCESS;
}
Output:
CRC option 1: 0x4167, expected 0x4167
CRC option 2: 0x62FD, expected 0x4167
Edit: I created the tables by slightly adapting the code from the accepted answer from How to configure calculation of CRC table as follows:
uint16_t crcTable[256];
void Init(uint16_t polynomial) {
uint16_t remainder;
for (int dividend = 0; dividend < 256; ++dividend) {
remainder = dividend;
for (uint8_t bit = 8; bit > 0; --bit) {
if (remainder & 1)
remainder = (remainder >> 1) ^ polynomial;
else
remainder = (remainder >> 1);
}
crcTable[dividend] = remainder;
}
printf("static const uint_t crcTable[256u] = {");
for (int i = 0; i<32; ++i) {
printf("\n ");
for (int j=0; j<8; ++j) {
printf("0x%04Xu, ",crcTable[i*8+j]);
}
}
printf("\n};\n");
}
For a reflected CRC16, only the bits of each byte of a message are reversed, the message itself is not reversed. The other issue is that crcTable1021 needs to be based on a left shifting algorithm, or it can be a copy of crcTable8408 with the index and values reflected. (Comment - the 8408 CRC is a reflected CRC, while the 1021 is normally a non-reflected CRC, but in this case the input and output is being reflected to match the 8408 CRC). Example code that appears to be working:
static uint16_t crcTable8408[256u]; // could use table from question
static uint16_t crcTable1021[256u]; // could use table from automationwiki
// ... no changes ... //
uint16_t CalculateInv(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC; //already reversed in function call
for (int byte = 0; byte < nBytes; ++byte) { // fix
data = reverse(message[byte]) ^ (remainder >> 8); // fix
remainder = crcTable1021[data] ^ (remainder << 8); // fix
}
return reverse16(remainder);
}
void InitTables(void) { // generate tables
uint16_t polynomial = 0x8408;
uint16_t remainder;
for (int dividend = 0; dividend < 256; ++dividend) {
remainder = dividend;
for (uint8_t bit = 8; bit > 0; --bit) {
if (remainder & 1)
remainder = (remainder >> 1) ^ polynomial;
else
remainder = (remainder >> 1);
}
crcTable8408[dividend] = remainder;
crcTable1021[reverse(dividend)] = reverse16(remainder);
}
}
int main(void) {
uint16_t expected = 0x4167;
uint8_t pattern[] = "Hello World!";
InitTables(); // generate tables (or use constant tables)
uint16_t result = Calculate(pattern, 12, 0x6363);
printf("CRC option 1: 0x%04X, expected 0x%04x\n", result, expected);
result = CalculateInv(pattern, 12, 0xC6C6);
printf("CRC option 2: 0x%04X, expected 0x%04X\n", result, expected);
return 0;
}
You can use crcany to generate the code (in C) for any CRC you specify. As it happens, the 16-bit CRC reflected with polynomial 0x1021, initial value 0xc6c6, and final xor 0 is already in the list of standard CRCs. This is the code generated, and it produces 0x4167 for the 12 bytes "Hello, World!":
crc16iso_iec_14443_3_a.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 crc16iso_iec_14443_3_a_bit(unsigned crc, void const *mem, size_t len);
// Compute the CRC of the low bits bits in val.
unsigned crc16iso_iec_14443_3_a_rem(unsigned crc, unsigned val, unsigned bits);
// Compute the CRC a byte at a time.
unsigned crc16iso_iec_14443_3_a_byte(unsigned crc, void const *mem, size_t len);
// Compute the CRC a word at a time.
unsigned crc16iso_iec_14443_3_a_word(unsigned crc, void const *mem, size_t len);
crc16iso_iec_14443_3_a.c:
#include <stdint.h>
#include "crc16iso_iec_14443_3_a.h"
// This code assumes that unsigned is 4 bytes.
unsigned crc16iso_iec_14443_3_a_bit(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
crc &= 0xffff;
while (len--) {
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
}
return crc;
}
unsigned crc16iso_iec_14443_3_a_rem(unsigned crc, unsigned val, unsigned bits) {
crc &= 0xffff;
val &= (1U << bits) - 1;
crc ^= val;
while (bits--)
crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
return crc;
}
#define table_byte table_word[0]
static unsigned short const table_word[][256] = {
{0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1,
0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a,
0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64,
0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a,
0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50,
0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9,
0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44,
0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d,
0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3,
0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581,
0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb,
0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324,
0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb,
0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710,
0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e,
0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704,
0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e,
0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3,
0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e,
0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78},
{0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08, 0xcec0, 0xd718,
0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8, 0x9591, 0x8c49, 0xa621, 0xbff9,
0xf2f1, 0xeb29, 0xc141, 0xd899, 0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9,
0x0f81, 0x1659, 0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b,
0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb, 0xb6a2, 0xaf7a,
0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa, 0x7862, 0x61ba, 0x4bd2, 0x520a,
0x1f02, 0x06da, 0x2cb2, 0x356a, 0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de,
0x12b6, 0x0b6e, 0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae,
0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff, 0x1d37, 0x04ef,
0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f, 0x6555, 0x7c8d, 0x56e5, 0x4f3d,
0x0235, 0x1bed, 0x3185, 0x285d, 0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d,
0xff45, 0xe69d, 0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc,
0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c, 0x8ccc, 0x9514,
0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4, 0x420c, 0x5bd4, 0x71bc, 0x6864,
0x256c, 0x3cb4, 0x16dc, 0x0f04, 0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5,
0x4d8d, 0x5455, 0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95,
0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7, 0x613f, 0x78e7,
0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37, 0x3a6e, 0x23b6, 0x09de, 0x1006,
0x5d0e, 0x44d6, 0x6ebe, 0x7766, 0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16,
0xa07e, 0xb9a6, 0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2,
0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962, 0x5f3b, 0x46e3,
0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233, 0x91fb, 0x8823, 0xa24b, 0xbb93,
0xf69b, 0xef43, 0xc52b, 0xdcf3, 0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721,
0xbd49, 0xa491, 0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51,
0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100, 0xb2c8, 0xab10,
0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0},
{0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05, 0xc6c2, 0x9c1e,
0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7, 0x8595, 0xdf49, 0x302d, 0x6af1,
0xe6f4, 0xbc28, 0x534c, 0x0990, 0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea,
0x958e, 0xcf52, 0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e,
0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc, 0x86ae, 0xdc72,
0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab, 0x406c, 0x1ab0, 0xf5d4, 0xaf08,
0x230d, 0x79d1, 0x96b5, 0xcc69, 0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb,
0xd0af, 0x8a73, 0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1,
0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6, 0x4521, 0x1ffd,
0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924, 0x054d, 0x5f91, 0xb0f5, 0xea29,
0x662c, 0x3cf0, 0xd394, 0x8948, 0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32,
0x1556, 0x4f8a, 0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd,
0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f, 0x0cec, 0x5630,
0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9, 0xca2e, 0x90f2, 0x7f96, 0x254a,
0xa94f, 0xf393, 0x1cf7, 0x462b, 0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4,
0x5fa0, 0x057c, 0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be,
0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2, 0xc915, 0x93c9,
0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510, 0x8a42, 0xd09e, 0x3ffa, 0x6526,
0xe923, 0xb3ff, 0x5c9b, 0x0647, 0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d,
0x9a59, 0xc085, 0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f,
0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d, 0x8f0f, 0xd5d3,
0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a, 0x49cd, 0x1311, 0xfc75, 0xa6a9,
0x2aac, 0x7070, 0x9f14, 0xc5c8, 0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c,
0xdf78, 0x85a4, 0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366,
0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031, 0x4af6, 0x102a,
0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3},
{0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721, 0xe5d8, 0xf963,
0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9, 0xc3a1, 0xdf1a, 0xfad7, 0xe66c,
0xb14d, 0xadf6, 0x883b, 0x9480, 0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e,
0x6de3, 0x7158, 0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872,
0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa, 0x4cf2, 0x5049,
0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3, 0xa92a, 0xb591, 0x905c, 0x8ce7,
0xdbc6, 0xc77d, 0xe2b0, 0xfe0b, 0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0,
0x5d2d, 0x4196, 0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e,
0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237, 0x30ce, 0x2c75,
0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef, 0x99e4, 0x855f, 0xa092, 0xbc29,
0xeb08, 0xf7b3, 0xd27e, 0xcec5, 0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b,
0x37a6, 0x2b1d, 0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64,
0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc, 0x2d6e, 0x31d5,
0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f, 0xc8b6, 0xd40d, 0xf1c0, 0xed7b,
0xba5a, 0xa6e1, 0x832c, 0x9f97, 0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098,
0xa555, 0xb9ee, 0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36,
0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c, 0x47e5, 0x5b5e,
0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4, 0x619c, 0x7d27, 0x58ea, 0x4451,
0x1370, 0x0fcb, 0x2a06, 0x36bd, 0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13,
0xcfde, 0xd365, 0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8,
0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920, 0xf878, 0xe4c3,
0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59, 0x1da0, 0x011b, 0x24d6, 0x386d,
0x6f4c, 0x73f7, 0x563a, 0x4a81, 0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd,
0xff10, 0xe3ab, 0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673,
0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a, 0x92f3, 0x8e48,
0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2},
{0x0000, 0x0b44, 0x1688, 0x1dcc, 0x2d10, 0x2654, 0x3b98, 0x30dc, 0x5a20, 0x5164,
0x4ca8, 0x47ec, 0x7730, 0x7c74, 0x61b8, 0x6afc, 0xb440, 0xbf04, 0xa2c8, 0xa98c,
0x9950, 0x9214, 0x8fd8, 0x849c, 0xee60, 0xe524, 0xf8e8, 0xf3ac, 0xc370, 0xc834,
0xd5f8, 0xdebc, 0x6091, 0x6bd5, 0x7619, 0x7d5d, 0x4d81, 0x46c5, 0x5b09, 0x504d,
0x3ab1, 0x31f5, 0x2c39, 0x277d, 0x17a1, 0x1ce5, 0x0129, 0x0a6d, 0xd4d1, 0xdf95,
0xc259, 0xc91d, 0xf9c1, 0xf285, 0xef49, 0xe40d, 0x8ef1, 0x85b5, 0x9879, 0x933d,
0xa3e1, 0xa8a5, 0xb569, 0xbe2d, 0xc122, 0xca66, 0xd7aa, 0xdcee, 0xec32, 0xe776,
0xfaba, 0xf1fe, 0x9b02, 0x9046, 0x8d8a, 0x86ce, 0xb612, 0xbd56, 0xa09a, 0xabde,
0x7562, 0x7e26, 0x63ea, 0x68ae, 0x5872, 0x5336, 0x4efa, 0x45be, 0x2f42, 0x2406,
0x39ca, 0x328e, 0x0252, 0x0916, 0x14da, 0x1f9e, 0xa1b3, 0xaaf7, 0xb73b, 0xbc7f,
0x8ca3, 0x87e7, 0x9a2b, 0x916f, 0xfb93, 0xf0d7, 0xed1b, 0xe65f, 0xd683, 0xddc7,
0xc00b, 0xcb4f, 0x15f3, 0x1eb7, 0x037b, 0x083f, 0x38e3, 0x33a7, 0x2e6b, 0x252f,
0x4fd3, 0x4497, 0x595b, 0x521f, 0x62c3, 0x6987, 0x744b, 0x7f0f, 0x8a55, 0x8111,
0x9cdd, 0x9799, 0xa745, 0xac01, 0xb1cd, 0xba89, 0xd075, 0xdb31, 0xc6fd, 0xcdb9,
0xfd65, 0xf621, 0xebed, 0xe0a9, 0x3e15, 0x3551, 0x289d, 0x23d9, 0x1305, 0x1841,
0x058d, 0x0ec9, 0x6435, 0x6f71, 0x72bd, 0x79f9, 0x4925, 0x4261, 0x5fad, 0x54e9,
0xeac4, 0xe180, 0xfc4c, 0xf708, 0xc7d4, 0xcc90, 0xd15c, 0xda18, 0xb0e4, 0xbba0,
0xa66c, 0xad28, 0x9df4, 0x96b0, 0x8b7c, 0x8038, 0x5e84, 0x55c0, 0x480c, 0x4348,
0x7394, 0x78d0, 0x651c, 0x6e58, 0x04a4, 0x0fe0, 0x122c, 0x1968, 0x29b4, 0x22f0,
0x3f3c, 0x3478, 0x4b77, 0x4033, 0x5dff, 0x56bb, 0x6667, 0x6d23, 0x70ef, 0x7bab,
0x1157, 0x1a13, 0x07df, 0x0c9b, 0x3c47, 0x3703, 0x2acf, 0x218b, 0xff37, 0xf473,
0xe9bf, 0xe2fb, 0xd227, 0xd963, 0xc4af, 0xcfeb, 0xa517, 0xae53, 0xb39f, 0xb8db,
0x8807, 0x8343, 0x9e8f, 0x95cb, 0x2be6, 0x20a2, 0x3d6e, 0x362a, 0x06f6, 0x0db2,
0x107e, 0x1b3a, 0x71c6, 0x7a82, 0x674e, 0x6c0a, 0x5cd6, 0x5792, 0x4a5e, 0x411a,
0x9fa6, 0x94e2, 0x892e, 0x826a, 0xb2b6, 0xb9f2, 0xa43e, 0xaf7a, 0xc586, 0xcec2,
0xd30e, 0xd84a, 0xe896, 0xe3d2, 0xfe1e, 0xf55a},
{0x0000, 0x042b, 0x0856, 0x0c7d, 0x10ac, 0x1487, 0x18fa, 0x1cd1, 0x2158, 0x2573,
0x290e, 0x2d25, 0x31f4, 0x35df, 0x39a2, 0x3d89, 0x42b0, 0x469b, 0x4ae6, 0x4ecd,
0x521c, 0x5637, 0x5a4a, 0x5e61, 0x63e8, 0x67c3, 0x6bbe, 0x6f95, 0x7344, 0x776f,
0x7b12, 0x7f39, 0x8560, 0x814b, 0x8d36, 0x891d, 0x95cc, 0x91e7, 0x9d9a, 0x99b1,
0xa438, 0xa013, 0xac6e, 0xa845, 0xb494, 0xb0bf, 0xbcc2, 0xb8e9, 0xc7d0, 0xc3fb,
0xcf86, 0xcbad, 0xd77c, 0xd357, 0xdf2a, 0xdb01, 0xe688, 0xe2a3, 0xeede, 0xeaf5,
0xf624, 0xf20f, 0xfe72, 0xfa59, 0x02d1, 0x06fa, 0x0a87, 0x0eac, 0x127d, 0x1656,
0x1a2b, 0x1e00, 0x2389, 0x27a2, 0x2bdf, 0x2ff4, 0x3325, 0x370e, 0x3b73, 0x3f58,
0x4061, 0x444a, 0x4837, 0x4c1c, 0x50cd, 0x54e6, 0x589b, 0x5cb0, 0x6139, 0x6512,
0x696f, 0x6d44, 0x7195, 0x75be, 0x79c3, 0x7de8, 0x87b1, 0x839a, 0x8fe7, 0x8bcc,
0x971d, 0x9336, 0x9f4b, 0x9b60, 0xa6e9, 0xa2c2, 0xaebf, 0xaa94, 0xb645, 0xb26e,
0xbe13, 0xba38, 0xc501, 0xc12a, 0xcd57, 0xc97c, 0xd5ad, 0xd186, 0xddfb, 0xd9d0,
0xe459, 0xe072, 0xec0f, 0xe824, 0xf4f5, 0xf0de, 0xfca3, 0xf888, 0x05a2, 0x0189,
0x0df4, 0x09df, 0x150e, 0x1125, 0x1d58, 0x1973, 0x24fa, 0x20d1, 0x2cac, 0x2887,
0x3456, 0x307d, 0x3c00, 0x382b, 0x4712, 0x4339, 0x4f44, 0x4b6f, 0x57be, 0x5395,
0x5fe8, 0x5bc3, 0x664a, 0x6261, 0x6e1c, 0x6a37, 0x76e6, 0x72cd, 0x7eb0, 0x7a9b,
0x80c2, 0x84e9, 0x8894, 0x8cbf, 0x906e, 0x9445, 0x9838, 0x9c13, 0xa19a, 0xa5b1,
0xa9cc, 0xade7, 0xb136, 0xb51d, 0xb960, 0xbd4b, 0xc272, 0xc659, 0xca24, 0xce0f,
0xd2de, 0xd6f5, 0xda88, 0xdea3, 0xe32a, 0xe701, 0xeb7c, 0xef57, 0xf386, 0xf7ad,
0xfbd0, 0xfffb, 0x0773, 0x0358, 0x0f25, 0x0b0e, 0x17df, 0x13f4, 0x1f89, 0x1ba2,
0x262b, 0x2200, 0x2e7d, 0x2a56, 0x3687, 0x32ac, 0x3ed1, 0x3afa, 0x45c3, 0x41e8,
0x4d95, 0x49be, 0x556f, 0x5144, 0x5d39, 0x5912, 0x649b, 0x60b0, 0x6ccd, 0x68e6,
0x7437, 0x701c, 0x7c61, 0x784a, 0x8213, 0x8638, 0x8a45, 0x8e6e, 0x92bf, 0x9694,
0x9ae9, 0x9ec2, 0xa34b, 0xa760, 0xab1d, 0xaf36, 0xb3e7, 0xb7cc, 0xbbb1, 0xbf9a,
0xc0a3, 0xc488, 0xc8f5, 0xccde, 0xd00f, 0xd424, 0xd859, 0xdc72, 0xe1fb, 0xe5d0,
0xe9ad, 0xed86, 0xf157, 0xf57c, 0xf901, 0xfd2a},
{0x0000, 0x9fd5, 0x37bb, 0xa86e, 0x6f76, 0xf0a3, 0x58cd, 0xc718, 0xdeec, 0x4139,
0xe957, 0x7682, 0xb19a, 0x2e4f, 0x8621, 0x19f4, 0xb5c9, 0x2a1c, 0x8272, 0x1da7,
0xdabf, 0x456a, 0xed04, 0x72d1, 0x6b25, 0xf4f0, 0x5c9e, 0xc34b, 0x0453, 0x9b86,
0x33e8, 0xac3d, 0x6383, 0xfc56, 0x5438, 0xcbed, 0x0cf5, 0x9320, 0x3b4e, 0xa49b,
0xbd6f, 0x22ba, 0x8ad4, 0x1501, 0xd219, 0x4dcc, 0xe5a2, 0x7a77, 0xd64a, 0x499f,
0xe1f1, 0x7e24, 0xb93c, 0x26e9, 0x8e87, 0x1152, 0x08a6, 0x9773, 0x3f1d, 0xa0c8,
0x67d0, 0xf805, 0x506b, 0xcfbe, 0xc706, 0x58d3, 0xf0bd, 0x6f68, 0xa870, 0x37a5,
0x9fcb, 0x001e, 0x19ea, 0x863f, 0x2e51, 0xb184, 0x769c, 0xe949, 0x4127, 0xdef2,
0x72cf, 0xed1a, 0x4574, 0xdaa1, 0x1db9, 0x826c, 0x2a02, 0xb5d7, 0xac23, 0x33f6,
0x9b98, 0x044d, 0xc355, 0x5c80, 0xf4ee, 0x6b3b, 0xa485, 0x3b50, 0x933e, 0x0ceb,
0xcbf3, 0x5426, 0xfc48, 0x639d, 0x7a69, 0xe5bc, 0x4dd2, 0xd207, 0x151f, 0x8aca,
0x22a4, 0xbd71, 0x114c, 0x8e99, 0x26f7, 0xb922, 0x7e3a, 0xe1ef, 0x4981, 0xd654,
0xcfa0, 0x5075, 0xf81b, 0x67ce, 0xa0d6, 0x3f03, 0x976d, 0x08b8, 0x861d, 0x19c8,
0xb1a6, 0x2e73, 0xe96b, 0x76be, 0xded0, 0x4105, 0x58f1, 0xc724, 0x6f4a, 0xf09f,
0x3787, 0xa852, 0x003c, 0x9fe9, 0x33d4, 0xac01, 0x046f, 0x9bba, 0x5ca2, 0xc377,
0x6b19, 0xf4cc, 0xed38, 0x72ed, 0xda83, 0x4556, 0x824e, 0x1d9b, 0xb5f5, 0x2a20,
0xe59e, 0x7a4b, 0xd225, 0x4df0, 0x8ae8, 0x153d, 0xbd53, 0x2286, 0x3b72, 0xa4a7,
0x0cc9, 0x931c, 0x5404, 0xcbd1, 0x63bf, 0xfc6a, 0x5057, 0xcf82, 0x67ec, 0xf839,
0x3f21, 0xa0f4, 0x089a, 0x974f, 0x8ebb, 0x116e, 0xb900, 0x26d5, 0xe1cd, 0x7e18,
0xd676, 0x49a3, 0x411b, 0xdece, 0x76a0, 0xe975, 0x2e6d, 0xb1b8, 0x19d6, 0x8603,
0x9ff7, 0x0022, 0xa84c, 0x3799, 0xf081, 0x6f54, 0xc73a, 0x58ef, 0xf4d2, 0x6b07,
0xc369, 0x5cbc, 0x9ba4, 0x0471, 0xac1f, 0x33ca, 0x2a3e, 0xb5eb, 0x1d85, 0x8250,
0x4548, 0xda9d, 0x72f3, 0xed26, 0x2298, 0xbd4d, 0x1523, 0x8af6, 0x4dee, 0xd23b,
0x7a55, 0xe580, 0xfc74, 0x63a1, 0xcbcf, 0x541a, 0x9302, 0x0cd7, 0xa4b9, 0x3b6c,
0x9751, 0x0884, 0xa0ea, 0x3f3f, 0xf827, 0x67f2, 0xcf9c, 0x5049, 0x49bd, 0xd668,
0x7e06, 0xe1d3, 0x26cb, 0xb91e, 0x1170, 0x8ea5},
{0x0000, 0x81bf, 0x0b6f, 0x8ad0, 0x16de, 0x9761, 0x1db1, 0x9c0e, 0x2dbc, 0xac03,
0x26d3, 0xa76c, 0x3b62, 0xbadd, 0x300d, 0xb1b2, 0x5b78, 0xdac7, 0x5017, 0xd1a8,
0x4da6, 0xcc19, 0x46c9, 0xc776, 0x76c4, 0xf77b, 0x7dab, 0xfc14, 0x601a, 0xe1a5,
0x6b75, 0xeaca, 0xb6f0, 0x374f, 0xbd9f, 0x3c20, 0xa02e, 0x2191, 0xab41, 0x2afe,
0x9b4c, 0x1af3, 0x9023, 0x119c, 0x8d92, 0x0c2d, 0x86fd, 0x0742, 0xed88, 0x6c37,
0xe6e7, 0x6758, 0xfb56, 0x7ae9, 0xf039, 0x7186, 0xc034, 0x418b, 0xcb5b, 0x4ae4,
0xd6ea, 0x5755, 0xdd85, 0x5c3a, 0x65f1, 0xe44e, 0x6e9e, 0xef21, 0x732f, 0xf290,
0x7840, 0xf9ff, 0x484d, 0xc9f2, 0x4322, 0xc29d, 0x5e93, 0xdf2c, 0x55fc, 0xd443,
0x3e89, 0xbf36, 0x35e6, 0xb459, 0x2857, 0xa9e8, 0x2338, 0xa287, 0x1335, 0x928a,
0x185a, 0x99e5, 0x05eb, 0x8454, 0x0e84, 0x8f3b, 0xd301, 0x52be, 0xd86e, 0x59d1,
0xc5df, 0x4460, 0xceb0, 0x4f0f, 0xfebd, 0x7f02, 0xf5d2, 0x746d, 0xe863, 0x69dc,
0xe30c, 0x62b3, 0x8879, 0x09c6, 0x8316, 0x02a9, 0x9ea7, 0x1f18, 0x95c8, 0x1477,
0xa5c5, 0x247a, 0xaeaa, 0x2f15, 0xb31b, 0x32a4, 0xb874, 0x39cb, 0xcbe2, 0x4a5d,
0xc08d, 0x4132, 0xdd3c, 0x5c83, 0xd653, 0x57ec, 0xe65e, 0x67e1, 0xed31, 0x6c8e,
0xf080, 0x713f, 0xfbef, 0x7a50, 0x909a, 0x1125, 0x9bf5, 0x1a4a, 0x8644, 0x07fb,
0x8d2b, 0x0c94, 0xbd26, 0x3c99, 0xb649, 0x37f6, 0xabf8, 0x2a47, 0xa097, 0x2128,
0x7d12, 0xfcad, 0x767d, 0xf7c2, 0x6bcc, 0xea73, 0x60a3, 0xe11c, 0x50ae, 0xd111,
0x5bc1, 0xda7e, 0x4670, 0xc7cf, 0x4d1f, 0xcca0, 0x266a, 0xa7d5, 0x2d05, 0xacba,
0x30b4, 0xb10b, 0x3bdb, 0xba64, 0x0bd6, 0x8a69, 0x00b9, 0x8106, 0x1d08, 0x9cb7,
0x1667, 0x97d8, 0xae13, 0x2fac, 0xa57c, 0x24c3, 0xb8cd, 0x3972, 0xb3a2, 0x321d,
0x83af, 0x0210, 0x88c0, 0x097f, 0x9571, 0x14ce, 0x9e1e, 0x1fa1, 0xf56b, 0x74d4,
0xfe04, 0x7fbb, 0xe3b5, 0x620a, 0xe8da, 0x6965, 0xd8d7, 0x5968, 0xd3b8, 0x5207,
0xce09, 0x4fb6, 0xc566, 0x44d9, 0x18e3, 0x995c, 0x138c, 0x9233, 0x0e3d, 0x8f82,
0x0552, 0x84ed, 0x355f, 0xb4e0, 0x3e30, 0xbf8f, 0x2381, 0xa23e, 0x28ee, 0xa951,
0x439b, 0xc224, 0x48f4, 0xc94b, 0x5545, 0xd4fa, 0x5e2a, 0xdf95, 0x6e27, 0xef98,
0x6548, 0xe4f7, 0x78f9, 0xf946, 0x7396, 0xf229}
};
unsigned crc16iso_iec_14443_3_a_byte(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
crc &= 0xffff;
while (len--)
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
return crc;
}
// This code assumes that integers are stored little-endian.
unsigned crc16iso_iec_14443_3_a_word(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
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;
}
Related
implicit conversion changes signedness: 'int' to 'unsigned long' in c using keil
I'm new in the programingo of STM32, I've whatched aome tutorials, but whe I've put in practice the last, keil give me some warnings (the tutorial is about of GPIO INPUT OUTPUT LIBRARY FROM SCRATCH). the warnigs are: gpi_drive.c(35): warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion] *CR |= ((dir<<(pin*4)) | (opt<<(pin*4+2))); ~~ ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ gpi_drive.c(34): warning: variable 'CR' may be uninitialized when used here [-Wconditional-uninitialized] *CR &= ~(0xfu<<(pin)*4); /*Reset the target pin*/ ^~ gpi_drive.c(7): note: initialize the variable 'CR' to silence this warning volatile unsigned long * CR; #include "gpi_drive.h" void init_GP(unsigned short port, unsigned short pin, unsigned short dir, unsigned short opt) { volatile unsigned long * CR; unsigned short offset = 0x00; if (pin > 7) { pin -=8; offset = 0x01; } if (port == 1) { RCC_APB2ENR |= 4; /*Enabling port A*/ CR = (volatile unsigned long *) (&GPIO_A + offset); } if (port == 2) { RCC_APB2ENR |= 8; /*Enabling port B*/ CR = (volatile unsigned long *) (&GPIO_B + offset); } if (port == 3) { RCC_APB2ENR |= 0x10; /*Enabling port C*/ CR = (volatile unsigned long *) (&GPIO_C + offset); } *CR &= ~(0xfu<<(pin)*4); /*Reset the target pin*/ //this is the line 34 *CR |= ((dir<<(pin*4u)) | (opt<<(pin*4+2))); //this is the line 35 } This is the code that I have, I don't know how to make that the numbers of the rows appears, sorry for this. And if you need more information let know, and thak you so much
Allocating return pointer in child function with malloc() but not getting return data
Can someone please help me understand why my printf statement in the main loop prints nothing? If I add a regular hello world printf statement in the main loop it also does not print anything to the console. However, if I comment out the line that prints the returned data, this hello world print statement does work. I have tried multiple methods of passing the string data between the two functions with no luck. char * getADCValue() { uint8_t id; int32_t adc; int32_t volt; uint8_t i; uint8_t ch_num; int32_t iTemp; uint8_t buf[3]; bcm2835_spi_begin(); bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST ); bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_1024); bcm2835_gpio_fsel(SPICS, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(SPICS, HIGH); bcm2835_gpio_fsel(DRDY, BCM2835_GPIO_FSEL_INPT); bcm2835_gpio_set_pud(DRDY, BCM2835_GPIO_PUD_UP); id = ADS1256_ReadChipID(); /*if (id != 3) { printf("Error, ASD1256 Chip ID = 0x%d", (int)id); } else { printf("Ok, ASD1256 Chip ID = 0x%d", (int)id); }*/ ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_15SPS); ADS1256_StartScan(0); while((ADS1256_Scan() == 0)); adc = ADS1256_GetAdc(0); volt = (adc * 100) / 167; buf[0] = ((uint32_t)adc >> 16) & 0xFF; buf[1] = ((uint32_t)adc >> 8) & 0xFF; buf[2] = ((uint32_t)adc >> 0) & 0xFF; iTemp = volt; /* uV */ char * return_data = malloc(1024); if (!return_data) return NULL; sprintf(return_data, "%ld.%01ld V", iTemp /1000000, (iTemp%1000000)/100000); return return_data; } int main() { char * returnValue = getADCValue(); printf("Voltage Value: %s", returnValue); free(returnValue); return 0; }
Thanks for the suggestions guys. It ended up being the bcm library calls as suggested. Somehow lost my bcm2835 init call and this resulted in something going haywire with my file descriptors.
No output for Embedded application with PIC12, MPLAB and UART
I am working on RGB LED project and that's controlled by a PIC12F1572. The software that I am using is MPLAB IDE with the HiTech C compiler. The plan is to use serial communication to send LED RGB combination data commands to the PIC to be stored in a variable that will make it perform the LED blink and glowing I have been able to establish UART communication.Every function or step I code is right by syntax and works on linux command line terminal if I compile.. And it fails if I try to simulate using register injection in MPLAB.I wanted to run it in simulation also (anyone knows how register injection actuallly works in MPLAB?) The problem I face together when I try to debug . it compiles but doesn't work here is my code : Any idea or hint about the problem will be highly appreciated. I personally fee that placing the code [hierarchical way] may be wrong Thanks! #include <xc.h> #include "mcc.h" #include "LED.h" #include "tmr0.h" #include "interrupt_manager.h" void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color); void main(void) { uint8_t data, i, j; uint16_t R_value, G_value, B_value; uint8_t value; uint8_t RX_Buffer[FRAMESIZE] ,RGB_data[6] ,HEX_data[6]; // initialize the device SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts while (1) { // EUSART_Write(0x61); while (!RCIF) { data = EUSART_Read(); // Read received character for (i = 0; i < FRAMESIZE; i++) { RX_Buffer[i] = data; } EUSART_Write(data); } //check if any data is received for (j = 0; j = 5; j++) // get the RGB value in the separate array { RGB_data[j] = RX_Buffer[j + 3]; HEX_data[value] = RGB_data[j] / 16; } if (RX_Buffer[0] == 'R' && RX_Buffer[FRAMESIZE - 1] == '\n') { //ASCII to HEX separate values // uint32_t number = (uint32_t)strtol(HEX_data, NULL, 16); // R_value = number >>16; // G_value = (number & 0xffff) >> 8; // B_value = (number & 0x0000FF); R_value = (uint16_t) atoh(HEX_data[0], HEX_data[1]); G_value = (uint16_t) atoh(HEX_data[2], HEX_data[3]); B_value = (uint16_t) atoh(HEX_data[4], HEX_data[5]); } SetLedColor(R_value, G_value, B_value); } } void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color) { if (R_color == 0xFF) { LATAbits.LATA2 = 1; } else { LATAbits.LATA2 = 0; } if (G_color == 0xFF) { LATAbits.LATA4 = 1; } else { LATAbits.LATA4 = 0; } if (B_color == 0xFF) { LATAbits.LATA5 = 1; } else { LATAbits.LATA5 = 0; } }
So till the receiving the UART frame and echoed back and from the storing data make LED blink , I am able to succeed and this is what I wanted for primary step here by hierarchical way #include "mcc_generated_files/mcc.h" #include <stdlib.h> #include <stdio.h> #include "atoh.h" #include "LED.h" #define _XTAL_FREQ 16000000 #define FRAMESIZE 19 void main(void) { uint8_t data,i,j,got_char; uint8_t R_value, G_value ,B_value; uint8_t value; uint8_t RX_Buffer[FRAMESIZE]; uint8_t RGB_data[6] ,HEX_data[6]; // initialize the device SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts while (1) { if (EUSART_DataReady) { for (i = 0; i<FRAMESIZE; i++) { RX_Buffer[i] = EUSART_Read(); if (RX_Buffer[i] == '\n') break; } RX_Buffer[i] = '\n'; //append '\n' at the end of stoaring array for detection of frame RX_Buffer[i+1] = '\0'; // End of an array EUSART_WriteAnArrayOfBytes(RX_Buffer); if(RX_Buffer[0]=='R' && RX_Buffer[FRAMESIZE-2] == '\n') //check for correct frame { LATAbits.LATA2 = 1; __delay_ms(2000); LATAbits.LATA2 = 0; __delay_ms(1000); } } }
Erasing external FLASH
I'm working with a MCF51EM256 Freescale microcontroller and I've some problems to store data in the external flash memory to make it persistent. I need to store this struct: typedef struct { ui64_s Ea_ps; ui64_s Ea_ng; ui64_s Er_q1; ui64_s Er_q2; ui64_s Er_q3; ui64_s Er_q4; uint16 F_ea; uint16 F_er; }Ws_EnergyAcc64; Where: typedef union{ uint64 v; uint32 p[2]; } ui64_s; and: typedef unsigned long long int uint64; typedef unsigned long int uint32; typedef unsigned short int uint16; In order to do this, I've implemented this function: void Save_Flash_WsEnergyAcc(long addr, Ws_EnergyAcc64* Acc) { // WsEnergyAcc struct needs 56 bytes in Flash uint32 F_ea_32 = (uint32) Acc->F_ea; uint32 F_er_32 = (uint32) Acc->F_er; Flash_Erase(addr); Flash_Erase(addr + 4); Flash_Burst(addr, 2, Acc->Ea_ps.p); Flash_Erase(addr + 8); Flash_Erase(addr + 12); Flash_Burst(addr + 8, 2, Acc->Ea_ng.p); Flash_Erase(addr + 16); Flash_Erase(addr + 20); Flash_Burst(addr + 16, 2, Acc->Er_q1.p); Flash_Erase(addr + 24); Flash_Erase(addr + 28); Flash_Burst(addr + 24, 2, Acc->Er_q2.p); Flash_Erase(addr + 32); Flash_Erase(addr + 36); Flash_Burst(addr + 32, 2, Acc->Er_q3.p); Flash_Erase(addr + 40); Flash_Erase(addr + 44); Flash_Burst(addr + 40, 2, Acc->Er_q4.p); Flash_Erase(addr + 48); Flash_Burst(addr + 48, 2, &F_ea_32); Flash_Erase(addr + 52); Flash_Burst(addr + 52, 2, &F_er_32); } Where "Flash_Burst" and "Flash_Erase": #define FLASH_MASS_ERASE_CMD 0x41 #define FLASH_ERASE_CMD 0x40 #define FLASH_PROGRAM_CMD 0x20 #define FLASH_BURST_CMD 0x25 /* Macros to call the function using the different features */ #define Flash_Erase(Address) \ Flash_Cmd((UINT32)Address, (UINT16)1, (UINT32*)CUSTOM_ROM_ADDRESS, FLASH_ERASE_CMD) #define Flash_Burst(Address, Size, DataPtr) \ Flash_Cmd((UINT32)Address, (UINT16)Size, (UINT32*)DataPtr, FLASH_BURST_CMD) UINT8 /*far*/ Flash_Cmd(UINT32 FlashAddress, UINT16 FlashDataCounter, UINT32 *pFlashDataPtr, UINT8 FlashCommand) { /* Check to see if FACCERR or PVIOL is set */ if (FSTAT &0x30) { /* Clear Flags if set*/ FSTAT = 0x30; } if (FlashDataCounter) { do { /* Wait for the Last Busrt Command to complete */ while(!(FSTAT&FSTAT_FCBEF_MASK)){};/*wait until termination*/ /* Write Data into Flash*/ (*((volatile unsigned long *)(FlashAddress))) = *pFlashDataPtr; FlashAddress += 4; pFlashDataPtr++; /* Write Command */ FCMD = FlashCommand; /* Put FCBEF at 1 */ FSTAT = FSTAT_FCBEF_MASK; asm (NOP); asm (NOP); asm (NOP); /* Check if Flash Access Error or Protection Violation Error are Set */ if (FSTAT&0x30) { /* If so, finish the function returning 1 to indicate error */ return (1); } }while (--FlashDataCounter); } /* wait for the last command to complete */ while ((FSTAT&FSTAT_FCCF_MASK)==0){};/*wait until termination*/ /* Return zero to indicate that the function executed OK */ return (0); } I also defined: extern unsigned char __CUSTOM_ROM[]; extern unsigned char __CUSTOM_ROM_SIZE[]; #define CUSTOM_ROM_ADDRESS (unsigned long int)__CUSTOM_ROM #define CUSTOM_ROM_SIZE (unsigned long int)__CUSTOM_ROM_SIZE I don't understand what is CUSTOM_ROM_ADDRESS, and it causes a link error in my project: C:/Freescale/CW MCU v10.6.4/MCU/ColdFire_Tools/Command_Line_Tools/mwldmcf|Linker|Error >Undefined : "__CUSTOM_ROM" I think it could be the data wich is stored in the erased address, and I tryed to do something like this (instead Flash_Erase(address)): void EraseFlash(long addr) { uint32 eraseData = 0xFFFFFFFF; Flash_Cmd((uint32)addr, (uint16)1, (uint32*)&eraseData, 0x40); } It works in the first execution of "Save_Flash_WsEnergyAcc", but I cannot explain why it blocks the MCU the next times. ¿Can someone tell me what I'm doing wrong? Thank you all!
The MCF51EM256 Freescale microcontroller only allows erase flash memory by 1024 bytes sectors. If I call the Erase function each time I want to write the flash memory the MCU will be blocked.
Combine 2 enums with math operators
I have this enums: enum bus { MEDIA_BUS_UNKNOWN, MEDIA_BUS_VIRTUAL = 1 << 1, MEDIA_BUS_PCI = 1 << 2, MEDIA_BUS_USB = 1 << 3, }; and: enum bus get_bus( char *sys ) { FILE *fd; char file[PATH_MAX]; char s[1024]; if(!strcmp(sys, "/sys/devices/virtual")) return MEDIA_BUS_VIRTUAL; snprintf(file, PATH_MAX, "%s/modalias", sys); fd = fopen(file, "r"); if(!fd) return MEDIA_BUS_UNKNOWN; if(!fgets(s, sizeof(s), fd)) { fclose(fd); return MEDIA_BUS_UNKNOWN; } fclose(fd); if(!strncmp(s, "pci", 3)) return MEDIA_BUS_PCI; if(!strncmp(s, "usb", 3)) return MEDIA_BUS_USB; return MEDIA_BUS_UNKNOWN; } I want to create a function to return device(s) with pci or usb bus: const char *get_device(const enum bus desired_bus) { enum bus bus; ................................................... for( i = 0; i < md->md_size; i++, md_ptr++ ) { bus = get_bus( md_ptr->sys ); if( ( bus & desired_bus ) == desired_bus ) return md_ptr->node; } and call this function to return device(s): get_device(const enum bus desired_bus) if request is for devices with pci or usb bus type: get_device(MEDIA_BUS_PCI | MEDIA_BUS_USB); It is possible to use math operators for enum?
Sure you can use math operators, but I believe you're looking for bitwise operations, right?. In this case, you enum members values need to be power of two, sou you will be able to do test like this: if(desired_bus & MEDIA_BUS_PCI) if a previously desired_bus |= MEDIA_BUS_PCI was done the if will have MEDIA_BUS_PCI value, so if is true meaning the bit is set. code example: enum bus { MEDIA_BUS_UNKNOWN, MEDIA_BUS_VIRTUAL = 1 << 1, MEDIA_BUS_PCI = 1 << 2, MEDIA_BUS_USB = 1 << 3, }; /* set flags */ desired_bus |= (MEDIA_BUS_PCI | MEDIA_BUS_USB); and then: /* test if flag MEDIA_BUS_PCI was requested.. */ if(desired_bus & MEDIA_BUS_PCI) In case of it is not set, we get a 0 value that match to our MEDIA_BUS_UNKNOWN value that I think that is a nice to mean error. EDIT A more complete working C example: enum bus { MEDIA_BUS_UNKNOWN, MEDIA_BUS_VIRTUAL = 1 << 1, MEDIA_BUS_PCI = 1 << 2, MEDIA_BUS_USB = 1 << 3, }; enum bus get_bus( const char *sys ); int main(int argc, char *argv[]) { const char *sym = argv[1]; enum bus b = get_bus(sym); if(b & MEDIA_BUS_VIRTUAL) printf("MEDIA_BUS_VIRTUAL requested\n"); if(b & MEDIA_BUS_USB) printf("MEDIA_BUS_USB requested\n"); return 0; } enum bus get_bus( const char *sys ) { if(!strcmp("pci", sys)) return MEDIA_BUS_VIRTUAL; if(!strcmp("usb", sys)) return MEDIA_BUS_USB; if(!strcmp("pci&usb", sys)) return MEDIA_BUS_VIRTUAL | MEDIA_BUS_USB; return MEDIA_BUS_UNKNOWN; } If you invoke the compiled program with: a.exe usb: will output: MEDIA_BUS_USB requested a.exe "pci&usb" will output: MEDIA_BUS_VIRTUAL requested MEDIA_BUS_USB requested NOTE: You might need to use a type like unsigned instead of enum bus (that highest size is int) to hold a set of enum bus values.
Yes, but for your case, you'll want to make sure that each combination of enum-values is unique, and easily decomposed. To do this, you should make each one a distinct power of two: enum bus { MEDIA_BUS_UNKNOWN = 1, MEDIA_BUS_VIRTUAL = 2, MEDIA_BUS_PCI = 4, MEDIA_BUS_USB = 8, }; (You can then test for a match by writing e.g. desired_bus & MEDIA_BUS_PCI.)
It's a matter of personal taste, but I find using enums to hold bitmasks rather misleading. I would rather do it with #defines, to be able to define mask combinations easily. For instance: #define MEDIA_BUS_UNKNOWN 0x00 #define MEDIA_BUS_GPU 0x10 #define MEDIA_BUS_CPU 0x20 #define MEDIA_BUS_VIRTUAL (0x1 | MEDIA_BUS_CPU) #define MEDIA_BUS_PCI (0x2 | MEDIA_BUS_CPU) #define MEDIA_BUS_USB (0x3 | MEDIA_BUS_CPU) #define MEDIA_BUS_AGP (0x4 | MEDIA_BUS_GPU) #define MEDIA_BUS_PCIE (0x5 | MEDIA_BUS_GPU) #define MEDIA_BUS_PU_MASK 0x30 // to isolate the PU type #define MEDIA_BUS_TYPE_MASK 0x0F // to isolate the bus type typedef int bus_type; (a rather silly example, but I could not find better without straying too far from the OP's question)