The Spectrum’s Key I/O Port
The ZX Spectrum is minimalistic, relying on just a few I/O ports to manage all peripherals (keyboard, display, cassette, and beeper).
The Main Port: The most crucial I/O address is `FEH′ (254 decimal), which is used for both input and output control.
I/O Port Decoding (The Trick)
The Spectrum simplifies hardware design by only connecting I/O logic to the lowest bit (A0) and the highest byte (A8-A15) of the Z80’s 16-bit address lines.
The Rule: Any I/O instruction that has an even number in the low 8 bits of the port address (i.e., A0=0) is seen by the core hardware. This means the Spectrum responds to IN A, (FEH)
, IN A, (FCH)
, and many other addresses. However, all hardware is wired to the same port logic.
The Keyboard Scan Routine
The Spectrum keyboard is arranged as an 8 × 5 matrix. The CPU must strobe (output a signal to) the 8 rows and then read the 5 columns.
Step 1: Strobe the Row (Output) To check a row of keys, the CPU writes a mask to port `FEH′. The bits set to ‘0’ select the target row.
KEYBOARD_PORT EQU 0FEH
LD A, 0EFH ; Mask for Row 1 (Bits V, G, F, D, S, A, Caps Shift, 1)
OUT (KEYBOARD_PORT), A ; Output the strobe mask
Step 2: Read the Columns (Input) The same port (`FEH′) is then used for input. The lowest 5 bits of the input byte indicate which keys in the selected row are pressed.
IN A, (KEYBOARD_PORT) ; Read the key status into the Accumulator (A)
; Bits 0-4 contain key status (0 = key pressed)
AND 01FH ; Mask off the high bits (optional, but good practice)
The Full Scan and Key Buffer
The full keyboard routine must loop through all 8 rows, strobing and reading each one sequentially. The results of the 8 reads are stored in an 8-byte key buffer in RAM (e.g., at `5C00H′), which the main program checks before the next screen refresh.
Check for Key Press: A key is pressed if the corresponding bit in the buffer is low (0).
Example: Checking the ‘SPACE’ Key (Assumes ‘SPACE’ is in Row 7, Bit 0)
LD HL, KEY_BUFFER + 7 ; HL ← Address of Row 7's status byte
LD A, (HL)
BIT 0, A ; Check Bit 0 (the SPACE key)
JP Z, SPACE_PRESSED ; Z=1 means the bit is 0 (key is pressed)