Overview
Read keyboard input by polling the I/O ports directly. The Spectrum’s keyboard is arranged in a matrix of 8 rows, each accessible via a specific port address. Keys are active low (0 = pressed). Use when you need responsive input without relying on the ROM.
Code
; =============================================================================
; KEYBOARD READING - ZX SPECTRUM
; Read keyboard matrix via I/O ports
; Taught: Game 1 (Ink War), Unit 1
; CPU: ~50 cycles | Memory: ~40 bytes
; =============================================================================
KEY_PORT equ $fe
; Keyboard row addresses (active low)
ROW_QAOP equ $fb ; Q W E R T (bits: T R E W Q)
ROW_ASDF equ $fd ; A S D F G (bits: G F D S A)
ROW_YUIOP equ $df ; Y U I O P (bits: P O I U Y)
ROW_12345 equ $f7 ; 1 2 3 4 5 (bits: 5 4 3 2 1)
ROW_09876 equ $ef ; 0 9 8 7 6 (bits: 6 7 8 9 0)
ROW_SPACE equ $7f ; Space, Sym, M, N, B
; Read keyboard and return direction code
; Returns: A = 0 (none), 1 (up), 2 (down), 3 (left), 4 (right)
read_keyboard:
xor a
ld (key_pressed), a ; Clear previous
; Check Q (up)
ld a, ROW_QAOP
in a, (KEY_PORT)
bit 0, a ; Q is bit 0
jr nz, .not_q
ld a, 1
ld (key_pressed), a
ret
.not_q:
; Check A (down)
ld a, ROW_ASDF
in a, (KEY_PORT)
bit 0, a ; A is bit 0
jr nz, .not_a
ld a, 2
ld (key_pressed), a
ret
.not_a:
; Check O (left)
ld a, ROW_YUIOP
in a, (KEY_PORT)
bit 1, a ; O is bit 1
jr nz, .not_o
ld a, 3
ld (key_pressed), a
ret
.not_o:
; Check P (right)
ld a, ROW_YUIOP
in a, (KEY_PORT)
bit 0, a ; P is bit 0
jr nz, .not_p
ld a, 4
ld (key_pressed), a
.not_p:
ret
key_pressed:
defb 0
Usage:
main_loop:
halt ; Wait for frame
call read_keyboard
ld a, (key_pressed)
or a
jr z, main_loop ; No key pressed
cp 1
jr z, handle_up
cp 2
jr z, handle_down
; ... etc
jr main_loop
Trade-offs
| Aspect | Cost |
|---|---|
| CPU | ~50 cycles per read |
| Memory | ~40 bytes |
| Limitation | No debouncing (keys may auto-repeat) |
When to use: Any game needing keyboard input. ROM-free approach works on all Spectrums.
When to avoid: When you need debounced input for menus or single-press detection.
Keyboard Matrix Reference
| Port | Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 |
|---|---|---|---|---|---|
| $F7 | 1 | 2 | 3 | 4 | 5 |
| $EF | 0 | 9 | 8 | 7 | 6 |
| $FB | Q | W | E | R | T |
| $FD | A | S | D | F | G |
| $DF | P | O | I | U | Y |
| $BF | Enter | L | K | J | H |
| $7F | Space | Sym | M | N | B |
| $FE | Shift | Z | X | C | V |
Related
Patterns: Game Loop (HALT)
Vault: ZX Spectrum