16-bit CRC-CCITT in Matlab

4.3k views Asked by At

Given the calcCRC() C function shown below, what is the equivalent Matlab function?

16-bit CRC-CCITT in C:

/*
 * FUNCTION: calcCRC calculates a 2-byte CRC on serial data using
 * CRC-CCITT 16-bit standard maintained by the ITU
 * ARGUMENTS: queue_ptr is pointer to queue holding are a to be CRCed
 * queue_size is offset into buffer where to stop CRC calculation
 * RETURNS: 2-byte CRC
 */
unsigned short calcCRC(QUEUE_TYPE *queue_ptr, unsigned int queue_size) {
    unsigned int i=0, j=0;
    unsigned short crc=0x1D0F; //non-augmented initial value equivalent to augmented initial value 0xFFFF

    for (i=0; i<queue_size; i+=1) {
        crc ^= peekByte(queue_ptr, i) << 8;

        for(j=0;j<8;j+=1) {
            if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
            else crc = crc << 1;
        }
    }

    return crc;
}

Below is the Matlab code I have come up with that seems to be equivalent but does not output the same results:

(Incorrect) 16-bit CRC-CCITT in Matlab:

function crc_val = crc_ccitt_matlab (message)
    crc = uint16(hex2dec('1D0F'));

    for i = 1:length(message)
        crc = bitxor(crc,bitshift(message(i),8));

        for j = 1:8
            if (bitand(crc, hex2dec('8000')) > 0)
                crc = bitxor(bitshift(crc, 1), hex2dec('1021'));
            else
                crc = bitshift(crc, 1);
            end
        end
    end

    crc_val = crc;
end

Here is a sample byte array, represented as an integer array:

78 48 32 0 251 0 215 166 201 0 1 255 252 0 1 2 166 255 118 255 19 0 0 0 0 0 0 0 0 0 0 0 0 3 0

The expected output is two bytes base10(44 219) which is base2(00101100 11011011) or base10(11483).

My Matlab function gives base10(85) which is base2(00000000 01010101).

Any ideas on what is causing the output to not be the expected?

1

There are 1 answers

1
Mark Adler On

You should try bitsll() instead of bitshift(). The former is guaranteed to do what you want, whereas the behavior of the latter depends on properties of crc.

You will also need to and with 0xffff at the end.