Source file: /~heha/Mikrocontroller/SLB0587Ersatz.zip/slb0587.a90

;Phasenanschnittsteuerung SLB0587-Ersatz mit ATtiny11-13
;UNFERTIG!

#define ATtiny

.NOLIST
#ifdef ATtiny
.include "tn11def.inc"
#else
.include "m8def.inc"
#endif
;.include "makros.i90"
.LIST
.listmac

;****************
;** Konstanten **
;****************

;Belegung GPIO (Pin)
;.equ TRIAC2	=0	;(7) Triac-Steuerausgang, 0=EIN, TS=AUS
.equ SENSOR2	=1	;(6) Sensorkontakt für zweiten Triac
.equ SENSOR	=2	;(5) Sensorkontakt für ersten Triac
.equ USENSE	=3	;(4) Spannungsüberwachung am 1. Triac
.equ TRIAC	=4	;(3) Triac-Steuerausgang, 0=EIN, TS=AUS
.equ MODE	=5	;(2) an + (A), offen (B), an - (C)
;Zurzeit nur ein Triac, WAHLWEISE an TRIAC oder TRIAC2 anschließbar!


;************************
;** RAM-Speicherzellen **
;************************
.def tmp0	= r17	;Zwischenwert (Berechnung)
.def KeyBits	= r18	;Diverse Bits zur Tastensteuerung
;0 = Sensor vorher gedrückt (Unterdrückung einzelner Fehler)
;1 = Sensor gilt als gedrückt (>50ms)
;2 = Sensor-Langzeitdruck (>400ms)
;3 = Richtungsbit, 1=hoch, 0=runter (Helligkeit)
;4 = MODE klebt an + (Modus "A" lt. Datenblatt)
;5 = MODE klebt an - (Modus "C" lt. Datenblatt)
;6 = Licht EIN (ansonsten ist "Hell" der Speicherwert)
.def KeyCnt	= r19	;Zähler für Autorepeat
.def Hell	= r11	;Soll-Helligkeit (Zündwinkel)
.def Real	= r12	;Ist-Helligkeit wegen Softstart (Zündwinkel)
.def HellMin	= r13	;Mindest-Helligkeit (25%)
.def HellMax	= r14	;Höchst-Helligkeit (95%)
.def T2		= r15	;Halbe Periodendauer

.equ CPUCLK	= 1000000	;Hz
.equ DEFGPIO	= 0x3F;2Eh	;Normalzustand für GPIO-Ausgaberegister
.equ DEFTRIS	= 0x0D;3Fh	;Normalzustand für TRIS-Ausgaberegister: Eingänge
.equ DEFOPT	= 0x86	;keine Pull-Ups(!!), Vorteiler=128, Zählerperiode > 32ms
;Zur Begrenzung der Nulldurchgangs-Suche (15 und 22 sind Millisekunden)
.equ MINCT0	= 10;15*CPUCLK/1000/128	;Minimaler "erlaubter" Zählerstand (117)
.equ MAXCT0	= 255;22*CPUCLK/1000/128	;Maximaler "erlaubter" Zählerstand (171)

;*********************
;** Programm im ROM **
;*********************
	.org	0
	rjmp	startup

;====================
;== Unterprogramme ==
;====================

AdjustLimits:
;Anhand des gespeicherten Wertes für T2 die Werte HellMin(30%), HellMax(95%)
;berechnen und ggf. "Hell" eingrenzen
	mov	tmp0,T2
	lsr	tmp0		;viertel Periodendauer (50%) laden
	lsr	tmp0		;achtel Periodendauer (75%)
	mov	r16,T2
	sub	r16,tmp0	;3/8 Periodendauer (25%)
	cp	Hell,HellMin	;Hell-HellMin, C=1 wenn Hell<HellMin (OK)
	brcc	al1
	 mov	Hell,HellMin
al1:	lsr	tmp0		;1/16 Periodendauer (88%)
	lsr	tmp0		;1/32 Periodendauer (94%)
	cp	Hell,HellMax	;Hell-HellMax, C=1 wenn Hell<HellMax (nicht OK)
	brcs	al2
	 mov	Hell,HellMax
al2:	ret

ZeroCross:	;Sucht Nulldurchgang (des Stroms) so dass Spannung negativ wird
;Bei >22ms Periodendauer wird von einem Fehler ausgegangen
;Warten bis USENSE=H, dabei Zählerüberlauf detektieren
; movlw	DEFGPIO&~(1<<SENSOR2)
; movwf	GPIO
zc_1:	in	r16,TCNT0
	cpi	r16,MAXCT0
	brcc	zc_err
	sbis	PinB,USENSE
	 rjmp	zc_1		;warte solange USENSE=L
; movlw	DEFGPIO
; movwf	GPIO
zc_2:	in	r16,TCNT0
	cpi	r16,MAXCT0
	brcc	zc_err
	sbic	PinB,USENSE
	 rjmp	zc_2		;warte solange USENSE=H
	cpi	r16,MINCT0
	brcs	zc_1		;warte solange zu wenig Zeit vergangen ist
	lsr	r16		;Zählerwert halbieren
	mov	T2,r16		;neue halbe Periodendauer
	clr	r16		;Zähler neu starten
	out	TCNT0,r16
	ret
zc_err:	sec
	ret

HandleSensor:	;Aufruf alle 20ms, nachdem USENSE auf L gegangen ist
;SENSOR ist H, wenn eine externe Kapazität (Mensch) den H-L-Wechsel verzögert
	sbis	PinB,SENSOR
	 rjmp	hs_touched
;	btfsc	GPIO,SENSOR2
;	 goto	hs_touched
;Sensor nicht berührt
	sbrc	KeyBits,0
	 rjmp	hs_killonspike	;Einzel-OFF-Impuls ignorieren
	sbrs	KeyBits,1
	 ret			;Wenn nicht berührt gewesen, nichts tun!
	cbr	KeyBits,1<<1	;Beim nächsten Mal nichts tun
	sbrs	KeyBits,2
	 rjmp	hs_release_short
	ldi	r16,1<<3	;Richtungsbit
	sbrs	KeyBits,4	;Wenn MODE an + klebt Richtung NICHT ändern
	 eor	KeyBits,r16
	rjmp	hs_switch_off
hs_release_short:
	sbrs	KeyBits,6	;Licht brennt?
	 rjmp	hs_switch_on	;nein, einschalten
hs_switch_off:
	cbr	KeyBits,1<<6	;Licht AUS
	ret
hs_switch_on:
	sbrc	KeyBits,4	;Klebt an +? Maximum laden!
	 mov	Hell,HellMax
	sbrc	KeyBits,5	;Klebt an -? Maximum laden!
	 mov	Hell,HellMax
	sbr	KeyBits,1<<6	;Licht AN
	ret
hs_killonspike:
	cbr	KeyBits,1<<0
hs_ret:	ret
hs_touched:	;Sensor berührt
	sbrs	KeyBits,0
	 rjmp	hs_killoffspike
	sbrs	KeyBits,1
	 rjmp	hs_inittouch	;Wenn nicht berührt gewesen, Zähler init.
	dec	KeyCnt
	brne	hs_ret		;nichts tun wenn <>0
	sbrc	KeyBits,2	;"Lange" Berührung?
	 rjmp	hs_longtouch
	sbrc	KeyBits,4	;Klebt an +? Minimum laden!
	 mov	Hell,HellMin
	sbrc	KeyBits,5	;Klebt an -? Minimum laden!
	 mov	Hell,HellMin
				;Licht AN
	sbr	KeyBits,(1<<2)|(1<<6)	;auf "lange Berührung" umschalten
	ldi	KeyCnt,5	;Zähler laden, erster Repeat länger als 3
hs_longtouch:
	cp	Hell,HellMin	;Minimum ist erreicht?
	brne	hs_1
	 sbr	KeyBits,1<<3	;Richtung RAUF
hs_1:	cp	Hell,HellMax	;Maximum ist erreicht?
	brne	hs_2
	 cbr	KeyBits,1<<3	;Richtung RUNTER
hs_2:	sbrc	KeyBits,3
	 dec	Hell		;RAUF (Anschnittwinkel verkleinern)
	sbrs	KeyBits,3
	 inc	Hell		;RUNTER (Anschnittwinkel vergrößern)
	ldi	KeyCnt,3
	ret
hs_inittouch:
	sbr	KeyBits,1<<1	;"Berührt" melden
	cbr	KeyBits,1<<2	;"Kurzer Tastendruck" melden
	ldi	KeyCnt,8	;Zähler für 400ms
	ret
hs_killoffspike:
	sbr	KeyBits,1<<0
	ret

HandleSoftstart:	;Aufruf nach HandleSensor (alle 20ms)
;Nachführung von "Real" an "Hell"; Aufruf nur wenn EIN!
	cp	Hell,Real	;C=1 wenn Hell<Real
	brcs	hs_soft		;wenn Real>Hell
	mov	Real,Hell	;Zündwinkel halten oder  vergrößern
	ret
hs_soft:
	dec	Real		;Zündwinkel langsam verkleinern
	ret

ReadMode:	;Verbindung (nach + oder -) am MODE-Pin prüfen
	cbr	KeyBits,(1<<4)|(1<<5)
	sbi	DDRB,MODE	;H ausgeben
	nop
	sbic	PinB,MODE	;wenns an Minus (Udd) klebt
	 rjmp	rm_nominus
	cbi	DDRB,MODE	;Treiber sofort entlasten (Kurzschluss!)
	sbr	KeyBits,1<<5
	ret
rm_nominus:
	cbi	PortB,MODE	;L ausgeben
	nop
	sbic	PinB,MODE	;wenns an Plus (Uss) klebt
	 sbr	KeyBits,1<<4
	sbi	PortB,MODE
	cbi	DDRB,MODE	;Z ausgeben
	ret

FireNow:	;Drei Zündimpulse (je 10µs) ausgeben
	ldi	tmp0,10
fn_loop:
	;movlw	DEFTRIS&~((1<<TRIAC)|(1<<TRIAC2))
	;tris	GPIO		;L ausgeben - Zündung
	cbi	PortB,TRIAC
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	;movlw	DEFTRIS
	;tris	GPIO		;Z ausgeben
	sbi	PortB,TRIAC	;H ausgeben
	dec	tmp0
	brne	fn_loop
	ret

FireNeg:	;Zündung Triac zur negativen (ersten) Halbwelle
fn_wait:
	in	r16,TCNT0
	eor	r16,Real
	brne	fn_wait
	rjmp	FireNow
;Bei der negativen Halbwelle wäre die Messung des Zünderfolgs möglich.
;Die dazu notwendige Zeit könnte zur positiven Halbwelle wiederholt werden,
;da hierbei nicht messbar.
	;retlw	0
	
FirePos:	;Zündung Triac zur positiven (zweiten) Halbwelle
fp_wait:
	in	r16,TCNT0
	mov	tmp0,Real
	add	tmp0,T2
	eor	r16,tmp0
	brne	fp_wait
	rjmp	FireNow
	;retlw	0
	
;===================
;== Hauptprogramm ==
;===================
startup:
;* Aktion 1:
;  Ports einrichten, Option setzen
	ldi	r16,DEFOPT	;Vorteiler ???
	out	TCCR0,r16
	ldi	r16,DEFGPIO
	out	PortB,r16
	ldi	r16,DEFTRIS
	out	DDRB,r16
#if 0
test:
 movlw DEFGPIO&~(1<<TRIAC)
 movwf GPIO
 movlw DEFGPIO&~(1<<MODE)
 movwf GPIO
 goto test
#endif
;* Aktion 2:
;  H-L-Flanke abwarten, Timer starten (Timer zählt aufwärts)
fail:
; movlw	DEFGPIO
; movwf	GPIO			;gib H aus solange Low
f1:	sbis	PinB,USENSE
	 rjmp	f1
; movlw	DEFGPIO&~(1<<SENSOR2)	;gib L aus solange High
; movwf	GPIO
f2:	sbic	PinB,USENSE
	 rjmp	f2
; btfsc	GPIO,SENSOR
;  goto fail
	clr	r16
	out	TCNT0,r16
;* Aktion 3:
;  Variablen vorbelegen
	clr	KeyBits
	rcall	ReadMode
	rcall	ZeroCross	;Periodendauer messen
	rcall	AdjustLimits
	mov	Hell,HellMin
;Hauptschleife
mainloop:
	rcall	ZeroCross
	brcs	fail
; call	ReadMode
;Lt. Datenblatt 0,9ms warten, bevor Sensor eingelesen wird,
;das ist Zählerstand 7(!)
; btfsc	GPIO,SENSOR
;  bsf	GPIO,MODE
; btfss	GPIO,SENSOR
;  bcf	GPIO,MODE
	rcall	HandleSensor	;Unmittelbar nach ZeroCross!
	rcall	AdjustLimits
	sbrs	KeyBits,6	;weiter nur wenn EIN
	 rjmp	mainloop
	rcall	HandleSoftstart
	rcall	FireNeg
	rcall	FirePos
	rjmp	mainloop

Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded