docs(recon): memllib usage inventory — the §7.5 prerequisite, with a wrinkle
Plan §5 names an inventory of the load-bearing memllib surface as the
prerequisite for the vendor-vs-fork-pin decision. Built it from the firmware
LINKER MAP rather than grep — the same method that would have caught daisysp
(S8) mechanically instead of by reading.
Result: all 24 compiled translation units contribute kept sections to the image;
no discarded-only TU exists. memllib is not a daisysp situation. "The
load-bearing subset" is ~1.8 MB across 84 files — essentially all of memllib
minus examples/. There is no small subset to lift; synth/ alone is 1.3 MB and
all three of its TUs link.
The wrinkle, which was not visible when §7.5 was decided: src/memllib is not a
third-party dependency, it is the LAB's shared library
(MusicallyEmbodiedML/memllib), and our fork is 3 commits ahead but 31 commits
BEHIND — +2034/-153 across exactly the files we link, including "new staticmlp",
"jolts", "noise", "verb". Vendoring as-is freezes that gap permanently.
Recommendation recorded: rebase the three small NISPS commits onto upstream main
FIRST, then vendor. Same self-contained end state, but it does not silently
discard work that sounds directly relevant, and it is the only moment that merge
is cheap — after vendoring there is no upstream history to merge against.
Flagged for an operator call before the PlatformIO cut, which this gates.
2026-07-21 14:12:55 +02:00
|
|
|
---
|
|
|
|
|
kind: finding
|
|
|
|
|
date: 2026-07-21
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# memllib usage inventory — the prerequisite for the §7.5 ownership decision
|
|
|
|
|
|
|
|
|
|
_Prerequisite named by `../plans/simplification-plan.md` §5: "inventory which memllib surface
|
|
|
|
|
(AudioDriver, MEMLNaut board, display/menu, MIDI) is load-bearing" before choosing between a
|
|
|
|
|
fork-pin and vendoring. The operator's §7.5 decision is **vendor the parts we use** ("everything
|
|
|
|
|
should be self contained in this repo"). This document is the evidence that decision needs, plus one
|
|
|
|
|
consequence that was not visible when it was made._
|
|
|
|
|
|
|
|
|
|
## Method
|
|
|
|
|
|
|
|
|
|
Not grep. The firmware was built for real (`arduino-cli`, `rp2040:rp2040:solderparty_rp2350_stamp_xl`,
|
|
|
|
|
SLPWorkshop variant) and the **linker map** was read: `MEMLNaut-NISPS.ino.map` distinguishes
|
|
|
|
|
translation units that merely compiled from those contributing sections to the final image. This is
|
|
|
|
|
the same method that would have caught the daisysp finding (S8) mechanically instead of by reading.
|
|
|
|
|
|
|
|
|
|
## Result: the compile surface is 24 TUs, and all 24 are linked
|
|
|
|
|
|
|
|
|
|
| subdir | .cpp linked / present | headers | size |
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
| `audio/` | 4 / 4 | 12 | 132K |
|
|
|
|
|
| `hardware/` | 7 / 7 | 21 | 176K |
|
|
|
|
|
| `interface/` | 8 / 8 | 8 | 108K |
|
|
|
|
|
| `synth/` | 3 / 3 | 10 | 1.3M |
|
|
|
|
|
| `utils/` | 2 / 2 | 9 | 80K |
|
|
|
|
|
| **total** | **24 / 24** | **60** | **~1.8M** |
|
|
|
|
|
|
|
|
|
|
Every translation unit reachable through the sketch-tree symlinks contributes kept sections to the
|
|
|
|
|
image — **no discarded-only TU exists**. memllib is therefore *not* a daisysp situation (41 .cpp
|
|
|
|
|
compiled, zero consumers). It is genuinely load-bearing.
|
|
|
|
|
|
|
|
|
|
The library has 30 `.cpp` in total; the 6 not counted above live outside the five symlinked subdirs
|
|
|
|
|
(e.g. `examples/`) and are never compiled by the firmware build. Those are the only part safe to
|
|
|
|
|
drop outright.
|
|
|
|
|
|
|
|
|
|
Firmware's direct include surface is just six entry points — `audio/AudioDriver.hpp`,
|
|
|
|
|
`hardware/memlnaut/MEMLNaut.hpp`, `hardware/memlnaut/Pins.hpp`,
|
|
|
|
|
`hardware/memlnaut/display/{View,SingleSelectView}.hpp`, `interface/MIDIInOut.hpp`, `PicoDefs.hpp`,
|
|
|
|
|
`utils/perf.hpp` — but the transitive closure is the whole of those five subdirs.
|
|
|
|
|
|
|
|
|
|
**Consequence for vendoring: "the load-bearing subset" is ~1.8 MB / 84 files, i.e. essentially all
|
|
|
|
|
of memllib minus `examples/`.** There is no small subset to lift. `synth/` alone is 1.3 MB (mostly
|
|
|
|
|
`maximilian.cpp`) and all three of its TUs link.
|
|
|
|
|
|
feat(firmware): bump memllib to current upstream and dissolve the fork
The §7.5 decision was "rebase our commits onto upstream, then vendor". On
inspection there was no rebase to do, and the inventory that recommended it
(7a30da9) was wrong on two counts — both corrected in this commit.
All three fork commits touch only `examples/`. That directory is not in the
sketch symlink forest (firmware/MEMLNaut-NISPS/src/ links exactly audio,
hardware, interface, synth, utils, PicoDefs.hpp), so it is never compiled.
They existed to let the RL code build against nisps/core *while it was being
ported*, and that port is done — nisps/ml/{jolt,ou_noise,feedback,geo_push}.hpp
cite the upstream sources directly. Two of the 31 commits I flagged as
"work we are missing", `9fcd459 jolts` and `d0d8a72 noise`, are precisely the
ones already absorbed.
So the question was never rebase-or-not but which snapshot to vendor. Current
upstream, because the staleness was already costing us:
- upstream has DisplayDriver::NavigateToView; the pin does not. The SelfTest
variant called it and had been failing to compile (worked around in
b953681). It was written against a newer memllib, not against nothing.
- e291192 "l r input swap" is a hardware bug fix: the physical L/R input
sockets are wired to opposite codec ADC channels. Every mode on the old
pin sees its stereo input backwards.
Verified by building all three variants with arduino-cli:
SLPWorkshop 145348 flash (+320) 87388 RAM (+4)
PAFSynth 145300 flash (+312) 107060 RAM (+4)
SelfTest 141840 flash (+320) 12028 RAM (+4)
Exactly one compile error: the .ino used kSampleRate in a constexpr, and
upstream 1997699 made it a runtime `extern size_t` so a mode can pick its own
rate. constexpr -> const; it is a once-per-second diagnostic print. The uniform
+316 is the AudioDriver/DisplayDriver deltas — the bulky new upstream code
(GrainDelayI16, ReverbI16, ModFXI16, CCSelectView, RLView, VUMeterView,
PSRAMManager) is header-only and unreferenced, so the linker drops all of it.
.gitmodules points at upstream again: with the pin on an upstream commit, the
fork holds nothing the firmware compiles. Phase 0 pointed it at the fork only
because b37fc53 existed on no remote. The fork's feat/nisps-core-swap branch
stays pushed; nothing is destroyed.
Refs: plan §5, §7.5; ALIGNMENT Q4.
2026-07-21 17:04:10 +02:00
|
|
|
## The fork divergence — and the correction to this document's first version
|
docs(recon): memllib usage inventory — the §7.5 prerequisite, with a wrinkle
Plan §5 names an inventory of the load-bearing memllib surface as the
prerequisite for the vendor-vs-fork-pin decision. Built it from the firmware
LINKER MAP rather than grep — the same method that would have caught daisysp
(S8) mechanically instead of by reading.
Result: all 24 compiled translation units contribute kept sections to the image;
no discarded-only TU exists. memllib is not a daisysp situation. "The
load-bearing subset" is ~1.8 MB across 84 files — essentially all of memllib
minus examples/. There is no small subset to lift; synth/ alone is 1.3 MB and
all three of its TUs link.
The wrinkle, which was not visible when §7.5 was decided: src/memllib is not a
third-party dependency, it is the LAB's shared library
(MusicallyEmbodiedML/memllib), and our fork is 3 commits ahead but 31 commits
BEHIND — +2034/-153 across exactly the files we link, including "new staticmlp",
"jolts", "noise", "verb". Vendoring as-is freezes that gap permanently.
Recommendation recorded: rebase the three small NISPS commits onto upstream main
FIRST, then vendor. Same self-contained end state, but it does not silently
discard work that sounds directly relevant, and it is the only moment that merge
is cheap — after vendoring there is no upstream history to merge against.
Flagged for an operator call before the PlatformIO cut, which this gates.
2026-07-21 14:12:55 +02:00
|
|
|
|
|
|
|
|
`src/memllib` is not a third-party dependency. It is **the lab's shared library**
|
feat(firmware): bump memllib to current upstream and dissolve the fork
The §7.5 decision was "rebase our commits onto upstream, then vendor". On
inspection there was no rebase to do, and the inventory that recommended it
(7a30da9) was wrong on two counts — both corrected in this commit.
All three fork commits touch only `examples/`. That directory is not in the
sketch symlink forest (firmware/MEMLNaut-NISPS/src/ links exactly audio,
hardware, interface, synth, utils, PicoDefs.hpp), so it is never compiled.
They existed to let the RL code build against nisps/core *while it was being
ported*, and that port is done — nisps/ml/{jolt,ou_noise,feedback,geo_push}.hpp
cite the upstream sources directly. Two of the 31 commits I flagged as
"work we are missing", `9fcd459 jolts` and `d0d8a72 noise`, are precisely the
ones already absorbed.
So the question was never rebase-or-not but which snapshot to vendor. Current
upstream, because the staleness was already costing us:
- upstream has DisplayDriver::NavigateToView; the pin does not. The SelfTest
variant called it and had been failing to compile (worked around in
b953681). It was written against a newer memllib, not against nothing.
- e291192 "l r input swap" is a hardware bug fix: the physical L/R input
sockets are wired to opposite codec ADC channels. Every mode on the old
pin sees its stereo input backwards.
Verified by building all three variants with arduino-cli:
SLPWorkshop 145348 flash (+320) 87388 RAM (+4)
PAFSynth 145300 flash (+312) 107060 RAM (+4)
SelfTest 141840 flash (+320) 12028 RAM (+4)
Exactly one compile error: the .ino used kSampleRate in a constexpr, and
upstream 1997699 made it a runtime `extern size_t` so a mode can pick its own
rate. constexpr -> const; it is a once-per-second diagnostic print. The uniform
+316 is the AudioDriver/DisplayDriver deltas — the bulky new upstream code
(GrainDelayI16, ReverbI16, ModFXI16, CCSelectView, RLView, VUMeterView,
PSRAMManager) is header-only and unreferenced, so the linker drops all of it.
.gitmodules points at upstream again: with the pin on an upstream commit, the
fork holds nothing the firmware compiles. Phase 0 pointed it at the fork only
because b37fc53 existed on no remote. The fork's feat/nisps-core-swap branch
stays pushed; nothing is destroyed.
Refs: plan §5, §7.5; ALIGNMENT Q4.
2026-07-21 17:04:10 +02:00
|
|
|
(`MusicallyEmbodiedML/memllib`), and our fork was 3 commits ahead / 31 behind.
|
|
|
|
|
|
|
|
|
|
**The first version of this document (commit `7a30da9`) drew the wrong conclusion from that, and
|
|
|
|
|
recommended a rebase-then-vendor on the strength of it. Two facts checked afterwards overturn it:**
|
|
|
|
|
|
|
|
|
|
1. **All three of our commits touch only `examples/`** — `bf9691c` (swap memlp includes for
|
|
|
|
|
nisps/core, inline RL utilities), `32cc831` (newlib RNG fix), `b37fc53` (seed-helper rename).
|
|
|
|
|
`examples/` is **not in the sketch symlink forest** (`firmware/MEMLNaut-NISPS/src/` symlinks
|
|
|
|
|
exactly `audio hardware interface synth utils PicoDefs.hpp`), so it is never compiled. Those
|
|
|
|
|
commits existed to let the RL code build against `nisps/core` **while it was being ported**, and
|
|
|
|
|
that port is finished: `nisps/ml/{jolt,ou_noise,feedback,geo_push}.hpp` cite the upstream sources
|
|
|
|
|
directly. So there is nothing of ours to carry forward, and **no rebase to perform** — vendoring
|
|
|
|
|
the five linked subdirs drops `examples/` and our three commits with it.
|
|
|
|
|
2. **Two of the "31 commits of work we are missing" were already absorbed.** `nisps/ml/jolt.hpp:3`
|
|
|
|
|
cites `9fcd459 "jolts"` and `nisps/ml/ou_noise.hpp:3` cites `d0d8a72 "noise"` as their sources.
|
|
|
|
|
The alarm in the first version — "the 31 commits contain work that sounds directly relevant" —
|
|
|
|
|
was therefore overstated for exactly the two commits it named.
|
|
|
|
|
|
|
|
|
|
So the real question was never "rebase or not" but **"which snapshot do we vendor: the pinned
|
|
|
|
|
`188496d` we build today, or current upstream?"**
|
|
|
|
|
|
|
|
|
|
## The staleness was already costing us
|
|
|
|
|
|
|
|
|
|
Upstream `main` **has `DisplayDriver::NavigateToView`** (`display/DisplayDriver.hpp:54`); the pinned
|
|
|
|
|
commit does not. The SelfTest firmware variant called it and had been failing to compile — fixed in
|
|
|
|
|
`b953681` by routing around the missing method. That variant was not written against broken code; it
|
|
|
|
|
was written against a **newer memllib than the pin**. The gap is not theoretical.
|
|
|
|
|
|
|
|
|
|
Upstream also carries `e291192 "l r input swap"`, a **hardware bug fix**: the physical L/R input
|
|
|
|
|
sockets are wired to the opposite codec ADC channels, so `AudioDriver.cpp` now swaps them at the
|
|
|
|
|
lowest level. Every mode on the pinned commit sees its stereo input backwards.
|
|
|
|
|
|
|
|
|
|
## Verified: current upstream builds, and costs almost nothing
|
|
|
|
|
|
build(firmware): migrate to PlatformIO and vendor memllib (plan §5)
One cut, no dual path. Closes ALIGNMENT defect 3 ("Arduino-CLI build
machinery is actively hostile") and vision bullet 4.
platformio.ini carries 16 [env:], one per variant, each passing
-DMEMLNAUT_MODE_TYPE; selftest passes -DNISPS_SELFTEST=1 instead. The env list
IS the registry now — the .ino comment-registry and the NISPS_ST_* token-paste
table are deleted rather than migrated. L12 noted that table was already
silently missing the currently-shipped SLPWorkshop variant, which is the whole
argument against having a second list.
Also deleted: the Python/sed machinery that rewrote the COMMITTED .ino on every
build, the sketch symlink forest, the global TFT_eSPI User_Setup.h mutation
(now -D flags — TFT_eSPI's own documented PlatformIO recipe), the UF2
boot-mount detection stack (upload_protocol=picotool talks to the bootloader
directly), and build-firmware-arch.sh entirely. Scripts 683 -> 435 lines.
memllib is vendored at lib/memllib/ from upstream e291192; no submodules
remain. VENDORED.md records provenance and the re-sync procedure.
S9: a firmware-build CI job compiles three representative envs against a cached
toolchain and reports per-variant flash/RAM. Firmware is in an automated gate
for the FIRST time. The old ci.yml comment justified excluding it as "low
verification value" — an assessment that did not survive contact, since the
SelfTest variant sat broken for an unknown period calling a DisplayDriver
method that did not exist at the pinned memllib commit, and nothing noticed
because nothing built it.
Verified: all 16 envs build from an empty cache, each within ~520 bytes of the
arduino-cli binary it replaces, flash and RAM. Measured as .text+.rodata /
.data+.bss+vector+uninitialized — NOT PlatformIO's console line, which
double-counts .data on this board. This does not prove the hardware boots; no
flash+smoke test was possible and that stays an operator chokepoint.
slpworkshop 248232/145028 pafsynth 256880/149716 selftest 216228/17960
(all 16 in the CI log format; none exceeds 2% of a 16 MB flash)
Two traps recorded so nobody rediscovers them: vendoring memllib's subdirs
without a src/ wrapper makes PlatformIO's library builder silently compile
NOTHING while still linking; and project build_flags land BEFORE the
framework's own -std=gnu++17 -Os, so build_unflags is required.
CORRECTION carried in this commit: the firmware sizes in c19d846's message and
the first version of the memllib recon doc were wrong — SLPWorkshop 145348,
PAFSynth 145300, SelfTest 141840. They came from building variants in sequence
through a SHARED incremental arduino-cli build directory, which reused stale
objects and under-reported by ~75 KB. Clean-cache rebuilds of the identical
commit give 216736/18492 for SelfTest. The real cost of the memllib upstream
bump is +216 bytes flash, not +316. Never measure firmware size through a
reused build dir.
HISTORY NOTE: this commit and the docs commit before it were rebuilt (force-push,
2026-07-21) so that each contains only what its message describes. The first
versions had the firmware deletions stranded in the docs commit by a shared-index
race between concurrent agents; content is byte-identical to the originals.
Gates: run-all-tests.sh ALL GREEN (nisps/ untouched by this change beyond
include paths); 16/16 pio envs build.
2026-07-21 20:17:58 +02:00
|
|
|
Submodule moved to `e291192` (upstream `main`).
|
feat(firmware): bump memllib to current upstream and dissolve the fork
The §7.5 decision was "rebase our commits onto upstream, then vendor". On
inspection there was no rebase to do, and the inventory that recommended it
(7a30da9) was wrong on two counts — both corrected in this commit.
All three fork commits touch only `examples/`. That directory is not in the
sketch symlink forest (firmware/MEMLNaut-NISPS/src/ links exactly audio,
hardware, interface, synth, utils, PicoDefs.hpp), so it is never compiled.
They existed to let the RL code build against nisps/core *while it was being
ported*, and that port is done — nisps/ml/{jolt,ou_noise,feedback,geo_push}.hpp
cite the upstream sources directly. Two of the 31 commits I flagged as
"work we are missing", `9fcd459 jolts` and `d0d8a72 noise`, are precisely the
ones already absorbed.
So the question was never rebase-or-not but which snapshot to vendor. Current
upstream, because the staleness was already costing us:
- upstream has DisplayDriver::NavigateToView; the pin does not. The SelfTest
variant called it and had been failing to compile (worked around in
b953681). It was written against a newer memllib, not against nothing.
- e291192 "l r input swap" is a hardware bug fix: the physical L/R input
sockets are wired to opposite codec ADC channels. Every mode on the old
pin sees its stereo input backwards.
Verified by building all three variants with arduino-cli:
SLPWorkshop 145348 flash (+320) 87388 RAM (+4)
PAFSynth 145300 flash (+312) 107060 RAM (+4)
SelfTest 141840 flash (+320) 12028 RAM (+4)
Exactly one compile error: the .ino used kSampleRate in a constexpr, and
upstream 1997699 made it a runtime `extern size_t` so a mode can pick its own
rate. constexpr -> const; it is a once-per-second diagnostic print. The uniform
+316 is the AudioDriver/DisplayDriver deltas — the bulky new upstream code
(GrainDelayI16, ReverbI16, ModFXI16, CCSelectView, RLView, VUMeterView,
PSRAMManager) is header-only and unreferenced, so the linker drops all of it.
.gitmodules points at upstream again: with the pin on an upstream commit, the
fork holds nothing the firmware compiles. Phase 0 pointed it at the fork only
because b37fc53 existed on no remote. The fork's feat/nisps-core-swap branch
stays pushed; nothing is destroyed.
Refs: plan §5, §7.5; ALIGNMENT Q4.
2026-07-21 17:04:10 +02:00
|
|
|
|
build(firmware): migrate to PlatformIO and vendor memllib (plan §5)
One cut, no dual path. Closes ALIGNMENT defect 3 ("Arduino-CLI build
machinery is actively hostile") and vision bullet 4.
platformio.ini carries 16 [env:], one per variant, each passing
-DMEMLNAUT_MODE_TYPE; selftest passes -DNISPS_SELFTEST=1 instead. The env list
IS the registry now — the .ino comment-registry and the NISPS_ST_* token-paste
table are deleted rather than migrated. L12 noted that table was already
silently missing the currently-shipped SLPWorkshop variant, which is the whole
argument against having a second list.
Also deleted: the Python/sed machinery that rewrote the COMMITTED .ino on every
build, the sketch symlink forest, the global TFT_eSPI User_Setup.h mutation
(now -D flags — TFT_eSPI's own documented PlatformIO recipe), the UF2
boot-mount detection stack (upload_protocol=picotool talks to the bootloader
directly), and build-firmware-arch.sh entirely. Scripts 683 -> 435 lines.
memllib is vendored at lib/memllib/ from upstream e291192; no submodules
remain. VENDORED.md records provenance and the re-sync procedure.
S9: a firmware-build CI job compiles three representative envs against a cached
toolchain and reports per-variant flash/RAM. Firmware is in an automated gate
for the FIRST time. The old ci.yml comment justified excluding it as "low
verification value" — an assessment that did not survive contact, since the
SelfTest variant sat broken for an unknown period calling a DisplayDriver
method that did not exist at the pinned memllib commit, and nothing noticed
because nothing built it.
Verified: all 16 envs build from an empty cache, each within ~520 bytes of the
arduino-cli binary it replaces, flash and RAM. Measured as .text+.rodata /
.data+.bss+vector+uninitialized — NOT PlatformIO's console line, which
double-counts .data on this board. This does not prove the hardware boots; no
flash+smoke test was possible and that stays an operator chokepoint.
slpworkshop 248232/145028 pafsynth 256880/149716 selftest 216228/17960
(all 16 in the CI log format; none exceeds 2% of a 16 MB flash)
Two traps recorded so nobody rediscovers them: vendoring memllib's subdirs
without a src/ wrapper makes PlatformIO's library builder silently compile
NOTHING while still linking; and project build_flags land BEFORE the
framework's own -std=gnu++17 -Os, so build_unflags is required.
CORRECTION carried in this commit: the firmware sizes in c19d846's message and
the first version of the memllib recon doc were wrong — SLPWorkshop 145348,
PAFSynth 145300, SelfTest 141840. They came from building variants in sequence
through a SHARED incremental arduino-cli build directory, which reused stale
objects and under-reported by ~75 KB. Clean-cache rebuilds of the identical
commit give 216736/18492 for SelfTest. The real cost of the memllib upstream
bump is +216 bytes flash, not +316. Never measure firmware size through a
reused build dir.
HISTORY NOTE: this commit and the docs commit before it were rebuilt (force-push,
2026-07-21) so that each contains only what its message describes. The first
versions had the firmware deletions stranded in the docs commit by a shared-index
race between concurrent agents; content is byte-identical to the originals.
Gates: run-all-tests.sh ALL GREEN (nisps/ untouched by this change beyond
include paths); 16/16 pio envs build.
2026-07-21 20:17:58 +02:00
|
|
|
**CORRECTION (2026-07-21, same day).** The first version of this table, and the numbers in commit
|
|
|
|
|
`c19d846`'s message, were WRONG — SLPWorkshop 145348, PAFSynth 145300, SelfTest 141840, with a
|
|
|
|
|
"+316 uniform delta". They were produced by building three variants in a row through a **shared
|
|
|
|
|
incremental `arduino-cli` build directory** (`/tmp/memlnaut-firmware-build`), which reused stale
|
|
|
|
|
objects and under-reported by roughly 75 KB. The error surfaced when the PlatformIO migration could
|
|
|
|
|
not reproduce them; a clean-cache rebuild of the identical commit in a throwaway worktree confirmed
|
|
|
|
|
it. **Never measure firmware size through a reused build directory.**
|
|
|
|
|
|
|
|
|
|
Measured properly (clean build dir per measurement, SelfTest variant):
|
|
|
|
|
|
|
|
|
|
| memllib pin | flash | RAM |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `b37fc53` (old pin, pre-bump) | 216520 | 18480 |
|
|
|
|
|
| `e291192` (upstream main) | 216736 | 18492 |
|
|
|
|
|
| **delta** | **+216** | **+12** |
|
|
|
|
|
|
|
|
|
|
The conclusion is unchanged and if anything stronger: the 31-commit upstream bump costs ~216 bytes
|
|
|
|
|
of a 16 MB flash. The bulky new upstream code (`GrainDelayI16`, `ReverbI16`, `ModFXI16`,
|
|
|
|
|
`CCSelectView`, `NameInputView`, `RLView`, `VUMeterView`, `PSRAMManager`) is header-only and
|
|
|
|
|
unreferenced, so the linker drops all of it; the delta is the AudioDriver/DisplayDriver changes.
|
|
|
|
|
|
|
|
|
|
Absolute sizes for every variant, post-bump, are in the Phase 4 migration commit — all 16 build,
|
|
|
|
|
and none exceeds 2% of flash.
|
feat(firmware): bump memllib to current upstream and dissolve the fork
The §7.5 decision was "rebase our commits onto upstream, then vendor". On
inspection there was no rebase to do, and the inventory that recommended it
(7a30da9) was wrong on two counts — both corrected in this commit.
All three fork commits touch only `examples/`. That directory is not in the
sketch symlink forest (firmware/MEMLNaut-NISPS/src/ links exactly audio,
hardware, interface, synth, utils, PicoDefs.hpp), so it is never compiled.
They existed to let the RL code build against nisps/core *while it was being
ported*, and that port is done — nisps/ml/{jolt,ou_noise,feedback,geo_push}.hpp
cite the upstream sources directly. Two of the 31 commits I flagged as
"work we are missing", `9fcd459 jolts` and `d0d8a72 noise`, are precisely the
ones already absorbed.
So the question was never rebase-or-not but which snapshot to vendor. Current
upstream, because the staleness was already costing us:
- upstream has DisplayDriver::NavigateToView; the pin does not. The SelfTest
variant called it and had been failing to compile (worked around in
b953681). It was written against a newer memllib, not against nothing.
- e291192 "l r input swap" is a hardware bug fix: the physical L/R input
sockets are wired to opposite codec ADC channels. Every mode on the old
pin sees its stereo input backwards.
Verified by building all three variants with arduino-cli:
SLPWorkshop 145348 flash (+320) 87388 RAM (+4)
PAFSynth 145300 flash (+312) 107060 RAM (+4)
SelfTest 141840 flash (+320) 12028 RAM (+4)
Exactly one compile error: the .ino used kSampleRate in a constexpr, and
upstream 1997699 made it a runtime `extern size_t` so a mode can pick its own
rate. constexpr -> const; it is a once-per-second diagnostic print. The uniform
+316 is the AudioDriver/DisplayDriver deltas — the bulky new upstream code
(GrainDelayI16, ReverbI16, ModFXI16, CCSelectView, RLView, VUMeterView,
PSRAMManager) is header-only and unreferenced, so the linker drops all of it.
.gitmodules points at upstream again: with the pin on an upstream commit, the
fork holds nothing the firmware compiles. Phase 0 pointed it at the fork only
because b37fc53 existed on no remote. The fork's feat/nisps-core-swap branch
stays pushed; nothing is destroyed.
Refs: plan §5, §7.5; ALIGNMENT Q4.
2026-07-21 17:04:10 +02:00
|
|
|
|
|
|
|
|
Exactly **one** compile error had to be fixed: `MEMLNaut-NISPS.ino:169` used `kSampleRate` in a
|
|
|
|
|
`constexpr`, and upstream `1997699 "mode sample rate"` made it a runtime `extern size_t` so a mode
|
|
|
|
|
can choose its own rate. `constexpr` → `const`; it is a once-per-second diagnostic print.
|
|
|
|
|
|
|
|
|
|
## Where this leaves the vendoring
|
|
|
|
|
|
|
|
|
|
Vendor **from current upstream**, not from the old pin. Take the five linked subdirs +
|
|
|
|
|
`PicoDefs.hpp`; drop `examples/` (~1.8 MB → the vendored surface). Record the exact upstream commit
|
|
|
|
|
so a future re-sync is a documented diff rather than an archaeology exercise.
|
|
|
|
|
|
|
|
|
|
The submodule now points at **upstream** rather than the fork: with the pin moved to an upstream
|
|
|
|
|
commit, the fork has nothing the firmware compiles. The fork's `feat/nisps-core-swap` branch remains
|
|
|
|
|
pushed, so nothing is destroyed.
|
|
|
|
|
|
|
|
|
|
This unblocks the PlatformIO migration (plan §5).
|