Mini SX1 Decoder Programmiermodul
Ein weiteres Mini-Projekt wurde "notwendig" um feststellen zu können, ob die
gewonnenen Einsichten
ausreichend sind, um wenigstens SX1-Decoder der Fa. Doehler und Haass programmieren zu können.
Dieses Modul eignet sich NICHT für den Betrieb an einer
Standardzentrale wie die CC2000 o.ä.
weil der Datentransfer auf dem Bus die SX-Adressen 106 und 109 verändert.
Mit meiner Mini-Zentrale ist das kein Problem, weil dort keine Gleisfunktionen
implementiert sind und
keine Veränderung von irgendeiner Adresse stattfindet oder darauf reagiert wird.
Um mit möglichst wenig Bauteilen, und den damit verbundenen Lötstellen,
auszukommen habe ich diese
Schaltung auf einer Lochrasterplatine aufgebaut.

Weglassen könnte ich noch den Programmierstecker und den Quarz mit den beiden
Kondensatoren.
Aber in Erwartung häufig notwendiger Programmierung und um exakte Impulszeiten
realisieren zu
können, habe ich nicht darauf verzichtet.

Das Hardwarekonzept:
Zur Ansteuerung des Programmiergleises dient die L6202 Vollbrücke, die der Atmel
Mikro Mega8 direkt
ansteuern kann. Lt. Datenblatt sind C1 bis C3 notwendig und der Siebelko C10
sollte samt D2 eine
ordentliche Versorgungsspannung liefern. Der Baustein hat einen Anschluss für
den Strommesswiderstand
(Sense). D1 begrenzt die Messspannung am Eingang des Analogkomparator AIN0.
Die Vergleichsspannung liefert der Spannungsteiler R4, R3, ca.0,3 Volt. Die
Schreibleitung X1 Pin 5 ist
über die empfohlenen 100 Ohm an PD4 angeschlossen. Der 7805 wird auch gebraucht
und versorgt den
Prozessor.
Mit 10 Euro ist alles bezahlt und in 3 Stunden gelötet. Die beiden IC's haben
edle Sockel bekommen.
Praktisch sind noch 2 Messdrähte an PD5 und am enable Eingang der Brücke zum
Triggern des Scope's.
Das Softwarekonzept:
Den Datenaustausch habe ich via SX-Bus vorgesehen, d.h. die Funktionalität zum
Lesen und Schreiben
bestimmter Adressen unter Programmkontrolle ist notwendig. Die Routinen für den
SX-Bus habe ich
meinen Decodern für Schalten und Melden entnommen und angepasst.
Eine wichtige Ergänzung der SX-Routinen ist die Einführung von Flags für den
Synchronbereich und als
"Done" Bit für Schreiben und Lesen. Das ermöglicht die simple Synchronisation
der Hauptprogramm-
Funktionen mit den Interrupt gesteuerten SX Programmteilen.
Ereignisgesteuerte Programme sind wesentlich einfacher zu gestalten, wenn man
für Eingangssignale
eine Flankenerkennung einbaut. Deshalb folgt nach jedem Lesen des
Anforderungskanals, K106, die
hierfür notwendige Logik:
ldi r17,106
; K106 ist der Anforderungskanal
rcall adre_rech
rcall wart_lesen
lds r30,$62 ; K106 akt Stand aus
Übergabezelle holen
sts K106,r30 ; und im Statusbyte
speichern
;** Flankenerkennung ************** **
lds r31,$65 ; letzten gelesenen Wert holen
sts $66,r31 ; nach alt schieben
sts $65,r30 ; nach neu speichern
mov r11,r30 ; Neu
eor r11,r31 ; veränderte Bit sind in r11 Hi
and r30,r11 ; neue Hi in r30
and r31,r11 ; neue Lo in r31
sbrc r30,6 ; Programmieren anfordern mit neuem Hi in Bit 6
rjmp anforder
sbrc r30,7 ; Do it = neues Hi
rjmp doit
sbrc r31,7 ; Do it = neues Lo zum Abbau des Vorganges
rjmp doit_abbau
rjmp nixles
Die Bit in r30 und r31 sind nur 1 Zyklus lang
gesetzt, d.h. sie sind wieder Lo wenn der
nächste Lesevorgang den identischen Logikpegel liefert.
Die Subroutinen:
adre_rech:
mov r18,r17 ;
Dezimaladresse
andi r18,0b01110000 ; Unteradresse isolieren
swap r18
ldi r19,6
sub r19,r18
sts $61,r19 ;
abspeichern
ldi r18,0b00001111 ; Gruppenadresse isolieren
and r17,r18
eor r17,r18 ;
invertieren
sts $60,r17 ;
abspeichern zur Übergabe an Leseroutine
ret
wart_lesen:
clr r29
wa_3:
sbis PIND,3 ;
Warten bis Schreiben gestartet
rjmp wa_3
wa_4:
sbic PIND,3 ;
Warten bis fertig geschrieben
rjmp wa_4
ret
Die eigentlichen Decoderprogrammteile "loklesen" bzw. "lokschreiben" sind
ablaufgesteuert und dürfen
wegen der notwendigen genauen Impulszeiten nicht unterbrochen werden. Deshalb
wird vor dem " rcall " der
externe Interrupt " INT0 " abgeschaltet.
Ersts nach Beendigung der Programmierfunktion erfolgt die Wiederfreigabe für den
Datentransfer auf dem
Sx-Bus. Hier die Programmstellle zum Aufruf der Schreibfunktion "
lokschreiben ":
bit3set:
ldi r17,105 ; K105 ist H-Bit und
Adressen Kanal
rcall adre_rech
rcall wart_lesen
lds r30,$62 ; K105 akt
sts K105,r30
ldi r17,104 ; K104 ist "II BBB
VVV"
rcall adre_rech
rcall wart_lesen
lds r30,$62 ; K104 akt
sts K104,r30
clr r17
out GICR,r17 ; enable INT10 AUS
rcall lokschreiben
ldi r17,0x40
out GICR,r17 ; enable INT10 EIN
Lesen und Schreiben auf dem SX-Bus:
Der Funktionswechsel zwischen Lesen und Schreiben und der Adresswechsel darf nur
dann erfolgen, wenn kein
Vorgang läuft und der aktuelle Zustand der SX-Datenleitung erfasst ist. Hier die
Programmstelle:
;** Datenleitung übernehmen **
sbis PIND,0 ; Skip wenn Datenleitung LO
rjmp dat_hi
ldi r25,0x01 ; Setze LSB weil Datenleitung HI
or r1,r25 ; Eintragen in
Vorlaufregister
;** Innerhalb der gültigen Synchrongruppe ist PD1 = 1 oder PD3 =1 **
;** der Wartezähler ist bis zum gültigen Datebyte != 0
dat_hi:
sbic PIND,1 ;
Schreiben bereits Ein ?
rjmp schreib ; ja,
weiterschreiben
sbic PIND,3 ; Lesen
Bereits Ein ?
rjmp lesen ;
ja, weiterlesen
sbis PIND,5 ; Sync
gültig = 1
rjmp synctest ; nein
weiterscannen
dec r20
; Wartezähler fertig ?
breq auftrag ; ja, neuer
Auftrag kann begonnen werden
rjmp synctest ; Nein, weiter
auf Unteradresse warten
;** Entscheidung lesen oder Schreiben **
auftrag:
cbi PORTD,5 ; Wartezähler = 0, Flag
Syncbit Aus!
tst r29 ;
Anforderung aus dem Hauptprogramm
brne schreibsta ; Schreiben = 1
rjmp lessta ; Lesen
= 0
;***************************************************************************
schreibsta: ; der Schreibstart
lds r10, $63 ; in $63 ist das zu schreibende Byte
usw. usw.
Soweit die Ablaufsteuerung und Kommunikation mit der Steuersoftware. Es folgt
das "Eingemachte" der
Decoderbedienung, die ich, wie beschrieben, weitgehend aus dem Testprogramm von
Herrn Haass übernommen
habe. Ich denke das sind Programmmodule, die es schon seit geraumer Zeit gibt
und die sich bewährt haben.
Möglicherweise ist es auch eine Portierung von "kenne ich nicht Prozessor" auf
den Atmel Mega8.
Nach diversen Stunden Assemblerzeilen studieren, wurde mir aber die, stellenweise
elegante (trickreiche)
Programmierung klar und ich musste lediglich die Bedienung der Hardware, sprich
die Ansteuerung des L6202
und den Messeingang anpassen .
Die Isolierung der SX1-relevanten Teile aus dem " Multiprotokoll-System " (SX1,
SX2, DCC, Motorola) für alle
D&H-Decoder ist letztlich auch gelungen und im Teil "haassprog.asm" nachzulesen.
Doehler & Haass Subroutinen:
Die
Details zu den Prinzipien und Signalverläufen habe ich an anderer Stelle bereits beschrieben.
Unterprogramm "loklesen":
Dieses Modul benötigt keine Startdaten und schreibt das Leseergebnis umcodiert
in das SX1-Format
in die Speicherzellen der Kanäle (Adressen) K104 und K105.
Die Adresszuweisungen des SRAM stehen im Hauptprogramm:
.EQU K104 = $D8 ;
Adresskanal
.EQU K105 = $D9 ; Datenkanal
.EQU K106 = $DA ; Anforderungskanal
.EQU K109 = $DD ; Zustandskanal
Für die Ansteuerung der Gleise verwende ich die integrierte Motor-Vollbrücke
L6202. Die Eingangssignale
kommen direkt vom AT Mega8. Die Portpins sind im Hauptprogramm zugewiesen:
.EQU enable = 3 ;
für L6202 Brücke
.EQU IN1 = 4
.EQU IN2 = 5
Das Ausgangssignal des Mega8 Analogkomparators ist auf dem I/O Register ACSR das
Bit ACO und wird
z.B. so abgefragt:
sbic ACSR,ACO ;
Skip wenn kein Strom fließt: AIN0 > AIN1 ACO = Lo
Ich habe mich bemüht, das Programm so zu kommentieren, dass ich es hoffentlich
in einem Jahr wieder verstehe.
Ergo gibt es diese Informationen nur dort !
Unterprogramm "lokschreiben":
Für das Programmieren der Decoderdaten werden die Kanäle K104, K105, K106 und
K109 verwendet.
Die erforderlichen Zuweisungen sind bereits erläutert.
Beim Start des Programmierens werden die Daten im Decoder zuerst gelöscht. Dazu
werden in den beiden
Sende-Bytes " byte_1
und byte_2 " alle Bits gesetzt
(255 = 0xFF= 0b11111111) bevor die
Senderoutine " p_altzyk
" in Aktion kommt. Aus diesem
Modul wird die Erzeugung der Gleisspannung
"gecallt". Dieses Modul hat 3 Einsprungadressen:
o_pd1:
für Ausgabe log Hi,
o_pd0: für
Ausgabe log Lo
o_pdat: für
die Ausgabe entsprechen logischem Zustand des Carry-Bit.
Nach der für D&H Decoder notwendigen Wartezeit von etwa 250 Millisekunden,
erfolgt der 2. Schreibvorgang
mit den neuen Parametern für Adresse, Anzahl Halteabschnitte, Impulsbreite
der Motorregelung, Wert für die
Massensimulation (Beschleunigung) und dem Wert der maximalen Geschwindigkeit.
Die in K104 und K105
übergebenen Werte müssen aber noch " D&H-gerecht" umkodiert werden. Die
geschieht hier:
p_altp2:
; 2. Durchlauf:
cbr r25,bit5
; 'error' - bit
; *** Datenbyte1 Adresse und Halteabschnitte aufbereiten ********************
ldi yl,K105
; K105
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 nochmal 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
; zur Senderoutine !
Ein ganz entscheidend wichtige Programmfunktion !!
Die Ansteuerung des Gleis nach SX-Mode besorgt dann der Abschnitt
" o_pdat1: " wobei
das Steuerbit für die jeweilige Schaltrichtung Register 25 Bit 0 ist.
;****************************************************************************
; SX1 PROG Datenausgabe auf Gleis Steuerung der Endstufe
; Impulszeiten: Takt 8 uSek. Daten 12 uSek.
;****************************************************************************
o_pd1:
; Data=1:
ldi temp1,0b00000001 ; = bit.0
eor r25,temp1
; invertieren Bit 0;
rjmp o_pdat1
;
o_pd0:
; Data=0:
nop
nop
rjmp o_pdat1
o_pdat:
; Data aus carry:
ldi temp1,0b00000001 ; = bit.0
brcc o_pdat1
; von lsr byte_1 ist carry wie b0 vorher
eor r25,temp1
;
o_pdat1:
; Ansteuerung Gleis:
rcall t_10us
; Angepasst nach Scopemessung für 12 uSek
cbi PORTC,enable ; Enable AUS 2
Takte
cbi PORTC,IN1
; Sink 1 2 Takte
cbi PORTC,IN2
; Sink 2 2 Takte
sbi PORTC,enable ; Brücke EIN
rcall t_07us
; Angepasst nach Scopemessung für 8 uSek
sbrc r25,0
;
rjmp o_pdoq
;
o_pdon:
cbi PORTC,enable ; Brücke AUS
sbi PORTC,IN1
; Source 1
cbi PORTC,IN2
; Sink2
sbi PORTC,enable ; Brücke EIN
ret ;
o_pdoq:
cbi PORTC,enable ; Brücke AUS
cbi PORTC,IN1
; Sink 1
sbi PORTC,IN2
; Source 2
sbi PORTC,enable ; Brücke EIN
ret ;
In " o_pdat1 " wir zuerst der akt. Schaltzustand als Datensignal weitere
10 Mikrosekunden gehalten, was mit den
Laufzeiten der übrigen Befehle zu einer Impulsbreite von 12 uSek. führt.
Danach werden in jedem Fall beide Gleise an GND gelegt ( Sink1 und Sink2 ) und
die Taktzeit 7 bzw. 8uSek
gewartet. Danach entscheidet r25 Bit 0 welches Potential an die Gleise kommt.
Schlussbemerkung:
Ohne das Programm, das mir Herr Haass freundlicherweise überlassen hat, hatte
ich keine Chance den
Umkodierungen auf die Schliche zu kommen, da ich nirgends entsprechende
Beschreibungen gefunden habe.
Das muss aber nicht heißen, dass es diese Informationen nicht gibt!
Meine Tests habe ich mit kleinen DHL050 Decodern durchgeführt, das
Programmiermodul an meine Mini-Zentrale
angeschlossen und den DecoderProgrammer von Henning Voosen verwendet.
Die Fahrtests mit den umprogrammierten Loks fanden auf meinem Selectrix System
aus einer CC2000
mit TRIX Handy Control statt.
Über andere Konfigurationen kann ich mangels
Testobjekten keine Aussagen machen.
Dankbar wäre ich den "geneigten Lesern" für Fehlermeldungen, Hinweise oder
Anregungen!
Winfried Steinhart im November 2008
Links auf meine Dateien:
Hauptprogramm: lok_prog.asm
ProgModul:
haassprog.asm
Prinzip, Signale:
deco_progra.htm