;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
|
|