ccalculationcrccrc8

Is there a difference in how crc8-atm and crc8-maxim are calculated?


I want to implement CRC8 generator. CRC8-ATM works without problems. However, when using the polynomial of CRC8-MAXIM, the calculation result is different. Did I calculate the wrong way?

==============================
CRC8-ATM
dat: "AB" = 01000001 01000010
ply: 0x107 = 100000111
res: 0x87
==============================
01000001 01000010 00000000
 1000001 11
----------------------------
         10000010 00000000
         10000011 1
----------------------------
                1 1000000
                1 00000111
----------------------------
my_res:           10000111 => 0x87 (OK)
==============================
CRC8-MAXIM
dat: "AB" = 01000001 01000010
ply: 0x131 = 100110001
res: 0xA5
==============================
01000001 01000010 00000000
 1001100 01
----------------------------
    1101 00000010 00000000
    1001 10001
----------------------------
     100 10001010 00000000
     100 110001
----------------------------
          1001110 00000000
          1001100 01
----------------------------
               10 01000000
               10 0110001
----------------------------
my_res :          00100010 => 0x22 (Must be 0xA5)

For the calculation results, refer to the site below.

https://crccalc.com

If anyone is familiar with the implementation of CRC8, please help.


Solution

  • Yes, there is.
    Regular CRC-8 and CRC-8/MAXIM have different RefIn and RefOut configurations :

    Here is a piece of code computing CRC8 algorithms:

    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    uint8_t uint8_reverse(uint8_t val)
    {
        uint8_t ret = 0;
        for (size_t i = 0; i < 8; i++)
        {
            if (val & 0x80)
            {
                ret |= (1 << i);
            }
            val <<= 1;
        }
        return ret;
    }
    
    uint8_t crc8(uint8_t const * data, size_t data_size, uint8_t poly, uint8_t init,
                 bool refin, bool refout, uint8_t xor_out)
    {
        uint8_t crc = init;
        for (size_t i = 0; i < data_size; i++)
        {
            crc = crc ^ (refin ? uint8_reverse(data[i]) : data[i]);
            for (size_t j = 0; j < 8; j++)
            {
                if (crc & 0x80)
                {
                    crc = (crc << 1) ^ poly;
                }
                else
                {
                    crc <<= 1;
                }
            }
        }
        return (refout ? uint8_reverse(crc) : crc) ^ xor_out;
    }
    
    int main(void)
    {
        printf("--- Check data ---\n");
        const uint8_t check[9] = "123456789";
        printf("crc8:          0x%02x\n", crc8(check, 9, 0x07, 0x00, 0, 0, 0x00));
        printf("crc8-cdma2000: 0x%02x\n", crc8(check, 9, 0x9b, 0xff, 0, 0, 0x00));
        printf("crc8-darc:     0x%02x\n", crc8(check, 9, 0x39, 0x00, 1, 1, 0x00));
        printf("crc8-itu:      0x%02x\n", crc8(check, 9, 0x07, 0x00, 0, 0, 0x55));
        printf("crc8-maxim:    0x%02x\n", crc8(check, 9, 0x31, 0x00, 1, 1, 0x00));
    
        printf("--- 'AB' data ---\n");
        const uint8_t ab_data[2] = "AB";
        printf("crc8:          0x%02x\n", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x00));
        printf("crc8-itu:      0x%02x\n", crc8(ab_data, 2, 0x07, 0x00, 0, 0, 0x55));
        printf("crc8-maxim:    0x%02x\n", crc8(ab_data, 2, 0x31, 0x00, 1, 1, 0x00));
    
        return 0;
    }
    

    It outputs:

    --- Check data ---
    crc8:          0xf4
    crc8-cdma2000: 0xda
    crc8-darc:     0x15
    crc8-itu:      0xa1
    crc8-maxim:    0xa1
    --- 'AB' data ---
    crc8:          0x87
    crc8-itu:      0xd2
    crc8-maxim:    0xa5
    

    Note that most of the time RefIn and RefOut have the same value, and code optimization is possible (i.e. avoiding all byte reversing operations).