; *************************************************************** ; * Copyright by mad.dax@t-online.de * ; * DCC-Decoder Testversion * ; * 14 / 28 und 126 Fahrstufen ( Fahrstufe 14 = 27 ) * ; * ?berg?nge Stufenlos * ; * PWM mit 6125 HZ, internes Timing mit CV6 trimmbar * ; * kurze und lange Adressierung ( 7 und 14 Bit je nach CV ) * ; * F1 / F2 als Ausgänge * ; * Programming on the Track mit DDW-Server V 0.7.5 und * ; * Java DCC Railroad Network Client V 4.11 getestet * ; * Bedienung auch mit GPlan V 0.70 getestet * ; * Version: 06.06 in Arbeit * ; *************************************************************** ; * Umgeänderter Code Zum Funktionsdecoder für Wagenbeleuchtung * ; * Hardware muß geändert werden / Schaltung nur mit Transistoren an den PB´s * ; * oder Häuser, Sound etc...* ; * CV28 Bit 3 auf 1 ( 04 in dec ) dann F1 - F4 Aktiv * ; * CV28 Bit 2 auf 1 ( 02 in dec ) dann F1 - F2 PBO = 1 (Vor ) PB1 = 1 ( Zur.)* ; * Getestet mit Twin Center und Intellibox * ; * Code geändert damit 4 Stellige Adressen erkannt werden können* ; * Code ausdokumentiert * ; * Danke an alle Mitwirkenden * ; * geplant eventuell noch eine Umschaltung als Motordecoder* ; * diese Änderungen by Muetze 01.2009 * ; *************************************************************** ; ; Hardware Anforderungen: ; ; Standard Belegung ; ; Tiny 15 PDIP/SOIC ; ;(RESET/ADC0) PB5 = 1 8 = VCC ;(ADC3) PB4 = 2 7 = PB2 (ADC1/SCK/T0/INT0) ;(ADC2) PB3 = 3 6 = PB1 (AIN1/MISO/OC1A) ; GND = 4 5 = PB0 (AIN0/AREF/MOSI) ; ; DCC Decoder ; ;RESET PB5 = 1 8 = VCC ;Funktion 2 PB4 = 2 7 = PB2 DCC Eingang ;Funktion 1 PB3 = 3 6 = PB1 Ausgang Rückwärts / Funktion 3 ; GND = 4 5 = PB0 Ausgang Vorwärts / Funktion 4 ;NB: NMRA-DCC Basisprotokoll (abs. FRU, 7-bit-Adr., 14 FS) ;N1: NMRA-DCC erweitert (abs. FRU, 7-bit-Adr., 5 Funkt., 28 FS) ;N2: NMRA-DCC erweitert (abs. FRU, 7-bit-Adr., 5 Funkt., 128 FS) ;N3: NMRA-DCC erweitert (abs. FRU, 14-bit-Adr., 5 Funkt., 28 FS) ;N4: NMRA-DCC erweitert (abs. FRU, 14-bit-Adr., 5 Funkt., 128 FS) ; ; Software Funktionen: ; .NOLIST .INCLUDE "tn15def.inc" ;Datei des verwendeten Prozessors von AVR Studio ; ; Konstanten FlagReg ; .equ CONREV = 4 ;Consist Reverse Direction bei 1 .equ SERVMODE = 3 ;Programmiermodus .equ BitNew =2 ;Flag Neues Bit eingetroffen .equ LoTiF =1 ;Long Time Flag .equ Bit =0 ;Bit Wert ; ; Konstanten Funktion ; .equ FTasten = 1 ;F Tasten Funktionsbit nr.1 .equ Motordec = 0 ;Motordecoder Funktionsbit Nr 0 ( noch nicht verwendet ) ; Konstanten DCCReg ; .equ LongADR = 7 ;Lange Adresse bei 1 .equ RevDir = 6 ;Fahrtrichtung reversiert bei 1 .equ DIR =5 ;Fahrtrichtung 1=vorwärts, 0=rückwärts .equ FL =4 ;Fahr Licht .equ F4 =3 ;F4 Funktionstaste F4 Port B1 .equ F3 =2 ;F3 Rangiergang bei 1-Signal oder F3 Port B0 .equ F2 =1 ;F2 Funktionstaste F2 Port B4 .equ F1 =0 ;F1 Funktionstaste F1 Port B3 .equ SampleTime = 255 - 105 ;139- ca. 30 Befehlszyklen 75% der High-Signal Periodendauer = 87us ohne Precaler .equ WaitTime = 255 - 200 ;250? maximale Bitlänge = 10000us bei Prescaler 64 .equ EEAdresse = 0 ;Speicherplatz eigene Adresse im EEPROM .equ EEStart = 1 ;Speicherplatz Start-Speed nicht benutzt .equ EEIncrease = 2 ;Speicherplatz Beschleunigungskonstante im EEPROM .equ EEDecrease = 3 ;Speicherplatz Verzögerungskonstante im EEPROM .equ EEMaxSpeed = 4 ;Speicherplatz Höchstgeschwindigkeit im EEPROM .equ EEOSCCAL = 5 ;Speicherplatz OSCCAL im EEPROM .equ EELongADR = 28 ;Speicherplatz Lange Adresse gesetzt im EEPROM .equ EELongADRHI =16 ;Speicherplatz Lange Adresse EEPROM .equ EELongADRLO = 17 ;Speicherplatz Lange Adresse EEPROM .equ EECONAdr = 18 ;Speicherplatz Consist Adresse EEPROM .equ ACKTime = 63 ;5 ms bei Timer 1 = CK/128 .equ RESTime = 250 ;20 ms bei Timer 1 = CK/128 .equ EEFunktion = 27 ;Speicherplatz Funktionsart EEPROM 0 Motordec. 1 Funktionsdec 2 Steuerwagedec .equ EETest = 20 ;Speicherplatz Funktionsart EEPROM Testzwecke ; ; Benutzte Register ; .def RAM = R0 ;Reserviert für RAM Zugriff .def ISTSpeed = R1 ;berechnete Geschwindigkeit .def SOLLSpeed = R2 ;Soll Geschwindigkeit .def IncCnt = R3 ;Beschleunigungszähler/Bremszähler .def IncVAL = R4 ;Beschleunigungkonstante .def IncCnt1 = R5 ;Beschleunigungszähler/Bremszähler .def DecVAL = R6 ;Bremskonstante .def MaxSpeed = R7 ;Höchstgeschwindigkeit .def ByteA = R8 ;Empfangenes Byte .def ByteB = R9 ;Empfangenes Byte .def ByteC = R10 ;Empfangenes Byte .def ByteD = R11 ;Empfangenes Byte .def ByteE = R12 ;Empfangenes Byte .def ByteF = R13 ;Empfangenes Byte .def HIAdresse = R14 ;eigene Adresse HI-Byte für lange Adresse .def LoAdresse = R15 ;eigene Adresse Lo-Byte für lange Adresse .def TEMPS = R16 ;SREG Sicherungsregister .def TEMPI = R17 ;TEMP Register für Initialisierung und Interupt-Schmierregister .def TEMP1 = R18 ;TEMP Register für Hauptprogramm und Initialisierung .def TEMP2 = R19 ;TEMP Register für Hauptprogramm .def TEMP3 = R20 ;TEMP Register für Hauptprogramm .def CONAdr = R21 ;Consist-Adresse ( Mehrfachtraktion ) .def Adresse = R22 ;eigene Adresse .def FlagReg = R23 ;Flag Register .def DCCReg = R24 ;DCC Register für Funktionen und Fahrtrichtung .def ByteCNT = R25 ;Bytezähler für Datenhandling .def BitCNT = R26 ;Bitzähler für Datenhandling .def PRGCHECK = R27 ;Checkbyte für CV Schreiben .def Funktion = R28 ;Welche Funktion ist ausgewählt Bit0 = 0 Motordec. Bit1 = 0 Funktionsdec oder Bit2 = 1 Steuerwagedec ;def FREI = R29 ;def Reserviert = R30 ;def Reserviert = R31 ; ; ; Code beginnt hier ; .CSEG .ORG $0000 ; ; Reset- und Interrupt-Vektoren rjmp RESET ; Reset handler rjmp EXT_INT0 ; IRQ0 handler reti ;PIN_CHANGE ; Pin change handler reti ;TIM1_CMP ; Timer1 compare match rjmp TIM1_OVF ; Timer1 overflow handler rjmp TIM0_OVF ; Timer0 overflow handler reti ;EE_RDY ; EEPROM Ready handler reti ;ANA_COMP ; Analog Comparator handler reti ;ADC ; ADC Conversion Handler ; ; ; **************** Ende der Interrupt Service Routinen ********************* ; ; ; 8x8 Bit Unsigned Multiplication von ATMEL ;def TEMP1 =r16 ;multiplicand ;def TEMP2 =r17 ;multiplier ;def TEMP2 =r17 ;result Low byte ;def TEMP3 =r18 ;result High byte MUL8X8: clr TEMP3 ;Lösche Inhalt von Temp3 / clear result High byte ldi ByteCNT,8 ;Lade in ByteCnt eine 8 / init loop counter lsr TEMP2 ;schiebe das Register TEMP2 um einen nach rechts / rotate multiplier MULSTART: brcc MULMORE ;Ist das Carry Flag = 0 springe zu MULMORE / carry set add TEMP3,TEMP1 ;Addire Inhalt von Temp1 zu Temp3 / add multiplicand to result High byte MULMORE: ror TEMP3 ;In Temp3 alls um einen nach rechts / rotate right result High byte ror TEMP2 ;In Temp2 alls um einen nach rechts / rotate right result L byte and multiplier dec ByteCNT ;Zähle den inhalt von ByteCNT runter / decrement loop counter brne MULSTART ;Ist der Wert von MULSTART nicht gleich mit ByteCNT dann springe zu MULSTART / if not done, loop more ret ;zurück zur Sprungmarke ( rcall ) writeEEPROM: sbic EECR,EEWE ; wird momentan noch geschrieben ? rjmp PC-1 ; Schleife out EEAR,TEMP1 ; Erfasse EEProm Schreibadresse out EEDR,TEMP2 ; Erfasse EEProm Schreibdaten cli ; alle Interrupts ausschalten sbi EECR,EEMWE ; Setze EEProm Master-Schreibbit sbi EECR,EEWE ; Setze EEProm Schreib-Befehl sbic EECR,EEWE ; wird momentan noch geschrieben ? rjmp PC-1 ; Schleife sei ; alle Interrupts wieder einschalten ret ; Rücksprung readEEPROM: sbic EECR, EEWE ; wird noch geschrieben ? rjmp PC-1 ; Schleife out EEAR, TEMP1 ; Erfasse EEProm-Leseadresse sbi EECR, EERE ; Setze EEProm-Lesebefehl in TEMP2, EEDR ; Lese EEprom-Daten ret ; Rücksprung EXT_INT0: ;Flankenwechsel von Low auf High in TEMPS,SREG ; SREG sichern clr TEMPI ; Timer anhalten out TCCR0,TEMPI ; Prescaler steht auf STOP-Counter mit 000 in TEMPI,TIFR ; lösche Timer 0 Interrupt Flag andi TEMPI,0b00000010 ; das eventuell während dieses Interuptaufrufes out TIFR,TEMPI ; gesetzt worden ist cbr FlagReg, (1< SOLL breq Gleich ; wenn Wert nicht gleich brsh DECSpeed ; wenn Wert größer gleich brlo INCSpeed ; wenn Wert kleiner Gleich: clr IncCNT ; lösche Beschleunigungsz?hler clr IncCNT1 ; lösche Beschleunigungsz?hler out SREG,TEMPS ; SREG rücksichern reti ; Rücksprung und Interupts wieder einschalten INCSpeed: cp IncCNT, IncVAL ; vergleiche Beschleunigungszähler brne OVF1 ; Springe wenn kleiner clr IncCNT ; lösche Beschleunigungszähler clr IncCNT1 ; lösche Beschleunigungsz?hler inc ISTSpeed ; erhöhe Speed rjmp PWMOut ; weiter DECSpeed: cp IncCNT, DECVAL ; vergleiche Beschleunigungsz?hler brne OVF1 ; Springe wenn kleiner clr IncCNT ; lösche Beschleunigungszähler clr IncCNT1 ; lösche Beschleunigungszähler dec ISTSpeed ; verringere Speed PWMOut: tst ISTSpeed ; ist Speed 0 brne OUTZ ; dann 0 ansonsten Out ldi TEMPI,0b01000101 ; Timer/Counter1 PWM vom out TCCR1,TEMPI ; Ausgang trennen ;cbi PortB, PB0 ; alles auf Null out SREG,TEMPS ; SREG rücksichern reti ; Rücksprung und Interupts wieder einschalten OUTZ: sbrs DCCReg, DIR ; wenn Fahrtrichtung vorw?rts rjmp REV ; Überspringe setzen Ausgang rückwärts ;cbi PORTB, PB0 ; setze Ausgang für vorwärts out OCR1A, ISTSpeed ; Wert für Speed nach Timer 1 Compare ldi TEMPI,0b01101011 ; Timer/Counter1 PWM ;out TCCR1,TEMPI ; Ausgang direkt out SREG,TEMPS ; SREG rücksichern reti ; Rücksprung und Interupts wieder einschalten REV: ;sbi PORTB, PB0 ; setze Ausgang für rückwärts out OCR1A, ISTSpeed ; Wert für Speed nach Timer 1 Compare ldi TEMPI,0b01111011 ; Timer/Counter1 PWM ;out TCCR1,TEMPI ; Ausgang indirekt OVF1: out SREG,TEMPS ; SREG r?cksichern reti ; Rücksprung und Interupts wieder einschalten TIM0_OVF: in TEMPS,SREG ; SREG sichern clr TEMPI ; Timer anhalten out TCCR0,TEMPI ; Prescaler steht auf STOP-Counter mit 000 sbrs FlagReg,LoTiF; ist der Interrupt wegen der Sample-Zeit ausgeloest worden rjmp SAMPLE ; ja, dann sample das Bit clr BitCnt ; nein, dann loesche den BitCounter wieder clr ByteA ; nein, dann loesche Register ByteA clr ByteB ; nein, dann loesche Register ByteB clr ByteC ; nein, dann loesche Register ByteC clr ByteD ; nein, dann loesche Register ByteD clr ByteE ; nein, dann loesche Register ByteE clr ByteF ; nein, dann loesche Register ByteF cbr FlagReg, (1<