📄 keyscan.asm
字号:
;REVISION HISTORY
;9/10/99 incorporated new keyscan routine to fix ps/2 ghosting problem
;8/13/98
; changed sense of usb connect bit in port 3
;========================================================================
; KEYBOARD SCAN TASK
; The keyboard is organized as 8 rows by 18 columns. The I/O ports are
; assigned as:
; P2
; bit7 bit0
; r7 r6 r5 r4 r3 r2 r1 r0
;
; P3 P1 P0
; bit7 bit4 bit7 bit0 bit7 bit0
; c17 c16 c15 c14 c13 c12 c11 c10 c9 c8 c7 c6 c5 c4 c3 c2 c1 c0
;
; The three LEDs are on port 3 bits[2:0]
;
; The keycode table is organized as 18 columns with 8 rows per column.
; ksc_x_index selects a column from 0 to 17
; ksc_y_index selects a row from 0 to 7
;========================================================================
;------------------------------------------------------------------------
; ram variables to support the scan matrix
;------------------------------------------------------------------------
DEBOUNCE_ARRAY_SIZE: equ 06h ; 6 keys debounced
LEFT_CTRL_BIT: equ 01
LEFT_SHIFT_BIT: equ 02
LEFT_ALT_BIT: equ 04
LEFT_GUI_BIT: equ 08
RIGHT_CTRL_BIT: equ 10h
RIGHT_SHIFT_BIT: equ 020h
RIGHT_ALT_BIT: equ 040h
RIGHT_GUI_BIT: equ 080h
APP_BIT: equ 01h
ksc_x_index: equ ksc_ram_base
ksc_y_index: equ (ksc_ram_base + 1)
ksc_changes: equ (ksc_ram_base + 2) ; keypress ksc_changes in a column
ksc_matrix_addr: equ (ksc_ram_base + 3) ; keycode table index
ksc_down_up: equ (ksc_ram_base + 4) ; 00h: key went up, FFh: key went down
ksc_phantom: equ (ksc_ram_base + 5) ; flag indicates phantom key situation
; the debounce test. ;
ksc_p0out: equ (ksc_ram_base + 6)
ksc_p1out: equ (ksc_ram_base + 7)
ksc_p3out: equ (ksc_ram_base + 8)
;
; debounce_array contains 6 bytes
ksc_db_keys: equ (ksc_ram_base + 9) ; define 6 bytes to debounce a
; maximum of 6 keys pressed
; ksc_db_counts contains 6 counters
ksc_db_counts: equ (ksc_ram_base + 15) ; define 6 counter bytes for
;keyswitch image contains 18 bytes
ksc_image: equ (ksc_ram_base + 21) ;scan matrix image
ksc_mod0: equ (ksc_ram_base + 39) ;modifier byte 0
ksc_mod1: equ (ksc_ram_base + 40) ;modifier byte 1
ksc_work: equ (ksc_ram_base + 41) ;modifier byte 1
ksc_delay: equ (ksc_ram_base + 42) ;delay byte
;the next three variables are used for phantom key detection
ksc_row_hits: equ (ksc_ram_base + 43) ;bit field containing
;all rows with at least 1 key pressed
ksc_col_hits: equ (ksc_ram_base + 44) ;current count of columns with at least
;one key pressed
ksc_key_count: equ (ksc_ram_base + 45) ;total number of keys pressed
KSC_RAM_SIZE: equ 46
;========================================================================
; FUNCTION: ksc_putkey
;
; calls either ps2key_putkey or usbkey_putkey, depending upon the
; keyboard currently being supported.
;
;
;========================================================================
ksc_putkey:
push A
mov A,[dual_ifc_keyboard]
cmp A,PS2_KEYBOARD
pop A
jnz .usb
call ps2key_putkey
ret
.usb:
call usbkey_putkey
ret
;========================================================================
; FUNCTION: ksc_scan_keys
;
; Keyboard scanning function
;
;========================================================================
ksc_scan_keys:
call ksc_Debounce_Task ; task for debounce
mov A, 0 ; init. phantom key flag to false
mov [ksc_phantom], A
mov [ksc_col_hits],A
mov [ksc_row_hits],A
mov [ksc_changes],A
mov [ksc_key_count],A
mov [ksc_x_index],A
mov X, 18 ; 18 columns
call ksc_StartScan ; write initial scan pattern
.column_loop:
DELAY 25
iord PORT2_DATA_REG ; read input port
cpl ; complement so down switch is '1'
mov [ksc_mod1], A ; save the port 2 data
DELAY 25
iord PORT2_DATA_REG ; read input port
iord PORT2_DATA_REG ; read input port again
cpl
and [ksc_mod1], A ; and with last look
jz .nokeysdown ; if keys are down in this column
push A
call count_ones
add A,[ksc_key_count]
mov [ksc_key_count],A
pop A
or [ksc_row_hits],A ; keep track of all rows with keys down
inc [ksc_col_hits] ; and count of columns with a key down
.nokeysdown:
mov A,[ksc_changes] ; if key changes have already been found in a previous column
cmp A, 0
jnz .key_has_changed ; skip to next column to scan for phantom situation
; else
mov A, [X + ksc_image - 1] ; get previous column data
xor A, [ksc_mod1] ; compare with current data
mov [ksc_changes], A ; and save positions where a change occurred
cmp A, 0 ; test for state change
jnz .key_has_changed ; if no key state change
inc [ksc_x_index] ; increment the column
.key_has_changed:
call ksc_NextPattern ; write a new scan pattern
dec X ; done yet?
jnz .column_loop
.exit:
mov A,[ksc_changes]
cmp A,0 ; did we find any key changes from the above scan?
jz .exit1 ; no, exit now
; yes, was there a phantom situation during the above scan?
call check_phantom ;
jc .exit1 ; yes, exit now, because we cannot determine state of keys
mov A,[ksc_x_index] ; else restore X to the proper column index
cpl A ; based on the value of ksc_x_index
add A,19
mov X,A
call ksc_KeyChanged ; then call ksc_KeyChanged to record key changes
CLEARC
.exit1:
ret
;========================================================================
; initialize all columns to begin a keyboard scan
; 0 in c[0]
; 1 in c[19:1]
; clear ksc_x_index to indicate column under test
;========================================================================
ksc_StartScan:
push A ; save accumulator on stack
mov A, feh ; write a zero to c[0]
iowr PORT0_DATA_REG ; write ones to c[7:1]
mov [ksc_p0out], A ; remember what was written to Port0
mov A, ffh ; write all ones to c[15:8]
iowr PORT1_DATA_REG
mov [ksc_p1out], A ; remember what was written to Port1
mov A, [ksc_p3out] ; load data written to Port3
or A, P3_KEY_MASK ; write all ones to c[19:16]
iowr PORT3_DATA_REG ; LED data unchanged
mov [ksc_p3out], A ; remember what was written to Port3
pop A ; restore accumulator from stack
ret ; return
;========================================================================
; Write the columns with the next pattern in the keyboard scan.
; the pattern is generated as a left shift to walk the columns from zero
; to 19. Increment the ksc_x_index to track the column under test.
;
; Port 3 Port 1 Port 0
; bit7 bit4 bit7 bit0 bit7 bit0
; c19 c18 c17 c16 c15 c14 c13 c12 c11 c10 c9 c8 c7 c6 c5 c4 c3 c2 c1 c0
;========================================================================
ksc_NextPattern:
push A ; save accumulator on stack
mov A, 0ffh ; set the carry bit
rlc
mov A, [ksc_p0out] ; load c[7:0] data
rlc ; rotate left
mov [ksc_p0out], A ; update memory copy
iowr PORT0_DATA_REG
mov A, [ksc_p1out] ; load c[15:8] data
rlc ; rotate left
mov [ksc_p1out], A ; update memory copy
iowr PORT1_DATA_REG
mov A, [ksc_p3out] ; load c[19:16] data
jc .CarryIn
rlc ; rotate left
and A, ~P3_KEY_LSBIT_MASK ; clear bit we need to shift into
jmp .WriteP3
.CarryIn:
rlc
or A,P3_KEY_LSBIT_MASK ; set bit we need to shift into
.WriteP3:
and A, P3_KEY_MASK ; clear all other bits
push A ; save c[19:16] on stack
mov A, [ksc_p3out] ; load value from memory
and A, ~P3_KEY_MASK ; zero the column lines
mov [ksc_p3out], A ; store value back to memory
pop A ; restore scan lines from stack
or A, [ksc_p3out] ; combine with the LED bits
mov [ksc_p3out], A ; save memory copy
iowr PORT3_DATA_REG ; write to the output port
pop A ; restore accumulator from stack
ret ; ret
;========================================================================
; A column had one or more buttons that changed state (up to down or down
; to up). Scan the rows to find out which one(s) changed.
;========================================================================
ksc_KeyChanged:
push A
mov A, 0 ; zero the row index
mov [ksc_y_index], A
mov A, 1 ; initialize the scan bit
.row_loop:
push A ; save scan bit on stack
and A, [ksc_changes] ; test bit position in row data
jz .next_row ; keep testing
call ksc_FoundKey ; found a key
.next_row:
inc [ksc_y_index] ; increment row
pop A ; restore scan bit
rlc ; rotate left to test next bit
jnc .row_loop
.done_KeyChanged:
pop A
ret ; return
;========================================================================
; We have a key identified by an ksc_x_index and a ksc_y_index. Combine the two
; into a single index and lookup the keycode, check if up or down change.
;========================================================================
ksc_FoundKey:
push A ; save accumulator on stack
mov A, X
mov [ksc_matrix_addr], A ; save current scanned column
pop A ; restore and save accumulator on stack
push A
and A, [X + ksc_image - 1] ; see whether up or down change
mov A, 00h ; key went up
jnz .calc_matrix
mov A, FFh ; process this key make
.calc_matrix: ; calculate offset into code matrix
mov [ksc_down_up], A ; set flag
mov X, [ksc_matrix_addr] ; restore current column
mov A, [ksc_x_index] ; load column number
asl ; multiply by eight
asl
asl
add A, [ksc_y_index] ; add in the row index
mov [ksc_matrix_addr], A ; store
; test debounce array for match
call ksc_Debounce_test ; check if debounce in progress on this key
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -