2.2 Hash
Der Hash wird über die UID des Senders gebildet. Dazu werden das obere und das untere Word per XOR verknüpft.
Zusätzlich müssen die Bits 7-9 auf die Werte 110 binär gesetzt werden.
1
2
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Hash
1 1 0
Damit die Berechnung des Hashs anschaulicher wird, werden jetzt im folgenden die Berechnung Schritt für Schritt erklärt.
Das untere Word der UID bekommt man, indem einfach das untere Word ausmaskiert wird. D.h. die UID wird per AND mit einem Wert verknüpft, in dem nur die unteren 16 Bits gesetzt sind:
Das obere Word erhält man, indem die UID um 16 Bits nach rechts verschoben wird:
Beide Teile werden per XOR verknüpft:
1
(UID & 0x0000FFFF) ^ (UID >> 16)
Bit 7 soll den Wert 0 haben, also wird das Ergebnis der XOR Verknüpfung mit einer Mask per AND verknüpft, in der dieses Bit nicht gesetzt ist:
1
((UID & 0x0000FFFF) ^ (UID >> 16)) & 0xFF7F
Die Bits 8 und 9 sollen den Wert 1 haben. Also wird das Ergebnis per OR mit einer Maske verknüpft, die diese Bits gesetzt haben:
1
(((UID & 0x0000FFFF) ^ (UID >> 16)) & 0xFF7F) | 0x0300
Und nochmals als Funktion:
1
2
3
4
unsigned short CalcHash(unsigned long UID)
{
return (((UID & 0x0000FFFF) ^ (UID >> 16)) & 0xFF7F) | 0x0300;
}
Und wozu wird der Hash nun benutzt?
Zum einen dazu, doppelte Adressen zu vermeiden. Wenn ein Teilnehmer am CAN Bus eine Nachricht mit dem eigenen Hash empfängt, muß ein neuer Hash gewählt werden. Was gleichbedeutend dazu ist, eine neue UID zu wählen. Denn es kann sein, daß der andere Teilnehmer die gleiche UID hat. Es kann sein, muß aber nicht. Denn der Wertebereich für die UID sidn 32 Bit, für den Hash 16 Bit. Also können verschiedene UIDs auch zum gleichen Hash führen.
Und dann kann der Hash dazu benutzt werden, die Nachricht von Nachrichten der MS1 zu unterscheiden. Märklin hat ja definiert, daß die Bits 7-9 die Werte 110 binär haben müssen (siehe oben). Und damit auch in der Meldungskennung die Bits 7-9 die Werte 110 binär haben (siehe 2. Mesldungskennung). Diese Bits haben in einer Nachricht der MS1 nienmals diese Werte. Und damit können diese CS2/MS2 Nachrichten von den MS1 Nachrichten unterschieden werden. Wir verknüpfen also einfach den Hash per AND mit einer Maske, die nur diese 3 Bits enthält und können das Ergebnis mit den gewünschten Wert vergleichen:
1
2
3
4
int IsCs2Msg(unsigned short Hash)
{
return (Hash & 0x0380) == 0x0300;
}
2.2.1 Folgenummer
Werden Daten übertragen, wie z.B. die Loks der MS2 oder die lokomotive der CS2, dann wird anstelle des Hashs die Folgenummer übertragen. D.h. die zu einer Datenübertragung gehörenden Pakete bekommen eine fortlaufende Nummer. Da ja die Bits 7-9 einen definierten Wert haben müssen, werden für die Folgenummer nur 13 Bits benutzt. Die untersten 7 Bits werden in die untersten Bits des Hashwerts geschrieben. Die obersten 6 Bits werden in die obersten Bits des zweiten Bytes des Hash geschrieben. Die folgenden Skizze zeigt, wo die einzelnen Bits der Folgenummer im Hash landen:
1
2
3
4
5
6
7
8
9
10
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Hash
1 1 0 |
|
|
|
|
|
|
|
0 0 0 x x x x x x x x x x x x x Folgenummer
Und nun das ganze als Algorithmus. Die unteren Bits werden einfach wieder ausmaskiert:
Die oberen Bits werden auch ausmaskiert und dann um die 3 Stellen nach links verschoben:
1
(Folgenummer & 0x1f80) << 3
Und dann müssen nur die beiden Werte mit OR zusammen verknüpft werden. Dann müssen nur noch die Bits 7-9 wie oben beschrieben gesetzt werden. Damit ergibt sich der Hash aus der Folgenummer wie folgt:
1
2
3
4
unsigned short CalcHashFromFolgenummer(unsigned short Folgenummer)
{
return ((((Folgenummer & 0xfc00) << 3) | (Folgenummer & 0x007F)) & 0xFF7F) | 0x0300;
}
Achtung: Märklin hält sich hier nicht unbedingt an die eigene Doku. In der Lokliste der MS2 war keine Folgenummer gesetzt, sondern der Hash hatte den Wert 0. Da damit die Bits 7-9 nicht den Wert 110 binär haben, sind diese Nachrichten nicht als CS2/MS2 Nachrichten erkennbar!