Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CRC 4 implementation for C#

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;
}
like image 291
Zebi Avatar asked Jan 29 '23 08:01

Zebi


2 Answers

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;
}
like image 63
Evk Avatar answered Feb 02 '23 11:02

Evk


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

like image 45
Zebi Avatar answered Feb 02 '23 11:02

Zebi