From b83d5400f98f2f2a588b900d39f700da87fe3543 Mon Sep 17 00:00:00 2001 From: Hexa Dust Date: Wed, 14 Jan 2026 19:05:14 +0000 Subject: [PATCH] indirect voice access --- sid-hl.4th | 36 ++++++++++++++ sid.4th | 144 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 sid-hl.4th diff --git a/sid-hl.4th b/sid-hl.4th new file mode 100644 index 0000000..5afe484 --- /dev/null +++ b/sid-hl.4th @@ -0,0 +1,36 @@ +( PS2! c c p-addr -- Data byte A, high address byte B, port address C - OUT to port with A and B registers set +: PC2! SWAP >< OR PC! ; +( SID! c c -- Data value, register 0-31; bits 5,6 are for interrupt settings; bit 7 /CS is handled +: SID! + 2DUP 128 OR 84 PC2! + 2DUP 127 AND 84 PC2! + 128 OR 84 PC2! ; + +( Voice control register flags +: SID:CTL:GATE 1 ; +: SID:CTL:SYNC 2 ; +: SID:CTL:RING 4 ; +: SID:CTL:TEST 8 ; +: SID:CTL:TRI 16 ; +: SID:CTL:SAW 32 ; +: SID:CTL:PWM 64 ; +: SID:CTL:NOISE 128 ; + +( Frequency table: +: SID:NOTE:C4 4389 ; +: SID:NOTE:C4# 4650 ; +: SID:NOTE:D4 4927 ; +: SID:NOTE:D4# 5220 ; +: SID:NOTE:E4 5530 ; +: SID:NOTE:F4 5859 ; +: SID:NOTE:F4# 6207 ; +: SID:NOTE:G4 6577 ; +: SID:NOTE:G4# 6968 ; +: SID:NOTE:A4 7382 ; +: SID:NOTE:A4# 7821 ; +: SID:NOTE:B4 8286 ; +( Octave shifts +: SID:OCT:UP 2* ; +: SID:OCT:DOWN 2/ ; + +: SID:VOICE ( n -- ) diff --git a/sid.4th b/sid.4th index 1749136..2353409 100644 --- a/sid.4th +++ b/sid.4th @@ -1,3 +1,5 @@ +(--- SID chip access ---) + : PC2! ( c c p-addr -- Data byte A, high address byte B, port address C - OUT to port with A and B registers set ) SWAP >< OR PC! ; : SID! ( c c -- Data value, register 0-31; bits 5,6 are for interrupt settings; bit 7 /CS is handled ) @@ -5,7 +7,8 @@ 2DUP 127 AND 84 PC2! 128 OR 84 PC2! ; -( -- n Voice control register flags ) +(--- SID chip control register flags ---) + : SID:CTL:GATE 1 ; : SID:CTL:SYNC 2 ; : SID:CTL:RING 4 ; @@ -15,6 +18,27 @@ : SID:CTL:PWM 64 ; : SID:CTL:NOISE 128 ; +(--- Frequency table ---) + +: SID:NOTE:C4 4389 ; +: SID:NOTE:C4# 4650 ; +: SID:NOTE:D4 4927 ; +: SID:NOTE:D4# 5220 ; +: SID:NOTE:E4 5530 ; +: SID:NOTE:F4 5859 ; +: SID:NOTE:F4# 6207 ; +: SID:NOTE:G4 6577 ; +: SID:NOTE:G4# 6968 ; +: SID:NOTE:A4 7382 ; +: SID:NOTE:A4# 7821 ; +: SID:NOTE:B4 8286 ; + +( Octave shifts ) +: SID:OCT:UP 2* ; +: SID:OCT:DOWN 2/ ; + +(--- Direct access ---) + ( Voice 1 ) : SID0/1:FREQ! ( n -- Reg 0,1 - frequency voice 1 ) DUP 255 AND 0 SID! >< 255 AND 1 SID! ; @@ -78,23 +102,6 @@ 1024 SID21/22:CUT! 10 SID23:RES SID23! 15 SID24:VOL SID24! ; -( -- n Frequency table: ) -: SID:NOTE:C4 4389 ; -: SID:NOTE:C4# 4650 ; -: SID:NOTE:D4 4927 ; -: SID:NOTE:D4# 5220 ; -: SID:NOTE:E4 5530 ; -: SID:NOTE:F4 5859 ; -: SID:NOTE:F4# 6207 ; -: SID:NOTE:G4 6577 ; -: SID:NOTE:G4# 6968 ; -: SID:NOTE:A4 7382 ; -: SID:NOTE:A4# 7821 ; -: SID:NOTE:B4 8286 ; -( n -- n Octave shifts ) -: SID:OCT:UP 2* ; -: SID:OCT:DOWN 2/ ; - ( Voice contorl registers ) VARIABLE SID:V1:CTL : SID:V1:CTL! ( c -- Set CTL register for voice 1 ) @@ -188,3 +195,104 @@ SID:TEST:MELODY SID:TEST:FILTER SID:TEST:SONG +(--- Voice selection ---) + +CREATE SID:VOICE-BASES 0 , 7 , 14 , ( 3'base ) +CREATE SID:VOICE-CTLS 0 , 0 , 0 , ( 3clt-reg-shadow ) + +: SID:VOICE-BASE-ADDR ( voice -- 'reg-no ) + CELL * SID:VOICE-BASES + ; +: SID:VOICE-CTL-ADDR ( voice -- 'ctl-addr ) + CELL * SID:VOICE-CTLS + ; + +CREATE SID:VOICE-BASE-PTR SID:VOICE-BASES , +CREATE SID:VOICE-CTL-PTR SID:VOICE-CTLS , + +: SID:SELECT-VOICE ( voice -- ) ( select SELECT voice ) + DUP + SID:VOICE-BASE-ADDR SID:VOICE-BASE-PTR ! + SID:VOICE-CTL-ADDR SID:VOICE-CTL-PTR ! ; + +: SID:VOICE-REG-NO ( -- n ) ( Base SID register number for selected voice ) + SID:VOICE-BASE-PTR @ @ ; + +(--- Voice register ops ---) + +: SID:VOICE! ( c n -- ) ( Store byte in selected voice register n ) + SID:VOICE-REG-NO + SID! ; + +: SID:VOICE-CTL ( -- a-addr ) ( Control register shadow for current voice ) + SID:VOICE-CTL-PTR @ ; + +: SID:VOICE-FREQ! ( n -- ) ( Reg 0,1 - Set frequency ) + DUP 255 AND 0 SID:VOICE! >< 255 AND 1 SID:VOICE! ; +: SID:VOICE-PWM! ( n -- ) ( Reg 2,3 - Set pulse wave duty cycle ) + DUP 255 AND 2 SID:VOICE! >< 15 AND 3 SID:VOICE! ; +: SID:VOICE-CTL! ( c -- ) ( Reg 4 - Set control register; write-through shadow ) + DUP SID:VOICE-CTL ! 4 SID:VOICE! ; +: SID:VOICE-ATK/DEC! ( c -- ) ( Reg 5 - Set attack duration / decay duration ) + 15 AND SWAP 4 LSHIFT OR 5 SID:VOICE! ; +: SID:VOICE-SUS/REL! ( c -- ) ( Reg 6 - Set sustain level / release duration ) + 15 AND SWAP 4 LSHIFT OR 6 SID:VOICE! ; + +: SID:VOICE-PLAY ( freq -- ) ( Start note at given frequency ) + SID:VOICE-FREQ! SID:VOICE-CTL @ SID:CTL:GATE OR 4 SID:VOICE! ; +: SID:VOICE-STOP ( -- ) ( Stop note ) + SID:VOICE-CTL @ SID:CTL:GATE INVERT AND 4 SID:VOICE! ; + +(--- Other registers ---) + +: SID:CUTOFF! ( n -- ) ( Reg 21/22 - Set filter cutoff frequency 0 - 2047 / 11 bits ) + DUP 7 AND 21 SID! 3 RSHIFT 255 AND 22 SID! ; + +( Reg 23 - filter resonance 0 - 15 / 4 bits, ext, voice 3, voice 2, voice 1 ) +: SID:FILTER:RES 15 AND 4 LSHIFT ; +: SID:FILTER:V1 1 OR ; +: SID:FILTER:V2 2 OR ; +: SID:FILTER:V3 4 OR ; +: SID:EXT 8 OR ; +: SID:FILTER-RES-FLAGS! + 23 SID! ; + +( Reg 24 - filter mode and main volume control ) +: SID:VOLUME 15 AND ; +: SID:FILTER:LOWPASS 16 OR ; +: SID:FILTER:BANDPASS 32 OR ; +: SID:FILTER:HIGHPASS 64 OR ; +: SID:MUTEVOICE3 128 OR ; +: SID:VOL-FILTER! + 24 SID! ; + +(--- Reset ---) + +: SID:VOICE-RST ( -- ) ( Reset selected voice state ) + SID:NOTE:C4 SID:VOICE-FREQ! + 2048 SID:VOICE-PWM! + 0 SID:VOICE-CTL! + 4 2 SID:VOICE-ATK/DEC! + 10 9 SID:VOICE-SUS/REL! ; + +: SID:OTHER-RST + 1024 SID:CUTOFF! + 10 SID:FILTER:RES SID:FILTER-RES-FLAGS! + 15 SID:VOLUME SID:VOL-FILTER! ; + +: SID:RST ( Full SID chip reset ) + 2 SID:SELECT-VOICE SID:VOICE-RST + 1 SID:SELECT-VOICE SID:VOICE-RST + 0 SID:SELECT-VOICE SID:VOICE-RST + SID:OTHER-RST ; + +(--- Test ---) + +: DELAY 10000 0 DO LOOP ; + +: SID:TEST:NOTE + SID:NOTE:C4 SID:VOICE-PLAY + DELAY DELAY + SID:VOICE-STOP ; + +SID:RST + +SID:CTL:TRI SID:VOICE-CTL! ( Select triangle waveform ) +SID:TEST:NOTE