;**************************************************************************
;*	Steinhart Winfried	19.05.07
;*
;*	SELECTRIX-Decoder für 4 Weichen-Servos
;*
;**************************************************************************


;*************************************************************************** 

;* Target MCU           :ATtiny2313
;*
;* Taktleitung PORTD, PIN PD3 (7), Datenleitung PORTD Pin PD0 (2)
;* Taktfrequenz 8 MHZ
;*************************************************************************** 





;***************  Anwendungswerte eintragen ! ******************************
;
;* Kalibrierwert eintragen wie angezeigt (Advanced) für 8 Mhz Clock
;* Fuse """" INTERNAL CLOCK DIVIDE NICHT PROGRAMMIEREN """" ***************
;* Fuse INTERNER RC-OSCILLATOR 8MHZ setzen !!				***************

.SET Leskal = 0x54


;***************  Adressliste *********************************************
;
; Die Adresse bestimmt die Gruppennummer und die Unteradresse UA

; Gru= 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01, 00

; UA6= 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15
; UA5= 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
; UA4= 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
; UA3= 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
; UA2= 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
; UA1= 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
; UA0= 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111
;**************************************************************************

.SET Gru = 15
		; Aus Liste für die Adresse entnommen (z.B. Adr. 64)

;**************************************************************************
;* Das Datenwort wird aus jeweils 2 Registern für 1 Unteradresse
;* gebildet
;**************************************************************************

;	bitregLow:				bitregHi:				für: UaGru = 0

;	r2						r3						UA 0
;	r5 -------------------- r6 --------------------	UA 2
;	r8						r9						UA 4
;	r11 ------------------- r12 ------------------- UA 6

;	bitregLow				bitregHI:				für: UaGru = 1

;	r4						r5						UA 1		
;	r7 -------------------- r8 -------------------- UA 3
;	r10						r11						UA 5

;***************************************************************************


.DEF bitregLow 	= r5		
.DEF bitregHi 	= r6
.SET UagGru		= 0
.SET Nibble		= 0

;**		Servo 1 und 2 wird vom Timer1 gesteuert mit 10Bit Auflösung		****
;**		Wiederholzeit ca. 16 MillSek., 1 Tick ca. 16 µSek.				****

.SET Pos1Lo		= 90
.SET Pos1Mitte 	= 100
.SET Pos1Hi		= 110

.SET Pos2Lo		= 90
.SET Pos2Mitte 	= 100
.SET Pos2Hi		= 110

;**		Servo 3 und 4 wird vom Timer0 gesteuert mit 8Bit Auflösung		****
;**		Wiederholzeit ca. 8 MillSek., 1 Tick ca. 32 µSek.				****

.SET Pos3Lo		= 45
.SET Pos3Mitte 	= 50
.SET Pos3Hi		= 55

.SET Pos4Lo		= 45
.SET Pos4Mitte 	= 50
.SET Pos4Hi		= 55

;*  Nach Build und Programmieren Mittenposition OHNE SX-Bus-Signal testen.
;*
;***************************************************************************


.include "tn2313def.inc"

.CSEG

;***** Programm-Code					**
;**************************************************************************

	rjmp	RESET		;Reset Handle
	rjmp	EXT_INT0
	rjmp	EXT_INT1
	rjmp	TIM_CAPT1
	rjmp	TIM_COMP1
	rjmp	TIM_OVF1
	rjmp	TIM_OVF0
	rjmp	UART_RXC
	rjmp	UART_DRE
	rjmp	UART_TXC
	rjmp	ANA_COMP


;**	Hier gehts los					**
;**************************************************************************

RESET:
	ldi 	r20,Leskal		; gelesener Kalibrier-Wert für 1.6 Mhz Clk
	out 	OSCCAL, r20


	ldi		r17,low(RAMEND)	; Programm-Startadresse laden
	out		SPL,r17			; Stackpointer LO
	
	wdr						; Watchdog Reset
	ldi		r17,0x8			; Watchdog enable WDE
	out		WDTCR,r17
	
	ldi		r17,0x3			;*** Takteingang PORT D Bit PD2 ***
	out		MCUCR,r17		; ISC00 mit ISC01 für INT0 raising edge
	

	ldi		r17,0x04		; Prescaler Timer 0
	out		TCCR0B,r17		; CK/256
	
	ldi		r17,0xA3		; Clear OC0A und OC0B on Compare Match
	out		TCCR0A,r17


	ldi		r17,0x1C		; Bit 2,3,4 auf Ausgang
	out		DDRB,r17		; setzen.

	ldi		r17,0x70		; Bit 4,5,6 auf Ausgang
	out		DDRD,r17		; setzen.

	ldi		r17,0xA3		; 10 Bit PWM, OC1 not inverted PWM
	out		TCCR1A,r17		; Timer1 Controlregister 1A

	ldi		r17,0x03		; Timer1 mit clk/64 starten,16 mSek
	out		TCCR1B,r17		; Timer1 Controlregister 1B

	ldi		r17,0x40
	out		GIMSK,r17		; enable INT10

	clr 	r17
	out		OCR1AH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos1Mitte
	out		OCR1AL,r17		; Position 1 Mitte

	clr 	r17
	out		OCR1BH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos2Mitte
	out		OCR1BL,r17		; Position 2 Mitte

	ldi		r17,Pos3Mitte	; Position 3 Mitte
	out		OCR0A,r17

	ldi		r17,Pos4Mitte	; Position 4 Mitte
	out		OCR0B,r17

	sei						; enable Int. im Statusregister
	

;**	Warteschleife					**
;***************************************************************************
forever:
	wdr					; Watchdog Reset00000
	rjmp	forever


;**	Interruptservice-Routinen			**
;***************************************************************************

EXT_INT1:	reti
TIM_CAPT1:	reti
TIM_COMP1:	reti
TIM_OVF1:	reti
UART_RXC:	reti
UART_DRE:	reti
UART_TXC:	reti
ANA_COMP:	reti
TIM_OVF0:	reti


;***************************************************************************
;*	Dieser Entry ist der Interrupt nach steigender Taktflanke.
;*	Der TRIX-Takt hat 50 Mikrosek. Zykluszeit, d.h.während dem Scan der
;*	insgesamt 96 Bits für eine Basisadress-Information muss jedes
;*	Datenbit erkannt werden.
;*	Die Daten werden von Bit = r12 nach Links in die niedrigeren
;*	Register geschoben. (Rotate left through Carry)
;*	In diesem Testprogramm ist PORT D PIN D0 der Dateneingang.
;*	Die Schiebebefehle bringen eine Verzögerungszeit bis zum Lesen
;*	der Datenleitung. Damit ist sichergestellt, dass der Input mit
;*	dem "richtigen" Status gelesen wird.

;*	Diese Interrupt-Service-Routine braucht ca. 40 Takte incl.
;*	Annahmezeit und Return wenn kein Syncsignal vorliegt.

EXT_INT0:			;Interrupt-Service-Routine

;**	Software Störunterdrückung 12 Befehle HI-Signal	**

	sbis	PIND,2		; Pin 2, PortD ist INT0-Eingang
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti
	sbis	PIND,2
	reti

		
;**	Schieberegister für 1 Synch-Block + Vorlaufregister	**


	lsl	r13		; Vorlaufregister für Syncvergleich
	rol	r12		; Start für 96 Bit Schieberegister
	rol	r11
	rol	r10
	rol	r9		; Schieberegister through carry
	rol	r8
	rol	r7
	rol	r6
	rol	r5
	rol	r4
	rol	r3
	rol	r2
	rol	r1		; Synchrongruppe im Hi-Nibble,
				; Adresse im Lo-Nibble



;**	Datenleitung übernehmen					**

	clr		r25			; Bit 0 auf Datum LO stellen
	sbic	PIND,0		; Skip wenn Datenleitung LO
	
	ldi		r25,0x01	; Setze LSB weil Datenleitung HI
	or		r13,r25		; Eintragen in Vorlaufregister


	
;***************************************************************************
;*	Nach jedem Eintrag wird geprüft ob die 5 Synchronbits da sind.
;*	Nach TRIX SX-Codierung 0-0-0-1-x-1-B3-B2-1-B1-B0-1 in den obersten 12 Bit
;*	x ist das Gleisspannungsbit. B0 bis B3 ist die Basisadresse
;*
;*
;*	AVR-Micros erlauben nur in den oberen 16 Registern Immediate
;*	Befehle (andi, cpi usw.)
;***************************************************************************


	mov		r16,r1			; alte Synchronbits holen und testen
	andi	r16,0xF4		; die oberen 6 Bit gelten, 1-1-1-1-0-1-0-0
	cpi		r16,0x14		; 0-0-0-1-0-1-0-0 = Sync
	breq	sync1

	reti

sync1:

	mov		r16,r13			; neue Synchronbits im Vorlaufregister prüfen
	andi	r16,0xF4		; die oberen 6 Bit gelten, bit 0,1,3 auf 0
	cpi		r16,0x14		; Bit 5,6,7 Lo UND 4,2 Lo = Sync
	breq	sync			; beide Bitmuster gleich, Telegrammlänge ok
							; Daten in den Registern fertig

	reti

;***************************************************************************
;*	Wenn die Synchronbits komplett sind wird die Basisadresse geprüft.
;*	Die Prüfung ist in die Interruptloop eingeschlossen, d.h. reti muss
;*	ausgeführt sein damit das nächste Datenbit noch richtig erkannt wird.
;*	Der Interrupt wird abgeschaltet wenn Adresse stimmt.
;*	Die Adressdecodierung verlängert die Int.Service um ca 12 Takte auf
;*	ca 45 Takte.
;*	Die Prozessorfrequenz muss sicherstellen, dass das folgende Datenbit
;*	im nächsten Takt noch sicher erkannt wird.
;***************************************************************************


sync:

	mov		r16,r1		; 6 Bit sync + 2 Bit Adresse, B3-B2
	andi	r16,0x03	; sync-Bits löschen
	lsl 	r16
	lsl 	r16
	
	mov		r17,r2		; Adress- und Datenbyte 1-B1-B0-1-D7-D6-1-D5
	andi	r17,0x60	; Datenbits löschen		0-B1-B0-0-0-0-0-0
	swap 	r17			;						0-0-0-0-0-B1-B0-0
	lsr 	r17			;						0-0-0-0-0-0-B1-B0
	or 		r16,r17		; Adresse fertig r16 =	0-0-0-0-B3-B2-B1-B0


	cpi		r16,Gru		; **** Adresstest *********************

	breq	daten		; Adresse gültig, Daten extrahieren


	reti				; falsche Basis-Adresse, weiterscannen

daten:
	sbi		PORTD,5		; *** Triggerbit Adresse gültig !!

	ldi 	r22,UagGru	; ******** Anwender gesetzt ********

	cpi		r22,1		; Unteradressgruppe 2 ?
	breq	gruppe2

;***************************************************************************

;.DEF bitregLow = r11		; Aus Liste z.B. für UA 6 und Datenbit D0
							; D0=3 D1=2 D2=0
;.DEF bitregHi = r12		; D3=7 D4=5 D5=4 D6=2 D7=1

	clr 	r20				; Ergebnisregister
	sbrc 	bitregLow,3
	sbr 	r20,1			; Bit 0
	sbrc 	bitregLow,2
	sbr 	r20,2			; Bit 1
	sbrc 	bitregLow,0
	sbr 	r20,4			; Bit 2 

	sbrc 	bitregHi,7
	sbr 	r20,8			; Bit 3
	sbrc 	bitregHi,5
	sbr 	r20,16			; Bit 4
	sbrc 	bitregHi,4
	sbr 	r20,32			; Bit 5
	sbrc 	bitregHi,2
	sbr 	r20,64			; Bit 6
	sbrc 	bitregHi,1
	sbr 	r20,128			; Bit 7

	rjmp	fertig			; Datenwort in r20 fertig

	

gruppe2:

;.DEF bitregLow = r10		; Aus Liste z.B. für UA 6 und Datenbit D0
							; D0=7 D1=6 D2=4 D3=3 D4=1 D5=0
;.DEF bitregHi = r11		; D6=6 D7=5

	clr 	r20				; Ergebnisregister
	sbrc 	bitregLow,7
	sbr 	r20,1			; Bit 0 
	sbrc 	bitregLow,6
	sbr 	r20,2			; Bit 1
	sbrc 	bitregLow,4
	sbr 	r20,4			; Bit 2 
	sbrc 	bitregLow,3
	sbr 	r20,8			; Bit 3
	sbrc 	bitregLow,1
	sbr 	r20,16			; Bit 4 
	sbrc 	bitregLow,0
	sbr 	r20,32			; Bit 5

	sbrc 	bitregHi,6
	sbr 	r20,64			; Bit 6
	sbrc	bitregHi,5
	sbr 	r20,128			; Bit 7

							; Datenwort in r20 fertig

;****************************************************************

fertig:
	ldi		r17,Nibble
	tst		r17				; Low oder High Nibble ?
	breq	lownibble

	mov 	r19,r20			; Datenwort kopieren
	andi 	r19,0xF0		; High-Nibble stehenlassen

	sbrc	r19,4			; Bit 0 im High Nibble
	rjmp	bit4Hi
	clr 	r17
	out		OCR1AH,r17		; PWM Vergleichswert HI
	ldi		r17,pos1Lo
	out		OCR1AL,r17		; Position 1 low
	rjmp	bit5
bit4Hi:
	clr 	r17
	out		OCR1AH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos1Hi
	out		OCR1AL,r17		; Position 1 high

bit5:
	sbrc	r19,5			; Bit 1 im High Nibble
	rjmp	bit5Hi
	clr 	r17
	out		OCR1BH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos2Lo
	out		OCR1BL,r17		; Position 2 low
	rjmp	bit6
bit5Hi:
	clr 	r17
	out		OCR1BH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos2Hi
	out		OCR1BL,r17		; Position 2 high

bit6:
	sbrc	r19,6			; Bit 2 im High Nibble
	rjmp	bit6Hi
	ldi		r17,Pos3Lo		; Position 3 low
	out		OCR0A,r17
	rjmp	bit7
bit6Hi:
	ldi		r17,Pos3Hi		; Position 3 high
	out		OCR0A,r17
	
bit7:
	sbrc	r19,7			; Bit 3 im High Nibble
	rjmp	bit7Hi
	ldi		r17,Pos4Lo		; Position 4 low
	out		OCR0B,r17
	rjmp	exitpos
bit7Hi:
	ldi		r17,Pos4Hi		; Position 4 high
	out		OCR0B,r17

	rjmp	exitpos

lownibble:
	mov 	r19,r20			; Datenwort kopieren
	andi 	r19,0x0F		; Low-Nibble stehenlassen

	sbrc	r19,0			; Bit 0 im Low Nibble
	rjmp	bit0Hi
	clr 	r17
	out		OCR1AH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos1lo
	out		OCR1AL,r17		; Position 1 low
	rjmp	bit1
bit0Hi:
	clr 	r17
	out		OCR1AH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos1Hi
	out		OCR1AL,r17		; Position 1 high

bit1:
	sbrc	r19,1			; Bit 1 im Low Nibble
	rjmp	bit1Hi
	clr 	r17
	out		OCR1BH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos2Lo
	out		OCR1BL,r17		; Position 2 low
	rjmp	bit2
bit1Hi:
	clr 	r17
	out		OCR1BH,r17		; PWM Vergleichswert HI
	ldi		r17,Pos2Hi
	out		OCR1BL,r17		; Position 2 high

bit2:
	sbrc	r19,2			; Bit 2 im Low Nibble
	rjmp	bit2Hi
	ldi		r17,Pos3Lo		; Position 3 low
	out		OCR0A,r17
	rjmp	bit3
bit2Hi:
	ldi		r17,Pos3Hi		; Position 3 high
	out		OCR0A,r17
	
bit3:
	sbrc	r19,3			; Bit 3 im Low Nibble
	rjmp	bit3Hi
	ldi		r17,Pos4Lo		; Position 4 low
	out		OCR0B,r17
	rjmp	exitpos
bit3Hi:
	ldi		r17,Pos4Hi			; Position 4 high
	out		OCR0B,r17

exitpos:
	cbi		PORTD,5			;*** Triggerbit Adresse gültig !!!
	
	reti

;***************************************************************************

	.exit
		
</html>