Search code examples
javamicrochipcrc16

How to Calculate CRC-CCITT from ISO FDX-B microchip data


I'm having trouble calculating the correct CRC value for the 64 bit data stored in a ISO FDX-B complaint microchip. I know the correct CRC should be 0x73f9. Any help would be appreciated.

The raw data is:

Forward LSB - MSB
00010011 10000010 00011100 00101000 01011010 01101111 00000000 00000001
   19      130       28       40       90       111      0        1

Reverse MSB - LSB
10000000 00000000 11110110 01011010 00010100 00111000 01000001 11001000 
  128      0        246       90      20        56       65       200

I feed this into a routine crc16 respectfully;

    byte[] y = { (byte)19,      (byte)130,       (byte)28,       (byte)40,       (byte)90,       (byte)111,      (byte)0,        (byte)1 };

    crc = crc16(y);
    // crc = oxa7f0;

byte[] x = { (byte)128,      (byte)0,        (byte)246,       (byte)90,      (byte)20,        (byte)56,       (byte)65 ,      (byte)200};   

int crc = crc16(x);
// crc = 0x1438

Here's the crc routine:

// Calculates the 16 bit CRC value of the byte buffer
public static int crc16(byte[] bytes)
{
    int crc = 0x0; // initial value
    int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)

    for (byte b : bytes)
    {
        for (int i = 0; i < 8; i++)
        {
            boolean bit = ((b >> (7 - i) & 1) == 1);
            boolean c15 = ((crc >> 15 & 1) == 1);
            crc <<= 1;
            if (c15 ^ bit)
                crc ^= polynomial;
        }
    }

    crc &= 0xffff;

    return crc;
}

Solution

  • With some help from the Arduino community I was able to generate the correct checksum. The algorithm is correct and the solution is to start with an initial value of 0, a poly of 0x1021 and then bit reverse the calculated value. Doing so returns a calculated checksum of 0x9FCE and bit reversing that gives the expected checksum 0x73F9. I have updated the code above.

    1001 1111 1100 1110
    9    F    C    E
    
    7     3     F     9
    0111  0011  1111  1001