Checksum algorithms

BALTECH readers support the following checksum algorithms to detect transmission errors.

Cyclic redundancy check (CRC):

  • CRC-16

Block check character (BCC):

  • BCC-8
  • BCC-16

We highly recommend CRC-16

It may be a bit slower and harder to implement than BCC, but it's much more secure: The probability of a corrupted frame having the same checksum as the corresponding original frame is much smaller compared to BCC algorithms.

Implement CRC-16

Pass a start value to the CRC calculation routine. The routine will return a CRC value based on the start value and the content of the block. You may even calculate the CRC over a split block of data; to do so, calculate the CRC over the first block and pass the resulting CRC to the calculation routine of the second block as a new start value.

Every CRC algorithm is either forward shifting or backward shifting and has its own polynomial generator. These two properties are used to identify the algorithms in the below code examples.

Forward shifting CRC with generator polynom 0x1021

/* calculates the crc checksum over some data 
('block' is the pointer to the data, 
'len' is the length of the block, 'curcrc' is the startvalue */

CRC_POLYNOM = 0x1021; //(generator-polynom: X16 + X12 + X5 + 1) 

unsigned int calc_crc16_1021F(unsigned int curcrc, unsigned char* block, int len) 
{ 
    for (int i = 0; i < len; i++) {
        curcrc ^= (unsigned int)block[i] << 8; 
        for (j=0; j<8; j++) 
        { 
            if (curcrc & 0x8000) 
                curcrc = (curcrc << 1) ^ CRC_POLYNOM; 
            else 
                curcrc = (curcrc << 1); 
        } 
    } 
    return curcrc; 
}

Backward shifting CRC with generator polynom 0x8408

/* calculates the crc checksum over some data 
('block' is the pointer to the data, 
'len' is the length of the block, R'curcrc' is the startvalue */

unsigned int calc_crc16_8408B(unsigned int curcrc, unsigned char* block, int len) 
{
    for (int i = 0; i < len; i++) { 
        unsigned char chr = block[i] ^ ((unsigned char) curcrc);
        chr ^= chr << 4; 

        curcrc = (curcrc >> 8) ^ ((unsigned int) chr << 8) ^ 
            ((unsigned int) chr << 3) ^ ((unsigned int) chr >> 4); 
        } 
        return(curcrc);
    }

Implement BCC-8

/* calculates an 8-bit BCC checksum over some data 
('block' is the pointer to the data, 
'len' is the length of the block */ 

unsigned char calc_bcc8(unsigned char* block, int len) 
{ 
    unsigned char bcc8 = 0x00; 

    for (int i = 0; i < len; i++) { 
        bcc8 ^= block[i]; 
    } 

    return bcc8;
}

Implement BCC-16

/* calculates an 16-bit BCC checksum over some data 
('block' is the pointer to the data, 
'len' is the length of the block. */ 

unsigned int calc_bcc16(unsigned char* block, int len) 
{ 
    unsigned char bcc16[2]; 
    for (int i = 0; i < len; i++) { 
        bcc16[0] ^= block[i]; 
    } 
    bcc16[1] = ~bcc16[0]; 
    return *(unsigned int*)bcc16;
}