To calculate CRC I found a piece of code but I am not understanding the concept.
Here is the code:
count =128 and ptr=some value;
calcrc(unsigned char *ptr, int count)
{
unsigned short crc;
unsigned char i;
crc = 0;
while (--count >= 0)
{
crc = crc ^ (unsigned short)*ptr++ << 8;
i = 8;
do
{
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
} while(--i);
}
return (crc);
}
Please any body explain and tell me the logic.
This looks like a CRC (specifically it looks like CRC-16-CCITT, used by things like 802.15.4, X.25, V.41, CDMA, Bluetooth, XMODEM, HDLC, PPP and IrDA). You might want to read up on the CRC theory on the linked-to Wikipedia page, to gain some more insight. Or you can view this as a "black box" that just solves the problem of computing a checksum.
You will probably need to know that in C, the ^ operator is a bitwise XOR operator and the << operator is the left shift operator (equivalent to multiplication by 2 to the power of the number on the right of the operator). Also the crc & 0x8000 expression is testing for the most significant bit set of the variable crc.
This will help you to work out a low level explanation of what is occurring when this runs, for a high level explanation of what a CRC is and why you might need it, read the Wikipedia page or How Stuff Works.
One famous text on CRCs is "A Painless Guide to CRC Error Detection Algorithms" by Ross Williams. It takes some time to absorb but it's pretty thorough.
Take a look at my answer to
How could I guess a checksum algorithm?
Related
I am analyzing the MODBUS protocol (rs232 com port) used in the DPS5020 power supply module and I cannot understand the CRC calculation method in RTU mode (page 3) https://cloud.kyme32.ro/ftp_backup/DPS5020%20PC%20Software(2017.11.04)/DPS5020%20CNC%20Communication%20%20Protocol%20V1.2.pdf.
In the first example on page 4 for sending bytes 1, 3,0,2,0,2 the value CRC = 65CB (Hex) is indicated (2 byte swapped).
I've also tried several CRC calculators online but can't find the right value.
I also did a step-by-step diagram of the calculation and the right rotation of the bits, but the values do not return to me.
Is it necessary to use all the bytes of the frame (6) for the calculation or only the data values (4)? I have tried both without success...
Could you kindly put a little diagram of how the calculation is done and the return values step by step (16 bit xor with A001 value, rotate right yes / no ... etc)?
I know that in the end you have to swap the 2 bytes between them but the single values do not come back to me anyway.
Or is it simply a misprint of the manual?
All bytes in the frame are used in the CRC calculation.
Here is a C implementation of the CRC, which should answer your question about exactly what to shift and exclusive-or when:
#include <stddef.h>
#include <stdint.h>
uint16_t crc16modbus_bit(uint16_t crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffff;
for (size_t i = 0; i < len; i++) {
crc ^= data[i];
for (unsigned k = 0; k < 8; k++) {
crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
}
}
return crc;
}
(The initial CRC value is returned when called with mem equal to NULL.)
Where I can find this crc32() function in detail? I saw this Link but I couldn't figure out how CRC is being calculated.
I asked a question about updating the CRC based on the data stream instead of waiting to have all the data. I got the answer as follows (Thanks to #MarkAdler):
unsigned long crc = crc32(0, NULL, 0); // initial CRC
for (...) { // some sort of loop
... // generating a chunk of data
crc = crc32(crc, buf, len); // update the CRC with the data
... // this all gets repeated many times
}
... // loop is done, crc has the CRC
Can you please be more specific about the crc32() function?
Is there any pseudo code for that function which explains it?
And for loop here is for getting data right?
Thank you
More specific how?
Do you want an explanation of how to use it, or how it works internally? How it works internally is in the source code you linked.
Yes. You would get chunks of data from wherever, and feed them through crc32() to get the CRC-32/ISO-HDLC of the entire stream of data.
As for the source code you linked, that was not written to teach anyone about how CRC's work. It was written to be fast. Here is a simple, but slow (one bit at a time), CRC routine in C, that may, or may not, help you with what you're looking for:
uint32_t crc32iso_hdlc_bit(uint32_t crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0;
crc = ~crc;
for (size_t i = 0; i < len; i++) {
crc ^= data[i];
for (unsigned k = 0; k < 8; k++) {
crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
}
}
crc = ~crc;
return crc;
}
(That code was generated by crcany.)
If you would like to learn more about CRCs, start here.
I have a legacy C++ binary operation code like this:
constexpr static uint64_t val2bin(double val) {
uint64_t bin = (val > 0.) ? uint64_t(val/0.01)+1 : 0;
return (bin > 510) ? 511 : bin;
}
And the result is then used as part of expression:
static uint64_t const MASK = 0x1FF;
static uint64_t const VAL_OFFSET = 10;
((val2bin(val) & MASK) << VAL_OFFSET)
Doesn't it put an upper limit on val we can encode in this way? I am not able to comprehend what we are trying to achieve functionally by this?
Doesn't it put an upper limit on val we can encode in this way?
It will put an upper limit on the output you can have.
The operation performed here:
static uint64_t const MASK = 0x1FF;
static uint64_t const VAL_OFFSET = 10;
((val2bin(val) & MASK) << VAL_OFFSET)
will give val<<VAL_OFFSET as the output for val < 0x1FF and hence it won't cross the limit of uint64_t. For values greater than 0x1FF, the output will be MASK << VAL_OFFSET which still won't cross the limit of uint64_t (i.e. MASK = 511 therefore, the output is 523264). This is the aforementioned "upper limit" on the output i.e. 523264.
I am not able to comprehend what we are trying to achieve functionally by this?
Even I am not able to exactly comprehend what functionality we are trying to achieve here. Maybe you can provide some extra piece of code around this snippet and it may help.
I know this answer states the obvious but that's all I could infer as of now.
Best.
I need to create a program, that calculates CRC from file. It needs to be done bit by bit.
The way I would like to read a file:
unsigned char byte;
ifstream file;
bool result;
int number;
file.open("test.txt", ios::binary);
while(true)
{
byte = file.get();
number = (int)byte;
result = file.good();
if(!result)
break;
}
However, I don't know how to read it bit by bit.
My CRC's divisor (called a "polynomial") is 0x04C11DB7 and I need to import 1 new bit from file each time I calculate my buffer.
My idea is to add first 4 bytes to variable (for let's say "1234" it would be 0x31323334), then remove last bit (by moving the number 1 bit to the left), but I don't know how to add a new bit from the next char.
Do you mean something along these lines?
The CRC calculation may vary, but the focus here is on getting the file content "bit by bit".
#include <iostream>
#include <fstream>
int main(int argc, char* argv[])
{
unsigned char next;
unsigned long crc = 0;
if (argc < 2)
return -1;
std::fstream fs(argv[1], std::fstream::in);
while (!fs.bad() && !fs.eof())
{
fs >> next;
for (int i = 0; i < 8; i++)
{
crc += next & 1;
next >>= 1;
}
}
std::cout << "CRC " << crc << std::endl;
return 0;
}
The divisor is not just called a polynomial. It means that each bit is a coefficient of a polynomial (of degree 32) and thus the way of computing with polynomial differs significantly from working with integers. You can add (and substract, which is the same in this case) two polynomials with a simple XOR operation. Multiplying/Dividing with/by X means shifting. To the right or to the left depends on the order in which the coefficients of the polynomials are written. This is important to know because both directions (left to right and right to left) actually exist. In the case of 0x04C11DB7, the coefficient of X^0 is bit 0 and the coefficient of X^31 is bit 31. Be aware that the popular implementation of the IEEE802.3 CRC has the opposite bit order. So, just copying the implementation of an Ethernet CRC will not work.
This means the next bit to process is always bit 31. You must therefore check for 0x80000000. If the bit is set, XOR your polynomial. This means, you subtract the polynomical from your work register. In any case, shift the result to the left afterwards. Then a 0 bit is shifted in at the right. Replace it with the next bit to process by a binary or operation (| in C++). You obtain that bit in the same way: if you are reading byte by byte, your next bit is 1 or 0, depending on whether 0x80 is set in your input. Then shift your input to the left.
I am helping out a friend of mine who is a bit stuck and my own c++ skills are very rusty. My interest and curiosity is quite picked by this. so I shall try and explain this as best I can. Note its a 32 bit check.
uint32_t CRC32::calculate_CRC32(const uint32_t* plData, uint32_t lLength, uint32_t previousCrc32)
{
uint32_t lCount;
const uint32_t lPolynomial = 0x04C11DB7;
uint32_t lCrc = previousCrc32;
unsigned char* plCurrent = (unsigned char*) plData;
lCrc ^= *plCurrent++;
while (lLength-- != 0)
{
for (lCount = 0 ; lCount < lLength; lCount++)
{
if (lCrc & 1)
lCrc = (lCrc >> 8) ^ lPolynomial;
else
lCrc = lCrc >> 8;
}
}
return lCrc;
}
Now ILength is the number of bytes that the packet contains. plData is the packet for which data needs to be checked. As it is, the function works. But it works bit for bit. It needs to be improved to work byte for byte. So to all genius c++ developers out there who far surpasses my knowledge. Any ideas will be really helpful. Thanks in advance guys.
Read Ross Williams excellent tutorial on CRCs, especially section 9 on "A Table-Driven Implementation", which calculates the CRC a byte at a time instead of a bit at a time. You can also look at the somewhat more involved CRC implementation in zlib, which calculates it four bytes at a time. You can also calculate it eight bytes at a time.