mirror of
https://github.com/polpo/picogus.git
synced 2026-10-25 21:40:16 +00:00
opl: enable EMU8950 TLL via pre-computed table in flash (.flashdata section)
The TLL (Total Level Lookup) table is 128KB — too large for the RP2040's 256KB RAM when the firmware also runs code from RAM. Previous attempts to use a `const` array failed because the firmware uses a copy_to_ram binary type, which copies ALL sections including `.rodata` into RAM at boot. The fix: place the pre-computed table in the `.flashdata.tll_table` linker section. Both pico-sdk's `memmap_copy_to_ram.ld` and the local `fw_memmap_c2ram.ld` explicitly capture `.flashdata*` into the FLASH `.rodata` region, which is accessed via XIP cache and never copied to RAM. - gen_tll_table.py: new script that pre-computes makeTllTable() using the EMU8950_NO_FLOAT integer path, outputting tll_table_flash.c with the `.flashdata.tll_table` section attribute - tll_table_flash.c: generated 128KB table (32,768 uint32_t values) - emu8950.c: support EMU8950_TLL_FLASH — use extern const declaration and skip makeTllTable() at runtime when table is pre-computed in flash - CMakeLists: replace EMU8950_NO_TLL=1 with EMU8950_TLL_FLASH=1 TLL improves OPL2 accuracy by enabling the full Key Scale Level (KSL) attenuation lookup table rather than the inline approximation.
This commit is contained in:
1 parent
1ceb476dfd
commit
f3220f736a
5 files changed
+8539
-3
No files matched your search
+2
-2
@@ -170,8 +170,8 @@ function(config_target TARGET_NAME MULTIFW)
|
||||
SOUND_OPL=1
|
||||
USE_EMU8950_OPL=1
|
||||
EMU8950_ASM=1
|
||||
EMU8950_NO_TLL=1 # don't use lookup table for total level
|
||||
EMU8950_NO_FLOAT=1 # double check there is no float
|
||||
EMU8950_TLL_FLASH=1 # pre-computed TLL table stored in flash via .flashdata section (not copied to RAM)
|
||||
EMU8950_NO_FLOAT=1 # RP2040 has no FPU; float only used in TLL init anyway
|
||||
EMU8950_NO_TIMER=1 # disable timer which isn't used
|
||||
EMU8950_NO_TEST_FLAG=1 # disable test flags (which aren't used)
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ add_library(opl INTERFACE)
|
||||
target_sources(opl INTERFACE
|
||||
# ${CMAKE_CURRENT_LIST_DIR}/opl_api.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/emu8950.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/tll_table_flash.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/slot_render.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/opl_pico.c)
|
||||
target_compile_options(opl INTERFACE -fms-extensions) # want OPL_SLOT_RENDER to be unnamed within OPL_SLOT
|
||||
|
||||
+5
-1
@@ -200,8 +200,12 @@ static int16_t kl_tablex16[16] = {dB2x16(0.000), dB2x16(9.000), dB2x16(12.000),
|
||||
#endif
|
||||
|
||||
#if !EMU8950_NO_TLL
|
||||
#ifdef EMU8950_TLL_FLASH
|
||||
extern const uint32_t tll_table[8 * 16][1 << TL_BITS][4];
|
||||
#else
|
||||
static uint32_t tll_table[8 * 16][1 << TL_BITS][4];
|
||||
#endif
|
||||
#endif
|
||||
static int32_t rks_table[2][32][2];
|
||||
|
||||
#define min(i, j) (((i) < (j)) ? (i) : (j))
|
||||
@@ -368,7 +372,7 @@ static void makeSinTable(void) {
|
||||
}
|
||||
|
||||
static void makeTllTable(void) {
|
||||
#if !EMU8950_NO_TLL
|
||||
#if !EMU8950_NO_TLL && !defined(EMU8950_TLL_FLASH)
|
||||
int32_t tmp;
|
||||
int32_t fnum, block, TL, KL, kx;
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generates tll_table_flash.c for the EMU8950 OPL2 emulator.
|
||||
Pre-computes makeTllTable() so the result can be stored in RP2040 flash (XIP)
|
||||
instead of RAM, working around the 128KB RAM constraint.
|
||||
|
||||
Replicates the EMU8950_NO_FLOAT integer path from emu8950.c:
|
||||
kl_tablex16[fnum] = (uint16_t)(kl_values[fnum] * 32)
|
||||
dB2x16(3.000) = 96
|
||||
EG_STEPx16 = 3
|
||||
TL2EG(tl) = tl << 2
|
||||
"""
|
||||
|
||||
TL_BITS = 6
|
||||
EG_STEPx16 = 3
|
||||
|
||||
kl_values = [
|
||||
0.000, 9.000, 12.000, 13.875, 15.000, 16.125,
|
||||
16.875, 17.625, 18.000, 18.750, 19.125, 19.500,
|
||||
19.875, 20.250, 20.625, 21.000,
|
||||
]
|
||||
kl_tablex16 = [int(v * 32) & 0xFFFF for v in kl_values] # uint16_t cast
|
||||
dB2x16_3 = int(3.000 * 32) # = 96
|
||||
|
||||
def TL2EG(tl):
|
||||
return tl << 2
|
||||
|
||||
# Build table[128][64][4]
|
||||
table = [[[0] * 4 for _ in range(1 << TL_BITS)] for _ in range(8 * 16)]
|
||||
|
||||
for fnum in range(16):
|
||||
for block in range(8):
|
||||
idx = (block << 4) | fnum
|
||||
for TL in range(1 << TL_BITS):
|
||||
for KL in range(4):
|
||||
if KL == 0:
|
||||
table[idx][TL][KL] = TL2EG(TL)
|
||||
else:
|
||||
kx = ((KL & 1) << 1) | ((KL >> 1) & 1)
|
||||
tmp = kl_tablex16[fnum] - dB2x16_3 * (7 - block)
|
||||
if tmp <= 0:
|
||||
table[idx][TL][KL] = TL2EG(TL)
|
||||
else:
|
||||
table[idx][TL][KL] = (tmp >> (3 - kx)) // EG_STEPx16 + TL2EG(TL)
|
||||
|
||||
lines = []
|
||||
lines.append("/* Auto-generated by gen_tll_table.py — do not edit manually. */")
|
||||
lines.append("/* Pre-computed EMU8950 TLL (Total Level Lookup) table for RP2040 flash (XIP). */")
|
||||
lines.append("/* Replicates makeTllTable() integer path; stored as const in .flashdata section so")
|
||||
lines.append(" * pico-sdk copy_to_ram linker scripts keep it in flash rather than copying to RAM. */")
|
||||
lines.append("#include <stdint.h>")
|
||||
lines.append("")
|
||||
lines.append("/* __attribute__((section(\".flashdata.tll_table\"))) keeps this in flash even in")
|
||||
lines.append(" * copy_to_ram builds (both memmap_copy_to_ram.ld and fw_memmap_c2ram.ld capture")
|
||||
lines.append(" * .flashdata* into the FLASH .rodata region, not the RAM .data region). */")
|
||||
lines.append("const uint32_t __attribute__((section(\".flashdata.tll_table\")))")
|
||||
lines.append(" tll_table[128][64][4] = {")
|
||||
for i in range(128):
|
||||
lines.append(" { /* blk_fnum=" + str(i) + " */")
|
||||
for j in range(64):
|
||||
row = ", ".join(str(table[i][j][k]) for k in range(4))
|
||||
lines.append(" {" + row + "},")
|
||||
lines.append(" },")
|
||||
lines.append("};")
|
||||
|
||||
import os
|
||||
out_path = os.path.join(os.path.dirname(__file__), "tll_table_flash.c")
|
||||
with open(out_path, "w") as f:
|
||||
f.write("\n".join(lines) + "\n")
|
||||
|
||||
print(f"Written {len(table) * 64 * 4} uint32_t values to {out_path}")
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user