Doehler & Haass Decoder Lesen und Programmieren
SX1-Programmier-Modul Prinzipien und Signale
Sx-Bus Steuerkanäle
Im Adressraum des SX1-Bus sind bestimmte Adressen für die Systemsteuerung vorgesehen,
insbesondere gilt dies für den erweiterten SX-Bus "SX2" der hier nicht berücksichtigt ist.
Reservierte Adressen, nicht für allgemeine Verwendung empfohlen :
Adr. BitNr. 8 7 6 5 4 3 2 1
7 6 5 4 3 2 1 0
000 Datenbyte, erweiterte Lokparameter |I-Br.| |frei| |H| | max. V|
| Sonder Codierung Anschl. |
104 Daten Lok-Decoder |I-Br.| | Beschl. | | max. V|
105 Daten Lok-Decoder |H| | Basis- und Unteradresse |
106 Steuerkanal |D| |P| |0 0| |B| | Modus |
107 DCC reserviert
108 Adresserweiterung DCC
109 System Zustand |G| |P| |S| |K| |Betriebsart |
110 System Kanal
111 Modell-Uhrzeit
127 System Kanal
Für die Lok-Decoder Behandlung nach SX1 sind also die Kanäle 104, 105, 106 und 109 relevant.
Das SX-Lok-Decoder_Modul muss diese Adressen lesen und schreiben können.
Ablaufsteuerung und Kommunikation:
Der Lese- und Schreibvorgang spielt sich letztlich auf der Gleisspannung ab, denn der Decoder ist ja nur mit diesen
beiden "Drähten" an das System angeschlossen. Zum Senden wird also ein spezielles Gleissignal, eine Spannungs-
impulsfolge, verwendet die der Decoder "versteht". Das Auslesen der Decoderdaten kann nicht durch einen Befehl
an den Decoder angestoßen werden, sondern geschieht automatisch bei jedem Anlegen einer Gleichspannung. Der
Decoder sendet Stromimpulse die das Programmiermodul auswertet. Beide Vorgänge haben also mit dem "normalen"
Gleissignal nichts zu tun, d.h. es kann in keinem Fall gleichzeitig auf dem Gleis ein Fahrbetrieb stattfinden und es kann
nur ein einziger Decoder zu diesem Zeitpunkt mit dem Programmiermodul verbunden sein.
Für das Lesen und Schreiben der Decoderdaten ist auch keine leistungsfähige Endstufe, wie in einer Fahrzentrale
oder einem Booster, erforderlich. Auch die Verbindung zu einer SX-Zentrale oder einem SX-Interface ist prinzipiell
nicht notwendig, denn weder die SX-Busdaten noch das PX-Steuersignal, geschweige denn das Standardgleissignal
werden benötigt.
Das Programmiermodul muss aber gesteuert werden, Daten und Befehle empfangen, und Daten abliefern können.
Dies kann mit direkter Verbindung zu einem PC via serieller Schnittstelle ( RS 232 oder USB) geschehen oder man
benutzt den SX-Bus zum Datenaustausch beim ganz normalen Betrieb der Zentrale, die aber keine Programmier-
funktionalität haben muss.
Diesen Weg habe ich für mein Mini-Programmiermodul gewählt, weil dann die RS232 Schnittstelle bzw. die Pegel-
anpassung TTL-RS232 entfällt. Der Sx-Bus arbeitet ja auf TTL-Pegel. Die Software im Programmiermodul ist jedoch
wesentlich aufwändiger, was aber im Sinne meiner Mini-Projekte vorteilhaft ist, denn es muss nichts gekauft und
nichts Zusätzliches gelötet werden. Die Atmel 1 Euro-AVR-Zwerge sind allemal leistungsfähig genug.
Nachdem in einer SX-Zentrale keine Decoderdaten gespeichert oder verwendet werden ist das Programmier-
modul in jedem Fall eine "Stand-alone" Funktion, sofern es nicht in Verbindung mit einer speziellen Software verwendet
wird, die z.B. eine Lok-Datenbank enthält.
Im SX1-Modus werden nur zwei Byte Daten gesendet und empfangen. Zwei weitere Bytes werden zur Steuerung
verwendet. Wenn sich das Programmiermodul SX1-konform verhalten soll, sind das die Datenkanäle 104 und 105
und die Kommunikationskanäle 106 und 109. In SX Beschreibungen nennt sich K106 auch "Anforderungskanal",
K109 "Zustandskanal" , was auch der Funktion entspricht.
Übliche Software zum Lesen und Schreiben von Decodern geht davon aus, dass "am anderen Ende" der Leitung
eine SX-Zentrale "hängt", was vernünftigerweise einen Informationsaustausch vor dem Start des eigentlichen
Vorgangs notwendig macht, der z.B. so aussieht:
1. Bitte liebe Zentrale, schicke mir die Daten von K109.
2. Wenn die Antwort nicht innerhalb einer bestimmten Zeit kommt, Meldung: "Keine Zentrale vorhanden". Amen!
3. K109 Info ist eingetroffen und es wird geprüft ob der Fahrbetrieb, sprich die Gleisspannung abgeschaltet ist.
In K109 ist das Bit 7 (128) gesetzt, wenn Gleis eingeschaltet, Meldung: " Gleisspannung ist EIN". Amen.
4. Es könnte ja sein, dass noch ein Programmiervorgang in der Zentrale läuft, von der das Programm nichts
weiß. Deshalb Prüfung von Bit 6 (64), das gesetzt ist während ein Vorgang läuft.
Meldung: " Programmieren nicht frei". Amen.
5. Mit Bit 6 (64) gesetzt im Anforderungskanal K106 wird die Zentrale gebeten, sich in den Programmiermode
zu begeben. Z.B. muss die Strom-Messhardware eingeschaltet werden und eine Anzeige gemacht werden.
6. Die Bereitschaft zum Programmieren wird im Zustandskanal K109 mit Bit 5 und Bit 4 (96) gemeldet.
7. Wenn diese Information nicht innerhalb der Timeout-Periode ankommt,
Meldung: " Programmierfunktion nicht verfügbar". Amen
8. Nun ist alles so vorbereitet wie es sich nach SX-Konvention gehört, man schreitet zur Tat.
9. Im Anforderungskanal ist Bit 3 (8) gesetzt wenn man Schreiben lassen möchte, zur Leseaufforderung
ist dass Bit 3 auf NULL.
10. Wenn Lesen angesagt ist, kann nun gestartet werden.
Zum Schreiben werden aber noch Daten benötigt:
Im Adress-Byte K105 steht auf den unteren 7 Bit die SX-Busadresse, Bit 8 bestimmt die Anzahl
der Halteabschnitte 0 -> 1, 1 -> 2.
Im Daten-Byte K106 werden die Werte für Impulsbreite, Beschleunigung und max. Geschwindigkeit
übertragen (Codierung J J B B B V V V)
Die Umcodierung in das eigentliche Sendeformat geschieht im Programmiermodul,
11. Der eigentliche Auslöser ist dann das Bit 7 (128), auch "Do it" genannt , das im Kanal K106 gesendet wird.'
12. Nach dem Lesen schreibt ein SX-konformes Programmiermodul die Daten in die Kanäle K04 und K105.
Dass die frisch gelesenen Daten zur Verfügung stehen, signalisiert das Programmiermodul durch
Abschalten von Bit 5 (32) im K109.
13. Die Software wartet nun auf dieses Signal. Trifft es nicht innerhalb Timeout ein, erfolgt
Meldung: " Keine Daten verfügbar". Amen.
14. Ein Vorgang kann natürlich auch schiefgehen. Kontaktprobleme sind beliebte Fehlerquellen.
Deshalb führt das Programmier-Modul einige Plausibilitätskontrollen durch und beachtet ebenfalls
den zeitlichen Ablauf und Impulsbreiten. Im Fehlerfall wird in K104 und 105 0xFF (255) zurückgegeben
15. Letztlich wird das "Do It" Bit 7 (128) in K106 zurückgenommen und das Programmieren beendet.
Die relevanten Steuer- und Datenkanäle sind im SELECTRIX-Handbuch Teil 2
wie folgt dokumentiert
![]()
D&H Decoder lesen:
Wenn an das Gleis eine Gleichspannung angelegt wird, steigt die Spannung im Decoder an.
Bei etwa 3,5 Volt am ASIC startet die Decoderfunktion und er sendet seine Parameter
durch Stromimpulse, die an einem Messwiderstand von ca. 10 Ohm, zur blauen Klemme,
eine Messspannung erzeugen. Ein Spannungskomparator meldet bei Spannungen größer
als ca. 0,3 V "Stromfluss" an den Port-Pin des Prozessors im Programmiermodul.
Die Stromimpulse erzeugt der Decoder durch kurzzeitiges Einschalten des Motors in wechselnder
Fahrtrichtung damit die Lok stehenbleibt. Das Lesen und Programmieren ist natürlich nur dann
möglich, wenn nur 1 Decoder auf dem Gleis ist. In der Regel wird dafür ein spezielles
Programmiergleis an die Gleisklemmen der Zentrale geschaltet und alle übrigen Gleise
davon getrennt. Günstig ist deshalb eine Zentrale mit speziellen Klemmen für das
Programmiergleis und separater Programmier-Endstufe.
Der Messstrom ist natürlich auch von den Motoren bzw. deren Innenwiderstand abhängig,
aber auch kleinste Lokomotiven liefern ausreichende Stromimpulse.
Das Lesetelegramm startet immer mit 2 "langen" Impulsen gefolgt von 2 "kurzen".
Die Impulszeiten sind exemplarabhängig und streuen von 800 bis 1200 uSekunden fur eine
"lange" Information, die einer Log 1 entspricht. Zur sicheren Unterscheidung wird die Länge
der Startimpulse gemessen. Impulse, die kürzer sind als 75% dieser Dauer, werden als
"Halbimpulse" bezeichnet, weil sie nur paarweise vorkommen. Zwei Halbimpulse signalisieren
"Log 0".
Die Datenfolge im Lesetelegramm:
1 1 0 Ax Ax Ax Ax Ux Ux Ux H Ix Ix Bx Bx Bx Vx Vx Vx
| sync | Basisadr. | |Unteradr. | |H-bit| |Imp.| | Beschl.| |max. V|
Spannung am Messwiderstand (an blauer Klemme GND Scope):
Lesevorgang Steuern und Auswerten :
Die folgenden Programmausschnitte habe ich einem Testprogramm für eine Zentrale entnommen,
das mir Herr Haass freundlicherweise überlassen hat. Teilweise habe ich für mich Kommentare
hinzugefügt.
;-------------------------------------------------------------------------------;
; PROG SX1 Lesen ;
;-------------------------------------------------------------------------------;
; Nach Spannungsanstieg sendet ASIC Stromimpulse. "Lange" Pause zwischen den
; Impulsen bedeutet "Log 1 = Hi", "Kurze" Pause und ein weiterer Impuls
; signalisiert " LOG 0 = LO".
; Der Synchronteil besteht aus 2 langen Impulsen = Hi Hi und 2 kurzen = Lo
; dann folgen 16 Datenimpulse, jeweils 1 langer oder 2 kurze.
; Die Subroutine "l_data" misst die Impulse und gibt den Datenbitstatus
; im Carry zurück.
; Das Datenbyte 1 wird nach RECHTS in das Ergebnisregister rotiert,
; das Datenbyte 2 wird nach LINKS einrotiert.
p_altl: ; Vorspann:
cbr r25,bit5 ; r25.5 = error
rcall u_ein ;
sbr r18,test1 ; test1 = $8 t1+
rcall l_mess ; 1. "1" return mit Zählerstand in timp
rcall l_mess ; 2. "1" -> Längenmessung
ldi temp1,0b11111111 ; Zählerstand in timp
eor timp,temp1 ; timp = 255 - Messwert
rcall l_1imp ; Sync "0"
rcall l_1imp ;
ldi count1,8 ; carry clr und Zählerstand in dimp
p_altl1: ; 8 Impulse:
rcall l_data ; Datenbit in cy carry gesetzt = log 1 = Hi
; ********** NACH RECHTS den CARRY EINROTIEREN !!!!!!!!!***************
; DAMIT REIHENFOLGE PASST mit LSB UNTEN
ror info ; 8 Datenbit in Register info nach rechts rotiert,
; das zuerst gemessene Strombit landet auf Bit0
; und ist A0
dec count1 ;
brne p_altl1 ;
p_altl2: ; Korrektur Adresse:
ldi yl,K105
; ********** Adresskorrektur *************************************
ldi temp1,0b00001111 ; Invertiermaske für Gruppenadresse
eor temp1,info ; lower nibble invertiert, high unverändert
; im hi-nibble ist Bit7 das H-bit
; LSB der Unteradresse ist Bit4, MSB ist Bit6
; H U2 U1 U0 G3 G2 G1 G0
; 7 6 5 4 3 2 1 0 Bit Nr. in info
st Y,temp1 ; gelesene Adresse ablegen in Speicherzelle K105
ldi count1,8 ;
p_altl3: ; 8 Impulse:
rcall l_data ; Datenbit in carry gesetzt = log 1 = Hi
; ********** NACH LINKS den CARRY EINROTIEREN !!!!!!!!!***************
; DAMIT REIHENFOLGE PASST mit LSB UNTEN
rol info ; 8 Datenbit in Register info nach links rotiert,
; das zuerst gesendete Bit landet auf Bit7
; und ist I1
dec count1 ; Bitzähler
brne p_altl3 ;
p_altl4: ; Korrektur I0,I1, B:
mov temp1,info ; neues datenbyte in temp1
; *********** Korrektur Impulsbreite I ******************************
;
andi info,0b00111111 ; Bit 6 und 7 auf 0
sbrc temp1,7 ; Korrektur i0, i1, Bit 6 und 7 vertauscht ..
sbr info,bit6 ; in info setzen
sbrc temp1,6 ;
sbr info,bit7 ;
; *********** 1. Korrektur Beschleunigungswert ***************************
ldi temp1,0b00100000 ; Korrektur b
eor info,temp1 ; Bit 5 in info invertieren (MSB) ist B2
; *********** 2. Korrektur Beschleunigungswert ***************************
ldi temp1,0b00001000 ; = 1 (LSB von B-Wert) Addition vorbereiten
sbrs info,5 ; wenn Bit 5 in Info Hi, Ergebnis fertig
add info,temp1 ; wenn das invertierte Bit5 = 0, dann Add 1 zu B
ldi yl,K104 ; Ergebnis in Speicherzelle K104 ablegen
st Y,info ; I1 I0 B2 B1 B0 V2 V1 V0
; 7 6 5 4 3 2 1 0 Bit in info
p_altl5: ; Ende:
rcall p_uaus ; -> Spg aus
sbrs r25,5 ; Error?
ret ; -> normal zurück
p_altl6: ; Error:
ldi temp1,0b11111111 ;
ldi yl,K104 ;
st Y,temp1 ;
ldi yl,K105 ;
st Y,temp1 ;
ret ;
Besondere Beachtung verdient die Biterfassungsroutine " l_data". Der Programmierer hat sich eine
besondere Methode der "relativen Impulslängenmessung" einfallen lassen. Siehe Kommentar.
;-------------------------------------------------------------------------------;
; PROG SX1 Messen der Daten-Impulslänge,
; Länge prüfen und mit Ergebnis in carry zurück
; Der "Trick" ist der kürzere Tick mit 20uSek:
; Bei gleicher Impulslänge ist der Zählerstand in "dimp" um 25% höher,
; d.h. der Impuls darf um 25% kürzer sein und wird noch als "lang"
; erkannt. Noch kleinere Zählerstände bringen keinen Übertrag aus der
; Addition und werden als "kurz" interpretiert
;-------------------------------------------------------------------------------;
l_data: ; 1 oder 2 Impulse:
rcall l_1imp ; Zählen in dimp mit 20uSek Ticks
mov temp1,dimp ; neuer Zählerstand in dimp
add temp1,timp ; add (255-Zählerstand "lang" mit 25 gemessen)
; zu neuem Zählerstandstand mit 20 uSek. gemessen.
; Wenn Ergebnis kein carry bringt war Abstand kurz, d.h.
; Log 0 und deshalb nächste Zählloop für die ..
brcc l_1imp1 ; 2. Impulshälfte @ "0"
; return aus l_1imp1 immer mit carry = 0 = Bit Log 0
sec ; cy=1 Impulszeit war lang, also carry auf 1 für Log Hi
; sec eigentlich überflüssig !! Sonst wären wir nicht hier.
ret ; zurück immer mit carry set = bit Log 1
;-------------------------------------------------------------------------------;
; PROG SX1 1 * Stromimpuls + Pause ;
;-------------------------------------------------------------------------------;
l_1imp: ; 1 Impuls:
clr dimp ; Durchlaufzähler 2
l_1imp1: ; Strom:
rcall t_19us ; Messung mit 20 us Ticks
nop ;
inc dimp ;
mov temp1,dimp ;
cpi temp1,255 ;
breq u_err ; @ länger als 1,5 ms
sbic pinC,3 ; solange Strom fließt, loopen
rjmp l_1imp1 ;
l_1imp2: ; kein Strom:
rcall t_19us ; Messung mit 20 us
nop ;
inc dimp ;
mov temp1,dimp ;
cpi temp1,255 ;
breq u_err ; @ länger als 1,5 ms
sbis pinC,3 ; wenn Strom wieder da -> ende
rjmp l_1imp2 ;
sbi portC,test3 ; t3+
clc ; carry = 0
ret ; Zählerstand in dimp und temp1
;----------------------------------------------------------------------------------------------------------------------------------
Decoder Pogrammieren:
Zusammenfassung für die Datenbereitstellung zum Senden:
Adresskanal K105 :
SX1-Busadresse z.B. 65
Halteabschnitte z.B. 0 für 1 HalteabschnittDatenkanal K104:
Impulsbreite z.B. 3 von 1 bis 4
Beschleunigung z.B. 7 von 1 bis 7
max. Geschwind. z.B. 4 von 1 bis 7
1. Aus der SX Adresse Kanal 105, Basis- und Unteradresse bestimmen :
Modulodivision SX-Adr % 16 = Ganzzahlige Unteradresse, Rest ist Basisadresse
z.B.: 65 % 16 = 4 Rest 1 --> Basisadresse = 1 Unteradresse = 4
Sendebyte 1:
Die Basisadresse wird in 4 Bit übertragen, die Unteradresse in 3:
b_adr = 1 = 0 0 0 0 0 0 0 1
A3 A2 A1 A0
u_adr = 4 = 0 0 0 0 0 1 0 0
U2 U1 U0
Invertiert zum Senden 0 1 1
2. Halteabschnitte gibt es nur 1 oder 2:
h_wer = 0 = 0 0 0 0 0 0 0 1
H
zum Senden h_wer - 1 = 0 0
und invertiert 0 1
Sendebyte 2:
3. Die Impulsbreite wird in 2 Bit übertragen:
i_wer = 3 = 0 0 0 0 0 0 1 1
I1 I0
zum Senden i_wer - 1 = 0 1 0
4. Die Beschleunigung wir in 3 Bit übertragen:
b_wer = 7 = 0 0 0 0 0 1 1 1
B2 B1 B0
Korrektur zum Senden:
B2 invertieren 0 0 1 1
Wenn danach B2 = 1 -> addiere 7 = 1 1 1, wenn B2 = 0 -> fertig
b_wer 1 0 0 1 -> 1 0 1 B2=1 ->add 1 1 1 -> 1 0 0
2 0 1 0 -> 1 1 0 =1 1 1 1 -> 1 0 1
3 0 1 1 -> 1 1 1 =1 1 1 1 -> 1 1 0
4 1 0 0 -> 0 0 0 =0 0 0 0 -> 0 0 0
5 1 0 1 -> 0 0 1 =0 0 0 0 -> 0 0 1
6 1 1 0 -> 0 1 0 =0 0 0 0 -> 0 1 0
7 1 1 1 -> 0 1 1 =0 0 0 0 -> 0 1 1
5. Die max. Geschwindigkeit wird in 3 Bit übertragen:
v_wer = 4 = 0 0 0 0 0 1 0 0
V2 V1 V0
6. Das komplette Sendebyte 2 wird vor dem Senden invertiert.
7. Telegrammaufbau:
Nach jeweils 2 Datenbit folgt als Trennbit eine Log 1, das Ende ist "0 0 0 1 1"
d d 1 d d 1 d d 1 d d 1 d d 1 d d 1 d d 1 d d 1 0 0 0 1 1
Sendereihenfolge ------>
A0 A1 T A2 A3 T U0 U1 T U2 H T I1 I0 T B2 B1 T B0 V2 T V1 V0 T 0 0 0 1 1
| Byte 1 | | Byte 2 | | Ende |
0 1 2 3 4 5 6 7 7 6 5 4 3 2 1 0
| Bitnummer im Sendebyte 1 | | im Sendebyte 2 |
Die Decoder erwarten im Sendetelegramm bestimmte Formate für die Parameter:
Basisadresse unverändert, Sendereihenfolge A0, A1, A2, A3
Unteradresse invertiert, U0, U1, U2
H Bit invertiert
Sendebyte 2 komplett invertiert
Beim Senden von Byte 1 zuerst Bit 0, zuletzt Bit 7, z.B. mit Bit im carry nach ASL.
Beim Senden von Byte 2 zuerst Bit 7, zuletzt Bit 0, z.B. mit Bit im carry nach ASR.
Gleisspannung meiner Trix CC2000, rote Klemme zur blauen (GND Scope):
Gesendet wird in der Codierung der Gleisspannung, d.h.:
wechselnde Polarität ist "Log 1",
gleiche Polarität aufeinanderfolgender Impulse bedeutet "Log 0".
In den Impulspausen ist die Gleisspannung GND-Potential +- Diodendurchlassspannung ca. 0.8 V.
Die Pausenzeit ist ca. 8 Mikrosekunden, die Datenimpulse sind ca. 12 Mikrosekunden lang.
Die Frequenz ist beim Programmieren wesentlich höher, im Fahrbetrieb sind die Impulszeiten
10 + 40 Mikrosekunden.
Programmierablauf:
Nach Information von Herrn Adolf Haass, dem ursprünglichen Entwickler des Selectrix.Systems, ist es
notwendig zuerst die Daten im Decoder zu löschen, d.h. beide Sendebytes sind 0xFF ( invertierte log 0).
Nach einer Pause von mindestens 250 Millisekunden folgt die 2. Impulsserie mit den eigentlichen
Programmierdaten.
Den Programmierwunsch erkennt der Decoder an einer Impulsserie mit speziellem Inhalt und besonderem
Timing, um sicherzustellen, dass im Normalbetrieb nicht auf Programmieren umgeschaltet wird.
Zudem können die D&H Decoder nur innerhalb der ersten, etwa 3 Millisekunden nach dem Einschalten
in den Programmierstatus wechseln. Das Programmiermodul erkennt das "Erwachen" des Decoders am
Eintreffen des 1. Leseimpulses.
Im Normalbetrieb beinhaltet die Impulsserie einer Basisadresse 7 Datenkanäle, d.h. erst nach 7 Datenbytes
folgt wieder eine Sychronisier-Sequenz.
Das Sendetelegramm zum Umschalten in den Programmiermode hat als Vorspann " 1 1 0 0 0 1 1 1 1 "
dann folgt Synchrtonteil1, 2 Datenbytes, Synchronteil2, weitere 2 Datenbytes und ein Synchronteil :
| vorspann | sync1 | byte1 | byte2 | sync2 | byte1 | byte2 | sync3 |
Weitere Programmausschnitte aus dem Testprogramm von Herrn Haas, z.T. mit eigenen Kommentaren ergänzt.
;-------------------------------------------------------------------------------;
; PROG SX1 Programmierung SX1 ;
;-------------------------------------------------------------------------------;
p_altp: ; ASIC Programmierung
p_altp1: ; 1. Durchlauf zum Löschen der Decoderdaten:
ldi temp1,0b11111111 ; = löschen
mov byte_1,temp1 ;
mov byte_2,temp1 ;
rcall p_altzyk ; Aufruf der Senderoutine
rcall t_30ms ; Wartezeit bis zum 2. Durchlauf
rcall t_30ms ;
rcall t_30ms ;
rcall t_30ms ;
rcall t_30ms ;
rcall t_30ms ;
rcall t_30ms ;
rcall t_30ms ;
p_altp2: ; 2. Durchlauf zur Übertragung der Programmierdaten:
cbr r25,bit5 ; 'error' - bit
; *** Datenbyte1 Adresse und Halteabschnitte aufbereiten *************************
ldi yl,K105 ; K105 Datenformat ????
ld byte_1,Y ;
ldi temp1,0b11110000 ; Korrektur Adresse
eor byte_1,temp1 ; Gruppenadresse invertieren
; *** Datenbyte2 Beschleunigungswert, Impulsbreite und max. Geschwindigkeit *******
ldi yl,K104 ;
ld temp2,Y ;
; *** Korrektur Beschleunigungswert
ldi temp1,0b00100000 ; Bit 5 invertieren
eor temp2,temp1
;
ldi temp1,0b00111000 ;
sbrc temp2,5 ; Wenn Bit 5 gesetzt -> B = 7 addieren
add temp2,temp1 ;
andi temp2,0b00111111 ; Bit 6 und 7 löschen
mov byte_2,temp2 ;
ld temp2,Y ; K104 noch mal laden
clr temp1 ; Korrektur I1,I2 vertauschen
sbrc temp2,7 ; Wenn Bit7 in K104 gesetzt ....
sbr temp1,bit6 ; Bit6 setzen im Sendebyte
sbrc temp2,6 ; Wenn Bit6 in K104 gesetzt ....
sbr temp1,bit7 ; Bit7 setzen im Sendebyte
or byte_2,temp1 ; Ergebnis in Sendebyte übernehmen
ldi temp1,0b11111111 ;
eor byte_2,temp1 ; ganzes Sendebyte invertieren
rcall p_altzyk ;
p_altp3: ; Prog beendet:
ret ;
;-------------------------------------------------------------------------------;
; PROG SX1 Programmierzyklus ;
;-------------------------------------------------------------------------------;
p_altzyk: ; Programmierung:
rcall u_ein ; Sync auf 1. @EN ; Spannung einschalten
rcall o_pd1 ; Sende Log 1
rcall o_pd1 ;
rcall o_pd0 ; Sende Log 0
rcall o_pd0 ;
rcall o_pd0 ;
rcall o_pd1 ;
rcall o_pd1 ;
rcall o_pd1 ;
rcall o_pd1 ;
p_altzyk1: ; Vorspann:
rcall o_psyn ; Sende Synchronteil 1
rcall o_pkan ; Sende Daten alle Bit Log 0
rcall o_pkan ;
rcall o_psyn ; Sende Synchronteil 2
rcall o_pkan ;
rcall o_pkan ;
rcall o_psyn ; Sende Synchronteil 3
; Decoder schaltet auf Programmieren um
rcall t_10ms ; Wartezeit sollte genau sein
p_altzyk2: ; Dateneingabe:
rcall o_paus ;
rcall o_pd0 ; Nachspann 0 0 0 1 1 senden
rcall o_pd0 ;
rcall o_pd0 ;
rcall o_pd1 ;
rcall o_pd1 ;
rcall t_30ms ; Pause bis Gleisspannung ausschalten
rcall t_30ms ;
p_altzyk3: ; Ende:
andi r18,0b00001111 ; Gleis hochohmig
out portD,r18 ;
ret ;
Gleisspannung meiner Trix CC200, rote Klemme zur blauen (GND Scope):
Bis zum Ende von Synchronblock 3 wurden 111 Takte a 20 Mikrosekunden gesendet.
Somit ist der Programmierauftrag an den Decoder sicher innerhalb der max. Umschaltzeit
von ca. 3 Millisekunden erteilt. Bis zum Senden der Daten wird exakt 10 Millisekunden
gewartet.
Die Wartezeit bis zum 2. Durchlauf mit den eigentlichen Daten ist im Testprogramm 8 x 30
Millisekunden.
Im Programm ist unter dem Label p_altp2: auch die Datenaufbereitung, d.h. die
Formatkorrektur nachzulesen.
Die dargelegten "Weisheiten" habe ich aus diversen Artikeln zum Thema Selectrix zusammengesucht
und die Richtigkeit meiner Erkenntnisse, soweit möglich, mit dem Speicher-Scope nachvollzogen.
Leider sind die Informationen nicht vollständig und zum Teil widersprüchlich.
Die entscheidende Quelle ist aber das Testprogramm aus dem Haus Doehler und Haass, wovon
ich auch Teile in meiner Software verwende.
Geholfen hat mir auch ein Programmfragment, das mir Herr Henning Voosen überlassen hat. Herr Voosen
hat einen sehr schönen Windows Decoder-Programmer geschrieben, den ich auch für meine Tests verwende.
Bei http://www.henningvoosen.de unter downloads kostenlos zu haben.
Meinem Mini-SX-Programmier-Modul habe ich eine eigene Beschreibung gegönnt. Die Tests waren positiv.
Für Korrekturen, Hinweise oder "Fehlermeldungen" wäre ich in jedem Fall dankbar.
Steinhart 30.10.2008
Beschreibung meines Programmiermoduls für D&H Decoder an der Minizentrale: lok_prog_mod.htm