Overview
Trigger a note by setting frequency, waveform, and ADSR envelope, then toggling the gate bit. The gate-on starts the attack phase; gate-off triggers release. This is the core technique for all SID sound — music and effects both build on this foundation.
Code
; =============================================================================
; SID NOTE TRIGGER
; Play a single note on voice 1
; Taught: Game 6 (SID Symphony), Unit 1
; CPU: ~50 cycles | Memory: ~60 bytes
; =============================================================================
SID_BASE = $D400
; Voice 1 registers
SID_V1_FREQ_LO = SID_BASE + $00
SID_V1_FREQ_HI = SID_BASE + $01
SID_V1_PW_LO = SID_BASE + $02
SID_V1_PW_HI = SID_BASE + $03
SID_V1_CTRL = SID_BASE + $04
SID_V1_AD = SID_BASE + $05
SID_V1_SR = SID_BASE + $06
SID_VOLUME = SID_BASE + $18
; Control register bits
GATE_ON = %00000001
GATE_OFF = %00000000
WAVE_PULSE = %01000000
WAVE_SAW = %00100000
WAVE_TRI = %00010000
WAVE_NOISE = %10000000
; Initialise SID for playing notes
init_sid:
lda #$0F ; Max volume
sta SID_VOLUME
lda #$08 ; Pulse width 50%
sta SID_V1_PW_HI
lda #$00
sta SID_V1_PW_LO
lda #$00 ; Attack=0, Decay=0 (instant)
sta SID_V1_AD
lda #$F9 ; Sustain=15, Release=9
sta SID_V1_SR
rts
; Play a note
; Input: A = frequency high byte, X = frequency low byte
play_note:
stx SID_V1_FREQ_LO
sta SID_V1_FREQ_HI
lda #WAVE_PULSE | GATE_ON
sta SID_V1_CTRL ; Gate on - note starts
rts
; Release the note (start release phase)
release_note:
lda #WAVE_PULSE | GATE_OFF
sta SID_V1_CTRL ; Gate off - release begins
rts
Usage:
jsr init_sid
; Play middle C (C4 = 261.63 Hz on PAL = $1167)
lda #$11 ; Frequency high
ldx #$67 ; Frequency low
jsr play_note
; ... wait for note duration ...
jsr release_note ; Let note fade out
Trade-offs
| Aspect | Cost |
|---|---|
| CPU | ~50 cycles to trigger |
| Memory | ~60 bytes |
| Limitation | Single voice; no music sequencing |
When to use: Sound effects, learning SID basics, simple audio feedback.
When to avoid: Full music playback (use a music driver instead).
SID rate tables
The 4-bit Attack, Decay, and Release values map to durations defined in the SID datasheet. Release rates are slower than attack rates by roughly 3× for the same value:
| Value | Attack | Decay / Release |
|---|---|---|
| $0 | 2 ms | 6 ms |
| $1 | 8 ms | 24 ms |
| $2 | 16 ms | 48 ms |
| $3 | 24 ms | 72 ms |
| $4 | 38 ms | 114 ms |
| $5 | 56 ms | 168 ms |
| $6 | 68 ms | 204 ms |
| $7 | 80 ms | 240 ms |
| $8 | 100 ms | 300 ms |
| $9 | 250 ms | 750 ms |
| $A | 500 ms | 1.5 s |
| $B | 800 ms | 2.4 s |
| $C | 1 s | 3 s |
| $D | 3 s | 9 s |
| $E | 5 s | 15 s |
| $F | 8 s | 24 s |
So Release=9 used in init_sid above gives a ~750 ms tail — long enough to hear the note fade after release_note.
Frequency formula
For any note, the 16-bit SID frequency value is:
FREQ = Hz × 16777216 / clock
Where clock is 985,248 Hz (PAL) or 1,022,727 Hz (NTSC). So C4 (261.63 Hz) on PAL is 261.63 × 16777216 / 985248 ≈ 4455 = $1167.
Related
Vault: The SID Chip | Commodore 64
Evolution: Note Trigger → Envelope Shapes → Music Driver