Search code examples
c++algorithmhashcodecrc

Implementation of CRC-8. What does the init parameter do?


I want to write a program for CRC different standards (bit processing) Stuck on the init parameter. When init = 0x00 it works correctly, not only for CRC-8 ... But as soon as you change init, the values do not give out correctly. What is the problem ? Init only needs to change the initial value of the register?

CRC-8 / init = 0x00, poly = 0x07 - works fine
CRC-8 CDMA / init = 0xFF, poly = 0x9b - aldeady no

CRC-8:

   int CRC8() {
    dynamic_bitset<> regix = MyCRC::GetRegixAsBits(0x00, 8); // init = 0x00
    dynamic_bitset<> mess = MyCRC::GetIntAsBitset(0x41, 8);  // mess = 0x41
    dynamic_bitset<> poly = MyCRC::GetPolyAsBitset(8, 0x07); // poly = 0x07

    cout << regix << endl; // 0000 0000 == 0x00
    cout << mess << endl;  // 0100 0001 0000 0000 == 0x41 + 8 нулей
    cout << poly << endl;  // 0000 0111 == 0x07

    while (mess.size() > 0) {
        if (regix[7] == 0) {
            regix = regix << 1;
            regix[0] = mess[mess.size() - 1];
        }
        else {
            regix = regix << 1;
            regix[0] = mess[mess.size() - 1];
            regix = regix ^ poly;
        }
        mess.pop_back();
    }

    cout << hex << regix.to_ulong() << endl; // 1100 0000 = 0xC0 | 0xC0 (crccalc.com) OK

    return regix.to_ulong();
}

CRC-8 CDMA:

int CRC8_CDMA() {
    dynamic_bitset<> regix = MyCRC::GetRegixAsBits(0xFF, 8); // init = 0xFF
    dynamic_bitset<> mess = MyCRC::GetIntAsBitset(0x41, 8);  // mess = 0x41
    dynamic_bitset<> poly = MyCRC::GetPolyAsBitset(8, 0x9b); // poly = 0x9b

    cout << regix << endl; // 1111 1111 == 0xFF
    cout << mess << endl;  // 0100 0001 0000 0000 == 0x41 + 8 нулей
    cout << poly << endl;  // 1001 1011 == 0x9b

    while (mess.size() > 0) {
        if (regix[7] == 0) {
            regix = regix << 1;
            regix[0] = mess[mess.size() - 1];
        }
        else {
            regix = regix << 1;
            regix[0] = mess[mess.size() - 1];
            regix = regix ^ poly;
        }
        mess.pop_back();
    }

    cout << hex << regix.to_ulong() << endl; // 1110 0010 = 0xE2 | 0x28 (crccalc.com) FALSE

    return regix.to_ulong();
}

Solution

  • The sequence of operations of wrong. The order of operations for a left shift CRC should be MSB (most significant bit) of CRC ^= MSB of message, and if result is 1, then CRC <<= 1, CRC ^= poly, else CRC <<= 1. Then the process is repeated with the next to MSB of the message, and so on.

    It's also not shown what the ordering of bits is for Get...Bits... .

    For the first case I get 0xC0, for the second case I get 0x28 .

    The code can be simplified by xor'in 8 bits at at time:

    typedef unsigned char BYTE;
    
    BYTE gencrc1(BYTE *bfr, size_t len)
    {
    size_t i;
    BYTE crc = 0x00;
        while(len--){
            crc ^= *bfr++;
            for(i = 0; i < 8; i++){
                if(crc & 0x80){
                    crc <<= 1;
                    crc ^= 0x07;
                } else {
                    crc <<= 1;
                }
            }
        }
        return(crc);
    }
    
    BYTE gencrc2(BYTE *bfr, size_t len)
    {
    size_t i;
    BYTE crc = 0xff;
        while(len--){
            crc ^= *bfr++;
            for(i = 0; i < 8; i++){
                if(crc & 0x80){
                    crc <<= 1;
                    crc ^= 0x9b;
                } else {
                    crc <<= 1;
                }
            }
        }
        return(crc);
    }
    

    gencrc2 example using "long hand division" method, crc poly = 0x19b = 110011011, message = 0x41, appended with 8 zero bits (for remainder) .

                         11011000
               ------------------
    110011011  | 0100000100000000       0x41 with 8 zero bits 
                 11111111               crc init value is 0xff
                 --------
                 101111100
                 110011011
                 ---------
                  111001110
                  110011011
                  ---------
                   010101010
                   000000000
                   ---------
                    101010100
                    110011011
                    ---------
                     110011110
                     110011011
                     ---------
                      000001010
                      000000000
                      ---------
                       000010100
                       000000000
                       ---------
                        000101000
                        000000000
                        ---------
                         00101000       0x28 is remainder