Search code examples
javachecksumcrc

Calculate CRC8-Maxim checksum in Java


I'm trying to code a CRC8-Maxim calculator in java but I'm stuck. I've tried many API's such as Jacksum, but nothing worked like it should. The only thing I found is this website: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

If I choose the CRC8-Maxim setting, the result is exactly what I need it to be. (example: The checksum of VR1,?, should be D7)

Do you have any idea, how I could code that in java? I need it for my final school project and there's not much time left.

Thanks in advance! Benedikt

[EDIT] I tried it with this Code. It has the same lookup table and the same polynomial as the calculator at the website.

import java.io.UnsupportedEncodingException;

public final class Crc8 {

private static final short CRC8_POLYNOMIAL = 0x31;
private static final short CRC8_INIT_VALUE = 0x0;
private static final short[] CRC8_LOOKUP_TABLE = {
    0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, 0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E,
    0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, 0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D,
    0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, 0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8,
    0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, 0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB,
    0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, 0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13,
    0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, 0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50,
    0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, 0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95,
    0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, 0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6,
    0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, 0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54,
    0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, 0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17,
    0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, 0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2,
    0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, 0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91,
    0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, 0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69,
    0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, 0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A,
    0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, 0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF,
    0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, 0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC
};

private final boolean useLookupTable;
private short crc8;

public Crc8() {
    this(true);
}

public Crc8(boolean use_lookup_table) {
    useLookupTable = use_lookup_table;
    reset();
}

public Crc8 reset() {
    crc8 = CRC8_INIT_VALUE;
    return (this);
}

public Crc8 update(byte b) {
    if (useLookupTable) {
        crc8 = CRC8_LOOKUP_TABLE[(crc8 ^ b) & 0xFF];
    } else {
        crc8 ^= b;
        crc8 &= 0xFF;
        for (int j = 0; j < 8; j++) {
            if ((crc8 & 1) == 1) {
                crc8 >>= 1;
                crc8 ^= CRC8_POLYNOMIAL;
            } else {
                crc8 >>= 1;
            }
        }
    }
    return (this);
}

public Crc8 update(byte[] data, int offset, int length) {
    for (int i = offset; i < length; i++) {
        update(data[i]);
    }
    return (this);
}

public Crc8 update(byte[] data) {
    return update(data, 0, data.length);
}

public Crc8 update(String s) {
    try {
        return update(s.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException ex) {
        throw new RuntimeException(ex);
    }
}

public short get() {
    return ((short) (crc8 ^ 0xFF));
}

/**
 * Return calculated CRC8 in 2 capital hex digits with leading zeros.
 */
public String getHex() {
    return (String.format("%02X", get()));
}}

And this was the Main-class

public static void main(String[] args) {
    Crc8 crc = new Crc8(true);
    String input = "VR1,?,";
    crc.update(input);
    System.out.println("Input: " + input);
    String result  = crc.getHex();
    System.out.println("Output: " + result);

}

But unfournatly the result was E4 and not D7


Solution

  • Consider that java doesn't have unsigned ints. This is going to affect your right shift operators, >>=. This link talks about it: What is the Java equivalent of unsigned?. I think the important part, for what you're trying to do, is this:

    Signed vs unsigned shifts

    An important exception is the right shift operator, represented by two "greater than" symbols: >>. In both C/C++ and Java, this operator performs sign extension: that is, as well as shifting the bits of the number one place to the right, it preserves the sign. Specifically, after performing the shift, it copies the sign bit (the leftmost bit) into the leftmost position.

    Now, if we're treating an integer as unsigned, then we don't want to copy the sign bit, because it doesn't actually represent the sign! Instead, we want to leave it as zero. To achieve this, in Java, instead of writing >>, we write >>>. This variant of the shift is sometimes called a logical shift, and the previous variant— which takes account of the sign— an arithmetic shift. At the machine code level, most architectures in fact provide different instructions for the two shifts, and the C/C++ compiler chooses the appropriate one depending on whether we've declared the variable in question as unsigned. In Java, we must explicitly say which type we require.

    EDIT: Try putting these hex values 5652312C3F2C into Eric's Maxim/Dallas 1-Wire Online CRC Calculator . It gives D7 and gives a bunch of debug information that should help you figure out where you're going wrong.