Cannot reproduce working CRC-16/CCITT KERMIT with C#
I found an example of working CRC-16/CCITT KERMIT python code shown below: def make_crc_table(): poly = 0x8408 table = [] for byte in range(256): crc = 0 for bit in range(8): if (byte ^ crc) & 1: crc = (crc >> 1) ^ poly else: crc >>= 1 byte >>= 1 table.append(crc) return table table = make_crc_table() def crc_16_fast(msg): crc = 0xffff for byte in msg: crc = table[(byte ^ crc) & 0xff] ^ (crc >> 8) return crc ^ 0xffff # Test packet = "64 23 2F 36 27 2F 2F 23 1F 25" # Perform CRC16 (Kermit - with poly of 0x8408) msg = bytes.fromhex(packet) out = crc_16_fast(msg) hi, lo = out >> 8, out & 0xff print('{:04x} = {:02x} {:02x}'.format(out, hi, lo)) The output is shown below and matches what I expect: a40e = a4 0e I am trying to reproduce this in C#. I found the following code snippet, however it returns differing results from the python code. So far I have not been able to figure out what the difference is. How can I get the C# code to produce the same expected output? using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; public enum Crc16Mode : ushort { Standard = 0xA001, CcittKermit = 0x8408 } namespace CollinsWirelessTransModule { public class Crc16 { readonly ushort[] table = new ushort[256]; public ushort ComputeChecksum(params 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(params byte[] bytes) { ushort crc = ComputeChecksum(bytes); return BitConverter.GetBytes(crc); } public Crc16(Crc16Mode mode) { ushort polynomial = (ushort)mode; Console.WriteLine("Polynomial: " + polynomial.ToString("X")); 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; } } } class Program { static void Main(string[] args) { var commsCrc = new Crc16(Crc16Mode.CcittKermit); var checkBytes = new byte[] { 0x64, 0x23, 0x2F, 0x36, 0x27, 0x2F, 0x2F, 0x23, 0x1F, 0x25 }; var valueToPrint = commsCrc.ComputeChecksum(checkBytes); var bytesToPrint = BitConverter.GetBytes(valueToPrint); string hex = BitConverter.ToString(bytesToPrint); Console.WriteLine("Hex bytes: " + hex); // Wait for the user to respond before closing. Console.ReadKey(); } } } The output here does not match Python and looks like: Polynomial: 8408 Hex bytes: 76-C7 I made sure the polynomial and starting values were the same.
I found an example of working CRC-16/CCITT KERMIT python code shown below:
def make_crc_table():
poly = 0x8408
table = []
for byte in range(256):
crc = 0
for bit in range(8):
if (byte ^ crc) & 1:
crc = (crc >> 1) ^ poly
else:
crc >>= 1
byte >>= 1
table.append(crc)
return table
table = make_crc_table()
def crc_16_fast(msg):
crc = 0xffff
for byte in msg:
crc = table[(byte ^ crc) & 0xff] ^ (crc >> 8)
return crc ^ 0xffff
# Test
packet = "64 23 2F 36 27 2F 2F 23 1F 25"
# Perform CRC16 (Kermit - with poly of 0x8408)
msg = bytes.fromhex(packet)
out = crc_16_fast(msg)
hi, lo = out >> 8, out & 0xff
print('{:04x} = {:02x} {:02x}'.format(out, hi, lo))
The output is shown below and matches what I expect:
a40e = a4 0e
I am trying to reproduce this in C#. I found the following code snippet, however it returns differing results from the python code. So far I have not been able to figure out what the difference is. How can I get the C# code to produce the same expected output?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public enum Crc16Mode : ushort { Standard = 0xA001, CcittKermit = 0x8408 }
namespace CollinsWirelessTransModule
{
public class Crc16
{
readonly ushort[] table = new ushort[256];
public ushort ComputeChecksum(params 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(params byte[] bytes)
{
ushort crc = ComputeChecksum(bytes);
return BitConverter.GetBytes(crc);
}
public Crc16(Crc16Mode mode)
{
ushort polynomial = (ushort)mode;
Console.WriteLine("Polynomial: " + polynomial.ToString("X"));
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;
}
}
}
class Program
{
static void Main(string[] args)
{
var commsCrc = new Crc16(Crc16Mode.CcittKermit);
var checkBytes = new byte[] { 0x64, 0x23, 0x2F, 0x36, 0x27, 0x2F, 0x2F, 0x23, 0x1F, 0x25 };
var valueToPrint = commsCrc.ComputeChecksum(checkBytes);
var bytesToPrint = BitConverter.GetBytes(valueToPrint);
string hex = BitConverter.ToString(bytesToPrint);
Console.WriteLine("Hex bytes: " + hex);
// Wait for the user to respond before closing.
Console.ReadKey();
}
}
}
The output here does not match Python and looks like:
Polynomial: 8408
Hex bytes: 76-C7
I made sure the polynomial and starting values were the same.