0

I'm working in a project where there is this function that computes a CRC16 checksum.

uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {

    CrcVal = (unsigned char) (CrcVal >> 8) | (CrcVal << 8);
    CrcVal ^= DataIn;
    CrcVal ^= (unsigned char) (CrcVal & 0xff) >> 4;
    CrcVal ^= (CrcVal << 8) << 4;
    CrcVal ^= ((CrcVal & 0xff) << 4) << 1;

    return CrcVal &0xFFFF;
}

And it is used like this:

uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
        
uint16_t CrcResult=0;
    
for (size_t i = 0; i<10; i++) {
    CrcResult = x_crc(CrcResult, *(x + i));
}    
    
printf("\n\n\nCRC1 = 0x%04X\n",CrcResult);

Due to performance issues I need to convert to a lookup table. How can I do that, using the above function to generate the entries?

Thanks.

xgon
  • 175
  • 1
  • 3
  • 11
  • In fact it is possible to let some preprocessor magic produce the table. But due to company policies I'm not allowed to show some source. The key is to use anonymous enums to avoid huge line lengths during the preprocessing. Several compilers have quite limited capabilities. – the busybee Jul 04 '20 at 15:25

1 Answers1

2

Due to the shifting implementation, it is not clear that this is a left shifting CRC with polynomial 0x11021. Example code including a 256 by 16 bit table driven one. I'm thinking that compiler optimization will inline z_crc, which is the table one. If not, then change the function to take 3 parameters, crcvalue, buffer pointer, # of bytes.

#include <stdio.h>

typedef unsigned short uint16_t;
typedef unsigned char  uint8_t;

uint16_t crctbl[256];

uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {
    CrcVal = (unsigned char)(CrcVal>>8)|(CrcVal<<8);  /* rotate left 8 bits */
                                                /* crc ^=      (byte*0x10000)>>16 */
    CrcVal ^= DataIn;                           /* crc ^=       (byte*0x0001)     */
    CrcVal ^= (unsigned char)(CrcVal&0xff)>>4;  /* crc ^= ((crc&0xf0)*0x1000)>>16 */
    CrcVal ^= (CrcVal<<8)<<4;                   /* crc ^= ((crc&0x0f)*0x1000)     */
    CrcVal ^= ((CrcVal&0xff)<<4)<<1;            /* crc ^= ((crc&0xff)*0x0020)     */
    return CrcVal;                              /*                    0x1021      */
}

uint16_t y_crc(uint16_t CrcVal, uint8_t DataIn) {
    CrcVal ^= ((uint16_t)DataIn) << 8;
    for (uint16_t i = 0; i < 8; i++)
        CrcVal = (CrcVal&0x8000)?(CrcVal<<1)^0x1021:(CrcVal << 1);
    return CrcVal;
}

void inittbl()
{
    for (uint16_t j = 0; j < 256; j++)
        crctbl[j] = x_crc(0, (uint8_t)j);
}

uint16_t z_crc(uint16_t CrcVal, uint8_t DataIn) {
    CrcVal = crctbl[(CrcVal>>8)^DataIn]^(CrcVal<<8);
    return CrcVal;
}

int main()
{
uint16_t crcx = 0;
uint16_t crcy = 0;
uint16_t crcz = 0;
uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
    inittbl();
    for(size_t i = 0; i<10; i++)
        crcx = x_crc(crcx, *(x + i));
    for(size_t i = 0; i<10; i++)
        crcy = y_crc(crcy, *(x + i));
    for(size_t i = 0; i<10; i++)
        crcz = z_crc(crcz, *(x + i));
    if (crcx == crcy && crcx == crcz)
        printf("match\n");
    return 0;
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61