110 lines
4.1 KiB
NASM
110 lines
4.1 KiB
NASM
; ═══════════════════════════════════════════════════════════════════════════
|
|
; Keyboard Module - Direct ZX Spectrum matrix reading
|
|
; ═══════════════════════════════════════════════════════════════════════════
|
|
; Reads keyboard via IN port #FE (no WC API, no interrupts needed).
|
|
; TSConfig translates PS/2 → ZX matrix in hardware.
|
|
;
|
|
; ZX Spectrum keyboard matrix (active low):
|
|
; Port #FEFE: CAPS, Z, X, C, V (row 0)
|
|
; Port #FDFE: A, S, D, F, G (row 1)
|
|
; Port #FBFE: Q, W, E, R, T (row 2)
|
|
; Port #F7FE: 1, 2, 3, 4, 5 (row 3)
|
|
; Port #EFFE: 0, 9, 8, 7, 6 (row 4)
|
|
; Port #DFFE: P, O, I, U, Y (row 5)
|
|
; Port #BFFE: ENTER, L, K, J, H (row 6)
|
|
; Port #7FFE: SPACE, SYM, M, N, B (row 7)
|
|
;
|
|
; Each row: bit 0 = rightmost key, bit 4 = leftmost key
|
|
; Bit = 0 means key pressed, bit = 1 means not pressed
|
|
; ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
; Debounce counter (simple frame-based debouncing)
|
|
KBD_DEBOUNCE: DB 0
|
|
|
|
; ═══════════════════════════════════════════════════════════════════════════
|
|
; KBD_READ - Read keyboard and return action code
|
|
; ═══════════════════════════════════════════════════════════════════════════
|
|
; Output: A = action code
|
|
; 0 = nothing pressed
|
|
; 1 = ESC (Caps Shift + Space)
|
|
; 2 = next track (Space alone)
|
|
; 3 = prev track (P key)
|
|
; 4 = pause/unpause (M key)
|
|
; ═══════════════════════════════════════════════════════════════════════════
|
|
KBD_READ:
|
|
; Simple debouncing: skip reads for N frames after a keypress
|
|
LD A,(KBD_DEBOUNCE)
|
|
OR A
|
|
JR Z,KBD_DO_READ
|
|
DEC A
|
|
LD (KBD_DEBOUNCE),A
|
|
XOR A ; return 0
|
|
RET
|
|
|
|
KBD_DO_READ:
|
|
; --- Check ESC = Caps Shift + Space ---
|
|
; Caps Shift = row 0 bit 0 (#FEFE)
|
|
LD A,#FE
|
|
IN A,(#FE)
|
|
BIT 0,A ; Caps Shift
|
|
JR NZ,KBD_CHECK_SPACE ; not pressed
|
|
|
|
; Caps Shift is held. Check Space = row 7 bit 0 (#7FFE)
|
|
LD A,#7F
|
|
IN A,(#FE)
|
|
BIT 0,A ; Space
|
|
JR NZ,KBD_CHECK_SPACE ; not pressed
|
|
; ESC detected!
|
|
LD A,16
|
|
LD (KBD_DEBOUNCE),A
|
|
LD A,1
|
|
RET
|
|
|
|
KBD_CHECK_SPACE:
|
|
; --- Check SPACE alone (without Caps Shift) ---
|
|
; Space = row 7 bit 0 (#7FFE)
|
|
LD A,#7F
|
|
IN A,(#FE)
|
|
BIT 0,A
|
|
JR NZ,KBD_CHECK_P
|
|
|
|
; Check that Caps Shift is NOT held (to distinguish from ESC)
|
|
LD A,#FE
|
|
IN A,(#FE)
|
|
BIT 0,A ; CShift=0 means held
|
|
JR Z,KBD_CHECK_P ; CShift held → this is ESC, not SPACE
|
|
|
|
; SPACE alone = next track
|
|
LD A,12
|
|
LD (KBD_DEBOUNCE),A
|
|
LD A,2
|
|
RET
|
|
|
|
KBD_CHECK_P:
|
|
; --- Check P key = row 5 bit 0 (#DFFE) ---
|
|
LD A,#DF
|
|
IN A,(#FE)
|
|
BIT 0,A
|
|
JR NZ,KBD_CHECK_M
|
|
; P pressed = previous track
|
|
LD A,12
|
|
LD (KBD_DEBOUNCE),A
|
|
LD A,3
|
|
RET
|
|
|
|
KBD_CHECK_M:
|
|
; --- Check M key = row 7 bit 2 (#7FFE) ---
|
|
LD A,#7F
|
|
IN A,(#FE)
|
|
BIT 2,A
|
|
JR NZ,KBD_NOTHING
|
|
; M pressed = pause
|
|
LD A,12
|
|
LD (KBD_DEBOUNCE),A
|
|
LD A,4
|
|
RET
|
|
|
|
KBD_NOTHING:
|
|
XOR A
|
|
RET
|