Calculation of CCITT standard CRC with polynomial x^16 + x^12 + x^5 + 1 in Java
calculator, crc16, java, polynomial-math
Solution
Here is another version of the Kermit CRC. This one is a direct translation from the C codes in http://www.lammertbies.nl/comm/info/crc-calculation.html. The optimisation is that a table of CRC value for any byte is pre-computed at class loading time, and so the remaining of CRC computations is much simpler.
public class Crc {
private static final int POLYNOMIAL = 0x8408;
private static final int PRESET = 0;
static private int[] tab;
static {
tab = new int[256];
for (int i = 0; i < 256; i++) {
tab[i] = initial((byte) i);
}
}
private static int initial(byte c) {
int crc = 0;
for (int j = 0; j < 8; j++) {
if (((crc ^ c) & 1) == 1) {
crc = ((crc >> 1) ^ POLYNOMIAL);
} else {
crc = (crc >> 1);
}
c = (byte) (c >> 1);
}
return crc;
}
private static int update_crc(int crc, byte c) {
int cc = (0xff & c);
int tmp = (crc ^ cc);
crc = (crc >> 8) ^ tab[tmp & 0xff];
return crc;
}
private static int swab(int n) {
return (((n & 0xFF00) >> 8) + ((n & 0xFF) << 8));
}
public static int crc(String str) {
return crcb(str.getBytes());
}
public static int crcb(byte... i) {
int crc = PRESET;
for (byte c : i) {
crc = update_crc(crc, c);
}
return swab(crc);
}
public static void main(String[] args) {
int crc = Crc.crcb((byte) 0xFC, (byte) 5, (byte) 0x11);
System.out.println(Integer.toHexString(crc));
crc = Crc.crc("123456789");
System.out.println(Integer.toHexString(crc));
}
}
The output is as expected :
2756
8921
Problem
I need help with calculating of CCITT standard CRC with polynomial x^16 + x^12 + x^5 + 1 (0x1081) in Java. I have tried many examples on the internet but every one of them returns other values than the ones in the example. For example for this array [0xFC] [05] [11] the result needs to be [27] [56]. Using this code: ``` public static void main(String[] args) { byte[] array = new byte[3]; array[0] = (byte) 0xFC; array[1] = (byte) 0x05; array[2] = (byte) 0x11; // array[3] = (byte) 0x00; // array[4] = (byte) 0x00; System.out.println(Integer.toHexString(crc16(array))); } private static final int POLYNOMIAL = 0x1081; 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; } ``` I get result `FA DE` not [27] [56] Using this code: ``` public static void main(String[] args) { int crc = 0x0000; int polynomial = 0x1081; // byte[] testBytes = "123456789".getBytes("ASCII"); // byte[] array = args[0].getBytes(); byte[] array = new byte[3]; array[0] = (byte) 0xFC; array[1] = (byte) 0x05; array[2] = (byte) 0x11; for (byte b : array) { 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; System.out.println("CRC16-CCITT = " + Integer.toHexString(crc)); } ``` I get this `CRC16-CCITT = 8dca` Using this code: ``` private final int polynomial = 0x1081; private int[] table = new int[256]; public int ComputeChecksum(int[] bytes) { int crc = 0xffff; for (int i = 0; i < bytes.length; ++i) { int index = (crc ^ bytes[i]) % 256; crc = (crc >> 8) ^ table[index]; } return crc; } public CRC162() { int value; int temp; for (int i = 0; i < table.length; ++i) { value = 0; temp = i; for (byte j = 0; j < 8; ++j) { if (((value ^ temp) & 0x0001) != 0) { value = (value >> 1) ^ polynomial; } else { value >>= 1; } temp >>= 1; } table[i] = value; } } public static void main(String[] args) { CRC162 c = new CRC162(); int[] arr = new int[]{0xFC, 0x05, 0x11}; System.out.println(Integer.toHexString(c.ComputeChecksum(arr))); } ``` I get this `521` Hope someone can help me. I need this for communication with device using ID003 protocol. EDIT: Using this online calculator at http://www.lammertbies.nl/comm/info/crc-calculation.html for input FC0511 i get 0x2756 right from CRC-CCITT (Kermit).