Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CRC Calculation

Tags:

c

checksum

crc

I'm trying to interface with a 3rd party system and they have provided a code sample to calculate a CRC value when sending text data.

The C code the vendor provided looks like this:

#define CRCRES 0xf0b8  /* residue for good verify */ 
#define DEBUG 

unsigned crctbl[] = {0x0000, 0x1081, 0x2102, 0x3183, 
                     0x4204, 0x5285, 0x6306, 0x7387, 
                     0x8408, 0x9489, 0xa50a, 0xb58b, 
                     0xc60c, 0xd68d, 0xe70e, 0xf78f}; 

/* 
 * This uses a 32 byte table to lookup the crc 4 bits at a time. 
 * The CRC CCITT is used. 
 */ 


unsigned short calc_crc(unsigned char *ptr, unsigned length) 

{ 
  unsigned short crc; 
  unsigned short i; 
  unsigned char pos,ch; 

  crc = 0xffff;  /* precondition crc */ 
  for (i = 0; i < length; i++,ptr++) { 
    ch = *ptr; 
    pos = (crc ^ ch) & 15; 
    crc = ((crc >> 4) & 0x0fff) ^ crctbl[pos]; 
    ch >>= 4; 
    pos = (crc^ch) & 15; 
    crc = ((crc >> 4) & 0xffff) ^ crctbl[pos]; 
  } 
  crc = ~crc;  /* post condition */ 
  crc = (crc << 8) | (crc >> 8); /* bytewise reverse */ 
  return crc; 
} 


/* 
 * tests the block of code containing the crc to verify it's 
 * content.  This compares to the reversed and inverted 
 * residue. 
 */ 

int test_crc(unsigned char *ptr, unsigned length) 

{ 
  unsigned short crc; 
  unsigned char arr [] = {'X','Y','Z'}; 

  crc = calc_crc(arr,3); 
  printf("Calced crc of test to be %04x, (should be 470f)\n", crc); 
  return (crc == 0x470f); 
} 

I've copied this code and put in a sample C program. The test_crc method is not calculating the CRC to be 470f (its calculating it as DD7A).

I'm hoping someone can either verify that this code doesn't work as the vendor is saying it should or help me get test_crc to return the correct value.

Thanks for the help.

like image 338
Jeff Avatar asked Jan 24 '23 19:01

Jeff


2 Answers

Problem solved. The specs from the vendor were incorrect. The correct checksum for XYZ is DD7A. The documentation was incorrect.

Add that to the fact that on the page before when they explain what data to pass to the calc_crc method to get the crc for an actual message is also incorrect it made it a tricky project.

Thanks for the help.

like image 138
Jeff Avatar answered Jan 31 '23 23:01

Jeff


The calculation, as it goes, don't show any error that comes to my mind. Just review again the algorithm. In particular, looking for possible problems, note that constants being anded in different parts of the algorithm are 0x0fff and 0xffff. Maybe should it be 0x0fff and 0xfff0 to be more symmetric... Sometimes we think the real problem may come from another place, and forget to double check the obvious things... :)

like image 24
Diego Sevilla Avatar answered Jan 31 '23 22:01

Diego Sevilla