memlnaut-nisps/MEMLNaut-NISPS.ino

238 lines
5.7 KiB
Arduino
Raw Normal View History

2025-11-19 16:17:37 +01:00
//hardware
#include "src/memllib/utils/perf.hpp"
#include "src/memllib/interface/MIDIInOut.hpp"
#include "src/memllib/audio/AudioDriver.hpp"
#include "src/memllib/hardware/memlnaut/MEMLNaut.hpp"
#include "hardware/structs/bus_ctrl.h"
#include <memory>
//sound
#include "src/memllib/audio/AudioAppBase.hpp"
#include "PAFSynthAudioApp.hpp"
#include "ChannelStripAudioApp.hpp"
//interface
2025-11-23 16:48:14 +01:00
#include "src/memllib/hardware/memlnaut/display/XYPadView.hpp"
2025-11-19 16:17:37 +01:00
#include "src/memllib/hardware/memlnaut/display/MessageView.hpp"
#include "src/memllib/hardware/memlnaut/display/VoiceSpaceSelectView.hpp"
2025-11-23 16:48:14 +01:00
//modes
#include "modes/MEMLNautMode.hpp"
#include "modes/MEMLNautModePAFSynth.hpp"
#include "modes/MEMLNautModeChannelStrip.hpp"
#include "modes/MEMLNautModeSoundAnalysisMIDI.hpp"
2025-11-28 15:59:36 +01:00
#include "modes/MEMLNautModeXIASRI.hpp"
2026-02-22 12:39:27 +01:00
#include "modes/MEMLNautModeBreakOr.hpp"
2026-03-03 12:53:50 +01:00
#include "modes/MEMLNautModeVerbFX.hpp"
2025-11-19 16:17:37 +01:00
2025-11-28 15:59:36 +01:00
//hook up the memlnaut mode
2025-11-19 16:17:37 +01:00
2025-11-28 15:59:36 +01:00
// #define MEMLNAUT_MODE_TYPE MEMLNautModeSoundAnalysisMIDI
2026-02-22 12:39:27 +01:00
// #define MEMLNAUT_MODE_TYPE MEMLNautModeXIASRI
2026-03-03 12:53:50 +01:00
// #define MEMLNAUT_MODE_TYPE MEMLNautModeVerbFX
2026-02-22 12:39:27 +01:00
#define MEMLNAUT_MODE_TYPE MEMLNautModeBreakOr
2026-02-07 11:36:26 +01:00
// #define MEMLNAUT_MODE_TYPE MEMLNautModeChannelStrip
// #define MEMLNAUT_MODE_TYPE MEMLNautModePAFSynth
2025-11-19 16:17:37 +01:00
2025-11-28 15:59:36 +01:00
MEMLNAUT_MODE_TYPE AUDIO_MEM MEMLNautModeHub;
MEMLNautMode auto* AUDIO_MEM currentMode = &MEMLNautModeHub;
2025-11-19 16:17:37 +01:00
#define APP_SRAM __not_in_flash("app")
bool core1_separate_stack = true;
uint32_t get_rosc_entropy_seed(int bits) {
uint32_t seed = 0;
for (int i = 0; i < bits; ++i) {
// Wait for a bit of time to allow jitter to accumulate
busy_wait_us_32(5);
// Pull LSB from ROSC rand output
seed <<= 1;
seed |= (rosc_hw->randombit & 1);
}
return seed;
}
// Global objects
std::shared_ptr<MIDIInOut> APP_SRAM midi_interf;
// Inter-core communication
volatile bool APP_SRAM core_0_ready = false;
volatile bool APP_SRAM core_1_ready = false;
volatile bool APP_SRAM serial_ready = false;
volatile bool APP_SRAM interface_ready = false;
// Add these macros near other globals
#define MEMORY_BARRIER() __sync_synchronize()
#define WRITE_VOLATILE(var, val) \
do { \
MEMORY_BARRIER(); \
(var) = (val); \
MEMORY_BARRIER(); \
} while (0)
#define READ_VOLATILE(var) ({ MEMORY_BARRIER(); typeof(var) __temp = (var); MEMORY_BARRIER(); __temp; })
void setup() {
set_sys_clock_khz(AudioDriver::GetSysClockSpeed(), true);
bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS | BUSCTRL_BUS_PRIORITY_PROC1_BITS;
uint32_t seed = get_rosc_entropy_seed(32);
srand(seed);
2026-02-07 11:36:26 +01:00
midi_interf = std::make_shared<MIDIInOut>();
// Serial.println("MIDI setup complete.");
2025-11-19 16:17:37 +01:00
Serial.begin(115200);
// while (!Serial) {}
Serial.println("Serial initialised.");
WRITE_VOLATILE(serial_ready, true);
// Setup board
MEMLNaut::Initialize();
pinMode(33, OUTPUT);
2025-11-24 12:29:33 +01:00
currentMode->setupInterface();
2025-11-28 15:59:36 +01:00
2025-11-19 16:17:37 +01:00
// Setup interface with memory barrier protection
WRITE_VOLATILE(interface_ready, true);
Serial.println("Bound interface to MEMLNaut.");
WRITE_VOLATILE(core_0_ready, true);
while (!READ_VOLATILE(core_1_ready)) {
MEMORY_BARRIER();
delay(1);
}
currentMode->addViews();
std::shared_ptr<MessageView> helpView = std::make_shared<MessageView>("Help");
2025-11-23 16:48:14 +01:00
String title = currentMode->getHelpTitle();
2025-11-19 16:17:37 +01:00
helpView->post(title);
helpView->post("TA: Down: Clear replay memory");
helpView->post("MA: Up: Randomise / Down: Jolt ");
helpView->post("MB: Up: Positive reward");
helpView->post("MB: Down: Negative reward");
helpView->post("X: Learning rate");
helpView->post("Y: Reward Scale");
helpView->post("Z: Exploration noise");
helpView->post("Joystick: Explore / SW: Drag sound");
MEMLNaut::Instance()->disp->AddView(helpView);
MEMLNaut::Instance()->addSystemInfoView();
Serial.println("Finished initialising core 0.");
}
PERF_DECLARE(MLSTATS);
#define ML_INFERENCE_PERIOD_US 5000
void loop() {
PERIODIC_RUN_US(
PERF_BEGIN(MLSTATS);
2025-11-24 12:29:33 +01:00
currentMode->processAnalysisParams();
2025-11-19 16:17:37 +01:00
MEMLNaut::Instance()->loop();
PERF_END(MLSTATS);
, ML_INFERENCE_PERIOD_US)
2025-11-23 16:48:14 +01:00
//show profiling stats
2025-11-19 16:17:37 +01:00
PERIODIC_RUN_US(
2025-11-23 16:48:14 +01:00
static size_t blip_counter = 0;
2025-11-19 16:17:37 +01:00
if (blip_counter++ > 10) {
blip_counter = 0;
Serial.println(".");
// Blink LED
digitalWrite(33, HIGH);
constexpr float audioHeadroomMul = 1.0 / (1000000 * 48.0 / kSampleRate);
Serial.printf("ml: %d, aud: %d, q: %f\n", PERF_GET_MEAN(MLSTATS), AUDIOLOOP_MEAN, AUDIOLOOP_MEAN * audioHeadroomMul);
} else {
// Un-blink LED
digitalWrite(33, LOW);
2025-11-23 16:48:14 +01:00
},
100000)
2026-03-05 23:25:21 +01:00
currentMode->loopCore0();
2025-11-19 16:17:37 +01:00
}
void AUDIO_FUNC(audio_block_callback)(float in[][kBufferSize], float out[][kBufferSize], size_t n_channels, size_t n_frames) {
for (size_t i = 0; i < n_frames; ++i) {
stereosample_t x{
in[0][i],
in[1][i]
},
y;
y = currentMode->process(x);
out[0][i] = y.L;
out[1][i] = y.R;
2025-11-24 12:29:33 +01:00
// PERIODIC_RUN(
// Serial.printf("x: %f\n", x.L + x.R);
// , 100);
2025-11-23 16:48:14 +01:00
currentMode->analyse(x);
}
2025-11-19 16:17:37 +01:00
}
void setup1() {
while (!READ_VOLATILE(serial_ready)) {
MEMORY_BARRIER();
delay(1);
}
while (!READ_VOLATILE(interface_ready)) {
MEMORY_BARRIER();
delay(1);
}
2026-02-22 13:41:09 +01:00
if (midi_interf) {
currentMode->setupMIDI(midi_interf);
}
2025-11-19 16:17:37 +01:00
2025-11-24 12:29:33 +01:00
currentMode->setupAudio(AudioDriver::GetSampleRate());
2025-11-19 16:17:37 +01:00
AudioDriver::SetBlockCallback(audio_block_callback);
2025-11-24 12:29:33 +01:00
2025-11-19 16:17:37 +01:00
// Start audio driver
AudioDriver::Setup();
WRITE_VOLATILE(core_1_ready, true);
while (!READ_VOLATILE(core_0_ready)) {
MEMORY_BARRIER();
delay(1);
}
Serial.println("Finished initialising core 1.");
}
void loop1() {
// Audio app parameter processing loop
PERIODIC_RUN_US(
currentMode->loop();
, ML_INFERENCE_PERIOD_US)
2025-11-23 16:48:14 +01:00
2025-11-19 16:17:37 +01:00
PERIODIC_RUN_US(
midi_interf->Poll();
2026-03-05 23:25:21 +01:00
, 1000)
2025-11-19 16:17:37 +01:00
}