So I have this C code that I need to port to C#:
C Code:
uint16 crc16_calc(volatile uint8* bytes, uint32 length)
{
uint32 i;
uint32 j;
uint16 crc = 0xFFFF;
uint16 word;
for (i=0; i < length/2 ; i++)
{
word = ((uint16*)bytes)[i];
// upper byte
j = (uint8)((word ^ crc) >> 8);
crc = (crc << 8) ^ crc16_table[j];
// lower byte
j = (uint8)((word ^ (crc >> 8)) & 0x00FF);
crc = (crc << 8) ^ crc16_table[j];
}
return crc;
}
Ported C# Code:
public ushort CalculateChecksum(byte[] bytes)
{
uint j = 0;
ushort crc = 0xFFFF;
ushort word;
for (uint i = 0; i < bytes.Length / 2; i++)
{
word = bytes[i];
// Upper byte
j = (byte)((word ^ crc) >> 8);
crc = (ushort)((crc << 8) ^ crc16_table[j]);
// Lower byte
j = (byte)((word ^ (crc >> 8)) & 0x00FF);
crc = (ushort)((crc << 8) ^ crc16_table[j]);
}
return crc;
}
This C algorithm calculates the CRC16 of the supplied bytes using a lookup table crc16_table[j]
However the Ported C# code does not produce the same results as the C code, am I doing something wrong?
word = ((uint16*)bytes)[i];
reads two bytes from bytes into a uint16, whereas
word = bytes[i];
just reads a single byte.
Assuming you're running on a little endian machine, your C# code could change to
word = bytes[i++];
word += bytes[i] << 8;
Or, probably better, as suggested by MerickOWA
word = BitConverter.ToInt16(bytes, i++);
Note that you could avoid the odd-looking extra increment of i by changing your loop:
for (uint i = 0; i < bytes.Length; i+=2)
{
word = BitConverter.ToInt16(bytes, i);
Related
I have this code which calculate CRC-32, I need to edit this code with: Polynomial 0x04C11DB7 ,Initial value: 0xFFFFFFFF , XOR:0 .
So CRC32 for string "123456789" should be"0376E6E7", I found a code, it's very slow , But it works any way.
```internal static class Crc32
{
internal static uint[] MakeCrcTable()
{
uint c;
uint[] crcTable = new uint[256];
for (uint n = 0; n < 256; n++)
{
c = n;
for (int k = 0; k < 8; k++)
{
var res = c & 1;
c = (res == 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
}
crcTable[n] = c;
}
return crcTable;
}
internal static uint CalculateCrc32(byte[] str)
{
uint[] crcTable = Crc32.MakeCrcTable();
uint crc = 0xffffffff;
for (int i = 0; i < str.Length; i++)
{
byte c = str[i];
crc = (crc >> 8) ^ crcTable[(crc ^ c) & 0xFF];
}
return ~crc; //(crc ^ (-1)) >> 0;
}
}```
Based on the added comments, what you are looking for is CRC-32/MPEG-2, which reverses the direction of the CRC, and eliminates the final exclusive-or, compared to the implementation you have, which is a CRC-32/ISO-HDLC.
To get there, you need to flip the CRC from reflected to forward. You bit-flip the polynomial to get 0x04c11db7, check the high bit instead of the low bit, reverse the shifts, both in the table generation and use of the table, and exclusive-or with the high byte of the CRC instead of the low byte.
To remove the final exclusive-or, remove the tilde at the end.
I'm trying to port the CRC calculation function for Modbus RTU from C# to Python.
C#
private static ushort CRC(byte[] data)
{
ushort crc = 0xFFFF;
for (int pos = 0; pos < data.Length; pos++)
{
crc ^= (UInt16)data[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
Which I run like this:
byte[] array = { 0x01, 0x03, 0x00, 0x01, 0x00, 0x01 };
ushort u = CRC(array);
Console.WriteLine(u.ToString("X4"));
Python
def CalculateCRC(data):
crc = 0xFFFF
for pos in data:
crc ^= pos
for i in range(len(data)-1, -1, -1):
if ((crc & 0x0001) != 0):
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return crc
Which I run like this:
data = bytearray.fromhex("010300010001")
crc = CalculateCRC(data)
print("%04X"%(crc))
The result from the C# example is: 0xCAD5.
The result from the Python example is: 0x8682.
I know from fact by other applications that the CRC should be 0xCAD5, as the C#-example provides.
When I debug both examples step-by-step, the variable 'crc' has difference values after these code lines:
crc ^= (UInt16)data[pos];
VS
crc ^= pos
What am I missing?
/Mc_Topaz
Your inner loop uses the size of the data array instead of a fixed 8 iterations. Try this:
def calc_crc(data):
crc = 0xFFFF
for pos in data:
crc ^= pos
for i in range(8):
if ((crc & 1) != 0):
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return crc
data = bytearray.fromhex("010300010001")
crc = calc_crc(data)
print("%04X"%(crc))
I have to translate a CRC16 calculation from C to C# but get the message that I cannot implicitly convert type 'int' to 'bool' on the (crc & 0x8000) and on return (crc & 0xFFFF)
The code so far:
public unsafe short Crc16(string str)
{
short crc = 0;
for(int i = 0; i < str.Length; i++)
{
crc = (crc << 1) ^ str[i] ^ ((crc & 0x8000) ? 0x1021 : 0);
}
return (crc & 0xFFFF);
}
EDIT: Changed char parameter to string
Original C code
short Crc16( char *str )
{
short crc=0;
unsigned int i;
for (i=0; i<strlen(str); i++)
crc = (crc << 1) ^ *(str+i) ^ ((crc & 0x8000)? 0x1021:0 );
return (crc & 0xffff);
}
In C, 0 and FALSE are synonymous, and any number that is not 0 is true. (reference)
To make the conversion you would do it something like this:
public short CalcCrc16(string str)
{
short crc = 0;
int i;
unchecked
{
foreach(char c in str)
{
short exponent = (crc & 0x8000) != 0 ? 0x1021 : 0;
crc = (crc << 1) ^ ((short)c) ^ exponent);
}
return (short)(crc & 0xFFFF);
}
}
So now that we have the C code to work with, I changed the code sample I have here to match. Below is the explanation of the changes:
char* is the C equivalent of a string
The for loop is iterating over the characters *(str + i) can be rewritten as str[i], and is equivalent to C#'s str.GetChar(i)
The ternary condition is to determine whether the exponent is 0x1021 or 0.
I broke up the lines so you could see the algorithm a bit clearer.
I changed for(int i = 0; i < str.Length; i++) to a foreach on the characters because it was easier to understand.
Using C#.net,WPF application.I'm going to connect to a device (MODBUS protocol), I have to calculate CRC (CRC16).
Function which i use calculate normal crc16 and value is correct,but i want the value for CRC16(modbus) one.
Help me to sort out.
There are a lot of resources online about the calculation of the crc16 for the modbus protocol.
For example:
http://www.ccontrolsys.com/w/How_to_Compute_the_Modbus_RTU_Message_CRC
http://www.modbustools.com/modbus_crc16.htm
I think that translating that code in c# should be simple.
You can use this library:
https://github.com/meetanthony/crccsharp
It contains several CRC algorithms included ModBus.
Usage:
Download source code and add it to your project:
public byte[] CalculateCrc16Modbus(byte[] bytes)
{
CrcStdParams.StandartParameters.TryGetValue(CrcAlgorithms.Crc16Modbus, out Parameters crc_p);
Crc crc = new Crc(crc_p);
crc.Initialize();
var crc_bytes = crc.ComputeHash(bytes);
return crc_bytes;
}
Just use:
public static ushort Modbus(byte[] buf)
{
ushort crc = 0xFFFF;
int len = buf.Length;
for (int pos = 0; pos < len; pos++)
{
crc ^= buf[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
crc >>= 1;
}
}
// lo-hi
//return crc;
// ..or
// hi-lo reordered
return (ushort)((crc >> 8) | (crc << 8));
}
(curtesy of https://www.cyberforum.ru/csharp-beginners/thread2329096.html)
Boost CRC (Added due to title)
auto v = std::vector< std::uint8_t > { 0x12, 0x34, 0x56, 0x78 };
auto result = boost::crc_optimal<16, 0x8005, 0xFFFF, 0, true, true> {};
result.process_bytes(v.data(), v.size());
I found this C# code for CRC16 but I need it on F# :
using System;
public class Crc16 {
const ushort polynomial = 0xA001;
ushort[] table = new ushort[256];
public ushort ComputeChecksum(byte[] bytes) {
ushort crc = 0;
for(int i = 0; i < bytes.Length; ++i) {
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes) {
ushort crc = ComputeChecksum(bytes);
return BitConverter.GetBytes(crc);
}
public Crc16() {
ushort value;
ushort temp;
for(ushort i = 0; i < table.Length; ++i) {
value = 0;
temp = i;
for(byte j = 0; j < 8; ++j) {
if(((value ^ temp) & 0x0001) != 0) {
value = (ushort)((value >> 1) ^ polynomial);
}else {
value >>= 1;
}
temp >>= 1;
}
table[i] = value;
}
}
}
Here is where I started :
let ComputeChecksum(bytes : byte array) =
let mutable crc = 0us
for i = 0 to bytes.Length do
let index = (crc ^^^ bytes.[i]) // ? uint16 and byte
So I think C# version is taking here first or second byte. So I want to know how C# '^' will work here ? And how can I translate this line of C# code to F# ?
This computes the same result as your C# code.
type Crc16() =
let polynomial = 0xA001us
let table = Array.init 256 (fun i ->
((0us, uint16 i), [0y..7y])
||> Seq.fold (fun (value, temp) j ->
let newValue =
match (value ^^^ temp) &&& 0x0001us with
| 0us -> value >>> 1
| _ -> ((value >>> 1) ^^^ polynomial)
newValue, temp >>> 1)
|> fst)
member __.ComputeChecksum(bytes:byte[]) =
(0us, bytes) ||> Seq.fold (fun crc byt ->
let index = byte (crc ^^^ (uint16 byt))
(crc >>> 8) ^^^ table.[int index])
C# ^ and F# ^^^ are both the XOR operator. They should work the same. Is that what you're asking?