Stream 6: extract firmware glue under firmware/
Move the Arduino sketch into firmware/MEMLNaut-NISPS/ and bridge the
hardware (memllib) to the platform-agnostic nisps/ library through a
slim glue layer. Delete the legacy root-level *AudioApp.hpp,
modes/MEMLNautMode*.hpp, voicespaces/, IMLInterface.hpp, XiasriAnalysis,
and the src/memlp submodule.
Glue layout (firmware/MEMLNaut-NISPS/glue/):
audio_driver.hpp - bridge memllib block callback to Mode::process
via per-Mode templated trampoline (no virtual dispatch)
peripherals.hpp - joystick/pots/buttons -> Mode::set_input + ML primitives
midi_io.hpp - MIDI in -> mode.note_on/update_bpm/set_playing,
drains mode ControlEvent ring -> MIDI UART
mode_select.hpp - using-aliases mapping MEMLNautMode<Name> to
nisps::modes::*Mode (build script rewrites the
#define MEMLNAUT_MODE_TYPE line)
input_router.hpp / output_router.hpp - top-level wire/drain entry points
The sketch tree uses src/{memllib,daisysp,nisps} symlinks because
Arduino-CLI rejects ".." in include paths from sketch-tree headers.
mode_select.hpp #undefs Arduino's sq/min/max/abs/round macros before
including nisps headers (some nisps engines use those identifiers as
method names). The audio bridge struct is extern in the header and
defined in the .ino because inline + __not_in_flash section attribute
collide at link time.
Verification: arduino-cli compile succeeds for PAFSynth, ChannelStrip,
and BreakOr (rp2040:rp2040:solderparty_rp2350_stamp_xl:opt=Optimize3,
-std=gnu++20). Host C++ tests under nisps/build still pass (3 binaries,
110+ tests). Build script (scripts/build-firmware.sh) updated to point
at the new sketch path; mode-rewrite logic unchanged.
Closes meml-gkm.
2026-04-29 16:05:38 +02:00
|
|
|
// firmware/glue/mode_select.hpp — Compile-time mode selection.
|
|
|
|
|
//
|
|
|
|
|
// The active firmware mode is chosen at compile time via `MEMLNAUT_MODE_TYPE`
|
|
|
|
|
// (the .ino's master macro). The macro expands to one of the canonical mode
|
|
|
|
|
// type aliases below; build scripts rewrite the active line.
|
|
|
|
|
//
|
|
|
|
|
// Each alias maps a short human-readable name (`MEMLNautModePAFSynth`) to a
|
|
|
|
|
// concrete `nisps::modes::*Mode` C++ type. The legacy
|
|
|
|
|
// `modes/MEMLNautMode*.hpp` wrappers are gone; the same identifier now refers
|
|
|
|
|
// to the new platform-agnostic mode type.
|
|
|
|
|
//
|
|
|
|
|
// This indirection (via using-aliases) lets the build script's mode-rewrite
|
|
|
|
|
// logic stay near-identical: it still sees lines of the form
|
|
|
|
|
// #define MEMLNAUT_MODE_TYPE MEMLNautModePAFSynth
|
|
|
|
|
// and rewrites between alternatives.
|
|
|
|
|
|
|
|
|
|
#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 "../src/nisps/modes/breakor.hpp"
|
|
|
|
|
#include "../src/nisps/modes/channel_strip.hpp"
|
|
|
|
|
#include "../src/nisps/modes/elysiamorf.hpp"
|
feat(firmware): ExternalSynthMIDIMode + 6 device variants
Joystick -> MLP -> MIDI CC for an external hardware synth, using the
compile-time device templates from nisps/midi/generated. ExternalSynthMIDIMode
<const MidiDevice&, NOut> mirrors SoundAnalysisMIDIMode (NoOpEngine,
kRouteOutputsToEngine=false, pushes ControlChange events). A consteval
pick_cc_slots curates which NOut params fill the output slots (prefers musical
params over Bank Select/global). Adds six flashable variants
(MEMLNautModeExtSynth{Sub37,SubPhatty,Pro12,AnalogKeys,Hydrasynth,JD800}) wired
into mode_select.hpp + the .ino variant list + NISPS_ST guards, and a src/nisps/
midi symlink so the sketch tree can reach nisps/midi.
Host-compile-verified under C++20 (incl. via the sketch include path) and
lint-clean; full arduino-cli build + flash is on the hardware (no toolchain here.
2026-06-28 20:13:08 +02:00
|
|
|
#include "../src/nisps/modes/external_synth_midi.hpp"
|
Stream 6: extract firmware glue under firmware/
Move the Arduino sketch into firmware/MEMLNaut-NISPS/ and bridge the
hardware (memllib) to the platform-agnostic nisps/ library through a
slim glue layer. Delete the legacy root-level *AudioApp.hpp,
modes/MEMLNautMode*.hpp, voicespaces/, IMLInterface.hpp, XiasriAnalysis,
and the src/memlp submodule.
Glue layout (firmware/MEMLNaut-NISPS/glue/):
audio_driver.hpp - bridge memllib block callback to Mode::process
via per-Mode templated trampoline (no virtual dispatch)
peripherals.hpp - joystick/pots/buttons -> Mode::set_input + ML primitives
midi_io.hpp - MIDI in -> mode.note_on/update_bpm/set_playing,
drains mode ControlEvent ring -> MIDI UART
mode_select.hpp - using-aliases mapping MEMLNautMode<Name> to
nisps::modes::*Mode (build script rewrites the
#define MEMLNAUT_MODE_TYPE line)
input_router.hpp / output_router.hpp - top-level wire/drain entry points
The sketch tree uses src/{memllib,daisysp,nisps} symlinks because
Arduino-CLI rejects ".." in include paths from sketch-tree headers.
mode_select.hpp #undefs Arduino's sq/min/max/abs/round macros before
including nisps headers (some nisps engines use those identifiers as
method names). The audio bridge struct is extern in the header and
defined in the .ino because inline + __not_in_flash section attribute
collide at link time.
Verification: arduino-cli compile succeeds for PAFSynth, ChannelStrip,
and BreakOr (rp2040:rp2040:solderparty_rp2350_stamp_xl:opt=Optimize3,
-std=gnu++20). Host C++ tests under nisps/build still pass (3 binaries,
110+ tests). Build script (scripts/build-firmware.sh) updated to point
at the new sketch path; mode-rewrite logic unchanged.
Closes meml-gkm.
2026-04-29 16:05:38 +02:00
|
|
|
#include "../src/nisps/modes/memlcelium.hpp"
|
|
|
|
|
#include "../src/nisps/modes/paf_synth.hpp"
|
|
|
|
|
#include "../src/nisps/modes/sound_analysis_midi.hpp"
|
|
|
|
|
#include "../src/nisps/modes/verb_fx.hpp"
|
|
|
|
|
#include "../src/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;
|
2026-06-28 04:14:30 +02:00
|
|
|
|
feat(firmware): ExternalSynthMIDIMode + 6 device variants
Joystick -> MLP -> MIDI CC for an external hardware synth, using the
compile-time device templates from nisps/midi/generated. ExternalSynthMIDIMode
<const MidiDevice&, NOut> mirrors SoundAnalysisMIDIMode (NoOpEngine,
kRouteOutputsToEngine=false, pushes ControlChange events). A consteval
pick_cc_slots curates which NOut params fill the output slots (prefers musical
params over Bank Select/global). Adds six flashable variants
(MEMLNautModeExtSynth{Sub37,SubPhatty,Pro12,AnalogKeys,Hydrasynth,JD800}) wired
into mode_select.hpp + the .ino variant list + NISPS_ST guards, and a src/nisps/
midi symlink so the sketch tree can reach nisps/midi.
Host-compile-verified under C++20 (incl. via the sketch include path) and
lint-clean; full arduino-cli build + flash is on the hardware (no toolchain here.
2026-06-28 20:13:08 +02:00
|
|
|
// ---- 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>;
|
|
|
|
|
|
2026-06-28 04:14:30 +02:00
|
|
|
// ---- SelfTest pseudo-variant ----
|
|
|
|
|
// A standalone guided hardware self-test (see glue/selftest.hpp). It is NOT a
|
|
|
|
|
// nisps Mode — it drives the display + raw peripherals directly. We expose a
|
|
|
|
|
// tiny tag type so the `MEMLNautModeSelfTest` alias type-checks and the build
|
|
|
|
|
// script's `MEMLNautMode*` grep discovers the variant; the .ino forks on
|
|
|
|
|
// `NISPS_SELFTEST` and never instantiates this tag.
|
|
|
|
|
namespace nisps_firmware { namespace selftest { struct SelfTestRig {}; } }
|
|
|
|
|
using MEMLNautModeSelfTest = ::nisps_firmware::selftest::SelfTestRig;
|
|
|
|
|
|
|
|
|
|
// Compile-time guard: NISPS_SELFTEST expands to 1 iff MEMLNAUT_MODE_TYPE is
|
|
|
|
|
// MEMLNautModeSelfTest, else 0. Computed in the .ino *after* the mode #define.
|
|
|
|
|
// Two-level CAT so MEMLNAUT_MODE_TYPE expands before the paste.
|
|
|
|
|
#define NISPS_ST_MEMLNautModePAFSynth 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeChannelStrip 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeXIASRI 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeSoundAnalysisMIDI 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeBreakOr 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeVerbFX 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeElysiamorfs 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeMEMLCelium 0
|
feat(firmware): ExternalSynthMIDIMode + 6 device variants
Joystick -> MLP -> MIDI CC for an external hardware synth, using the
compile-time device templates from nisps/midi/generated. ExternalSynthMIDIMode
<const MidiDevice&, NOut> mirrors SoundAnalysisMIDIMode (NoOpEngine,
kRouteOutputsToEngine=false, pushes ControlChange events). A consteval
pick_cc_slots curates which NOut params fill the output slots (prefers musical
params over Bank Select/global). Adds six flashable variants
(MEMLNautModeExtSynth{Sub37,SubPhatty,Pro12,AnalogKeys,Hydrasynth,JD800}) wired
into mode_select.hpp + the .ino variant list + NISPS_ST guards, and a src/nisps/
midi symlink so the sketch tree can reach nisps/midi.
Host-compile-verified under C++20 (incl. via the sketch include path) and
lint-clean; full arduino-cli build + flash is on the hardware (no toolchain here.
2026-06-28 20:13:08 +02:00
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthSub37 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthSubPhatty 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthPro12 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthAnalogKeys 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthHydrasynth 0
|
|
|
|
|
#define NISPS_ST_MEMLNautModeExtSynthJD800 0
|
2026-06-28 04:14:30 +02:00
|
|
|
#define NISPS_ST_MEMLNautModeSelfTest 1
|
|
|
|
|
#define NISPS_ST_CAT_(x) NISPS_ST_##x
|
|
|
|
|
#define NISPS_ST_CAT(x) NISPS_ST_CAT_(x)
|