Search code examples
javacrc16

ISO/IEC13239 CRC16 Implementation


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?


Solution

  • 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;
    }