Solved by this code -> https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1
I searched the web for a CRC 4 implementation in C# because I have to calculate a checksum by
Changing the numbers of the barcode into Hex representation, then to bytes and then to bits and then calculate a CRC4 checksum on the bit stream.
I already found this question from 8 years ago without an answer CRC-4 implementation in C#.
I tried changing the CRC 8 and 16 implementations to CRC 4 but they don't quite get the result I require.
0130E0928270FFFFFFF
should evaluate to 7
.
I found two C implementation but was unable to convert them to C#. For example this one:
short[] crc4_tab = {
0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};
/**
* crc4 - calculate the 4-bit crc of a value.
* @crc: starting crc4
* @x: value to checksum
* @bits: number of bits in @x to checksum
*
* Returns the crc4 value of @x, using polynomial 0b10111.
*
* The @x value is treated as left-aligned, and bits above @bits are ignored
* in the crc calculations.
*/
short crc4(uint8_t c, uint64_t x, int bits)
{
int i;
/* mask off anything above the top bit */
x &= (1ull << bits) -1;
/* Align to 4-bits */
bits = (bits + 3) & ~0x3;
/* Calculate crc4 over four-bit nibbles, starting at the MSbit */
for (i = bits - 4; i >= 0; i -= 4)
c = crc4_tab[c ^ ((x >> i) & 0xf)];
return c;
}
My current generation code (unit test) looks like this:
[TestMethod]
public void x()
{
var ordnungskennzeichen = 01;
var kundennummer = 51251496;
var einlieferungsbel = 9999;
var sendungsnr = 16777215;
var hex_ordnungskennzeichen = ordnungskennzeichen.ToString("x2");
var hex_kundennummer = kundennummer.ToString("x2");
var hex_einlieferungsbel = einlieferungsbel.ToString("x2");
var hex_sendungsnr = sendungsnr.ToString("x2");
var complete = hex_ordnungskennzeichen + hex_kundennummer + hex_einlieferungsbel + hex_sendungsnr;
var bytes = Encoding.ASCII.GetBytes(complete);
//var computeChecksum = crc4(???);
// Console.WriteLine(computeChecksum);
}
short[] crc4_tab = {
0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};
/**
* crc4 - calculate the 4-bit crc of a value.
* @crc: starting crc4
* @x: value to checksum
* @bits: number of bits in @x to checksum
*
* Returns the crc4 value of @x, using polynomial 0b10111.
*
* The @x value is treated as left-aligned, and bits above @bits are ignored
* in the crc calculations.
*/
short crc4(byte c, ulong x, int bits)
{
int i;
/* mask off anything above the top bit */
x &= ((ulong)1 << bits) -1;
/* Align to 4-bits */
bits = (bits + 3) & ~0x3;
/* Calculate crc4 over four-bit nibbles, starting at the MSbit */
for (i = bits - 4; i >= 0; i -= 4)
c = (byte) crc4_tab[c ^ ((x >> i) & 0xf)];
return c;
}
Converting it to C# is not very hard. c
is initial or previous nibble (4-bit number), x
is 64bit number you want to calculate crc4 of, bits
is number of bits in that 64bit number to actually use (the rest are ignored). Since you have array of bytes - you don't need to use 64bit number as x
- use can just use byte. Then the first two lines are irrelevant for you, because all they do is throwing away irrelevant bits from 64bit number and ensuring bits
is divisable by 4. So after removing irrelevant lines your implementation becomes:
static readonly byte[] crc4_tab = {
0x0, 0x7, 0xe, 0x9, 0xb, 0xc, 0x5, 0x2,
0x1, 0x6, 0xf, 0x8, 0xa, 0xd, 0x4, 0x3,
};
static byte crc4(byte c, byte x) {
var low4Bits = x & 0x0F;
var high4Bits = x >> 4;
c = crc4_tab[c ^ high4Bits];
c = crc4_tab[c ^ low4Bits];
return c;
}
static byte crc4(byte[] array) {
byte start = 0;
foreach (var item in array) {
start = crc4(start, item);
}
return start;
}
After further testing and communication with the Deutsche Post AG we made a correct implementation (for the purpose of Deutsche Post at least):
https://gist.github.com/Sbreitzke/b26107798eee74e39ff85800abf71fb1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With