Introduction to Cyclic Redundancy Check (CRC) algorithm written to embedded programmers

Posted by mispris006 on Sun, 28 Jun 2020 18:57:15 +0200

Preface

CRC checks (cyclic redundancy checks) are the most commonly used checks in data communication.In embedded software development, CRC algorithm is often used to verify various data.Therefore, mastering basic CRC algorithms should be a basic skill for embedded programmers.However, few embedded programmers I know can really master the CRC algorithm. Most of the CRC code that I usually see in a project is a very inefficient implementation.

In fact, there is a very good article on the Internet about the CRC algorithm by Ross Williams titled "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS".I often recommend this article to friends who ask me about the CRC algorithm, but many friends complain to me that the original text is too long and in English.I wish I could write a shorter article, so I have this article.However, I am no better than Ross Williams, and my articles are certainly not as good as those written by Ross Williams.So read the original text of Ross Williams for those who have no obstacles in English.

This article is intended for software developers, especially those engaged in embedded software development, rather than academics who specialize in mathematics or communications (and I don't write as well at this level).Therefore, the goal of this paper is to introduce the basic principle and implementation of CRC algorithm, and to control the depth of the mathematics used as far as possible to be understood by high school students.

In addition, since most embedded programmers are traveling halfway from home, many people only use C.Therefore, the sample code in this paper is all implemented in C language.As an introductory short article, the code given here focuses more on demonstration and is as readable as possible.Therefore, the code in this article does not seek the most efficient implementation, but is fast enough for general applications.

From Parity Check

The so-called verification of communication process refers to adding additional information after the communication data to determine whether the received data is the same as the sent data.For example, RS232 serial communication can set parity bits, so-called parity checking is to add a bit after each byte sent so that one of each byte is odd or even.For example, the bytes we are sending are 0x1a and the binary representation is 0001 1010.

With odd checks, a zero is added to the data, the data becomes 0001 1010, and the number of 1 in the data is odd (3).

With even checking, add a 1 after the data, the data becomes 0001 1010 1, the number of 1 in the data is even (4)

The receiver determines whether the data is wrong by calculating whether a number in the data satisfies parity.

The disadvantage of parity checking is also obvious. First, it detects errors with a probability of about 50%.That is, only half of the errors can be detected.In addition, a check bit is attached to each byte transmitted, which has a significant impact on the transmission efficiency.Therefore, parity checking is rarely used in high-speed data communication.The advantage of parity is also obvious, it is simple, so it can be implemented with hardware, which can reduce the burden on software.Therefore, parity checking is also widely used.

Parity checking is introduced here first. It is because this is the simplest way to check, and you will know later that parity checking is actually one of the CRC checks (CRC-1).

Accumulation and Check

Another common way of checking is to add up and check.There are many implementations of so-called accumulation and verification. The most common one is to add one byte of verification data at the end of a communication packet.This byte content is the byte-by-byte summation of the byte ignorance carriers for all data in the previous packet.Examples include the following:

The information we want to transfer is: 6, 23, 4

Packets with checksum: 6, 23, 4, 33

Here 33 is the checksum of the first three bytes.The receiver receives all the data and calculates the same accumulation of the first three data. If the accumulation is the same as the last byte, the transmitted data is considered to be correct.

Accumulation and checking are widely used because they are very simple to implement.However, the error-checking ability of this method is relatively general. For a single-byte check sum, there is a probability of 1/256 that the communication data that was originally wrong will be mistaken for the correct data.This check is described here because the CRC check is the same in the form of data transfer as the add-up and check, which can be expressed as: Communication data check bytes (or possibly multiple bytes)

Initial CRC algorithm

The basic idea of CRC algorithm is to treat the transmitted data as a very long number of digits.Divide this number by another number.The resulting remainder is appended to the original data as check data.Also take the data from the above example:

6, 23, 4 can be seen as a binary number: 0000011000010111 00000010

If 9 is chosen by dividing, the binary representation is: 1001

Then the division operation can be expressed as:

As you can see, the last remaining number is 1.If we use this remainder as a checksum, the data transferred is: 6, 23, 4, 1

The CRC algorithm is a bit similar to this process, but it does not use the usual division in the example above.In the CRC algorithm, binary data streams are used as coefficients of the polynomial, followed by the multiplication and division of the polynomial.Let's give an example.

For example, we have two binary numbers: 1101 and 1011.

1101 is associated with the following polynomial: 1x3+1x2+0x1+1x0=x3+x2+x0

1011 is associated with the following polynomial: 1x3+0x2+1x1+1x0=x3+x1+x0

Multiplication of two polynomials: (x3+x2+x0) (x3+x1+x0)=x6+x5+x4+x3+x3+x2+x1+x0

When the result is obtained, the modulo 2 operation is used to merge the same items.That is, multiplication and division use normal polynomial multiplication and division, while addition and subtraction use modulo 2 operations.The so-called modulo 2 operation is to divide the result by 2 and take the remainder.For example, 3 mod 2 = 1.Therefore, the resulting polynomial above is: x6+x5+x4+x3+x2+x1+x0, corresponding to the binary number: 111111

Addition and subtraction with modulo 2 is actually an operation, which is what we usually call XOR:

As mentioned above, half-day polynomials, in fact, even without introducing the concept of polynomial multiplication and division, can explain the particularity of these operations.Only polynomials are mentioned in almost all the literature explaining the CRC algorithm, so a few basic concepts are simply written here.However, it is very tedious to always use this polynomial representation, and the following instructions will try to use a more concise way of writing.

The division operation is similar to the multiplication concept given above, or the addition and subtraction are replaced by XOR.Here is an example:

The data to be transferred is: 1101011011

The divisor is set to 10011

Before calculating, four 0:11010110000 are added to the back of the original data, so the reason for adding 0 is explained later.

From this example, it can be seen that after the addition and subtraction of module 2, the problem of borrowing does not need to be considered, so division becomes simpler.The final remainder is the CRC checkword.In order to perform the CRC operation, that is, this special division operation, a dividend must be specified. In the CRC algorithm, this divider has a special name called "Generate Polynomial".Selection of the resulting polynomial is a very difficult problem. If not, the probability of detecting errors will be much lower.Fortunately, this problem has been studied by experts for a long time. For those of us users, we just need to use the ready-made results.

The most commonly used generation polynomials are as follows:

It is important to note that generating polynomials mentioned in the literature often refers to the bit width of a polynomial (Width, abbreviated as W), which is not the number of bits of the binary number corresponding to the polynomial, but the number of bits minus one.For example, the polynomial with bit width 8 used in CRC8 actually has nine bits corresponding to the binary number: 100110001.On the other hand, both polynomial and binary representations are cumbersome and inconvenient to communicate. Therefore, hexadecimal abbreviations are often used in literatures. Because the highest bit of the generated polynomial must be 1, and the position of the highest bit is known by the bit width, the highest one is removed from the abbreviation. For example, CRC32's generated polynomial abbreviated as 04C11DB7 actually represents 104C11DB7..Of course, besides being convenient, such abbreviations can also be useful in programming calculations.

For the example above, the bit width is 4 (W=4), according to the requirements of the CRC algorithm, the original data is filled with W zeros, or 4 zeros, before calculation.

There are two types of generating polynomials (CRC1) with bit width W=1, X1 and X1+X0. The reader can prove for himself that 10 corresponds to the parity check, while 11 corresponds to the parity check.So, as I write here, we know that parity is actually a special case of CRC checking, which is why I want to start with parity.

Programming implementation of CRC algorithm

So much said has finally reached the core.From the previous introduction, we know that the core of CRC checking is to implement the division operation without debit.Here is also an example of how to implement CRC checks.

Assume that our resulting polynomial is 100110001 (abbreviated as 0x31), or CRC-8

Then the calculation steps are as follows:

(1) Assign an initial value of 0 to the CRC register (8-bits, 1 bit less than the resulting polynomial)

(2) Add 8 0 after the stream to be transmitted

(3) While (data not processed)

(4) Begin

(5) If (CRC register first 1)

(6) reg = reg XOR 0x31

(7) Move the CRC register one bit to the left and read in a new data at the 0 bit position of the CRC register.

(8) End

(9) CRC registers are the remainder we require.

In fact, real CRC calculations often differ from those described above.This is due to the obvious disadvantage of this most basic CRC division, that is, adding some zeros at the beginning of the data stream does not affect the result of the final word check.This problem is very annoying, so the CRC algorithm that is actually used has basically made some small changes based on the original CRC algorithm.

The so-called change, that is, two concepts have been added, the first is "the initial value of the remainder" and the second is "the result XOR value".

The so-called "Remainder Initial Value" is to give an initial value to the CRC register at the beginning of the calculation of the CRC value."Result XOR Value" is the last checked value when the CRC register value is exclusively or with this value after the rest of the calculation is completed.

The three common CRC standards use individual parameters as shown in the table below.

With these distortions in place, common algorithmic descriptions look like this:

(1) Set up the CRC register and assign it the Remainder Initial Value.

(2) XOR the first 8-bit character of the data with the CRC register, and store the results in the CRC register.

(3) CRC registers move one bit to the right, MSB zeroes, move out and check LSB.

(4) Repeat the third step if the LSB is 0; if the LSB is 1, the CRC register is different or different from 0x31.

(5) Repeat steps 3 and 4 until all 8 shifts are completed.At this point, an 8-bit data processing is complete.

(6) Repeat steps 2 to 5 until all data is processed.

(7) The CRC value is the content of the final CRC register after performing or not operating with the Result XOR value.

The sample C code is shown below, and should be avoided in projects where calculation time is a requirement due to inefficiency.However, this code is better than the common calculation code on the web because it has a CRC parameter that allows the last computed CRC result to be passed into the function as the initial value for this calculation. This is useful for CRC calculation of large data blocks. Instead of reading all the data into memory at once, it reads part of it and calculates it once, after reading it all.This is useful for memory-constrained systems.

#define POLY        0x1021
/**
 * Calculating CRC-16 in 'C'
 * @para addr, start of data
 * @para num, length of data
 * @para crc, incoming CRC
 */
uint16_t crc16(unsigned char *addr, int num, uint16_t crc)
{
    int i;
    for (; num > 0; num--)              /* Step through bytes in memory */
    {
        crc = crc ^ (*addr++ << 8);     /* Fetch byte from memory, XOR into CRC top byte*/
        for (i = 0; i < 8; i++)             /* Prepare to rotate 8 bits */
        {
            if (crc & 0x8000)            /* b15 is set... */
                crc = (crc << 1) ^ POLY;    /* rotate and XOR with polynomic */
            else                          /* b15 is clear... */
                crc <<= 1;                  /* just rotate */
        }                             /* Loop for 8 bits */
        crc &= 0xFFFF;                  /* Ensure CRC remains 16-bit value */
    }                               /* Loop until num=0 */
    return(crc);                    /* Return updated CRC */
}

The code above is from http://mdfs.net/Info/Comp/Comms/CRC16.htm Yes, but the original code is wrong and I made some minor changes.

An example snippet code for this function is given below:

unsigned char data1[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
unsigned char data2[] = {'5', '6', '7', '8', '9'};
unsigned short c1, c2;
c1 = crc16(data1, 9, 0xffff);
c2 = crc16(data1, 4, 0xffff);
c2 = crc16(data2, 5, c2);
printf("%04x\n", c1);
printf("%04x\n", c2);

Readers can check that the results of c1 and c2 are 29b1.The initial value of crc in the code above is 0xFFFF because the divisor initial value required by the CCITT standard is 0xffff.

The above algorithm is inefficient for bit-by-bit calculation of data streams.In fact, after careful analysis of the mathematical properties of CRC calculations, we can do multi-bit and multi-bit calculations. The most common is a fast algorithm for looking up tables by bytes.The algorithm is based on the fact that the CRC code computed after this byte is equal to the lower 8-bit left shift of the last byte remainder CRC code, plus the CRC code computed after the sum of the last byte CRC right shift 8 bits and this byte.If we calculate the CRC of all the 8-bit binary sequence numbers (256 in total) and put them in a table, we just need to look up the corresponding values from the table to process them when encoding.

In this way, you can have the following code (I didn't write it either, I found it in the book Programming Embedded Systems in C and C++) by Mibael Barr, and I made a few small changes, too.):

/*
crc.h
*/
 
#ifndef CRC_H_INCLUDED
#define CRC_H_INCLUDED
 
/*
* The CRC parameters. Currently configured for CCITT.
* Simply modify these to switch to another CRC Standard.
*/
/*
#define POLYNOMIAL          0x8005
#define INITIAL_REMAINDER   0x0000
#define FINAL_XOR_VALUE     0x0000
*/
#define POLYNOMIAL          0x1021
#define INITIAL_REMAINDER   0xFFFF
#define FINAL_XOR_VALUE     0x0000
 
/*
#define POLYNOMIAL          0x1021
#define POLYNOMIAL          0xA001
#define INITIAL_REMAINDER   0xFFFF
#define FINAL_XOR_VALUE     0x0000
*/
 
/*
* The width of the CRC calculation and result.
* Modify the typedef for an 8 or 32-bit CRC standard.
*/
typedef unsigned short width_t;
#define WIDTH (8 * sizeof(width_t))
#define TOPBIT (1 << (WIDTH - 1))
 
/**
 * Initialize the CRC lookup table.
 * This table is used by crcCompute() to make CRC computation faster.
 */
void crcInit(void);
 
/**
 * Compute the CRC checksum of a binary message block.
 * @para message, Data for calculation
 * @para nBytes, Length of data
 * @note This function expects that crcInit() has been called
 *       first to initialize the CRC lookup table.
 */
width_t crcCompute(unsigned char * message, unsigned int nBytes);
 
#endif // CRC_H_INCLUDED
/*
 *crc.c
 */
 
#include "crc.h"
/*
* An array containing the pre-computed intermediate result for each
* possible byte of input. This is used to speed up the computation.
*/
static width_t crcTable[256];
 
/**
 * Initialize the CRC lookup table.
 * This table is used by crcCompute() to make CRC computation faster.
 */
void crcInit(void)
{
    width_t remainder;
    width_t dividend;
    int bit;
    /* Perform binary long division, a bit at a time. */
    for(dividend = 0; dividend < 256; dividend++)
    {
        /* Initialize the remainder.  */
        remainder = dividend << (WIDTH - 8);
        /* Shift and XOR with the polynomial.   */
        for(bit = 0; bit < 8; bit++)
        {
            /* Try to divide the current data bit.  */
            if(remainder & TOPBIT)
            {
                remainder = (remainder << 1) ^ POLYNOMIAL;
            }
            else
            {
                remainder = remainder << 1;
            }
        }
        /* Save the result in the table. */
        crcTable[dividend] = remainder;
    }
} /* crcInit() */
 
/**
 * Compute the CRC checksum of a binary message block.
 * @para message, Data for calculation
 * @para nBytes, Length of data
 * @note This function expects that crcInit() has been called
 *       first to initialize the CRC lookup table.
 */
width_t crcCompute(unsigned char * message, unsigned int nBytes)
{
    unsigned int offset;
    unsigned char byte;
    width_t remainder = INITIAL_REMAINDER;
    /* Divide the message by the polynomial, a byte at a time. */
    for( offset = 0; offset < nBytes; offset++)
    {
        byte = (remainder >> (WIDTH - 8)) ^ message[offset];
        remainder = crcTable[byte] ^ (remainder << 8);
    }
    /* The final remainder is the CRC result. */
    return (remainder ^ FINAL_XOR_VALUE);
} /* crcCompute() */
 

The crcInit() function in the code above is used to calculate the crcTable, so crcInit() must be called before calling crcCompute.However, for embedded systems, RAM is very stressful. It is best to calculate crcTable ahead of time and store it as constant data in the program store without taking up RAM space.CRC computing actually has a lot to introduce, but for ordinary programmers, it's almost as good to know.I'll write an article about the rest later.

Finally, a C++ code is given to implement the calculation of CRC8, CRC16 and CR323.Common CRC coefficients are collected.The code can be downloaded from here: https://code.csdn.net/liyuanbhu/crc_compute/tree/master

#ifndef CRCCOMPUTE_H
#define CRCCOMPUTE_H
 
#include <stdint.h>
 
template <typename TYPE> class CRC
{
public:
    CRC();
    CRC(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value);
    void build(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value);
    /**
     * Compute the CRC checksum of a binary message block.
     * @para message, Data for calculation
     * @para nBytes, Length of data
     */
    TYPE crcCompute(char * message, unsigned int nBytes);
    TYPE crcCompute(char * message, unsigned int nBytes, bool reinit);
protected:
    TYPE m_polynomial;
    TYPE m_initial_remainder;
    TYPE m_final_xor_value;
    TYPE m_remainder;
    TYPE crcTable[256];
    int m_width;
    int m_topbit;
    /**
     * Initialize the CRC lookup table.
     * This table is used by crcCompute() to make CRC computation faster.
     */
    void crcInit(void);
};
 
template <typename TYPE>
CRC<TYPE>::CRC()
{
    m_width = 8 * sizeof(TYPE);
    m_topbit = 1 << (m_width - 1);
}
 
template <typename TYPE>
CRC<TYPE>::CRC(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value)
{
    m_width = 8 * sizeof(TYPE);
    m_topbit = 1 << (m_width - 1);
    m_polynomial = polynomial;
    m_initial_remainder = init_remainder;
    m_final_xor_value = final_xor_value;
 
    crcInit();
}
 
template <typename TYPE>
void CRC<TYPE>::build(TYPE polynomial, TYPE init_remainder, TYPE final_xor_value)
{
    m_polynomial = polynomial;
    m_initial_remainder = init_remainder;
    m_final_xor_value = final_xor_value;
 
    crcInit();
}
 
template <typename TYPE>
TYPE CRC<TYPE>::crcCompute(char * message, unsigned int nBytes)
{
    unsigned int offset;
    unsigned char byte;
    TYPE remainder = m_initial_remainder;
    /* Divide the message by the polynomial, a byte at a time. */
    for( offset = 0; offset < nBytes; offset++)
    {
        byte = (remainder >> (m_width - 8)) ^ message[offset];
        remainder = crcTable[byte] ^ (remainder << 8);
    }
    /* The final remainder is the CRC result. */
    return (remainder ^ m_final_xor_value);
}
 
template <typename TYPE>
TYPE CRC<TYPE>::crcCompute(char * message, unsigned int nBytes, bool reinit)
{
    unsigned int offset;
    unsigned char byte;
    if(reinit)
    {
        m_remainder = m_initial_remainder;
    }
    /* Divide the message by the polynomial, a byte at a time. */
    for( offset = 0; offset < nBytes; offset++)
    {
        byte = (m_remainder >> (m_width - 8)) ^ message[offset];
        m_remainder = crcTable[byte] ^ (m_remainder << 8);
    }
    /* The final remainder is the CRC result. */
    return (m_remainder ^ m_final_xor_value);
}
 
class CRC8 : public CRC<uint8_t>
{
public:
    enum CRC8_TYPE {eCRC8, eAUTOSAR, eCDMA2000, eDARC, eDVB_S2, eEBU, eAES, eGSM_A, eGSM_B, eI_CODE,
                    eITU, eLTE, eMAXIM, eOPENSAFETY, eROHC, eSAE_J1850, eWCDMA};
    CRC8(CRC8_TYPE type);
    CRC8(uint8_t polynomial, uint8_t init_remainder, uint8_t final_xor_value)
        :CRC<uint8_t>(polynomial, init_remainder, final_xor_value){}
};
 
class CRC16 : public CRC<uint16_t>
{
public:
    enum CRC16_TYPE {eCCITT, eKERMIT, eCCITT_FALSE, eIBM, eARC, eLHA, eSPI_FUJITSU,
                     eBUYPASS, eVERIFONE, eUMTS, eCDMA2000, eCMS, eDDS_110, eDECT_R,
                     eDECT_X, eDNP, eEN_13757, eGENIBUS, eEPC, eDARC, eI_CODE, eGSM,
                     eLJ1200, eMAXIM, eMCRF4XX, eOPENSAFETY_A, eOPENSAFETY_B, ePROFIBUS,
                     eIEC_61158_2, eRIELLO, eT10_DIF, eTELEDISK, eTMS37157, eUSB,
                     eCRC_A, eMODBUS, eX_25, eCRC_B, eISO_HDLC, eIBM_SDLC, eXMODEM,
                     eZMODEM, eACORN, eLTE};
    CRC16(CRC16_TYPE type);
    CRC16(uint16_t polynomial, uint16_t init_remainder, uint16_t final_xor_value)
        :CRC<uint16_t>(polynomial, init_remainder, final_xor_value){}
};
 
class CRC32 : public CRC<uint32_t>
{
public:
    enum CRC32_TYPE {eADCCP, ePKZIP, eCRC32, eAAL5, eDECT_B, eB_CRC32, eBZIP2, eAUTOSAR,
                     eCRC32C, eCRC32D, eMPEG2, ePOSIX, eCKSUM, eCRC32Q, eJAMCRC, eXFER};
    CRC32(CRC32_TYPE type);
};
 
 
#endif // CRCCOMPUTE_H
#include "crcCompute.h"
 
template <typename TYPE>
void CRC<TYPE>::crcInit(void)
{
    TYPE remainder;
    TYPE dividend;
    int bit;
    /* Perform binary long division, a bit at a time. */
    for(dividend = 0; dividend < 256; dividend++)
    {
        /* Initialize the remainder.  */
        remainder = dividend << (m_width - 8);
        /* Shift and XOR with the polynomial.   */
        for(bit = 0; bit < 8; bit++)
        {
            /* Try to divide the current data bit.  */
            if(remainder & m_topbit)
            {
                remainder = (remainder << 1) ^ m_polynomial;
            }
            else
            {
                remainder = remainder << 1;
            }
        }
        /* Save the result in the table. */
        crcTable[dividend] = remainder;
    }
}
 
CRC8::CRC8(CRC8_TYPE type)
{
    switch (type)
    {
    case eCRC8:
        m_polynomial = 0x07; //http://reveng.sourceforge.net/crc-catalogue/all.htm
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eAUTOSAR:
        m_polynomial = 0x2f;
        m_initial_remainder = 0xff;
        m_final_xor_value = 0xff;
        break;
    case eCDMA2000:
        m_polynomial = 0x9b;
        m_initial_remainder = 0xFF;
        m_final_xor_value = 0x00;
        break;
    case eDARC:
        m_polynomial = 0x39;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eDVB_S2:
        m_polynomial = 0xd5;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eEBU:
    case eAES:
        m_polynomial = 0x1d;
        m_initial_remainder = 0xFF;
        m_final_xor_value = 0x00;
        break;
    case eGSM_A:
        m_polynomial = 0x1d;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eGSM_B:
        m_polynomial = 0x49;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0xFF;
        break;
    case eI_CODE:
        m_polynomial = 0x1d;
        m_initial_remainder = 0xFD;
        m_final_xor_value = 0x00;
        break;
    case eITU:
        m_polynomial = 0x07;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x55;
        break;
    case eLTE:
        m_polynomial = 0x9b;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eMAXIM:
        m_polynomial = 0x31;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eOPENSAFETY:
        m_polynomial = 0x2f;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    case eROHC:
        m_polynomial = 0x07;
        m_initial_remainder = 0xff;
        m_final_xor_value = 0x00;
        break;
    case eSAE_J1850:
        m_polynomial = 0x1d;
        m_initial_remainder = 0xff;
        m_final_xor_value = 0xff;
        break;
    case eWCDMA:
        m_polynomial = 0x9b;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    default:
        m_polynomial = 0x07;
        m_initial_remainder = 0x00;
        m_final_xor_value = 0x00;
        break;
    }
    crcInit();
 
}
 
CRC16::CRC16(CRC16_TYPE type)
{
    switch (type)
    {
    case eCCITT_FALSE:
    case eMCRF4XX:
        m_polynomial = 0x1021;
        m_initial_remainder = 0xFFFF;
        m_final_xor_value = 0x0000;
        break;
    case eIBM:
    case eARC:
    case eLHA:
    case eBUYPASS:
    case eVERIFONE:
    case eUMTS:
        m_polynomial = 0x8005;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eSPI_FUJITSU:
        m_polynomial = 0x1021;
        m_initial_remainder = 0x1d0f;
        m_final_xor_value = 0x0000;
        break;
    case eCCITT:
    case eKERMIT:
    case eXMODEM:
    case eZMODEM:
    case eACORN:
    case eLTE:
        m_polynomial = 0x1021;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eCDMA2000:
        m_polynomial = 0xc867;
        m_initial_remainder = 0xffff;
        m_final_xor_value = 0x0000;
        break;
    case eCMS:
    case eMODBUS:
        m_polynomial = 0x8005;
        m_initial_remainder = 0xffff;
        m_final_xor_value = 0x0000;
        break;
    case eDDS_110:
        m_polynomial = 0x8005;
        m_initial_remainder = 0x800d;
        m_final_xor_value = 0x0000;
        break;
    case eDECT_R:
        m_polynomial = 0x0589;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0001;
        break;
    case eDECT_X:
        m_polynomial = 0x0589;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eDNP:
    case eEN_13757:
        m_polynomial = 0x3d65;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0xffff;
        break;
    case eGENIBUS:
    case eEPC:
    case eDARC:
    case eI_CODE:
    case eX_25:
    case eCRC_B:
    case eISO_HDLC:
    case eIBM_SDLC:
        m_polynomial = 0x1021;
        m_initial_remainder = 0xffff;
        m_final_xor_value = 0xffff;
        break;
    case eGSM:
        m_polynomial = 0x1021;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0xffff;
        break;
    case eLJ1200:
        m_polynomial = 0x6f63;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eMAXIM:
        m_polynomial = 0x8005;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0xffff;
        break;
    case eOPENSAFETY_A:
        m_polynomial = 0x5935;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eOPENSAFETY_B:
        m_polynomial = 0x755b;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case ePROFIBUS:
    case eIEC_61158_2:
        m_polynomial = 0x1dcf;
        m_initial_remainder = 0xffff;
        m_final_xor_value = 0xffff;
        break;
    case eRIELLO:
        m_polynomial = 0x1021;
        m_initial_remainder = 0xb2aa;
        m_final_xor_value = 0x0000;
        break;
    case eT10_DIF:
        m_polynomial = 0x8bb7;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eTELEDISK:
        m_polynomial = 0xa097;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    case eTMS37157:
        m_polynomial = 0x1021;
        m_initial_remainder = 0x89ec;
        m_final_xor_value = 0x0000;
        break;
    case eUSB:
        m_polynomial = 0x8005;
        m_initial_remainder = 0xffff;
        m_final_xor_value = 0xffff;
        break;
    case eCRC_A:
        m_polynomial = 0x1021;
        m_initial_remainder = 0xc6c6;
        m_final_xor_value = 0x0000;
        break;
    default:
        m_polynomial = 0x8005;
        m_initial_remainder = 0x0000;
        m_final_xor_value = 0x0000;
        break;
    }
    crcInit();
}
 
 
CRC32::CRC32(CRC32_TYPE type)
{
    switch (type)
    {
    case eADCCP:
    case ePKZIP:
    case eCRC32:
    case eBZIP2:
    case eAAL5:
    case eDECT_B:
    case eB_CRC32:
        m_polynomial = 0x04c11db7;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    case eAUTOSAR:
        m_polynomial = 0xf4acfb13;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    case eCRC32C:
        m_polynomial = 0x1edc6f41;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    case eCRC32D:
        m_polynomial = 0xa833982b;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    case eMPEG2:
    case eJAMCRC:
        m_polynomial = 0x04c11db7;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0x00000000;
        break;
    case ePOSIX:
    case eCKSUM:
        m_polynomial = 0x04c11db7;
        m_initial_remainder = 0x00000000;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    case eCRC32Q:
        m_polynomial = 0x814141ab;
        m_initial_remainder = 0x00000000;
        m_final_xor_value = 0x00000000;
        break;
    case eXFER:
        m_polynomial = 0x000000af;
        m_initial_remainder = 0x00000000;
        m_final_xor_value = 0x00000000;
        break;
    default:
        m_polynomial = 0x04C11DB7;
        m_initial_remainder = 0xFFFFFFFF;
        m_final_xor_value = 0xFFFFFFFF;
        break;
    }
    crcInit();
}
 
#include <iostream>
#include <stdio.h>
#include "crcCompute.h"
 
using namespace std;
 
int main(int argc, char *argv[])
{
 
    CRC16 crc16(CRC16::eCCITT_FALSE);
    char data1[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
    char data2[] = {'5', '6', '7', '8', '9'};
    unsigned short c1, c2;
    c1 = crc16.crcCompute(data1, 9);
    c2 = crc16.crcCompute(data1, 4, true);
    c2 = crc16.crcCompute(data2, 5, false);
 
 
    printf("%04x\n", c1);
    printf("%04x\n", c2);
 
    return 0;
}

Topics: Programming REST less encoding