Sound Parameter Protocol
Sound Parameter Protocol
This page documents the protocol used by the KN5000 Main CPU to send sound parameter changes to the Sub CPU, traced from the UI widgets all the way to the DSP hardware. The investigation starts with the Reverb settings as a proof of concept, then systematically maps all parameters.
Architecture (3 layers)
┌─────────────────────────────────────────────────────────┐
│ LAYER 1: UI (Main CPU — NAKA Widget System) │
│ │
│ Widget event (e.g. slider changed) │
│ → Lsw* handler function (e.g. LswReverb at F7CFA5) │
│ → AssswbWr (ring buffer write at FDB1F3) │
└──────────────────────┬──────────────────────────────────┘
│ 4-byte command packets
│ via ring buffer at RAM 0xBD3C
▼
┌─────────────────────────────────────────────────────────┐
│ LAYER 2: Inter-CPU Transport │
│ │
│ sendCOMM (EF32F4) → DMA latch at 0x140000 │
│ Command byte: bits 7-5 = handler, bits 4-0 = count │
└──────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ LAYER 3: Sub CPU (Sound Processing) │
│ │
│ INT0 ISR → ring buffer 0x2B0D │
│ CC dispatch → Voice_CC_91 (reverb depth, at 0x02A46C) │
│ → Voice_CC_SetReverbDepth: store at voice[ch × 0x11F + 0x7F] │
│ Voice param structure: 287 bytes/voice at 0x041300 │
└─────────────────────────────────────────────────────────┘
Concrete trace: Reverb Depth (CC#91)
Sub CPU side (already decoded):
Voice_CC_91loads channel from(xiz+1), value from(xiz+3)- Calls
Voice_CC_SetReverbDepth: computeswa × 0x11F, points to0x04137F(= base 0x041300 + offset 0x7F) - Stores reverb depth in the per-voice parameter structure
For comparison, other CC handlers at nearby offsets:
| CC | Handler | Sub CPU function | Voice offset | Meaning |
|---|---|---|---|---|
| 0x91 | Voice_CC_91 | Voice_CC_SetReverbDepth | +0x7F | Reverb depth |
| 0x95 | Voice_CC_95 | Voice_CC_SetChorusEnable | +0x72 | Chorus depth |
| (sustain) | Voice_CC_Sostenuto | Voice_CC_SetPortamentoTime | +0x7E | Sostenuto |
Reverb preset loading path
When a reverb preset is selected on the REVERB & EQ PRESETS screen:
MainRevEqPresetLoad(at F746F4) dispatches on preset type (reverb-only / EQ-only / combined)- Calls
SoundPreset_Dispatchwhich loads preset data from ROM at 0xEDB36C - A loop sends 24 commands (code 0x63) via
AssswbWr, one per MIDI channel - Each command carries a parameter value from the preset data table
What we have to work with
32 Lsw* functions — each is a per-parameter widget handler:
- LswReverb, LswDSPEffect, LswDigitalEffect
- LswVolume, LswPan, LswMute
- LswSustain, LswSustainLength, LswSustainPedal
- LswKeyShift, LswTuning, LswBendRange
- LswGlidePedal, LswAfterTouch, LswPartExp
- LswLocalControl, LswMidiChannel, LswOrchestrator
- LswMasterTuning, LswKeyScaling, LswSound
- LswLeftHold, LswEditCheck
- LswPercDecay, LswPercLevel, LswDrawAttack, LswDrawRelease
- LswScalingType/Shift/Shift2/Mode/KeyX
All reference the same parameter table at 0xE952AA (per-channel config) and 0xE953CE (value lookup). They all follow the same pattern — they share the exit code at AudioCtrl_PopIzRet1.
Investigation plan
Phase 1: Proof of concept — Reverb Depth end-to-end trace
Fully trace LswReverb end-to-end — from the event 0x1E00042 through Audio_SendCommand → Audio_CommandEncoder → AssswbWr → sendCOMM → Sub CPU Voice_CC_91 → voice param offset 0x7F. Verify the command byte encoding.
Status: Complete
Phase 2: Lsw* function analysis
For each of the 32 Lsw* functions, identify:
- Which command code it sends (e.g., 0x63 for reverb)
- Which Sub CPU CC handler receives it
- Which offset in the 287-byte voice structure it writes to
- The valid value range
Status: Partially complete — see Phase 2 Results below
Phase 3: Preset tables and DSP parameter mapping
Decode the preset data tables, per-algorithm parameter config blocks, DSP command protocol on the Sub CPU, and complete parameter name catalog.
Status: Complete — see Phase 3 Results below
Phase 4: DSP hardware commands
Trace the DSP configuration path (0x130000 interface) to understand how the Sub CPU programs the actual DSP chips.
Status: Not started
Phase 1 Results: Sub CPU Voice Parameter Structure
Voice_CtrlChange Dispatcher (Sub CPU 0x02A46C)
The Sub CPU function Voice_CtrlChange receives 4-byte command packets via the inter-CPU ring buffer and dispatches them to per-CC handler functions. The packet format is:
Byte 0: Command type (determines dispatch to Voice_CtrlChange vs other handlers)
Byte 1: Channel number (0x00-0x19, 26 channels total)
Byte 2: CC number (MIDI Control Change number)
Byte 3: CC value (0x00-0x7F typically)
The channel number is validated: cp (xiz + 1), 0x1A — any channel >= 26 is rejected.
Per-Voice Parameter Structure
Each voice has a 287-byte (0x11F) parameter block, with 26 voices starting at base address 0x041300 in Sub CPU DRAM.
Address formula: 0x041300 + (channel × 0x11F) + offset
Complete CC → Voice Offset Mapping
| MIDI CC | Name | Handler | Voice Offset | Size | Operation | Default |
|---|---|---|---|---|---|---|
| 0x01 | Mod Wheel | Voice_ModWheel_Apply | (complex) | - | Multi-register update | - |
| 0x07 | Volume | Voice_CC_SetVolume | +0x74 | 2 | Lookup table at 0x011D16 | 0xFE00 |
| 0x0A | Pan | Voice_CC_SetPan | +0x76 | 2 | Store direct | - |
| 0x0B | Expression | Voice_CC_SetExpression | +0x78 | 2 | Lookup table at 0x011D16 | 0xFE00 |
| 0x40 | Sustain | Voice_CC_SetSustain | +0x72 | bit 0 | Set/clear bit 0 | 0 |
| 0x5B | Sostenuto | Voice_CC_SetSostenuto | +0x77 | 2 | Store direct | - |
| 0x5D | Soft Pedal | Voice_CC_SetSoftPedal | +0x7A | 2 | Store direct | - |
| 0x5E | Portamento | Voice_Portamento_OnHandler | (complex) | - | Multi-function chain | - |
| 0x78-0x82 | (Extended) | Jump table at 0x00F739 | various | - | See extended table | - |
| 0x91 | Reverb Depth | Voice_CC_SetReverbDepth | +0x7F | 2 | Store direct | 0x00 |
| 0x95 | Chorus Enable | Voice_CC_SetChorusEnable | +0x72 | bit 2 | Set/clear bit 2 | 0 |
| 0x97 | Unknown | Voice_CC_SetChorusDepth | +0x80 | 2 | Store direct | 0x06 |
| 0x9B | Unknown | Voice_CC_SetDelayDepth | +0x8D | 2 | Store direct | 0x01 |
| 0x9C | Pedal Control | Voice_CC_SetDelayEnable | +0x6A | bit 8 | Set/clear bit 8 | 0x00 |
| 0x9D | Unknown | Voice_CC_SetDelayFeedback | +0x8E | 2 | Store direct | 0x00 |
Extended CC Table (0x78-0x82)
CCs 0x78-0x82 are dispatched via a jump table at Sub CPU ROM 0x00F739 (11 word entries) with base 0x02A306. These include:
| CC | Target | Voice Offset | Purpose |
|---|---|---|---|
| 0x7B | Voice_CC_SetPortamentoRate | +0x7B | Portamento amount |
| 0x7C | Voice_CC_SetPortamentoDepth | +0x7C | Pitch bend (stores (value - 0x80) × 2) |
| 0x7D | Voice_CC_SetPortamentoTime | +0x7E | Sostenuto depth (stores value - 0x40) |
Flags Word at Offset +0x72
The 16-bit word at offset +0x72 is a bitfield shared by multiple CC handlers:
| Bit | CC | Meaning | Set mask | Clear mask |
|---|---|---|---|---|
| 0 | 0x40 | Sustain pedal on | 0x0001 | 0xFFFE |
| 2 | 0x95 | Chorus enable | 0x0004 | 0xFFFB |
| 14 | (0x5E chain) | Alt sustain mode | 0x4000 | 0xBFFF |
Volume and Expression: Lookup Table
CC 0x07 (Volume) and CC 0x0B (Expression) don’t store the raw CC value — they use a lookup table at ROM 0x011D16 to translate the 7-bit CC value into a 16-bit hardware value. This implements a non-linear response curve (likely logarithmic for perceived loudness).
When CC value is 0, a special “mute” value 0xFE00 is stored instead.
Reverb Depth Trace (CC 0x91) — Complete Path
Main CPU UI:
LswReverb (F7CFA5) handles event 0x1E00042 (value changed)
→ Audio_SendCommand: acquires audio lock #7, formats command
→ Audio_CommandEncoder: command encoding engine (parses format string)
→ AssswbWr (FDB1F3): writes 4-byte packet to ring buffer at 0xBD3C
Ring buffer: max 127 entries (508 bytes), 4 bytes each
Inter-CPU Transport:
sendCOMM (EF32F4): reads from ring buffer, acquires audio lock #2
→ InterCPU_Send_Data_Block (EF3345): encodes command byte
Command byte = (handler_id << 5) | (byte_count - 1)
→ Audio_DMA_Transfer (EF341B): writes payload to DMA latch at 0x140000
Handshake: wait SSTAT1 high → write → wait SSTAT1 low → DMA
Sub CPU:
INT0 ISR: receives from latch, HDMA transfers payload to ring buffer 0x2B0D
Main loop: reads 4-byte packet [type, channel, cc#, value]
→ Voice_CtrlChange (02A46C):
channel = (xiz+1) = 0x00-0x19
cc# = (xiz+2) = 0x91
value = (xiz+3) = 0x00-0x7F
→ Voice_CC_SetReverbDepth:
extz wa ; wa = channel
muls wa, 0x11F ; wa = channel × 287
lda_24 xde, 0x04137f ; de = base + 0x7F
lda_dri3 XHL, 0x07, 0xE8, 0xE0 ; store value at [de + wa]
ret
→ Reverb depth stored at: 0x041300 + (channel × 0x11F) + 0x7F
Reverb Preset Loading Path — Complete
When the user selects a reverb preset on the REVERB & EQ PRESETS screen:
Main CPU:
NAKA widget generates event 0x1E3000A/B/C (preset type: reverb/EQ/combined)
→ MainRevEqPresetLoad (F746F4): dispatches on event
→ SoundPreset_Dispatch: selects preset handler by type
type 0 (reverb): preset data from ROM 0xEDB36C
type 1 (EQ): preset data from ROM 0xEDB394
type 2 (combined): calls CombinedPreset_Load
For type 0 (reverb preset):
→ 0xFF0D99: unpacks preset data (24 bytes) from ROM table
→ Loop 24 times (iz = 0..23, one per MIDI channel):
pushw 0xFF ; target specifier
ldw wa, 0x63 ; command code 0x63
call AssswbWr ; write to ring buffer
→ SoundParam_NotifyChange: refresh UI display (event 0x4002, widget 0x7F)
Key Addresses Summary
| Address | CPU | Purpose |
|---|---|---|
| 0xBD3C | Main (internal RAM) | Command ring buffer (127 × 4 bytes) |
| 0x140000 | Shared (latch) | Inter-CPU DMA communication port |
| 0x041300 | Sub (DRAM) | Voice parameter structure base |
| 0x011D16 | Sub (ROM) | Volume/Expression lookup table |
| 0x00F739 | Sub (ROM) | CC 0x78-0x82 jump table |
| 0xE952AA | Main (ROM) | Per-channel config table (Lsw functions) |
| 0xE953CE | Main (ROM) | Per-channel value lookup table |
| 0xEDB36C | Main (ROM) | Reverb preset data table |
| 0xEDB394 | Main (ROM) | EQ preset data table |
Phase 2 Results: Lsw* Function Architecture
Key Finding: Data-Driven Widget System
The 32 Lsw* functions are generic widget callbacks, not per-parameter command generators. The actual CC/command identity comes from the NAKA widget configuration data, not from the Lsw function code.
Each Lsw function handles a specific widget TYPE (slider, on/off toggle, etc.):
- LswVolume, LswExpression → numeric slider with mute state (bit 15 check)
- LswPan → center-left-right slider (3-way display: “CTR”, “L%2d”, “R%2d”)
- LswReverb, LswDSPEffect → numeric slider (“%3d” format)
- LswSustain, LswDigitalEffect → on/off toggle (“ON “, “OFF”)
- LswKeyShift → signed slider (“%+3d”)
- LswTuning → signed fine-tune (“%+4d”)
Command Flow
NAKA Widget Config Data
(contains: CC number, value range, channel)
│
▼
Lsw* Function (generic handler for widget type)
handles event 0x1E00042 (value changed)
│
├─ bit 13 set? → Audio_SendCommand (send command to Sub CPU)
│ │
│ ├─ st32_24 0x03c21c, widget_data (buffer the widget config)
│ ├─ Audio_CommandEncoder (command encoder, reads template at 0x0AD8)
│ └─ AssswbWr → ring buffer → sendCOMM → DMA → Sub CPU
│
└─ bit 13 clear? → Strcpy (format display string only, no sound command)
The per-channel configuration table at 0xE952AA contains 4-byte flag words. The bit tested by each Lsw function determines whether the parameter is “active” for that channel:
| Lsw Function | Bit Tested | Display Format | Send Command? |
|---|---|---|---|
| LswVolume | bit 15 | "%4d" / "MUTE" |
Yes |
| LswMute | bit 15 | "%4d" / "MUTE" |
Yes |
| LswPan | bit 14 | "CTR" / "L%2d" / "R%2d" |
Yes |
| LswReverb | bit 13 | "%3d" |
Yes |
| LswDSPEffect | bit 12 | "%3d" |
Yes |
| LswSustain | bit 11 | "ON " / "OFF" |
No (Strcpy only) |
| LswSustainLength | bit 10 | "%2d" |
Yes |
| LswDigitalEffect | bit 3 | "ON " / "OFF" |
No (Strcpy only) |
| LswKeyShift | - | "%+3d" |
Yes |
| LswTuning | - | "%+4d" |
Yes |
| LswBendRange | - | "%3d" |
Yes |
| LswSound | - | " ------" |
No (Strcpy only) |
| LswGlidePedal | - | "ON " / "OFF" |
No (Strcpy only) |
| LswSustainPedal | - | "ON " / "OFF" |
No (Strcpy only) |
| LswAfterTouch | - | "ON " / "OFF" |
No (Strcpy only) |
| LswKeyScaling | - | "ON " / "OFF" |
No (Strcpy only) |
| LswOrchestrator | - | various | No (Strcpy only) |
| LswLocalControl | - | various | No (special) |
| LswMidiChannel | - | "CH%2d" / "OFF" |
Yes (3 variants) |
| LswMasterTuning | - | "%+4d" |
Yes (loop-based) |
| LswLeftHold | - | (format at E952A6) | Yes |
Functions That Send Sub CPU Commands
18 of the 32 Lsw functions call Audio_SendCommand to send commands to the Sub CPU. The remaining 14 only update display strings via Strcpy — these handle parameters that are processed locally by the Main CPU (sustain toggle, digital effect on/off, sound name display, etc.).
Remaining Work
To complete the CC-to-Lsw mapping, the NAKA widget configuration data for each screen needs to be decoded. The widget config contains the actual CC number for each parameter control. This is a data-driven system — the same LswReverb handler is used for ALL reverb depth sliders across all screens.
Phase 3 Results: DSP Command Path and Effect Type Mapping
Two Separate Command Paths
The sound subsystem uses two completely independent command paths based on the inter-CPU command byte:
CC Path (Voice Parameters):
Command 0x00-0x1F → Audio_CmdHandler_00_1F
→ Voice ring buffer (0x2B0D)
→ Voice_CtrlChange (02A46C)
→ Per-voice parameter store at 0x041300 + ch × 0x11F + offset
DSP Path (Effect Parameters):
Command 0x60-0x7F → Audio_CmdHandler_60_7F
→ DSP ring buffer (0x3B60)
→ Audio_Process_DSP (035AE5)
→ DSP algorithm configuration and parameter setting
Command byte encoding: (handler_id << 5) | payload_byte_count
- Reverb presets use 0x63 = handler 3 (DSP), count 3
- EQ presets use 0x64 = handler 3 (DSP), count 4
DSP Effect Name Table (ROM 0xE331E4)
The firmware maintains a master table of all DSP effect types as 16-character display strings starting at 0xE331E4. Each entry is 18 bytes (16 chars + null + 0xFF pad). The full table has 51 entries covering all effect categories:
| Flat Index | Address | Name | Category |
|---|---|---|---|
| 0x00 | E331E4 | VIBRATO | Modulation |
| 0x01 | E331F6 | PITCH SHIFTER | Modulation |
| 0x02 | E33208 | AUTO PAN | Modulation |
| 0x05 | E3323E | CELM | Internal |
| 0x06 | E33250 | CEL | Internal |
| 0x0B | E332AA | PARAMETRIC EQ | EQ |
| 0x0C | E332BC | NOISE FLANGER | Modulation |
| 0x0D | E332CE | SLOW ATTACKER | Dynamics |
| 0x0E | E332E0 | COMPRESSOR | Dynamics |
| 0x0F | E332F2 | EXCITER | Dynamics |
| 0x10 | E33304 | FUZZ | Distortion |
| 0x11 | E33316 | OVERDRIVE | Distortion |
| 0x12 | E33328 | DISTORTION | Distortion |
| 0x17 | E33382 | WAVE REVERB 2 | Reverb |
| 0x18 | E33394 | WAVE REVERB 1 | Reverb |
| 0x19-0x22 | E333A6-E33448 | (10 more reverbs) | Reverb |
| 0x23 | E3345A | ROCK ROTARY | Modulation |
| 0x27 | E334A2 | MODULATION DELAY | Delay |
| 0x28 | E334B4 | MULTI TAP DELAY | Delay |
| 0x29 | E334C6 | SINGLE DELAY | Delay |
| 0x2A | E334D8 | GATED REVERB | Reverb |
| 0x2C-0x32 | E334FC-E33568 | ENSEMBLE..NO OPERATION | Various |
(Unused/placeholder entries with “———-“ at indices 0x03-0x04, 0x07-0x0A, 0x13-0x16, 0x24-0x26, 0x2B omitted.)
DSP Algorithm ID → Name Mapping (Pointer Table at 0xE32A7A)
The firmware does NOT use the flat name table index as the DSP algorithm ID. Instead, it uses an indirect pointer table at 0xE32A7A with 40 entries (4 bytes each). This table maps DSP algorithm IDs (0-39) to name table entries in reverse display order:
| Algo ID | Name | Category |
|---|---|---|
| 0 | NO OPERATION | None |
| 1 | CHORUS | Modulation |
| 2 | MODULATED CHORUS | Modulation |
| 3 | ENHANCER | Dynamics |
| 4 | FLANGER | Modulation |
| 5 | PHASER | Modulation |
| 6 | ENSEMBLE | Modulation |
| 7 | (reserved) | - |
| 8 | GATED REVERB | Reverb |
| 9 | SINGLE DELAY | Delay |
| 10 | MULTI TAP DELAY | Delay |
| 11 | MODULATION DELAY | Delay |
| 12-14 | (reserved) | - |
| 15 | ROCK ROTARY | Modulation |
| 16 | ROOM REVERB 1 | Reverb |
| 17 | ROOM REVERB 2 | Reverb |
| 18 | PLATE REVERB 1 | Reverb |
| 19 | PLATE REVERB 2 | Reverb |
| 20 | CONCERT REVERB 1 | Reverb |
| 21 | CONCERT REVERB 2 | Reverb |
| 22 | DARK REVERB 1 | Reverb |
| 23 | DARK REVERB 2 | Reverb |
| 24 | BRIGHT REVERB 1 | Reverb |
| 25 | BRIGHT REVERB 2 | Reverb |
| 26 | WAVE REVERB 1 | Reverb |
| 27 | WAVE REVERB 2 | Reverb |
| 28-31 | (reserved) | - |
| 32 | DISTORTION | Distortion |
| 33 | OVERDRIVE | Distortion |
| 34 | FUZZ | Distortion |
| 35 | EXCITER | Dynamics |
| 36 | COMPRESSOR | Dynamics |
| 37 | SLOW ATTACKER | Dynamics |
| 38 | NOISE FLANGER | Modulation |
| 39 | PARAMETRIC EQ | EQ |
The display code at DspItem0CngFunc (F355F3) resolves names by: name_ptr = pointer_table[algo_id], then copies the 16-char string to the widget display buffer.
The reverb algorithms occupy IDs 16-27 (12 types = 6 pairs of variant 1/variant 2).
Per-Algorithm DSP Parameter Configuration (ROM 0xE4465C-0xE4485B)
The firmware uses a data-driven system to map DSP parameter slots to named parameters. Four 128-byte configuration blocks (512 bytes total) at ROM 0xE4465C are organized as 8 rows of 16 bytes, where each row corresponds to an algorithm category:
Block layout (4 blocks × 128 bytes):
Block 0 (E4465C): DSP1 master parameter list (algorithm browser)
Block 1 (E446DC): DSP1 per-category name indices (UI display mapping)
Block 2 (E4475C): DSP2 master parameter list
Block 3 (E447DC): DSP2 per-category name indices
Block 1 — DSP1 Per-Category Name Indices (E446DC):
| Row | ROM Addr | Category | Slot 0 | Slot 1 | Slot 2 | Slot 3 | Slot 4 | Slot 5 | Slot 6 | Slot 7 |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | E446DC | Distortion/Dynamics | FF | VOLUME | REV SEND | DRIVE | ADJUST | EMPH.GAIN | DEPTH | VOLUME |
| 2 | E446FC | Rotary (treble) | SLOW LFO | FAST LFO | RESONANCE | MANUAL | SLOW/FAST | TREB.FAST | - | SLOW |
| 3 | E4470C | Rotary (bass) | WIND UP | - | WIND DN | - | BASS FAST | BASS SLOW | OSC SPD | - |
| 4 | E4471C | Delay/Chorus/Flng/Phs | DELAY L | DELAY R | FEEDBACK L | DRY/WET D | DRY/WET C | - | DRY/WET F | DRY/WET P |
| 6 | E4473C | Reverb | REV TIME | PRE DLY | HI DAMP | ER.LEVEL | - | - | - | - |
(Rows 1, 5, 7 are empty/unused. Name abbreviations from parameter name table at E324C4.)
The reverb category has exactly 4 named UI parameters:
- REVERB TIME (name index 0x22) — Reverb decay time
- PRE DELAY (name index 0x23) — Time before reverb onset
- HIGH DAMP GAIN (name index 0x24) — High-frequency absorption
- ER.LEVEL (name index 0x25) — Early reflections level
The UI display loop at DspItem0CngFunc (F355F3) reads: name_index = ROM[DRAM[10668] + DRAM[0x021098] + slot], then resolves the display string from the parameter name table at E324C4.
The category offset in DRAM[0x021098] selects the row: 0x00 for distortion/dynamics, 0x20 for rotary treble, 0x40 for delay/chorus, 0x60 for reverb, etc.
Complete DSP Parameter Name Catalog (ROM 0xE324C4)
The parameter name table has 86 entries × 17 bytes (16-char name + null terminator). Key entries:
| Index | Name | Typical Unit | Used by |
|---|---|---|---|
| 0x01 | VOLUME | - | Distortion/Dynamics |
| 0x03 | REV SEND | - | Distortion/Dynamics |
| 0x04 | DRIVE | - | Distortion/Dynamics |
| 0x07 | DEPTH | - | Modulation effects |
| 0x08 | LFO SPEED | Hz | Modulation effects |
| 0x16-0x17 | DELAY L / DELAY R | ms | Delay effects |
| 0x18-0x19 | FEEDBACK L / FEEDBACK R | - | Delay effects |
| 0x1A-0x1D | DRY/WET (Delay/Chorus/Flanger/Phaser) | - | Various |
| 0x22 | REVERB TIME | s | Reverb |
| 0x23 | PRE DELAY | ms | Reverb |
| 0x24 | HIGH DAMP GAIN | - | Reverb |
| 0x25 | ER.LEVEL | - | Reverb |
| 0x26-0x27 | PITCH L / PITCH R | - | Pitch shifter |
| 0x28-0x2D | THRESHOLD / RATIO / ATTACK / RELEASE / SENS. / RATE | - | Compressor/Gate |
A companion unit suffix table at 0xE32418 (86 entries × 2 bytes ASCII) provides the display unit for each parameter (e.g., “s\0”, “ms”, “Hz”).
Reverb Preset Table — Complete Data (ROM 0xEDA6EC)
All 10 reverb presets stored contiguously at 0xEDA6EC (24 bytes each, 240 bytes total). The pointer table at 0xEDB36C indexes into this region.
| Preset | Algo ID | Algorithm Name | REV TIME | (pad) | PRE DLY | HI DAMP | ER.LVL | Param5 | Param6 | Param7 | B22 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0x11 (17) | ROOM REVERB 2 | 50 | 0 | 12 | 20 | 50 | 93 | 0 | 0 | 99 |
| 1 | 0x10 (16) | ROOM REVERB 1 | 24 | 0 | 97 | 24 | 99 | 94 | 0 | 0 | 99 |
| 2 | 0x12 (18) | PLATE REVERB 1 | 2 | 0 | 45 | 12 | 50 | 80 | 0 | 0 | 99 |
| 3 | 0x14 (20) | CONCERT REVERB 1 | 46 | 0 | 29 | 20 | 58 | 80 | 0 | 0 | 99 |
| 4 | 0x15 (21) | CONCERT REVERB 2 | 32 | 0 | 60 | 24 | 80 | 78 | 0 | 0 | 99 |
| 5 | 0x16 (22) | DARK REVERB 1 | 20 | 0 | 21 | 24 | 52 | 73 | 0 | 0 | 99 |
| 6 | 0x18 (24) | BRIGHT REVERB 1 | 33 | 0 | 2 | 0 | 96 | 79 | 0 | 0 | 99 |
| 7 | 0x19 (25) | BRIGHT REVERB 2 | 43 | 0 | 26 | 0 | 5 | 58 | 0 | 0 | 99 |
| 8 | 0x1A (26) | WAVE REVERB 1 | 15 | 0 | 17 | 21 | 23 | 79 | 0 | 0 | 99 |
| 9 | 0x1B (27) | WAVE REVERB 2 | 60 | 0 | 26 | 18 | 50 | 86 | 18 | 84 | 99 |
24-byte preset block structure:
- B0: DSP algorithm ID (0x10-0x1B for reverb types)
- B1: REVERB TIME (param slot 0) — range 2-60
- B2: Always 0 (padding / unused param slot 1)
- B3: PRE DELAY (param slot 2) — range 2-97
- B4: HIGH DAMP GAIN (param slot 3) — range 0-24
- B5: ER.LEVEL (param slot 4) — range 5-99
- B6: Unnamed param 5 — range 58-105 (possibly wet/dry mix or output level)
- B7-B8: Unnamed params 6-7 — usually 0 (non-zero only in WAVE REVERB 2: 18, 84)
- B9-B21: Zero-padded (unused)
- B22: Level — always 99 (0x63, master output level)
- B23: Zero
Note: B2 (PRE DELAY) is 0 in all 10 factory presets, meaning factory presets use no pre-delay. The user can adjust pre-delay manually via the UI. Preset 9 (WAVE REVERB 2) is the only one with non-zero B7-B8, suggesting the WAVE REVERB algorithm accepts additional modulation parameters.
EQ Preset Table — Complete Data (ROM 0xEDA7DC)
9 standalone EQ presets stored at 0xEDA7DC (24 bytes each, 216 bytes total). The pointer table at 0xEDB394 indexes into this region.
EQ presets use algorithm type 0x4F (79), which is outside the 40-entry DSP algorithm table — EQ parameters are handled by a separate subsystem.
24-byte EQ preset structure:
- B0: Algorithm type (always 0x4F)
- B1:B2: Band 1 frequency (big-endian 16-bit, range 18-600)
- B3:B4: Band 2 frequency (big-endian 16-bit, range 424-1258)
- B5:B6: Band 3 frequency (big-endian 16-bit, range 788-1520)
- B7:B8: Band 4 frequency (big-endian 16-bit, range 1026-1712)
- B9: Constant 0x54 (84)
- B10-B21: Zero-padded
- B22: Level — always 99
- B23: Zero
The four 16-bit values form a monotonically increasing sequence within each preset, strongly suggesting they are 4-band EQ crossover/center frequencies in Hz.
Combined Reverb+EQ Preset Table (ROM 0xEDA8B4)
9 combined presets at 0xEDA8B4 (48 bytes each = 24 bytes reverb + 24 bytes EQ). The pointer table at 0xEDB3B8 indexes into this region.
The combined preset loader (CombinedPreset_Load) reads the first 24 bytes as a reverb preset (sent with command 0x63) and computes lda xwa, (xwa + 24) to get the EQ portion’s address (sent with command 0x64). Note: lda in TLCS-900 is an address calculation, not a memory dereference.
Sub CPU DSP Command Processing
Audio_Process_DSP (035AE5) reads commands from the DSP ring buffer (2KB at 0x3B60) as a byte stream. Each message consists of a 1-byte framing code followed by a 7-byte header:
DSP Ring Buffer Message Format (8 bytes):
┌─────────────────────────────────────────────────────────┐
│ [framing] Framing byte: 0x2B/0x2C/0x2D → DRAM 17256 │
│ [hdr 0] Voice group (0x30-0x3F, low nibble = voice#) │
│ [hdr 1] Sub-qualifier (0x7F for main path) │
│ [hdr 2] Sub-command type (see dispatch table below) │
│ [hdr 3] Parameter data MSB │
│ [hdr 4] Payload size MSB │
│ [hdr 5] Payload size LSB / additional byte count │
│ [hdr 6] End marker / modifier │
└─────────────────────────────────────────────────────────┘
Framing byte dispatch:
0x2B → Voice DSP parameter update (per-voice params)
0x2C → Channel/voice configuration
0x2D → DSP effect configuration (preset loads, algorithm changes)
Sub-command types (header byte 2, for framing 0x2B):
0x00 → Select DSP algorithm (→ DSP_AlgoSelect)
Stores algo ID in voice structure at offset +0x68
Multiplies voice# × 0x11F to index into voice table at 0x041368
0x03 → Effect state control (→ DSP_EffectStateQuery)
0x10 → Set DSP parameter 0 (→ DSP_VoiceParamReadWrite, bc=0)
0x11 → Set DSP parameter 1 (→ DSP_VoiceParamReadWrite, bc=1)
0x12 → Set DSP parameter 2 (→ DSP_VoiceParamReadWrite, bc=2)
...
0x17 → Set DSP parameter 7 (→ DSP_VoiceParamReadWrite, bc=7)
0x20 → DSP mix/send routing (→ DSP_MixSendConfig)
0x22 → Additional config (→ DSP_ReadVoiceParam5D)
0x24 → Additional config (→ DSP_SetVoiceCoefficients)
0x27 → Additional config (→ DSP_ReadVoiceParam11)
0x30 → No-op (returns 0)
The 0x10-0x17 commands are dispatched via a jump table at Sub CPU ROM 0x0121DB (8 word entries).
DSP_VoiceParamReadWrite (parameter setter): Takes voice number (wa), parameter index (bc), and data pointer (xde). Computes voice structure address as 0x041368 + voice × 0x11F, reads/stores the parameter value at offset 0x1D8 + param_index within the global parameter table at 0x44FCE.
DSP_AlgoSelect (algorithm selector): Takes algorithm type ID, validates < 0x28 (40), allocates/configures the voice slot in the 287-byte voice structure array. Sets bit 0 of the voice flags to mark as allocated.
DSP Ring Buffer Control Structure (Sub CPU 0x3B60)
| Offset | Address | Field |
|---|---|---|
| +0 | 0x3B60 | Write pointer (16-bit, wraps at 0x800 = 2KB) |
| +2 | 0x3B62 | Read pointer (16-bit) |
| +4 | 0x3B64 | Available byte count (16-bit) |
| +6 | 0x3B66 | Data area base address (32-bit pointer) |
DSP Parameter Register Addresses
After the effect name table at 0xE3357A, a lookup table maps effect slots to DSP register addresses. The addresses increment by 0x10 per slot:
First set: 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5
Second set: 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7
These correspond to the DSP chip’s register-indirect access via 0x130000/0x130002, suggesting 8 effect processing slots with parameters addressable in 0x10-byte increments.
Extended Algorithm Table (80 entries)
The pointer table at 0xE32A7A actually contains 80 entries (not just 40), covering additional algorithm types including combination effects and the graphic EQ:
| Algo ID Range | Category |
|---|---|
| 0 | NO OPERATION |
| 1-6 | Modulation (Chorus, Mod.Chorus, Enhancer, Flanger, Phaser, Ensemble) |
| 8 | GATED REVERB |
| 9-11 | Delays (Single, Multi-tap, Modulation) |
| 15 | ROCK ROTARY |
| 16-27 | Reverbs (Room/Plate/Concert/Dark/Bright/Wave × 1/2) |
| 32-39 | Distortion/Dynamics (Dist, OD, Fuzz, Exciter, Comp, SlowAtk, NoiseFlng, PEQ) |
| 44-45 | CEL, CELM |
| 48-56 | Extended (AutoPan, PitchShift, Vibrato, PedalWah, AutoWah, RotarySpeaker, RingMod, HARS, MixUp) |
| 57-60, 63 | Presets (Standard, Percussive, Symphonic, Deep Space, String) |
| 64-75 | Combination effects (e.g., S.DELAY+CHORUS, PEQ+COMPRESSOR) |
| 79 | GEQ (Graphic EQ) |
Key Addresses Summary (DSP Path)
| Address | CPU | Purpose |
|---|---|---|
| 0xE324C4 | Main (ROM) | DSP parameter name table (86 × 17 bytes) |
| 0xE32418 | Main (ROM) | DSP parameter unit suffix table (86 × 2 bytes) |
| 0xE32A7A | Main (ROM) | DSP algorithm ID → name pointer table (80 × 4 bytes) |
| 0xE331E4 | Main (ROM) | Effect name string table (51 × 18 bytes) |
| 0xE34DA4 | Main (ROM) | DspItem0CngFunc dispatch table (17 × 2 bytes) |
| 0xE4465C | Main (ROM) | DSP1 master parameter list (128 bytes) |
| 0xE446DC | Main (ROM) | DSP1 per-category parameter name indices (128 bytes) |
| 0xE4475C | Main (ROM) | DSP2 master parameter list (128 bytes) |
| 0xE447DC | Main (ROM) | DSP2 per-category parameter name indices (128 bytes) |
| 0xEDA6EC | Main (ROM) | Reverb preset data (10 × 24 bytes) |
| 0xEDA7DC | Main (ROM) | EQ preset data (9 × 24 bytes) |
| 0xEDA8B4 | Main (ROM) | Combined preset data (9 × 48 bytes) |
| 0xEDB36C | Main (ROM) | Reverb preset pointer table (10 × 4 bytes) |
| 0xEDB394 | Main (ROM) | EQ preset pointer table (9 × 4 bytes) |
| 0xEDB3B8 | Main (ROM) | Combined preset pointer table (9 × 4 bytes) |
| 0x3B60 | Sub (DRAM) | DSP command ring buffer control (2KB, at 15200) |
| 0x0121DB | Sub (ROM) | DSP parameter 0-7 jump table (8 × 2 bytes) |
| 0x041368 | Sub (DRAM) | Voice structure base + 0x68 (DSP algo config) |
| 0x44FCE | Sub (DRAM) | Global DSP parameter storage table |
Remaining Questions
- Main CPU dispatch formatting: The function
HdaeRom_ProcessBlockreformats the 4-byte AssswbWr entries into DMA payloads. Further analysis would reveal exactly how preset bytes map to DSP ring buffer message fields. - DSP hardware registers: The exact register protocol for writing to the DSP chip at 0x130000/0x130002 requires tracing the Sub CPU’s DSP parameter output functions (Phase 4).
- WAVE REVERB extra parameters: Preset 9 (WAVE REVERB 2) has non-zero B7-B8 values (18, 84). These likely control waveform modulation parameters unique to the WAVE REVERB algorithm.
- EQ crossover frequencies: The 4 big-endian 16-bit values in EQ presets need verification as frequency values (Hz). The monotonic ordering suggests crossover points for a 4-band parametric EQ.