📄 keys.asm
字号:
;==========================================================
; This is a part of: Eversmith - AVRSMS
; Copyright (2003) Martin Thomas, Kaiserslautern, Germany.
; This Software is distributed under the Aladdin Free
; Public License (AFPL) Read the file license.txt included
; in the distibution-package. See main-file for more infor-
; mation and license.
;==========================================================
; Input Key handling (debouncing)
;=========================================
; SRAM Labels
.dseg
; Push-Button-States for debouncing
KeyOldState: .byte 1
KeyCount: .byte 8
KeyOnMsg: .byte 1
KeyOffMsg: .byte 1
.cseg
; Input-keys handled by this routines
; as bit-mask (0b00000001=only Pin0 is controlled by this;
; 0b11000011=Pins 7,6,1,0 are controlled by this routines)
; control in this application P0-P4 and P7 (for Menue)
.equ KEYMASK=0b10011111
; Keys are connected to PORTA
.equ KEYPORT=PORTA
.equ KEYDDR=DDRA
.equ KEYPIN=PINA
; number of counts for debouncing:
; this is the number of timer0 interrupts
; for which an input as to stay in the same state
; predefined are 10ms for the interrupt, so the
; key has to stay for KEYMAXCOUNT*10ms in the same
; state to be recognized as switched
.equ KEYMAXCOUNT=5
;=========================================
; Init Input Key-State
;
; call this from the RESET-Handler
; Input for push-buttons - active LOW
KeysInit:
push r16
push r17
push XL
push XH
; direction
in r16,KEYDDR ; old direction value
ldi r17,KEYMASK ; load keymask
com r17 ; invert keymask
and r16,r17 ; mask unmanaged dirs.
out KEYDDR,r16 ; set direction
; pull-ups
in r16,KEYPORT ; old pull-up-state
ldi r17,KEYMASK
or r16,r17 ; mask unmanaged pullups
out KEYPORT,r16 ; for input pins
nop ; set pull-ups and sync
; init Port-Change values used in T0OVR-Interrupt
; (debouncing)
in r16,KEYPIN ; load actual state
sts KEYOldState,r16 ; save startup-key-state
clr r16
sts KEYOnMsg,r16 ; clear "On"-"Messages"
sts KEYOffMsg,r16 ; dito for "Off"
; clear counters
ldi r16,KEYMAXCOUNT+2 ; store maximum value to counters
clr r17
ldi XL,low(KEYCOUNT) ; set X to start of counter
ldi XH,high(KEYCOUNT) ; array
KI_L1:
st X+,r16 ; store $00 to counter array
inc r17
cpi r17,$08 ; all 8 counters?
brne KI_L1 ; no - go on
pop XH
pop XL
pop r17
pop r16
ret
;=========================================
; Clear Bits in "on"-Message
; Bit-Mask in r16
KeysClearOnMsg:
push r16
push r17
com r16 ; invert
cli ; disable interrupt
lds r17,KeyOnMsg
and r17,r16
sts KeyOnMsg,r17
sei ; enable interrupt
pop r17
pop r16
ret
;=========================================
; Clear Bits in "off"-Message
; Bit-Mask in r16
KeysClearOffMsg:
push r16
push r17
com r16 ; invert
cli ; disable interrupt
lds r17,KeyOffMsg
and r17,r16
sts KeyOffMsg,r17
sei ; enable interrupt
pop r17
pop r16
ret
;=========================================
; Key-IRQ-Handler
;
; call this from Inside a Timer-Interrupt-Handler
; example:
; PIN=0011 (3,2 on/1,0 off)
; OLD=1010 (2,0 on/3,1 off)
; PIN XOR OLD=1001 -> unchanged 0, changed 1
KeysIRQHandler:
push r16
push r17
push r18
push r19
push r21
push XL
push XH
ldi XL,low(KEYCOUNT) ; set X to start of counter
ldi XH,high(KEYCOUNT) ; array
in r16,KEYPIN ; load actual state
lds r19,KeyOldState ; load old states from SRAM
eor r19,r16 ; Xor with old state
; changed state results to 1 @ bit-pos.
ldi r18,0b00000001 ; mask for Pin_0
KeyIRQ_L1:
mov r16,r18 ; copy to temp-Reg.
andi r16,KEYMASK ; check if its a managed Pin
tst r16 ; cpi r16,$00
breq KEYIRQ_L1_CT1 ; branch if unmanaged
; process managed Pin
ld r17,X ; load counter from SRAM
mov r16,r18 ; copy mask
and r16,r19 ; check if Pin changed
tst r16 ; cpi r16,$00
breq KEYIRQ_unch ; branch if state changed
; state has changed
clr r17
rjmp KEYIRQ_L1_STCNT; continue with next Pin/Bit
KEYIRQ_unch:
; state is unchanged
inc r17 ; compare counter
cpi r17,KEYMAXCOUNT
brlo KEYIRQ_L1_STCNT; branch of lower than maxcount
cpi r17,KEYMAXCOUNT ; counter exactly maxcount ?
brne KEYIRQ_L1_CT1 ; no -> no action
inc r17 ; increment counter
; store messages
in r16,KEYPIN ; load aktuell state
and r16,r18 ; mask bit 0->ON (grounded) 1->OFF (pull-up)
tst r16 ; cpi r16,$00
breq KEYIRQ_L1_ON ; grounded
lds r16,KeyOffMsg
or r16,r18 ; set bit in "off" Message
sts KeyOffMsg,r16
rjmp KEYIRQ_L1_STCNT
KEYIRQ_L1_ON:
lds r16,KeyOnMsg
or r16,r18 ; set bit in "on" Message
sts KeyOnMsg,r16
KEYIRQ_L1_STCNT:
st X,r17 ; store counter
KEYIRQ_L1_CT1:
adiw XH:XL,$01 ; increment counter-array pointer
clc ; clear carry
rol r18 ; rotate bit-mask
tst r18 ; cpi r18,$00, all Pins processed?
brne KeyIRQ_L1
KeyIRQ_L1_exit:
in r16,KEYPIN ; store act state as old state
sts KeyOldState,r16
pop XH
pop XL
pop r21
pop r19
pop r18
pop r17
pop r16
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -