implicit conversion changes signedness: 'int' to 'unsigned long' in c using keil - c

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

Related

Computing CRC16 with reflected / bit reversed input in 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;
}

Error[Pe513]: a value of type "void (*)(void *, CO_CANrxMsg_t *)" cannot be assigned to an entity of type "void (*)(void *, CanRxMsgTypeDef *)"

I try to compile CanOpenNode project. There is an error that I can not resolve, Can anyone help. Project is in "C".
Error:
Error[Pe513]: a value of type "void (*)(void *, CO_CANrxMsg_t *)" cannot be assigned to an entity of type "void (*)(void *, CanRxMsgTypeDef *)"
Error Line:
buffer->pFunct = pFunct;
Code:
CO_ReturnError_t CO_CANrxBufferInit(
CO_CANmodule_t *CANmodule,
uint16_t index,
uint16_t ident,
uint16_t mask,
bool_t rtr,
void *object,
void (*pFunct)(void *object, CO_CANrxMsg_t *message))
{
CO_ReturnError_t ret = CO_ERROR_NO;
//CAN_FilterConfTypeDef sFilterConfig;
uint16_t RXF, RXM;
if((CANmodule!=NULL) && (object!=NULL) && (pFunct!=NULL) && (index < CANmodule->rxSize)){
/* buffer, which will be configured */
CO_CANrx_t *buffer = &CANmodule->rxArray[index];
/* Configure object variables */
buffer->object = object;
buffer->pFunct = pFunct;
/* CAN identifier and CAN mask, bit aligned with CAN module. Different on different microcontrollers. */
//CAN identifier and CAN mask, bit aligned with CAN module registers
RXF = (ident & 0x07FF) << 2;
if (rtr) RXF |= 0x02;
RXM = (mask & 0x07FF) << 2;
RXM |= 0x02;
//configure filter and mask
if (RXF != buffer->ident || RXM != buffer->mask)
{
buffer->ident = RXF;
buffer->mask = RXM;
}
ret = CO_ERROR_NO;
}
else{
ret = CO_ERROR_ILLEGAL_ARGUMENT;
}
return ret;
}

errors encountered while interfacing eeprom with microcontroller

I am not an expert c programmers and in the c code I m getting these kinds of errors. I got many and tried to sort them out but can not solve these. The code is as follows:
/*
* EEPROM.c
* interfacing microchip 24aa64f IC with atmel sam4e
*/
#include <asf.h>
#include "EEPROM_I2C.h"
#define DEVICE_ADDRESS 0x50 // 7-bit device identifier 0101000, (refer datasheet)
//#define EEPROM_NAME 24AA6F
#define I2C_FAST_MODE_SPEED 400000//TWI_BUS_CLOCK 400KHz
#define TWI_CLK_DIVIDER 2
#define TWI_CLK_DIV_MIN 7
#define TWI_CLK_CALC_ARGU 4
#define TWI_CLK_DIV_MAX 0xFF
/*************************** Main function ******************************/
int eeprom_main( void )
{
struct micro24 ptMicro24 ;
typedef struct twi_options twi_options_t;
typedef struct Twi_registers Twi;
char TxBuffer[128] ;
char RxBuffer[128] ;
int BufferIndex;
unsigned int PageCount;
unsigned int error = 0 ;
unsigned int i;
ptMicro24.PageSize = 32;
ptMicro24.NumOfPage = 128;
ptMicro24.EepromSize = 128*32;
ptMicro24.SlaveAddress = DEVICE_ADDRESS;
ptMicro24.EepromName = 64;
/***************************** CLOCK SETTINGS TO GET 400KHz **********************
* Set the I2C bus speed in conjunction with the clock frequency.
* param p_twi Pointer to a TWI instance.
* return value PASS\Fail New speed setting is accepted\rejected
**********************************************************************************/
uint32_t twi_set_speed(struct Twi_registers *Twi, uint32_t ul_speed, uint32_t ul_mck)
//uint32_t twi_set_speed(Twi *p_twi, uint32_t ul_speed, uint32_t ul_mck)
{
uint32_t ckdiv = 0; //clock divider is used to increase both TWCK high and low periods (16-18)
uint32_t c_lh_div; //CHDIV (0-7) and CLDIV (8-15)
if (ul_speed > I2C_FAST_MODE_SPEED) { //ul_speed is the desired I2C bus speed
return FAIL;
}
c_lh_div = ul_mck / (ul_speed * TWI_CLK_DIVIDER) - TWI_CLK_CALC_ARGU; //ul_mck main clock of the device
/* cldiv must fit in 8 bits, ckdiv must fit in 3 bits */
while ((c_lh_div > TWI_CLK_DIV_MAX) && (ckdiv < TWI_CLK_DIV_MIN))
{
ckdiv++; // Increase clock divider
c_lh_div /= TWI_CLK_DIVIDER; //Divide cldiv value
}
/* set clock waveform generator register */
Twi->TWI_CWGR =
TWI_CWGR_CLDIV(c_lh_div) | TWI_CWGR_CHDIV(c_lh_div) |
TWI_CWGR_CKDIV(ckdiv);
return PASS;
}
/************************************ Initialize TWI master mode ************************
* Set the control register TWI_CR by MSEN and SVDIS
* param p_opt Options for initializing the TWI module
* return TWI_SUCCESS if initialization is complete
* twi_options... structure contains clock speed, master clock, chip and smbus
*****************************************************************************************/
uint32_t twi_master_start(struct Twi_registers *Twi, struct twi_options_t *twi_options_t)
//uint32_t twi_master_start(Twi *p_twi, const twi_options_t *p_opt)
{
uint32_t status = TWI_SUCCESS; // status success return code is 0
// Enable master mode and disable slave mode in TWI_CR
Twi -> TWI_CR_START = TWI_CR_START;
Twi->TWI_CR_MSEN = TWI_CR_MSEN; // Set Master Enable bit
Twi->TWI_CR_SVDIS = TWI_CR_SVDIS; // Set Slave Disable bit
/* Select the speed */
//new//if (twi_set_speed(Twi->TWI_SR, twi_options_t->speed, twi_options_t->master_clk) == FAIL)
//if (twi_set_speed(Twi, twi_options_t->speed, twi_options_t->master_clk) == FAIL)
//{
//status = TWI_INVALID_ARGUMENT; /* The desired speed setting is rejected */
//}
if (twi_options_t->smbus == 0)
{
Twi->TWI_CR_QUICK == 0;
status = TWI_INVALID_ARGUMENT;
}
else
if (twi_options_t->smbus == 1)
{
Twi->TWI_CR_QUICK == 1;
status = TWI_SUCCESS;
}
return status;
}
/***************************** WriteByte Function ********************************
This function uses a two bytes internal address (IADR) along with
Internal word address of eeprom.
Return Value: None
***********************************************************************************/
void WriteByte (struct micro24 *ptMicro24, char Data2Write,
unsigned int Address)
//Data2Write is the data to be written n the eeprom
//struct <micro24 *ptMicro24> : Structure of Microchip 24AA Two-wire Eeprom
//unsigned int Address>: Address where to write
{
unsigned int WordAddress;
unsigned int SlaveAddress;
unsigned char p0=0;
TWI_CR_START ==1;
if (ptMicro24->EepromName == 64 )
{
if ( Address > 0xFFFF)
{
p0 = 1;
/* Mask the 17th bit to get the 16th LSB */
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptMicro24->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptMicro24->SlaveAddress ;
WordAddress = Address ;
}
}
TWI_CR_STOP ==1;
//TWI_WriteSingleIadr(TWI_IADR_IADR,SlaveAddress, WordAddress,
// TWI_MMR_IADRSZ_2_BYTE, &Data2Write); // declared as extern
// to write to internal address, utilizing internal address and master mode register
//}
/******************** Increase Speed Function *****************************
* TWI is accessed without calling TWI functions
/***************************************************************************/
int NumOfBytes, Count;
int status;
uint32_t Buffer;
/* Enable Master Mode of the TWI */
TWI_CR_MSEN == 1;
// Twi.TWI_CR_MSEN ==1;
//TWI_CR->TWI_CR_MSEN = TWI_CR_MSEN ;
/* Set the TWI Master Mode Register */
Twi->TWI_MMR = (SlaveAddress & (~TWI_MMR_MREAD) | (TWI_MMR_IADRSZ_2_BYTE));
/* Set the internal address to access the wanted page */
Twi -> TWI_IADR = WordAddress ;
/* Wait until TXRDY is high to transmit the next data */
status = TWI_SR_TXRDY;
while (!(status & TWI_SR_TXRDY))
status = TWI_SR_TXRDY;
/* Send the buffer to the page */
for (Count=0; Count < NumOfBytes ;Count++ )
{
Twi ->TWI_THR_TXDATA = Buffer++;
/* Wait until TXRDY is high to transmit the next data */
status = TWI_SR_TXRDY;
while (!(status & TWI_SR_TXRDY))
status = TWI_SR_TXRDY;
}
/* Wait for the Transmit complete is set */
status = TWI_SR_TXCOMP;
while (!(status & TWI_SR_TXCOMP))
status = TWI_SR_TXCOMP;
// add some wait function according to datasheet before sending the next data
// e.g: 10ms
// e.g: WaitMiliSecond (10);
}
/****************************** ReadByte Function **************************
This function uses a two bytes internal address (IADR) along with
Internal word address of eeprom.
Return Value: None
****************************************************************************/
char ReadByte (struct micro24 *ptMicro24,
unsigned int Address) //int Address to read
{
unsigned int WordAddress;
unsigned int SlaveAddress;
char Data2Read ;
unsigned char p0=0;
TWI_CR_START == 1;
//p_twi -> TWI_CR_START = TWI_CR_START;
if (ptMicro24->EepromName == 64)
{
if ( Address > 0xFFFF) {
p0 = 1;
// Mask the 17th bit to get the 16th LSB
WordAddress = Address & 0xFFFF ;
SlaveAddress = ptMicro24->SlaveAddress + (p0<<16) ;
}
else {
SlaveAddress = ptMicro24->SlaveAddress ;
WordAddress = Address ;
}
}
//TWI_ReadSingleIadr(TWI_IADR_IADR,SlaveAddress,WordAddress,
// TWI_MMR_IADRSZ_2_BYTE,&Data2Read);
// declared as extern
// to write to internal address, utilizing internal address and master mode register
return (Data2Read);
}
}
errors are:
(24,19): error: storage size of 'ptMicro24' isn't known
67,5): error: dereferencing pointer to incomplete type
Twi->TWI_CWGR =
error: expected identifier before '(' token
#define TWI_CR_START (0x1u << 0) /**< \brief (TWI_CR) Send a START Condition */
error: expected identifier before '(' token
#define TWI_CR_MSEN (0x1u << 2) /**< \brief (TWI_CR) TWI Master Mode Enabled */
error: expected identifier before '(' token
#define TWI_CR_SVDIS (0x1u << 5) /**< \brief (TWI_CR) TWI Slave Mode Disabled */
error: dereferencing pointer to incomplete type
if (twi_options_t->smbus == 0)
It seems missing the declaration of struct micro24, this may be the cause of first error: error: storage size of 'ptMicro24' isn't known.
The same for declaration of Twi_registers, that is causing other errors.
Either you forgot to declare these structs or to include an header file declaring them.

Saving data to External EEPROM with PIC18

I have PIC18F87J11 with 25LC1024 external EEPROM, and I would like to store some data on it and be able to read it later on. I have done some research, but unfortunately I could not find a tutorial that uses similar board as mine. I am using MPLAB IDE with C18 compiler.
PIC18F87J11
Note: two more links are written as comment below.
This is where my problem is ...
In order to write to the 25LC1024 external EEPROM I followed the tutorial from microchip. The first problem is that this tut is written for PIC18F1220 and I'm using PIC18F87J11. So upon opening the project I get two files not found error, but I simply ignored them.
PICTURE
I copied the file AN1018.h and AN1018_SPI.c to the project I am working on, and I copied some piece of code from AN1018.c file.
Code from AN1018.c file
void main(void)
{
#define PAGESIZE 16
static unsigned char data[PAGESIZE]; // One-page data array
static unsigned char i;
init(); // Initialize PIC
data[0] = 0xCC; // Initialize first data byte
/* Low-density byte function calls */
LowDensByteWrite(data[0], 0x133); // Write 1 byte of data at 0x133
data[0] = 0xFF;
LowDensByteRead(data, 0x133);
printf("%x",data);
while(1){};
}
void init(void)
{
ADCON1 = 0x7F; // Configure digital I/O
PORTA = 0x08; // Set CS high (inactive)
TRISA = 0b11110111; // Configure PORTA I/O
PORTB = 0; // Clear all PORTB pins
TRISB = 0b11111100; // Configure PORTB I/O
}
My second problem is that the output message is always 1e0. In other words, I do not know if the write was successfully made or not. Also I am not sure about what I might be missing.
If I can receive some kind of help, I would appreciate it. To sum up everything, I want to store data to my external EEPROM and retain it when needed. Please know I am a beginner with Microcontroller programming.
As a first step (before reading & writing) you have to be sure that your SPI interface (hardware and software) is correctly configured. To check this step you can read the "Status Register" from the 25LC1024. Look the datasheet for "RDSR", the instruction to send to the eeprom should be 0b00000101 so (int)5.
Here some code for 18F* + 25LC* wirtten in sdcc of a really old project. The code is very basic, no external library used, you just have to replace register variable names and init config for your pic.
Some code comes from here, thanks to bitberzerkir!
spi.c
#ifndef SPI_HH
#define SPI_HH
#define SpiWrite(x) spiRW(x)
#define SpiRead() spiRW(0)
unsigned char spiRW(unsigned char data_){
SSPBUF = data_;
while(!PIR1bits.SSPIF);
PIR1bits.SSPIF = 0;
return SSPBUF;
}
void SpiInit() {
SSPSTAT = 0x40; // 01000000
SSPCON1 = 0x20; // 00100000
PIR1bits.SSPIF = 0;
}
#endif
eeprom.c
Note: Since the addr of 25LC1024 are 3x8bits make sure your compiler 'long' type has at least 24bit
#ifndef EEPROM_HH
#define EEPROM_HH
#include "spi.c"
#define CS PORTCbits.RC2
void EepromInit() {
SpiInit();
CS = 1;
}
unsigned char EReadStatus () {
unsigned char c;
CS = 0;
SpiWrite(0x05);
c = SpiRead();
CS = 1;
return c;
}
unsigned char EWriting() {
unsigned char c;
CS = 0;
SpiWrite(0x05);
c = SpiRead();
CS = 1;
return c & 1;
}
unsigned char EReadCh (unsigned long addr) {
unsigned char c;
// Send READ command and addr, then read data
CS = 0;
SpiWrite(0x03);
// Address in 3x8 bit mode for 25lc1024
SpiWrite(addr>>16);
SpiWrite(addr>>8);
SpiWrite((unsigned char) addr);
c = SpiRead();
CS = 1;
return c;
}
void EWriteCh (unsigned char c, unsigned long addr) {
// Enable Write Latch
CS = 0;
SpiWrite(0x06);
CS = 1;
// Send WRITE command, addr and data
CS = 0;
SpiWrite(0x02);
SpiWrite(addr>>16);
SpiWrite(addr>>8);
SpiWrite((unsigned char) addr);
SpiWrite(c);
CS = 1;
}
#endif
main.c
Set your init according to the datasheet
#include <pic18fregs.h>
#include "eeprom.c"
void main(void) {
char out;
TRISB = 0x01;
TRISC = 0x00;
PORTB = 0x00;
PORTC = 0x00;
EepromInit();
EWriteCh('a', 0x00);
out = EReadCh(0x00);
while(1);
}
If you want to read/write a buffer take care of pagination. Eg here:
// Page byte size, 64 for 25lc256 and 256 for 25lc1024
#define PSIZE 256
// Addr mem limit 7FFF for 25lc256, 1FFFF for 25lc1024
#define MLIMIT 0x1FFFF
void EReadBuff (unsigned char c[], unsigned long dim, unsigned long addr) {
unsigned int i;
// Send READ command and addr, then read data
CS = 0;
SpiWrite(0x03);
SpiWrite(addr>>16);
SpiWrite(addr>>8);
SpiWrite((unsigned char) addr);
for(i = 0; i < dim; ++i)
c[i] = SpiRead();
CS = 1;
}
void EWriteBuff (unsigned char c[], unsigned long dim, unsigned long addr) {
unsigned char i;
unsigned int begin = 0;
unsigned int end = dim > PSIZE ? PSIZE : dim;
while (end > begin && addr + end <= MLIMIT) { // check if addr is a siutable address [0, MLIMIT]
// Enable Write Latch
CS = 0;
SpiWrite(0x06);
CS = 1;
// Send WRITE command, addr and data
CS = 0;
SpiWrite(0x02);
SpiWrite(addr>>8);
SpiWrite((unsigned char) addr);
for(i = begin; i < end; ++i)
SpiWrite(c[i]);
CS = 1;
while(EWriting());
dim -= PSIZE;
begin += PSIZE;
addr += PSIZE;
end = begin + (dim > PSIZE ? PSIZE : dim);
}
}
#endif
I think before directly using the AN1018.h/AN1018_spi.c you will need to verify that it is compatible with your micro-controller. I recommend to check the datasheet of both micro-controllers and see the difference specifically for SPI module as the external EEPROM which you are using will be connected to SPI bus. If these two micro-controller has same register configuration/module for SPI then you can use it else you will have to write the driver on your own. You can use AN1018_spi.c for reference I guess you will just need to change some registers if required.
Then in you init function, you are not initializing SPI module, you will need to specify correct SPI clock, SPI mode based on your external device. Once you have properly initialize SPI module. You will need to write EEPROM_Read/EEPROM_Write function. In which you will have to following protocol given in datasheet of your external device for sending/receiving data from device using.
hi i googled and get a very good website Where i found post on Interfacing external EEPROM with PIC Microcontroller via i2c protocol with FM24C64 and the code which they given in post which i tested and working fine. i give that link may it help you. http://www.nbcafe.in/interfacing-external-eeprom-with-pic-microcontroller/

Unexpected float behaviour in C with AVR atmega8

I've been trying to figure out why I cannot get a sensible value from multiplying an unsigned int with a float value.
Doing something like 65535*0.1 works as expected but multiplying a float with a uint from memory creates mad values. I have a function that reads an ADC and returns an uin16_t. With this value I am printing it to a 4-digit led-display, which is working fine.
Multiplying the same value with 1.0 returns something different entirely (it's too large for my display so I don't really know what it is).
My code is below but the area of contention is at the bottom in main(). Any help would be great. Thanks
main.c:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD 'z'
#define DISP_RESET 'v'
#define ADC_AVG 3
volatile uint8_t hi,lo;
volatile uint16_t result;
ISR(ADC_vect)
{
lo = ADCL;
hi = ADCH;
MCUCR &= ~_BV(SE); //Clear enable sleep
}
void initSerial(void)
{
// set baud rate
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
// set frame format
UCSR0C |= (0x3 << UCSZ00); // 8n1
// set enable tx/rx
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
}
void initADC(void)
{
// AVCC and ADC0
ADMUX = _BV(REFS0);
// Enable, div128, + 1st setup
ADCSRA |= _BV(ADEN)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0)|_BV(ADIE);
}
uint16_t readADC(void)
{
uint16_t average=0;
// Start Conversion
ADCSRA |= _BV(ADSC);
for (char i=0;i<ADC_AVG;i++) {
MCUCR |= _BV(SE);
ADCSRA |= _BV(ADSC);
__asm volatile("sleep");
MCUCR &= ~_BV(SE);
result = (hi<<8);
result |= lo;
average += result;
}
average /= ADC_AVG;
return average;
}
void sendByte(char val)
{
while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
UDR0 = val;
}
/*
* Convert voltage to temperature based on a negative coefficient for MAX6613
*/
uint16_t analogToTemp(uint16_t val)
{
uint16_t temp;
//v = 5 * (val/1023.0);
//temp = (1.8455 - (5.0*(val/1023.0)))/0.01123;
temp = (1.8455 - (5.0*(val/1023.0)))*89;
//temp = val * M_PI;
//v = 5 * ( val/1024);
//temp = (2 - v) * 89;
return temp;
}
void initDisplay()
{
sendByte(DISP_RESET);
sendByte(DISP_BRIGHT_CMD);
sendByte(0);
}
void serialSegments(uint16_t val)
{
// 4 digit display
sendByte(val / 1000);
sendByte((val / 100) % 10);
sendByte((val / 10) % 10);
sendByte(val % 10);
}
int main(void)
{
uint16_t calc=0,sense=0;
DDRB |= _BV(DDB5);
PORTB |= _BV(PORTB5);
initSerial();
initADC();
initDisplay();
sei();
MCUCR |= (1 << SM0); // Setting sleep mode to "ADC Noise Reduction"
MCUCR |= (1 << SE); // Sleep enable
for(;;) {
//PORTB ^= _BV(PORTB5);
if (calc>=9999){ // I can't see the real value. Max val on display is 9999
//if (sense>=330){
PORTB |= _BV(PORTB5);
} else {
PORTB &= ~_BV(PORTB5);
}
sense = readADC();
//calc = sense*1.0; // refuses to calculate properly
calc = analogToTemp(sense); // a bunch of zeroes
//calc = 65535*0.1; // a-ok
serialSegments(calc);
_delay_ms(500);
serialSegments(sense);
_delay_ms(500);
}
return 0;
}
Makefile:
# AVR-GCC Makefile
PROJECT=Temp_Display
SOURCES=main.c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega328p
OSC_HZ=16000000UL
OPTIMISATION=2
PORT=/dev/ttyUSB0
CFLAGS=-mmcu=${MMCU} -std=gnu99 -Wall -O${OPTIMISATION} -DF_CPU=${OSC_HZ} -lm -lc
${PROJECT}.hex: ${PROJECT}.out
${OBJCOPY} -j .text -O ihex ${PROJECT}.out ${PROJECT}.hex
avr-size ${PROJECT}.out
$(PROJECT).out: $(SOURCES)
${CC} ${CFLAGS} -I./ -o ${PROJECT}.out ${SOURCES}
program: ${PROJECT}.hex
stty -F ${PORT} hupcl
avrdude -V -F -c arduino -p m168 -b 57600 -P ${PORT} -U flash:w:${PROJECT}.hex
clean:
rm -f ${PROJECT}.out
rm -f ${PROJECT}.hex
EDIT:
OK, i've simplified the code somewhat
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#define BAUD 9600
#include <util/setbaud.h>
#define DISP_BRIGHT_CMD 'z'
#define DISP_RESET 'v'
void initSerial(void)
{
// set baud rate
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
// set frame format
UCSR0C |= (0x3 << UCSZ00); // 8n1
// set enable tx/rx
UCSR0B = _BV(TXEN0);
}
void sendByte(char val)
{
while (! (UCSR0A & (1<<UDRE0)) ); //wait until tx is complete
UDR0 = val;
}
void initDisplay()
{
sendByte(DISP_RESET);
sendByte(DISP_BRIGHT_CMD);
sendByte(0);
}
void serialSegments(uint16_t val) {
// 4 digit display
sendByte(val / 1000);
sendByte((val / 100) % 10);
sendByte((val / 10) % 10);
sendByte(val % 10);
}
int main(void)
{
uint16_t i=0,val;
DDRB |= _BV(DDB5);
initSerial();
initDisplay();
for(;;) {
val = (uint16_t)(i++ * 1.5);
serialSegments(i);
_delay_ms(500);
serialSegments(val);
_delay_ms(500);
if (val > 9999){
PORTB |= _BV(PORTB5);
} else {
PORTB &= ~_BV(PORTB5);
}
}
return 0;
}
Unsuffixed floating point constant are of type double not float.
Use f suffix to have a float literal, e.g., 0.1f
This can make a huge overhead as MCUs like atmega8 don't have a floating point unit and all floating point operations have to be implemented in firmware by the implementation.
With small devices like atmega8 one usually try to avoid using float operations as without a FPU they are very expensive in CPU cycles.
Now there is no reason an implementation would no correctly translate an expression like:
calc = sense * 1.0;
when calc and sense are of uint16_t type.
Not exactly your code, maybe close enough, maybe not.
First off when I display the output and compare these to lines:
val = (unsigned int)(i++ * 1.5);
...
val = i+(i>>1); i++;
the result is the same. Disassembling shows a few things as well. First off avr-gcc
avr-gcc --version
avr-gcc (GCC) 4.3.4
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
uses floats not doubles, so the comments about 1.5F vs 1.5 are quite valid in general but not relevant here. Second it is producing floating point values, single precision, and is doing floating point math, the compiler did not take a shortcut there, it converts to float, does the multiply then converts back.
Using my hex display routine and your decimal display routine (modified to output on a serial terminal), here again it produces the same output, the floating point math does not appear to be the problem.
I started this task to see if the floating point performance was a killer, and it is, but the timing changes depending on how I test it. it took as much as 157 times longer for the code with the floating point compared to fixed point. If I leave in the call to serialSegments(), but have that call a dummy routine instead of the serial port it is 3 times slower for the float. Also I built two different ways and pulled in a libc/m which used a different set of floating point routines, the floating point routines chosen by the C compiler were 7 times slower than the libc/libm.a sitting in the /usr/lib64/avr/lib/ directory. Once you add the waiting on serial port and other delays you may not notice the difference in timing so this experiment while demonstrating that the float is quite painful, is probably not the smoking gun even if your code is timing sensitive, we are talking a few milliseconds.
In addition to the code below I tried this as well:
for(i=0;i<9999;i++)
{
vala = (unsigned int)(i * 1.5);
valb = i+(i>>1); i++;
if(vala!=valb)
{
hexstring16(i);
hexstring16(vala);
hexstring16(valb);
}
}
No fail. I limited to 9999 because serialSegments() only chops up decimals from 0 to 9999. Now your loop goes beyond that to 65535, but you would see that cause problems without the float though, right?
avr.c
#define UCSRA (*((volatile unsigned char *)(0xC0)))
#define UDR (*((volatile unsigned char *)(0xC6)))
#define TCCR0A (*((volatile unsigned char *)(0x44)))
#define TCCR0B (*((volatile unsigned char *)(0x45)))
#define TCNT0 (*((volatile unsigned char *)(0x46)))
#define TCCR1A (*((volatile unsigned char *)(0x80)))
#define TCCR1B (*((volatile unsigned char *)(0x81)))
#define TCNT1L (*((volatile unsigned char *)(0x84)))
#define TCNT1H (*((volatile unsigned char *)(0x85)))
void dummy ( unsigned int );
void uart_putc ( unsigned char c )
{
while(1) if(UCSRA&0x20) break;
UDR=c;
}
void hexstring16 ( unsigned int d )
{
unsigned int rb;
unsigned int rc;
rb=16;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_putc(rc);
if(rb==0) break;
}
uart_putc(0x0D);
uart_putc(0x0A);
}
#ifdef SEGMENTS
void sendByte(char val)
{
uart_putc(0x30+val);
}
void serialSegments(unsigned int val) {
// 4 digit display
dummy(val / 1000);
dummy((val / 100) % 10);
dummy((val / 10) % 10);
dummy(val % 10);
}
//void serialSegments(unsigned int val) {
//// 4 digit display
//sendByte(val / 1000);
//sendByte((val / 100) % 10);
//sendByte((val / 10) % 10);
//sendByte(val % 10);
//uart_putc(0x0D);
//uart_putc(0x0A);
//}
#else
void serialSegments(unsigned int val)
{
dummy(val);
}
//void serialSegments(unsigned int val)
//{
//hexstring(val);
//}
#endif
int main(void)
{
unsigned int i,val;
volatile unsigned int xal,xbl,xcl;
volatile unsigned int xah,xbh,xch;
hexstring16(0x1234);
TCCR1A = 0x00;
TCCR1B = 0x05;
xal=TCNT1L;
xah=TCNT1H;
for(i=0;i<9999;)
{
val = (unsigned int)(i++ * 1.5);
//serialSegments(val);
//hexstring16(val);
dummy(val);
}
xbl=TCNT1L;
xbh=TCNT1H;
for(i=0;i<9999;)
{
val = i+(i>>1); i++;
//serialSegments(val);
//hexstring16(val);
dummy(val);
}
xcl=TCNT1L;
xch=TCNT1H;
xal|=xah<<8;
xbl|=xbh<<8;
xcl|=xch<<8;
hexstring16(xal);
hexstring16(xbl);
hexstring16(xcl);
hexstring16(xbl-xal);
hexstring16(xcl-xbl);
return 0;
}
dummy.s
.globl dummy
dummy:
ret
vectors.s
.globl _start
_start:
rjmp reset
reset:
rcall main
1:
rjmp 1b
.globl dummy
dummy:
ret
Makefile
all : avrone.hex avrtwo.hex
avrone.hex : avr.c dummy.s
avr-as dummy.s -o dummy.o
avr-gcc avr.c dummy.o -o avrone.elf -mmcu=atmega328p -std=gnu99 -Wall -O2 -DSEGMENTS
avr-objdump -D avrone.elf > avrone.list
avr-objcopy avrone.elf -O ihex avrone.hex
a vrtwo.hex : avr.c vectors.s
avr-as vectors.s -o vectors.o
avr-as dummy.s -o dummy.o
avr-gcc -c avr.c -o avrtwo.o -mmcu=atmega328p -std=gnu99 -Wall -O2 -nostartfiles
avr-ld vectors.o avrtwo.o -o avrtwo.elf libc.a libm.a
avr-objdump -D avrtwo.elf > avrtwo.list
avr-objcopy avrtwo.elf -O ihex avrtwo.hex
clean :
rm -f *.hex
rm -f *.elf
This was all run on an arduino pro mini (atmega328p).
Multiplication 65535*0.1 works because it is optimized and precalculated by the compiler, so it translates to 6554.
calc and sense variables are of type uint16_t, and your function analogToTemp() is of that same type and returns that type too. Your runtime calculation inside this function is with uint16_t. It should be done with float, and then truncated to just integer part and casted to the uint16_t result of the function.

Resources