Automatische Lokanmeldung mit DCC/Railcom
CRC4
-
In der automatischen Anmeldung werden Dekoder-ID und Hash an die Zentrale übermittelt. Inbesondere die
Übermittlung der DekoderID ist Übertragungsfehlern ausgesetzt, da ja auf die Nachricht LOGON_ENABLE fallweise mehrere
Dekoder zugleich antworten können.
Deswegen werden diese Nachrichten zusätzlich zur Gewichtskodierung (Hamminggewicht von 4 je Byte) mit einer Prüfsumme gesichert. Verwendet wird CRC4/ITU.
Polynom: | x4 + x1 + 1 |
---|---|
Initwert: | 0 |
Berechnungstool
Beispielcode
- Implementierung mit bitweiser Berechnung:
uint8_t crc4itu_bit(const uint8_t *data) { uint8_t crc = 0; // init uint8_t length = 5; // length fix auf 5 Bytes for (uint8_t i=0; i<length; i++) { for (uint8_t s=0; s<8; s++) { if ((crc & 1) ^ ((data[i] >> s) & 1)) crc = (crc >> 1) ^ 0b1100; // reflected lsbs of polynomial else crc = crc >> 1; } } return crc; }
- Implementierung mit nibbleweiser Berechnung (schneller, kleine Tabelle)
uint8_t crc4itu_nibble(const uint8_t *data) { uint8_t table[] = { 0x0, 0xd, 0x3, 0xe, 0x6, 0xb, 0x5, 0x8, 0xc, 0x1, 0xf, 0x2, 0xa, 0x7, 0x9, 0x4 }; uint8_t crc = 0; uint8_t length = 5; for (uint8_t i=0; i<length; i++) { crc = table[(crc ^ (data[i] >> 0)) & 0xf]; crc = table[(crc ^ (data[i] >> 4)) & 0xf]; } return crc; }
- Implementierung mit byteweiser Berechnung (schnell, Tabelle mit 256 Bytes)
const unsigned char crc4_array[256] = { 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2 }; uint8_t crc4itu_byte(const uint8_t *data) { uint8_t crc = 0; uint8_t length = 5; while (length--) crc = crc4_array[crc ^ *(unsigned char const *)data++)]; return crc; }
Links, Quellen
-
CRC4/ITU ist mehrfach im Netz zu finden, zu beachten ist jeweils das Verwendete Polynom, der Initwert, die Bitorder und ob das Ergebnis nochmal
invertiert wird.
https://github.com/mozram/CRC4-ITU/blob/master/crc4_itu.c
https://stackoverflow.com/a/39091316