ISO/IEC13239 CRC16 Implementation

reox picture reox · Aug 20, 2013 · Viewed 8.2k times · Source

I need a CRC16 implementation for NFC Tags. As the standard tolds me this is ISO/IEC13239 and a sample C code is provided. I translated this code into Java but it gives me wrong results:

private static final char POLYNOMIAL = 0x8404;
private static final char PRESET_VALUE = 0xFFFF;

public static int crc16(byte[] data) {
char current_crc_value = PRESET_VALUE;
for (int i = 0; i < data.length; i++) {
    current_crc_value = (char) (current_crc_value ^ ((char) data[i]));
    for (int j = 0; j < 8; j++) {
    if ((current_crc_value & 0x0001) == 0x0001) {
        current_crc_value = (char) ((current_crc_value >>> 1) ^ POLYNOMIAL);
    } else {
        current_crc_value = (char) (current_crc_value >>> 1);
    }
    }
}
current_crc_value = (char) ~current_crc_value;

return current_crc_value;
}

As the standard tells me a byte sequence of 1,2,3,4 should create a CRC Value of 0x3991 A C Version is here on Page 42: http://www.waazaa.org/download/fcd-15693-3.pdf

Also other CRC Implementations does not work: crc16 implementation java The first gives me 0x9e33, the second 0x0FA1 (my implementation by the way says 0xE1E5)

Does someone find an error in my sample or is there another CRC16 Implementation thats really works?

Answer

clstrfsck picture clstrfsck · Aug 20, 2013

Your answer is pretty close, but I think there may be some problems with masking and polynomials. Here are some tweaks that seem to work for me:

private static final int POLYNOMIAL   = 0x8408;
private static final int PRESET_VALUE = 0xFFFF;

public static int crc16(byte[] data)
{
  int current_crc_value = PRESET_VALUE;
  for (int i = 0; i < data.length; i++ )
  {
    current_crc_value ^= data[i] & 0xFF;
    for (int j = 0; j < 8; j++)
    {
      if ((current_crc_value & 1) != 0)
      {
        current_crc_value = (current_crc_value >>> 1) ^ POLYNOMIAL;
      }
      else
      {
        current_crc_value = current_crc_value >>> 1;
      }
    }
  }
  current_crc_value = ~current_crc_value;

  return current_crc_value & 0xFFFF;
}