Overview
The Spectrum has no dedicated sound chip - just a 1-bit speaker controlled through port $FE. Toggle bit 4 on and off at different speeds to create tones. Vary the delay between toggles for pitch, and loop duration for length. Simple but effective for game feedback.
Code
; =============================================================================
; SOUND BEEP - ZX SPECTRUM
; Generate tones via speaker bit toggling
; Taught: Game 1 (Ink War), Unit 2
; CPU: Variable (blocks during playback) | Memory: ~40 bytes
; =============================================================================
KEY_PORT equ $fe
SPEAKER_BIT equ $10 ; Bit 4 of port $FE
; Rising tone (success sound)
; Good for: claiming cells, collecting items, positive feedback
sound_success:
ld hl, 400 ; Starting pitch (higher = lower frequency)
ld b, 20 ; Duration (number of cycles)
.loop:
push bc
push hl
; Generate one cycle of tone
ld b, h
ld c, l ; BC = delay count
.tone_loop:
ld a, SPEAKER_BIT ; Speaker on
out (KEY_PORT), a
call .delay
xor a ; Speaker off
out (KEY_PORT), a
call .delay
dec bc
ld a, b
or c
jr nz, .tone_loop
pop hl
pop bc
; Decrease delay (increase pitch)
ld de, 20
or a
sbc hl, de
djnz .loop
ret
.delay:
push bc
ld b, 5
.delay_loop:
djnz .delay_loop
pop bc
ret
; Falling tone (error/failure sound)
; Good for: invalid moves, damage, negative feedback
sound_error:
ld hl, 100 ; Start high pitched
ld b, 15 ; Duration
.error_loop:
push bc
push hl
ld b, h
ld c, l
.error_tone:
ld a, SPEAKER_BIT
out (KEY_PORT), a
call .delay
xor a
out (KEY_PORT), a
call .delay
dec bc
ld a, b
or c
jr nz, .error_tone
pop hl
pop bc
; Increase delay (decrease pitch)
ld de, 15
add hl, de
djnz .error_loop
ret
Simple single beep:
; Quick beep (for button press feedback)
sound_click:
ld hl, 200 ; Pitch
ld b, 5 ; Short duration
.click_loop:
push bc
push hl
ld b, h
ld c, l
.click_tone:
ld a, SPEAKER_BIT
out (KEY_PORT), a
call short_delay
xor a
out (KEY_PORT), a
call short_delay
dec bc
ld a, b
or c
jr nz, .click_tone
pop hl
pop bc
djnz .click_loop
ret
short_delay:
push bc
ld b, 3
.sd_loop:
djnz .sd_loop
pop bc
ret
Trade-offs
| Aspect | Cost |
|---|---|
| CPU | Blocks execution during playback |
| Memory | ~40 bytes per sound routine |
| Limitation | No background playback, mono only |
When to use: Short feedback sounds (clicks, beeps, success/error tones).
When to avoid: Background music or sounds during gameplay - CPU is blocked.
How It Works
- The speaker is controlled by bit 4 of port
$FE - Set bit 4 high (
$10) to push the speaker cone out - Set bit 4 low (
$00) to let it return - The speed of toggling determines the pitch
- Smaller delay = higher frequency = higher pitch
Pitch Reference
| Delay Value | Approximate Note |
|---|---|
| 50-100 | High beep |
| 100-200 | Medium tone |
| 200-400 | Low tone |
| 400+ | Very low rumble |
Related
Patterns: Game Loop (HALT)
Vault: ZX Spectrum