i2c refactor and speed up

This commit is contained in:
chriskiefer 2026-03-05 22:25:21 +00:00
parent 3ddbcdfed9
commit 9906cbd154
10 changed files with 67 additions and 33 deletions

View file

@ -164,6 +164,8 @@ void loop() {
digitalWrite(33, LOW); digitalWrite(33, LOW);
}, },
100000) 100000)
currentMode->loopCore0();
} }
@ -231,5 +233,5 @@ void loop1() {
PERIODIC_RUN_US( PERIODIC_RUN_US(
midi_interf->Poll(); midi_interf->Poll();
, 10000) , 1000)
} }

View file

@ -12,6 +12,7 @@
#include "../../src/memllib/interface/InterfaceBase.hpp" #include "../../src/memllib/interface/InterfaceBase.hpp"
#include <span> #include <span>
#include "../../voicespaces/VoiceSpaces.hpp" #include "../../voicespaces/VoiceSpaces.hpp"
@ -59,7 +60,7 @@ inline bool __not_in_flash_func(ratioSeq)(float phasor, float phaseOffset, float
} }
template<size_t NPARAMS=70, size_t NSEQUENCES=10> template<size_t NPARAMS=56, size_t NSEQUENCES=8>
class BreakOrAudioApp : public AudioAppBase<NPARAMS> class BreakOrAudioApp : public AudioAppBase<NPARAMS>
{ {
public: public:
@ -68,6 +69,8 @@ public:
queue_t bpmQueue; queue_t bpmQueue;
queue_t sequencerControlQueue; queue_t sequencerControlQueue;
queue_t i2cOutQueue;
bool sequencerPlaying = false; bool sequencerPlaying = false;
@ -95,6 +98,7 @@ public:
// currentVoiceSpace = voiceSpaces[0].mappingFunction; // currentVoiceSpace = voiceSpaces[0].mappingFunction;
queue_init(&bpmQueue, sizeof(float), 1); queue_init(&bpmQueue, sizeof(float), 1);
queue_init(&sequencerControlQueue, sizeof(int), 1); queue_init(&sequencerControlQueue, sizeof(int), 1);
queue_init(&i2cOutQueue, sizeof(float) * 8, 1);
}; };
bool __force_inline euclidean(float phase, const size_t n, const size_t k, const size_t offset, const float pulseWidth) bool __force_inline euclidean(float phase, const size_t n, const size_t k, const size_t offset, const float pulseWidth)
@ -121,14 +125,19 @@ public:
midiIO->flushQueue(); midiIO->flushQueue();
} }
if (sequencingSampleCounter==0) { if (sequencingSampleCounter==0) {
barPhasor += barPhasorInc;
if (barPhasor >= 1.f) {
barPhasor -= 1.f;
}
int i2cIdx=0;
for(auto &seq: ratioSeqStates) { for(auto &seq: ratioSeqStates) {
//update phasor //update phasor
seq.phasor += (seq.phasorInc * seq.phasorMul); float seqPhasor = barPhasor * seq.phasorMul;
if (seq.phasor >= 1.f) { seqPhasor = fmodf(seqPhasor + seq.phaseOffset, 1.f); // Wrap phasor to [0,1]
seq.phasor -= 1.f;
} bool trig = ratioSeq<3>(seqPhasor, seq.phaseOffset, seq.ratioSum, seq.ratios, seq.pulseWidth);
bool trig = ratioSeq<3>(seq.phasor, seq.phaseOffset, seq.ratioSum, seq.ratios, seq.pulseWidth); bool highAmp = ratioSeq<2>(seqPhasor, seq.phaseOffset, seq.ampRatioSum, seq.ampRatios, 0.5f);
bool highAmp = ratioSeq<2>(seq.phasor, seq.phaseOffset, seq.ampRatioSum, seq.ampRatios, 0.5f);
if (trig && !seq.lastTrig) { if (trig && !seq.lastTrig) {
if (trig) { if (trig) {
midiIO->queueNoteOn(seq.midiNote, highAmp ? 127 : 64); midiIO->queueNoteOn(seq.midiNote, highAmp ? 127 : 64);
@ -137,8 +146,10 @@ public:
} }
} }
seq.lastTrig = trig; seq.lastTrig = trig;
i2cValues[i2cIdx++] = trig;
} }
midiIO->flushQueue(); midiIO->flushQueue();
queue_try_add(&i2cOutQueue, &i2cValues);
} }
sequencingSampleCounter ++; sequencingSampleCounter ++;
@ -158,7 +169,7 @@ public:
maxiSettings::sampleRate = sample_rate; maxiSettings::sampleRate = sample_rate;
sampleRatef = static_cast<float>(sample_rate); sampleRatef = static_cast<float>(sample_rate);
updateBPM(90.f); updateBPM(90.f);
const size_t midiNotes[NSEQUENCES] = {36,37,38,39,40, 42,43,45,47,48}; const size_t midiNotes[NSEQUENCES] = {36,37,38,39,40, 42,43,45/*,47,48*/};
size_t midiNote = 0; size_t midiNote = 0;
for(auto &seq: ratioSeqStates) { for(auto &seq: ratioSeqStates) {
seq.midiNote = midiNotes[midiNote++]; seq.midiNote = midiNotes[midiNote++];
@ -174,7 +185,9 @@ public:
} }
void ProcessParams(const std::array<float, NPARAMS>& params) void ProcessParams(const std::array<float, NPARAMS>& params)
{ {
// if (sequencerPlaying) {
// }
firstParamsReceived = true; firstParamsReceived = true;
if (queue_try_remove(&bpmQueue, &bpm)) { if (queue_try_remove(&bpmQueue, &bpm)) {
bpm = 30.f + (bpm * 200.f); // Scale BPM from [0,1] to [30,230] bpm = 30.f + (bpm * 200.f); // Scale BPM from [0,1] to [30,230]
@ -198,6 +211,7 @@ public:
midiIO->queueClockStart(); midiIO->queueClockStart();
midiIO->flushQueue(); midiIO->flushQueue();
} }
Serial.printf("Sequencer %s\n", sequencerPlaying ? "Playing" : "Stopped");
} }
// currentVoiceSpace(params); // currentVoiceSpace(params);
size_t paramIdx = 0; size_t paramIdx = 0;
@ -210,7 +224,7 @@ public:
v.ratioSum = sum; v.ratioSum = sum;
// static float muls[7] = {0.25f, 0.33f, 0.5f, 1.f, 1.5f, 2.f, 3.f}; // static float muls[7] = {0.25f, 0.33f, 0.5f, 1.f, 1.5f, 2.f, 3.f};
// v.phasorMul = muls[(int)(params[paramIdx++] * 6.999999f)]; // v.phasorMul = muls[(int)(params[paramIdx++] * 6.999999f)];
static float muls[4] = {0.5f, 1.f, 2.f, 4.f}; static float muls[4] = {1.f, 2.f, 4.f, 8.f};
v.phasorMul = muls[(int)(params[paramIdx++] * 3.999999f)]; v.phasorMul = muls[(int)(params[paramIdx++] * 3.999999f)];
v.phaseOffset = ((int)(params[paramIdx++] * timeSigBeats)) * timeSigBeatsInv; v.phaseOffset = ((int)(params[paramIdx++] * timeSigBeats)) * timeSigBeatsInv;
@ -230,10 +244,10 @@ public:
float beatLengthInSeconds = 60.f / bpm; float beatLengthInSeconds = 60.f / bpm;
float barLengthInSeconds = beatLengthInSeconds * timeSigBeats; float barLengthInSeconds = beatLengthInSeconds * timeSigBeats;
float barLengthInSamples = barLengthInSeconds * (sampleRatef/ sequencingSampleDiv); float barLengthInSamples = barLengthInSeconds * (sampleRatef/ sequencingSampleDiv);
float barPhasorInc = 1.f/ barLengthInSamples; barPhasorInc = 1.f/ barLengthInSamples;
for(auto &v: ratioSeqStates) { // for(auto &v: ratioSeqStates) {
v.phasorInc = barPhasorInc; // v.phasorInc = barPhasorInc;
} // }
float midiClockLengthInSeconds = beatLengthInSeconds / 24.f; float midiClockLengthInSeconds = beatLengthInSeconds / 24.f;
float midiClockLengthInSamples = midiClockLengthInSeconds * sampleRatef; float midiClockLengthInSamples = midiClockLengthInSeconds * sampleRatef;
midiClockPhasorInc = 1.f / midiClockLengthInSamples; midiClockPhasorInc = 1.f / midiClockLengthInSamples;
@ -249,6 +263,8 @@ public:
protected: protected:
float i2cValues[8] = {0,0,0,0,0,0,0,0};
float sampleRatef; float sampleRatef;
bool firstParamsReceived = false; bool firstParamsReceived = false;
@ -256,8 +272,11 @@ protected:
float timeSigBeats=4.f; float timeSigBeats=4.f;
float timeSigBeatsInv=1.f/timeSigBeats; float timeSigBeatsInv=1.f/timeSigBeats;
float timeSigDivision=4.f; float timeSigDivision=4.f;
float barPhasorInc=0.f;
float barPhasor;
size_t sequencingSampleDiv = 50; size_t sequencingSampleDiv = 400;
size_t sequencingSampleCounter = 0; size_t sequencingSampleCounter = 0;
std::array<ratioSeqState, NSEQUENCES> ratioSeqStates; std::array<ratioSeqState, NSEQUENCES> ratioSeqStates;

View file

@ -23,5 +23,6 @@ concept MEMLNautMode = requires(T proc) {
{proc.processAnalysisParams()} -> std::same_as<void>; {proc.processAnalysisParams()} -> std::same_as<void>;
// {proc.getNMIDICtrlOutputs()} -> std::same_as<size_t>; // {proc.getNMIDICtrlOutputs()} -> std::same_as<size_t>;
{proc.setupInterface()} -> std::same_as<void>; {proc.setupInterface()} -> std::same_as<void>;
{proc.loopCore0()} -> std::same_as<void>;
requires std::same_as<decltype(T::kN_InputParams), const size_t>; requires std::same_as<decltype(T::kN_InputParams), const size_t>;
}; };

View file

@ -11,11 +11,14 @@
#include "MEMLNautMode.hpp" #include "MEMLNautMode.hpp"
#include <memory> #include <memory>
#include <array> #include <array>
#include "../src/memllib/interface/USeqI2C.hpp"
class MEMLNautModeBreakOr { class MEMLNautModeBreakOr {
public: public:
constexpr static size_t kN_InputParams = 4; // joystick x, y, rotate constexpr static size_t kN_InputParams = 4; // joystick x, y, rotate
USeqI2C i2cOut;
inline static BreakOrAudioApp<> audioAppBreakOr; inline static BreakOrAudioApp<> audioAppBreakOr;
std::array<String, BreakOrAudioApp<>::nVoiceSpaces> voiceSpaceList; std::array<String, BreakOrAudioApp<>::nVoiceSpaces> voiceSpaceList;
@ -24,6 +27,8 @@ public:
bool sequencerPlaying = false; bool sequencerPlaying = false;
void setupInterface() { void setupInterface() {
interface.setup(kN_InputParams, BreakOrAudioApp<>::kN_Params); interface.setup(kN_InputParams, BreakOrAudioApp<>::kN_Params);
interface.bindInterface(InterfaceRL::INPUT_MODES::JOYSTICK, true); interface.bindInterface(InterfaceRL::INPUT_MODES::JOYSTICK, true);
@ -36,22 +41,9 @@ public:
queue_try_add(&audioAppBreakOr.sequencerControlQueue, &sequencerPlaying); queue_try_add(&audioAppBreakOr.sequencerControlQueue, &sequencerPlaying);
} }
// //tiggle up
// if (state) {
// //store output
// savedAction = action;
// actionBeingDragged=true;
// msgView->post("Where do you want it?");
// }else{
// //button up
// if (actionBeingDragged) {
// this->storeExperience(1.f, controlInput, savedAction);
// actionBeingDragged=false;
// msgView->post("Here!");
// }
// }
}); });
i2cOut.begin();
} }
String getHelpTitle() { String getHelpTitle() {
@ -105,6 +97,17 @@ public:
void analyse(stereosample_t) {} void analyse(stereosample_t) {}
float i2cValues[8];
void loopCore0() {
PERIODIC_RUN_US(
if (queue_try_remove(&audioAppBreakOr.i2cOutQueue, &i2cValues)) {
// Serial.printf("i2c received: %f %f %f %f %f %f %f %f\n", i2cValues[0], i2cValues[1], i2cValues[2], i2cValues[3], i2cValues[4], i2cValues[5], i2cValues[6], i2cValues[7]);
bool i2cSuccess = i2cOut.sendValues(i2cValues, 8);
}
, 5000)
}
}; };

View file

@ -105,5 +105,6 @@ public:
void analyse(stereosample_t) {} void analyse(stereosample_t) {}
void loopCore0() {}
}; };

View file

@ -115,4 +115,6 @@ public:
void analyse(stereosample_t) {} void analyse(stereosample_t) {}
void loopCore0() {}
}; };

View file

@ -85,4 +85,6 @@ public:
} }
void loopCore0() {}
}; };

View file

@ -15,7 +15,7 @@
class MEMLNautModeVerbFX { class MEMLNautModeVerbFX {
public: public:
constexpr static size_t kN_InputParams = XiasriAnalysis::kN_Params; //ML constexpr static size_t kN_InputParams = XiasriAnalysis::kN_Params +4; //ML + joystick
InterfaceRL interface; InterfaceRL interface;
std::shared_ptr<InterfaceRL> interfacePtr; std::shared_ptr<InterfaceRL> interfacePtr;
XiasriAnalysis mlAnalysis{kSampleRate}; XiasriAnalysis mlAnalysis{kSampleRate};
@ -26,7 +26,7 @@ public:
void setupInterface() { void setupInterface() {
interface.setup(kN_InputParams, VerbFXAudioApp<>::kN_Params); interface.setup(kN_InputParams, VerbFXAudioApp<>::kN_Params);
interface.bindInterface(InterfaceRL::INPUT_MODES::MACHINE_LISTENING); interface.bindInterface(InterfaceRL::INPUT_MODES::JOYSTICK_AND_MACHINE_LISTENING);
interfacePtr = make_non_owning(interface); interfacePtr = make_non_owning(interface);
} }
@ -79,5 +79,7 @@ public:
// , 100); // , 100);
} }
void loopCore0() {}
}; };

View file

@ -80,4 +80,6 @@ public:
} }
void loopCore0() {}
}; };

@ -1 +1 @@
Subproject commit 1693e46e0b38c5920ebdf6cdf2a9107503003c8d Subproject commit 1e420bf8ed869d58df75663d3dbf6870aa543de1