Search code examples
cchecksumcrccrc16

CRC-16 output message check


I have a program that computes the CRC of characters using the CRC-16. The program is given below.

#include<stdio.h>
#include<stdint.h>

#define CRC16 0x8005

uint16_t gen_crc16(const uint8_t *data, uint16_t size)
{
uint16_t out = 0;
int bits_read = 0, bit_flag;


// test
printf("buffer in function %s\n", data);

/* Sanity check: */
if(data == NULL)
    return 0;

while(size > 0)
{
    bit_flag = out >> 15;

    /* Get next bit: */
    out <<= 1;
    out |= (*data >> bits_read) & 1; // item a) work from the least significant bits

    /* Increment bit counter: */
    bits_read++;
    if(bits_read > 7)
    {
        bits_read = 0;
        data++;
        size--;
    }

    /* Cycle check: */
    if(bit_flag)
        out ^= CRC16;

}

// item b) "push out" the last 16 bits
int i;
for (i = 0; i < 16; ++i) {
    bit_flag = out >> 15;
    out <<= 1;
    if(bit_flag)
        out ^= CRC16;
}

// item c) reverse the bits
uint16_t crc = 0;
i = 0x8000;
int j = 0x0001;
for (; i != 0; i >>=1, j <<= 1) {
    if (i & out) crc |= j;
}

return crc;
}

int main()
{
char buf[]="123456789";
int c , r;
printf ("the buf has %s", buf);
r = gen_crc16(buf,sizeof(buf)-1);
printf("%04hx\n", r);

return (0);
}

Problem: I am trying to modify this code in such a way I can append the returned CRC value at the end of input data and call the function gen_crc() again. gen_crc() function should return 0 this time.

Till now not able to achieve any help or suggestion are most welcome. I am a beginner

The above C program is taken as a reference from the earlier StackOverflow post


Solution

  • The code just needs to declare buf[11] so there's room to append the CRC, then append the CRC. Some other were changes made to work with Visual Studio (the indented blocks used for local variables). The CRC calculation could be simplified.

    #include<stdio.h>
    #include<stdint.h>
    
    #define CRC16 0x8005
    
    uint16_t gen_crc16(const uint8_t *data, uint16_t size)
    {
    uint16_t out = 0;
    int bits_read = 0, bit_flag;
    
    
        /* test */
        printf("buffer in function %s\n", data);
    
        /* Sanity check: */
        if(data == NULL)
            return 0;
    
        while(size > 0)
        {
            bit_flag = out >> 15;
        
            /* Get next bit: */
            out <<= 1;
            out |= (*data >> bits_read) & 1; /* item a) work from the least significant bits */
        
            /* Increment bit counter: */
            bits_read++;
            if(bits_read > 7)
            {
                bits_read = 0;
                data++;
                size--;
            }
        
            /* Cycle check: */
            if(bit_flag)
                out ^= CRC16;
        
        }
    
        /* Cycle check: */
        if(bit_flag)
            out ^= CRC16;
    
        }
    
                                            /* item b) "push out" the last 16 bits */
        {                                   /* block used for local variables */
        int i;
            for (i = 0; i < 16; ++i) {
                bit_flag = out >> 15;
                out <<= 1;
            if(bit_flag)
                out ^= CRC16;
            }
        }
    
                                            /* item c) reverse the bits */
        {                                   /* block used for local variables */
        uint16_t crc = 0;
        int i;
        i = 0x8000;
        int j = 0x0001;
            for (; i != 0; i >>=1, j <<= 1) {
                if (i & out) crc |= j;
            }
            return crc;
        }
    }
    
    int main()
    {
    char buf[11]="123456789";               /* leave room for crc */
    int r;
        printf ("the buf has %s", buf);
        r = gen_crc16(buf, 9);              /* 9 data bytes */
        printf("%04hx\n", r);
        buf[ 9] = (char)((r>>0)&0xff);      /* append crc to data */
        buf[10] = (char)((r>>8)&0xff);
        r = gen_crc16(buf, 11);             /* 9 data bytes + 2 crc bytes */
        printf("%04hx\n", r);
        return (0);
    }
    

    Simplified version that calculates the exact same CRC:

    #define CRC16 0xa001
    
    uint16_t gen_crc16(const uint8_t *data, uint16_t size)
    {
    uint16_t crc = 0;
    int i;
        while(size--){
            crc ^= *data++;
            for(i = 0; i < 8; i++)
                crc = (crc&1) ? (crc>>1)^CRC16 : (crc>>1);
        }
        return crc;         
    }