; Key scan Virtual Periperal
;
device pins28,pages4,banks8,turbo,oschs,stackx,optionx
; use oschs only for debugging
; set to 4MHz internal RC for actual operation
org 8
key_val ds 1 ; contains the key value in 2's complement
; this is for ease of display routine only
; to get real value, please remove the ~ signs in
; the virtual matrix
scanb ds 1 ; scan mask, the column to scan will have a zero
scan_result ds 1 ; result of scanning
cnt1 ds 1 ; column count (3 2 1 0, 3 being leftmost)
cnt2 ds 1 ; row count (3 2 1 0, 3 being the top row)
; virtual matrix index is computed as 4*cnt2+cnt1
key_state ds 1 ; store the states of the keyboard scan
debounce_cnt ds 1 ; debouncing count
temp equ cnt1 ; store the key scanned until key is released
; key scan states
fast_scan equ 7 ; scan all columns at once
debounce equ 6 ; debounce state
detailed_scan equ 5 ; scan a column at a time
release equ 4 ; wait until key is released
reset start ; goto 'start' on reset
org 0 ; interrupt routine
sb key_state.fast_scan ; current state=fast scan?
jmp chk_debounce ; no, check if debounce state
;do fast scan
mov rb,#%11110000 ; set all scan lines to low
mov scan_result,rb ; store result
and scan_result,#%11110000 ; mask all output lines
csne scan_result,#%11110000 ; to examine only inputs
jmp key_done ; no key pressed if results is 11110000
; key pressed, go to debounce state
clrb key_state.fast_scan ; clear current state
setb key_state.debounce ; next state= debounce
mov debounce_cnt,#20 ; 20 ms debouncing time
jmp key_done ; change state on next interrupt
chk_debounce
sb key_state.debounce ; current state=debouncing?
jmp chk_rescan ; no, check if detailed scan
;do debounce
decsz debounce_cnt ; count down
jmp key_done ; and continue on next interrupt if not done
; 20 ms elapsed
clrb key_state.debounce ; clear current state
setb key_state.detailed_scan ; next state=detailed scan
jmp key_done ; state transition on next interrupt
chk_rescan sb key_state.detailed_scan ; current state=detailed scan?
jmp chk_release ; no, check if it is key release check
mov cnt1,#3 ; leftmost column=3
;detailed scan
mov scanb,#%11110111 ; scan leftmost column first
detail_scan mov rb,scanb ; send scan mask out
mov scan_result,rb ; store result
and scan_result,#%11110000 ; examine only inputs
cse scan_result,#%11110000 ; any key?
jmp encode ; yes, encode it
dec cnt1 ; scan next column
stc ; maintain the 1's
rr scanb ; scan next column by moving the 0 to the right
snc ; no carry means last column has been scanned
jmp detail_scan ; still more to scan
; no key detected after scanning all columns, may be just noise on port
clrb key_state.detailed_scan ; clear current state
setb key_state.fast_scan ; return to fast scan
jmp key_done ; on next interrupt
encode mov cnt2,#0 ; find out on which row the key is pressed
stc ; we are looking for a zero so set carry to 1 first
cont_enc rl scan_result ; put the scan result in carry bit
sc ; skip if zero is not there
jmp lookup ; zero found, look up for value
inc cnt2 ; increment the row number
jmp cont_enc ; and continue
;virtual matrix offset=4 cnt2+cnt1
lookup clc ; clear carry to prepare for multiplication
rl cnt2 ; multiply by 2
rl cnt2 ; multiply by 4 and
add cnt2,cnt1 ; +cnt1
mov w,#virtual_matrix ; start of table
add w,cnt2 ; index into table
mov m,#0 ; prepare for iread which load the value at m:w
iread ; read the value into m:w
mov temp,w ; store
mov m,#$f ; restore m to eliminate side effects
clrb key_state.detailed_scan ; clear current state
setb key_state.release ; next state=check key release
jmp key_done ; on next interrupt
virtual_matrix dw ~$f
dw ~$0
dw ~$f
dw ~$f
dw ~9
dw ~8
dw ~7
dw ~$f
dw ~6
dw ~5
dw ~4
dw ~$f
dw ~3
dw ~2
dw ~1
dw ~$f
chk_release
sb key_state.release ; check key release state?
jmp key_done ; no
mov rb,scanb ; use last scanned column mask
mov scan_result,rb ; get key
and scan_result,#%11110000 ; mask outputs
cse scan_result,#%11110000 ; equ to $F0 if no key pressed anymore
jmp key_done ; key still pressed
; key released
mov key_val,temp ; store final value
clrb key_state.release ; state transition
setb key_state.fast_scan ; next state is scan again
key_done
mov w,#-250 ; 1 ms per interrupt at 4MHz, prescaler is /8
retiw ; return from interrupt now
start
;initialize port B
mov m,#$0f ; Points mode register to set data direction
mov !rb,#%11110000 ; RB0-3 will be outputs, and RB4-7 will be inputs
;set inputs with weak pull ups
mov m,#$0e ; points mode register to pull-up enable
mov !rb,#%00001111 ; Enable pull-ups on Port B inputs
mov m,#$0c ; set Schmitt-trigger to increase noise immunity
mov !rb,#%00001111 ; on RB4-7
mov m,#$F ; restore mode register
mov !option,#%10000010 ; RTCC divide rate=8
setb key_state.fast_scan ; initial state is fast scan
mov key_val,#0 ; no key pressed initially
loop
mov rb,key_val ; put key pressed on LEDs
jmp loop ; loop forever
file: /Techref/scenix/keyscan.src, 5KB, , updated: 1999/2/20 12:23, local time: 2024/11/19 06:08,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/Techref/scenix/keyscan.src"> scenix keyscan</A> |
Did you find what you needed?
|