8

I am currently working on a project, having an embedded system sending data to a PC via radio. The packets get a crc16 checksum at the end and it's calculated based on this algorithm:

uint16_t crc16 (const uint8_t * buffer, uint32_t size) {
    uint16_t crc = 0xFFFF;

    if (buffer && size)
        while (size--)
        {
            crc = (crc >> 8) | (crc << 8);
            crc ^= *buffer++;
            crc ^= ((unsigned char) crc) >> 4;
            crc ^= crc << 12;
            crc ^= (crc & 0xFF) << 5;
        }

    return crc;
}

Now I am looking for an equivalent in Java. I already found a good one here: http://introcs.cs.princeton.edu/java/51data/CRC16CCITT.java.html

public class CRC16CCITT { 

    public static void main(String[] args) { 
        int crc = 0xFFFF;          // initial value
        int polynomial = 0x1021;   // 0001 0000 0010 0001  (0, 5, 12) 

        // byte[] testBytes = "123456789".getBytes("ASCII");

        byte[] bytes = args[0].getBytes();

        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;
        System.out.println("CRC16-CCITT = " + Integer.toHexString(crc));
    }

}

But this doesnt work with my C Code.

Is anybody able to deliver an adaption or solution for a C and Java equivalent algorithm? Thank you!

Prince Agrawal
  • 3,619
  • 3
  • 26
  • 41
tellob
  • 1,220
  • 3
  • 16
  • 32
  • Why are you setting `crc = ` on every iteration as this is the same as ignoring every value but the last. – Peter Lawrey Nov 03 '12 at 12:53
  • So what do I have to write then? crc ^= ? I just copied the code from an open source project i ones worked with. – tellob Nov 03 '12 at 12:56
  • There are much faster ways to compute CRcs than this. Keep searching. There is a table-driven method. – user207421 Nov 03 '12 at 22:12
  • The link in the OP is dead, here is an updated link: [http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java.html](http://introcs.cs.princeton.edu/java/61data/CRC16CCITT.java.html) – gbmhunter Jun 25 '16 at 05:14

1 Answers1

26

The major difference between java and c in this case is the fact in c you use unsigned numbers and java has only signed numbers. While you can implement the same algorithm with signed numbers, you have to be aware of the fact the sign bit is carried over on shift operations, requiring an extra "and".

This is my implementation:

static int crc16(final byte[] buffer) {
    int crc = 0xFFFF;

    for (int j = 0; j < buffer.length ; j++) {
        crc = ((crc  >>> 8) | (crc  << 8) )& 0xffff;
        crc ^= (buffer[j] & 0xff);//byte to int, trunc sign
        crc ^= ((crc & 0xff) >> 4);
        crc ^= (crc << 12) & 0xffff;
        crc ^= ((crc & 0xFF) << 5) & 0xffff;
    }
    crc &= 0xffff;
    return crc;

}
thedayofcondor
  • 3,860
  • 1
  • 19
  • 28
  • This is the CRC function I use in my code - provided the initial value is the same (0xFFFF) and the polynomial is the same (0x1021) they should give the exact same result. – thedayofcondor Nov 03 '12 at 13:09
  • The package I get is: 1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 125 -7. 21 Bytes. The packages crc is then -1667. I had to change the order of the last to byte. When I use your algorithm crc delivers me 3377. – tellob Nov 03 '12 at 13:13
  • the data you should pass to my function is the buffer without the last two bytes. You can change my function to for (int i = 0; i < data.length-2; i++) so the last 2 bytes are not taken into account – thedayofcondor Nov 03 '12 at 13:23
  • This is how its currently looking like: byte[] bx = new byte[packet.length - 2]; for(int i = 0; i < bx.length; i++) bx[i] = packet[i]; System.out.println(crc16(bx)); – tellob Nov 03 '12 at 13:26
  • I saw i forgot to calculate the crc on the c side. But its still not working. Package content is: 1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 51 -100. c crc is 13212 and java crc with your function 3377. – tellob Nov 03 '12 at 14:03
  • so, to be clear, the data is: {1 20 0 -30 -1 72 -31 -110 64 1 0 2 0 3 0 4 0 5 0 } and the checksum should be {51 -100} which, as short in the right byte order is 13212 ? – thedayofcondor Nov 03 '12 at 14:24
  • yes, thats exactly what i get with the c package. but calculating it with your algorithm, crc = 3377 – tellob Nov 03 '12 at 16:13
  • byte[] fkk = {1,20,0,-30,-1,72,-31,-110,64,1,0,2,0,3,0,4,0,5,0}; debugPrintln("" + crc16(fkk)); // = 3377 – tellob Nov 03 '12 at 16:53
  • using the function and simply returning the value plus printing gives me 39987 instead of 13212. sure its working now? – tellob Nov 04 '12 at 00:16
  • Yes, you have just to swap the bytes. – thedayofcondor Nov 04 '12 at 00:29
  • 39987 is 9c33 in hex, 13212 is 339c – thedayofcondor Nov 04 '12 at 00:37
  • +1, much more efficient than other Java implementations with tables I have found. – dARKpRINCE Jul 11 '14 at 09:08
  • @thedayofcondor hi, i have a doubt here. With respect to this link, the answer i get by implementing the code above falls in bad_crc category. http://srecord.sourceforge.net/crc16-ccitt.html#results. Can i get some helping hand understand it. CRC and bits is not my cup of tea ;) – Calvin Apr 02 '16 at 08:06