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.
77 lines
3.8 KiB
C++
77 lines
3.8 KiB
C++
// firmware/glue/mode_select.hpp — Compile-time mode selection.
|
|
//
|
|
// The active firmware mode is chosen at compile time via `MEMLNAUT_MODE_TYPE`,
|
|
// defined per-variant as a PlatformIO build flag (one `[env:...]` per variant
|
|
// in platformio.ini, e.g. `-DMEMLNAUT_MODE_TYPE=MEMLNautModePAFSynth`) — there
|
|
// is no in-source registry and no build-time file rewriting.
|
|
//
|
|
// Each alias maps a short human-readable name (`MEMLNautModePAFSynth`) to a
|
|
// concrete `nisps::modes::*Mode` C++ type.
|
|
|
|
#pragma once
|
|
|
|
// Arduino's Common.h defines `sq(x)`, `min(a,b)`, `max(a,b)`, `abs(x)`,
|
|
// `round(x)` etc. as preprocessor macros. nisps/ uses some of these as
|
|
// regular function/method names (e.g. nisps::AnalysisEngine::sq()). Undef
|
|
// the Arduino macros locally before pulling in nisps headers; downstream
|
|
// firmware code that wants Arduino's macro behaviour can re-include
|
|
// Arduino.h after this point.
|
|
#ifdef sq
|
|
# undef sq
|
|
#endif
|
|
#ifdef min
|
|
# undef min
|
|
#endif
|
|
#ifdef max
|
|
# undef max
|
|
#endif
|
|
#ifdef abs
|
|
# undef abs
|
|
#endif
|
|
#ifdef round
|
|
# undef round
|
|
#endif
|
|
|
|
#include "nisps/modes/breakor.hpp"
|
|
#include "nisps/modes/channel_strip.hpp"
|
|
#include "nisps/modes/elysiamorf.hpp"
|
|
#include "nisps/modes/external_synth_midi.hpp"
|
|
#include "nisps/modes/memlcelium.hpp"
|
|
#include "nisps/modes/paf_synth.hpp"
|
|
#include "nisps/modes/slp_workshop.hpp"
|
|
#include "nisps/modes/sound_analysis_midi.hpp"
|
|
#include "nisps/modes/verb_fx.hpp"
|
|
#include "nisps/modes/xiasri.hpp"
|
|
|
|
// ---- Public name → nisps type aliases ----
|
|
// Build script greps for `MEMLNautMode*` lines, so we keep the prefix.
|
|
using MEMLNautModePAFSynth = ::nisps::modes::PAFSynthMode;
|
|
using MEMLNautModeChannelStrip = ::nisps::modes::ChannelStripMode;
|
|
using MEMLNautModeXIASRI = ::nisps::modes::XIASRIMode;
|
|
using MEMLNautModeSoundAnalysisMIDI = ::nisps::modes::SoundAnalysisMIDIMode;
|
|
using MEMLNautModeBreakOr = ::nisps::modes::BreakOrMode;
|
|
using MEMLNautModeVerbFX = ::nisps::modes::VerbFXMode;
|
|
using MEMLNautModeElysiamorfs = ::nisps::modes::ElysiamorfMode;
|
|
using MEMLNautModeMEMLCelium = ::nisps::modes::MEMLCeliumMode;
|
|
// SLP-Workshop: the Synth Library Portland workshop build. Reuses the
|
|
// MEMLCelium engine; foregrounds the Jolt (TogB1) + OU-explore (RVX1)
|
|
// adaptive-learning gestures wired in peripherals.hpp.
|
|
using MEMLNautModeSLPWorkshop = ::nisps::modes::SLPWorkshopMode;
|
|
|
|
// ---- External-synth MIDI-CC variants (one flashable variant per device) ----
|
|
// Joystick -> MLP -> MIDI CC for the named external hardware synth. Device
|
|
// templates live in nisps/midi/generated/midi_devices.hpp (source of truth:
|
|
// schemas/midi_devices/). Each drives a curated 8-param subset (pick_cc_slots).
|
|
using MEMLNautModeExtSynthSub37 = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kMoogSub37, 8u>;
|
|
using MEMLNautModeExtSynthSubPhatty = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kMoogSubPhatty, 8u>;
|
|
using MEMLNautModeExtSynthPro12 = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kCreamwarePro12Asb, 8u>;
|
|
using MEMLNautModeExtSynthAnalogKeys = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kElektronAnalogKeys, 8u>;
|
|
using MEMLNautModeExtSynthHydrasynth = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kAsmHydrasynth, 8u>;
|
|
using MEMLNautModeExtSynthJD800 = ::nisps::modes::ExternalSynthMIDIMode<::nisps::midi::generated::kRolandJd800, 8u>;
|
|
|
|
// ---- SelfTest ----
|
|
// The guided hardware self-test (see glue/selftest.hpp) is NOT a nisps Mode —
|
|
// it drives the display + raw peripherals directly and is selected by its own
|
|
// `selftest` PlatformIO env, which defines `NISPS_SELFTEST=1` and leaves
|
|
// `MEMLNAUT_MODE_TYPE` undefined (src/main.cpp's `#if !NISPS_SELFTEST` fork
|
|
// never instantiates `ActiveMode` in that env, so no alias is needed here).
|