Source file: /~heha/Mikrocontroller/InkrTast/Firmware.zip/InkrTast2s.a90

;Umsetzer Inkrementalgeber auf Hoch/Runter-Tasten
;Zur Nachrüstung eines Inkrementalgebers in Paralleleschaltung
;zu vorhandenen Hoch/Runter-Funktionstasten;
;diese müssen schnell genug reagieren und (hier:) nach Masse schalten
;Eine „nacheilende“ Tastenstimulation (für eine zu lahme Folgeschaltung)
;ist hier nicht implementiert
;Typ des Inkrementalgebers: 2 Pegelwechsel pro Rastung, symmetrisch*
;(bspw. ALPS EC11B)
;* Ob in Raststellung beide Schalter den gleichen oder unterschiedliche
;  Schaltzustände haben ist mit dieser Firmware unerheblich;
;  allerdings muss sich bei RESET der Schalter in Raststellung (Ruhe) befinden.
;Stromaufnahme: 200µA oder 0,2µA @ 5V, je nach Stellung des Inkrementalgebers
;  Wird nur erreicht, wenn die Ausgänge mit Pull-Ups beschaltet sind!
;080514	haftmann#software

;Hardware:
;Pinzuweisung:
#define	I1	3	;(2) Inkrementalgeber Kontakt A (nach Masse)
#define	I2	4	;(3) Inkrementalgeber Kontakt B (nach Masse)
#define	frei	0	;(5) frei (Pull-Up)
#define	O2	1	;(6) Tasten-Stimulusausgang - (nach Masse)
#define	O1	2	;(7) Tasten-Stimulusausgang + (nach Masse)
;Mit ALPS-Geber gibt O1 bei Rechtsdrehung Impulse aus.
;Anschlusslage:	+---+
;		| O |
;(C = GND)	+ACB+
;Bei Vertauschung von A und B kehrt sich die Richtung um.

;Zeiten
.equ	MAXKEY = 100	;Maximalzeit Tastendruckstimulation [ms]

.NOLIST
.include "tn12def.inc"	;Ein ATtiny11 würde auch reichen
.LIST
#define	CPUCLK	1200000	;[Hz] - beim ATtiny11 1000000

.def	zero	= R14	;immer Null
.def	cntsave	= R15	;Vorheriger binärer Zählerstand des Inkrementalgebers
.def	xorval	= R17	;immer 1<<I2
.def	drive	= R18	;Zu treibende Tasten (bei Zweierschritt)
.def	imask	= R19	;Stets 3<<I1

#if (I1+1 != I2)
#error	I2 muss 1 Bit "hoeher" sein als I1!
#endif

.cseg
	rjmp	OnReset		;Reset
	reti			;IRQ0
	rjmp	OnPinChange	;Pegelwechsel-Interrupt (aktiv!)
	rjmp	OnT0Ovl		;Timer0-Überlauf
	reti			;EEPROM fertig (nur ATtiny12)
	reti			;Analogvergleicher
	
OnPinChange:
	in	r0,PINB
	and	r0,imask
	sbrc	r0,I2
	 eor	r0,xorval	;Graykode -> Binärkode für 2 Bit
	mov	r1,r0
	sub	r1,cntsave	;Binäre Differenz
	sbrc	r1,I1		;Einerschritt?
	 rjmp	OneStep		;ja
	sbrs	r1,I2		;Zweierschritt?
	 reti			;nein, nichts tun (irrtümlicher Interrupt)
	mov	cntsave,r0
	out	DDRB,drive	;Je nach Richtung ausgeben
	clr	drive		;Nichts ausgeben bei plötzlichem Zweierschritt
	ldi	r16,5		;Vorteiler 1024 (maximal erreichbare Zeit: 0,2s)
	out	TCCR0,r16
	ldi	r16,256-CPUCLK/1024*MAXKEY/1000
	out	TCNT0,r16
	ldi	r16,1<<TOIE0
	out	TIFR,r16	;Anhängigen Interrupt löschen (falls vorhanden)
	out	TIMSK,r16
	ldi	r16,1<<SE	;Sleep = Sleep (Zähler läuft)
	out	MCUCR,r16
	reti
OneStep:
	ldi	drive,1<<O2
	sbrc	r1,I2		;Je nach Richtung
	 ldi	drive,1<<O1	;… nächste Tastenstimulation merken
OnT0Ovl:
	cbi	DDRB,O2		;Tastenstimulation ausschalten
	cbi	DDRB,O1
	ldi	r16,(1<<SE)|(1<<SM)
	out	MCUCR,r16	;Sleep = PowerDown
	out	TCCR0,zero	;Timer0 ausschalten
	out	TIMSK,zero	;Timer0-Überlaufinterrupt ausschalten
	reti
	
OnReset:
	clr	zero
	clr	drive		;Nichts ausgeben bei plötzlichem Zweierschritt
	ldi	imask,3<<I1
	ldi	xorval,1<<I1
	out	PORTB,imask	;Pullups am Inkrementalgeber aktivieren
	sbi	PORTB,frei	;Keine vagabundierenden Ströme
	in	cntsave,PINB
	and	cntsave,imask
	sbrc	cntsave,I2
	 eor	cntsave,xorval
	ldi	r16,1<<PCIE		;Pegelwechselinterrupt EIN
	out	GIMSK,r16
	ldi	r16,(1<<SE)|(1<<SM)	;Sleep = PowerDown
	out	MCUCR,r16
	sei
;Hauptschleife (schläft nur! Deshalb brauchen ISRs nichts retten!)
mainloop:
	sleep
	rjmp	mainloop

	.db	"haftmann#software",0
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded