4

I am trying to translate a CRC8 function from C to Java.

I got this code from the hardware manufacturer:

uint8_t CRCCalc (uint8_t* pointer, uint16_t len) {
    uint8_t CRC = 0x00;
    uint16_t tmp;

    while(len > 0) {
        tmp = CRC << 1;
        tmp += *pointer;
        CRC = (tmp & 0xFF) + (tmp >> 8);
        pointer++;
        --len;
    }

    return CRC;
}

My Java code is:

private int getCheckSum(byte[] data) {
        int tmp;
        int res = 0;
        for(int i = 0; i < data.length; i++) {
            tmp = res << 1;
            tmp += 0xff & data[i];
            res = (tmp & 0xff) + (tmp >> 8);
        }
        return res;
    }

Usually all works fine, but sometimes for example: For the hex 0997AD0200, the CRC should be 4, but my code gives me 8

I'm not sure what I missed.

Necreaux
  • 9,451
  • 7
  • 26
  • 43
Nikita G.
  • 65
  • 1
  • 8
  • This line `tmp += 0xff & data[i];` doesn't match what you have in C. Also, `uint8_t` pointer is mysterious. – sircodesalot May 14 '15 at 12:09
  • 2
    One other thing you should know, java doesn't have 'unsigned' integer types. Source: previous burns. (http://stackoverflow.com/questions/430346/why-doesnt-java-support-unsigned-ints) – sircodesalot May 14 '15 at 12:12
  • @sircodesalot Which is why I would go with `res = (tmp & 0xff) + (tmp >>> 8);` – biziclop May 14 '15 at 12:17

1 Answers1

5

This line is incorrect:

res = (tmp & 0xff) + (tmp >> 8);

In the original code CRC is an uint8_t, so the result of that calculation should be in the range 0-255. Hence you want this instead:

res = ((tmp & 0xff) + (tmp >> 8)) & 0xff;

What's happening in your version (which you can see if you add some prints in your crc loop) is that when tmp becomes 0x1FF you get res = 0xFF + 1 == 0x100, when it really should have been (uint8_t)(0xFF + 1) == 0.

Michael
  • 57,169
  • 9
  • 80
  • 125