Question

I am trying to validate checksums from a device and they give me the below C code for checksum validation, however I cannot convert this code to java and get it to produce the same checksum as the messages. Note this is the entire source code given in document and i have tried several of the example codes online and none of them work for me. Thanks.

const unsigned short NET_CRC_TABLE[256] =
{ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129,
0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5,
0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,     
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528,
0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 
0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 
0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 
0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 
0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A,     
0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA,         
0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025,     
0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589,   
0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 
0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 
0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 
0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 
0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 
0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 
0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; 

unsigned short NET_CRC_Calc(unsigned char * pData, unsigned short Count)
{ /* calculate serial CRC (<--CCITT) without changing data */
    unsigned char Index; 
    unsigned short Crc=0;

    while (Count--) { 
        Index = HBYTE_16(Crc);
        HBYTE_16(Crc) = LBYTE_16(Crc);
        LBYTE_16(Crc) = *pData++;
        Crc = (unsigned short)(Crc ^ NET_CRC_TABLE[Index]);
}

return Crc;
}

I have no idea what the definitions for HByte and LByte are (which is why I didn't post code initially). They are nowhere in the protocool document, so i assumed they were methods in the C library. Basically outside of the table my code is this:

int NET_CRC_Calc(int[] pData, int count) {
    int index;
    int crc = 0;

    for(;count > 0; count--) {
        index = crc >> 8;
        //TODO: Find out Hbyte method
        //LBYTE_16(crc) = pData[count]; ???
        crc = (int)(crc ^ NET_CRC_TABLE[index]);
    }
return crc;
}

If you would like to test your algorithm before posting (trust i will test anything for you!!), below is the string and expected output.

String command = "<Ver>1</Ver><DtTm></DtTm><Type>3</Type>";
Expected Output: 0x12AA
Was it helpful?

Solution

First of all, make sure you make the NET_CRC_TABLE of type int[]. You can copy the initializer, though.

Next is the pData argument, which is unsigned charin C, and should therefore be a byte array in Java. If you have bytes, make sure that you read unsigned values from the array, by doing

(pData[index] & 0xff)

Then the loop looks like this:

    int ptr = 0;
    while (count-- > 0) { 
        index = (crc >> 8) & 0xff;
        crc = ((crc & 0xff) << 8) | (pData[ptr++] & 0xff); 
        crc = crc ^ NET_CRC_TABLE[index];
    }

(I have taken liberty to rename the variables to lowercase, as usual in java. Using uppercase variable and method names is frowned upon in the Java world.)

=== EDIT ===

In the case that the whole array must be processed, it makes no sense to pass the count argument at all. Java knows the size of its arrays, unlike C. So, drop the count parameter and change the loop condition like:

while (ptr < pData.length) {

OTHER TIPS

Based on Ingo's answer, here is a complete solution:

boolean isValidCrc16(int[] crcTable, int crcCode, byte[] toValidate) {
    int ptr = 0;
    int index;
    int computedCrcCode = 0;      
    boolean isValid;

    while (ptr < toValidate.length) {
        index = (computedCrcCode >> 8) & 0xff;
        computedCrcCode = ((computedCrcCode & 0xff) << 8) | (toValidate[ptr++] & 0xff); 
        computedCrcCode = computedCrcCode ^ crcTable[index];
    }

    return computedCrcCode == crcCode;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top