-2

I have two crc16 calculators (in C and in Python). But Im receiving different results. Why?

calculator in C:

unsigned short __update_crc16 (unsigned char data, unsigned short crc16)
{
  unsigned short t;
  crc16 ^= data;
  t = (crc16 ^ (crc16 << 4)) & 0x00ff;
  crc16 = (crc16 >> 8) ^ (t << 8) ^ (t << 3) ^ (t >> 4);
  return crc16;
}


unsigned short get_crc16 (void *src, unsigned int size, unsigned short start_crc)
{
  unsigned short crc16;
  unsigned char *p;
  crc16 = start_crc;
  p = (unsigned char *) src;
  while (size--)
    crc16 = __update_crc16 (*p++, crc16);
  return crc16;
}

calculator in Python3:

def crc16(data):
    crc = 0xFFFF
    for i in data:
        crc ^= i << 8
        for j in range(0,8):
            if (crc & 0x8000) > 0:
                crc =(crc << 1) ^ 0x1021
            else:
                crc = crc << 1
    return crc & 0xFFFF
Clifford
  • 88,407
  • 13
  • 85
  • 165
Vit Amin
  • 574
  • 5
  • 20
  • 1
    Can you update the question with examples of the inputs and callings of each function, plus the two different output values? – quamrana Oct 20 '19 at 12:09
  • 3
    I’d say because they are completely different algorithms. – Sami Kuhmonen Oct 20 '19 at 12:20
  • thanks. could you help with the correct implementation of the current C calc in Python3? – Vit Amin Oct 20 '19 at 12:22
  • Were you expecting them to be the same? – Shawn Oct 20 '19 at 12:23
  • 3
    The C version has a `start_crc` parameter, whereas the Python version is hard coded to 0xFFFF. Your question might usefully contain example data, parameters and the actual output from the two implementations. – Clifford Oct 20 '19 at 12:23
  • Such a question really requires a [mcve]. Not only the way this is called but perhaps even the interpretation of the results is questionable. Also, formally, this is required by site rules. – Ulrich Eckhardt Oct 20 '19 at 12:54
  • You have not mentioned in the question, but you have asked in a comment about a Python implementation of the CRC in the C code. If that is what you want, you should edit the question to include that requirement, since it is not obvious which is the one you need, since they are both valid implementations of _different_ CRCs. – Clifford Oct 20 '19 at 13:18
  • As much as I appreciate you accepting my answer, I would really rather you updated the question in response to the comments. It will only attract further downvotes otherwise and while you have your answer, the question needs improving to be generally useful to the community. Which is kind of the point of SO; your questions form a valuable resource for all, not just a solution to your immediate problem. – Clifford Oct 20 '19 at 13:45

2 Answers2

5

There is more that one CRC-16. 22 catalogued at http://reveng.sourceforge.net/crc-catalogue/16.htm. A CRC is charactarised by its width, polynomial, initial state and the input and output bit order.

By applying the same data to each of your functions:

Python:

data = bytes([0x01, 0x23, 0x45, 0x67, 0x89])
print ( hex(crc16(data)) )

Result: 0x738E

C:

char data[] = {0x01, 0x23, 0x45, 0x67, 0x89};
printf ("%4X\n", get_crc16 (data, sizeof (data), 0xffffu));

Result: 0x9F0D

and also applying the same data to an online tool that generates multiple CRCs, such as https://crccalc.com/ you can identify the CRC from the result.

In this case your Python code is CRC-16-CCITT-FALSE, while the C result matches CRC-16/MCRF4XX. They both have the same polynomial, but differ in their input-reflected and output-reflected parameters (both false for CCITT, and true for MCRF4XX). This means that for MCRF4XX the bits are read from LSB first, and the entire CRC is nit reversed on output.

https://pypi.org/project/crccheck/ supports both CCITT and MCRF4XX and many others.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 1
    Note that the "MCRF4XX" refers to an implementation on a specific Microchip RFID reader. Unless you are dealing with such a device or a device that requires it, I suggest you use the more conventional CRC-16-CCITT-FALSE. – Clifford Oct 20 '19 at 14:05
  • I do have that device. This is the main problem ) I want to understand CRC deeply, so I will read the raw code in crccheck. Thank you a lot – Vit Amin Oct 20 '19 at 14:28
  • 2
    I would not bother understanding the CRC for the purposes of just using it once you have the correct CRC. Even then I would not attempt to understand it from code, there are plenty of resources that explain the mathematics of CRC and implementations can vary considerably. The MCRF4XX CRC is specifically discussed at https://ww1.microchip.com/downloads/en/AppNotes/00752a.pdf – Clifford Oct 20 '19 at 14:34
  • are u sure that the C result matches CRC-16/MCRF4XX? Not CRC-16/KERMIT? – Vit Amin Oct 21 '19 at 20:27
  • @VitAmin What makes you think that? My deduction method is clearly described in the answer. Using the same test data Kermit results in 0xAF85. – Clifford Oct 22 '19 at 05:56
  • @VitAmin Kermit CRC is also known as CRC-16/CCITT-TRUE. The Python code will produce that by initialising CRC to zero rather than 0xffff. – Clifford Oct 22 '19 at 06:09
1

I implemented a version of crc16 in C based on python crc16 lib. This lib calculate CRC-CCITT (XModem) variant of CRC16. I used my implementation in a stm32l4 firmware. Here is my C implementation:

unsigned short _crc16(char *data_p, unsigned short length){
  unsigned int crc = 0;
  unsigned char i;

  for(i = 0; i < length; i++){
     crc = ((crc<<8)&0xff00) ^ CRC16_XMODEM_TABLE[((crc>>8)&0xff)^data_p[i]];
  }

  return crc & 0xffff;

}

In the Python side, I was reading 18 bytes that was transmited by stm32. Here is a bit of my code (crc's part):

import crc16

# read first time
crc_buffer  = b''
bytes = serial_comunication.read(2) # int_16 - 2 bytes
crc_buffer = crc_buffer.join([crc_buffer,bytes])
crc = crc16.crc16xmodem(crc_buffer,0)

while aux < 8:
  crc_buffer  = b''
  bytes = serial_comunication.read(2)
  crc_buffer = crc_buffer.join([crc_buffer,bytes])
  crc = crc16.crc16xmodem(crc_buffer,crc)

print(crc)

In my tests, C and Python crc16 values always match, unless some connection problem occurs. Hope this helps someone!

wasp.lahis
  • 11
  • 2