;* ======================================================================== *; ;* The routines and data in this file (scan_kbd.asm) are dedicated to the *; ;* public domain via the Creative Commons CC0 v1.0 license by its author, *; ;* Joseph Zbiciak. *; ;* *; ;* https://creativecommons.org/publicdomain/zero/1.0/ *; ;* ======================================================================== *; ;; ======================================================================== ;; ;; ECS Keyboard Scanner ;; ;; ;; ;; Unlike the hand-controller scanner, this code currently does not ;; ;; generate events for the event queue. It can easily be wrapped with ;; ;; code to do that, though. ;; ;; ;; ;; There are two scanners: The keyboard scanner which returns ASCII ;; ;; codes, and the synth scanner which maintains a bitmap of pressed ;; ;; notes and a list of changes between calls. This file only contains ;; ;; the keyboard scanner. ;; ;; ;; ;; The keyboard scanner does a "transposed scan" as compared to the ECS's ;; ;; default scanner. This allows it to correctly pick up the SHIFT key. ;; ;; It also does an extra scanning step to try to pick out the CTL key. ;; ;; ;; ;; This keyboard scanner makes no attempt to gracefully handle multiple ;; ;; keys pressed at one time. Rather, it scans the keyboard, decodes, ;; ;; and returns the new key value if it's different than the last key it ;; ;; returned. Otherwise, it returns KEY.NONE. ;; ;; ======================================================================== ;; BYTEVAR ECS_KEY_LAST KEY.LEFT EQU $1C ; \ Can't be generated otherwise, so perfect KEY.RIGHT EQU $1D ; |_ candidates. Could alternately send 8 for KEY.UP EQU $1E ; | left... not sure... KEY.DOWN EQU $1F ; / KEY.ENTER EQU $A ; Newline KEY.ESC EQU 27 KEY.NONE EQU $FF KBD_DECODE PROC @@no_mods DECLE KEY.NONE, "ljgda" ; col 7 DECLE KEY.ENTER, "oute", KEY.NONE ; col 6 DECLE "08642", KEY.RIGHT ; col 5 DECLE KEY.ESC, "97531" ; col 4 DECLE "piyrwq" ; col 3 DECLE ";khfs", KEY.UP ; col 2 DECLE ".mbcz", KEY.DOWN ; col 1 DECLE KEY.LEFT, ",nvx " ; col 0 @@shifted DECLE KEY.NONE, "LJGDA" ; col 7 DECLE KEY.ENTER, "OUTE", KEY.NONE ; col 6 DECLE ")*-$\"/" ; col 5 DECLE KEY.ESC, "(/+#=" ; col 4 DECLE "PIYRWQ" ; col 3 DECLE ":KHFS^" ; col 2 DECLE ">MBCZ?" ; col 1 DECLE "% look for a 0 in row 6 BEQ @@have_shift ; / MVII #$BF, R1 ; \_ drive column 6 to 0 MVO R1, $FF ; / MVI $FE, R2 ; \ ANDI #$20, R2 ; > look for a 0 in row 5 BNEQ @@done_shift_ctrl ; / MVII #KBD_DECODE.control, R3 B @@done_shift_ctrl @@have_shift: MVII #KBD_DECODE.shifted, R3 @@done_shift_ctrl: ;; ------------------------------------------------------------ ;; ;; Start at col 7 and work our way to col 0. ;; ;; ------------------------------------------------------------ ;; CLRR R2 ; col pointer MVII #$FF7F, R1 @@col: MVO R1, $FF MVI $FE, R0 XORI #$FF, R0 BNEQ @@maybe_key @@cont_col: ADDI #6, R2 SLR R1 CMPI #$FF, R1 BNEQ @@col MVII #KEY.NONE, R0 B @@none ;; ------------------------------------------------------------ ;; ;; Looks like a key is pressed. Let's decode it. ;; ;; ------------------------------------------------------------ ;; @@maybe_key: MOVR R2, R4 SARC R0, 2 BC @@got_key ; row 0 BOV @@got_key1 ; row 1 ADDI #2, R4 SARC R0, 2 BC @@got_key ; row 2 BOV @@got_key1 ; row 3 ADDI #2, R4 SARC R0, 2 BC @@got_key ; row 4 BNOV @@cont_col ; row 5 @@got_key1: INCR R4 @@got_key: ADDR R3, R4 ; add modifier offset MVI@ R4, R0 CMPI #KEY.NONE, R0 ; if invalid, keep scanning BEQ @@cont_col CMP ECS_KEY_LAST, R0 @@none: MVO R0, ECS_KEY_LAST BNEQ @@new MVII #KEY.NONE, R0 @@new: ; maybe DIS here MVI $F8, R1 ; \ ANDI #$3F, R1 ; > set both I/O ports to "input" MVO R1, $F8 ; / ; maybe EIS here JR R5 ENDP