From 00cdfc08e00662790dd94796eda238addbc3c235 Mon Sep 17 00:00:00 2001 From: Brian Hrebec Date: Wed, 30 Aug 2023 23:54:06 -0500 Subject: [PATCH] Added ICM, knob CCs --- NuEVI/src/globals.h | 3 ++ NuEVI/src/hardware.cpp | 14 ++++++ NuEVI/src/hardware.h | 6 +++ NuEVI/src/menu.cpp | 33 ++++++++----- NuEVI/src/menu.h | 1 + NuEVI/src/settings.h | 12 ++--- NuEVI/src/xEVI.cpp | 102 ++++++++++++++++++++++++++++++----------- 7 files changed, 125 insertions(+), 46 deletions(-) diff --git a/NuEVI/src/globals.h b/NuEVI/src/globals.h index 07fc732..c2a898c 100644 --- a/NuEVI/src/globals.h +++ b/NuEVI/src/globals.h @@ -104,6 +104,9 @@ struct instrument_state_t { byte leverVal = 0; // keep track and make sure we send CC with 0 value when off threshold int pitchBend = 8192; int pbSend = 8192; // Pitch bend actually sent, modified by vibrato, etc + byte knobVals[4]; + byte rollCCVal = 0; + byte tiltCCVal = 0; // Key states byte quarterToneTrigger; diff --git a/NuEVI/src/hardware.cpp b/NuEVI/src/hardware.cpp index e94a686..e69cf6c 100644 --- a/NuEVI/src/hardware.cpp +++ b/NuEVI/src/hardware.cpp @@ -44,6 +44,7 @@ void initHardware() { breathFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter breathAltFilter.setFilter(LOWPASS, FILTER_FREQ, 0.0); // create a one pole (RC) lowpass filter spikeFilter.setFilter(HIGHPASS, 200, 0.0); // create a one pole (RC) lowpass filter + icmSensor.begin_I2C(ICM20948_I2CADDR_DEFAULT, &MainI2CBus); ledStrip.begin(); @@ -168,4 +169,17 @@ int readPressure() { int readAltPressure() { return breathAltFilter.input(pressureSensorAlt.readPressure()) * PRESSURE_SENS_MULTIPLIER; +} + +icm_result_t readICM() { + sensors_event_t accel; + sensors_event_t gyro; + sensors_event_t mag; + sensors_event_t temp; + icmSensor.getEvent(&accel, &gyro, &temp, &mag); + + return { + mag.magnetic.y, + mag.magnetic.x, + }; } \ No newline at end of file diff --git a/NuEVI/src/hardware.h b/NuEVI/src/hardware.h index a168a36..7dad9ad 100644 --- a/NuEVI/src/hardware.h +++ b/NuEVI/src/hardware.h @@ -16,6 +16,11 @@ extern WS2812Serial ledStrip; extern Adafruit_Sensor *accelSensor; extern Adafruit_ICM20948 icmSensor; +struct icm_result_t { + float tilt; + float roll; +}; + void initHardware(); void updateFilters(preset_t &preset); bool checkButtonState(uint8_t mask); // return true if the given buttons are pressed @@ -28,6 +33,7 @@ uint16_t utilTouched(); int readPressure(); int readAltPressure(); int readSpikePressure(); +icm_result_t readICM(); // xEVI hardware setup diff --git a/NuEVI/src/menu.cpp b/NuEVI/src/menu.cpp index 82326ba..778511a 100644 --- a/NuEVI/src/menu.cpp +++ b/NuEVI/src/menu.cpp @@ -778,9 +778,7 @@ private: class StatusMenu : public MenuScreen { public: - StatusMenu(MenuScreen& mainMenu) : _mainMenu(mainMenu) { - Serial.println("init statusmenu"); - } + StatusMenu(MenuScreen& mainMenu) : _mainMenu(mainMenu) { } void update(state_t& state, InputState& input, bool redraw) { InputState nullinput; if (input.changed && input.btnMenu) { @@ -1005,13 +1003,14 @@ ChoiceMenu<4, PortamentoMode> portMenu("GLIDE MOD", &preset_t::portamentoMode, { }); PresetValueMenu<0, uint8_t> portLimitMenu("GLIDE LMT", &preset_t::portamentoLimit, 1, 127, true); PresetValueMenu<0, uint8_t> pitchBendMenu("PITCHBEND", &preset_t::PBdepth, 0, 12, true); -ChoiceMenu<4, ExtraControl> extraCtlMenu("EXT CTL", &preset_t::extraControl, { {OFF, VIBRATO, GLIDE, CC} }, { - "OFF", - "VIBRATO", - "GLIDE", - "CC" - }); +ChoiceMenu<4, ExtraControl> extraCtlMenu("EXT CTL", &preset_t::extraControl, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" }); PresetValueMenu<128, uint8_t> extraCCMenu("EXT CC", &preset_t::extraCC, 0, 127, true, CC_NAMES); +ChoiceMenu<4, ExtraControl> tiltModeMenu("TILT MODE", &preset_t::icmTiltMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" }); +PresetValueMenu<128, uint8_t> tiltCCMenu("TILT CC", &preset_t::icmTiltCC, 0, 127, true, CC_NAMES); +ChoiceMenu<4, ExtraControl> rollModeMenu("ROLL MODE", &preset_t::icmRollMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" }); +PresetValueMenu<128, uint8_t> rollCCMenu("ROLL CC", &preset_t::icmRollCC, 0, 127, true, CC_NAMES); +ChoiceMenu<4, ExtraControl> accelModeMenu("ACCEL MODE", &preset_t::icmAccelMode, { {OFF, VIBRATO, GLIDE, CC} }, { "OFF", "VIBRATO", "GLIDE", "CC" }); +PresetValueMenu<128, uint8_t> accelCCMenu("ACCEL CC", &preset_t::icmAccelCC, 0, 127, true, CC_NAMES); PresetValueMenu<1, uint8_t> deglitchMenu("DEGLITCH", &preset_t::deglitch, 0, 70, true, { "OFF" }, "ms"); PresetValueMenu<29, uint8_t> pinkyMenu("PINKY KEY", &preset_t::pinkySetting, 0, 29, true, { "-12", "-11", "-10", "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", @@ -1065,7 +1064,7 @@ std::array breathMenuEntries = { }; SubMenu<11> breathMenu("BR SETUP", breathMenuEntries); -const std::array controlMenuEntries = { +const std::array controlMenuEntries = { &fingeringMenu, &rollerMenu, &biteCtlMenu, @@ -1078,9 +1077,15 @@ const std::array controlMenuEntries = { &portLimitMenu, °litchMenu, &pinkyMenu, - &pitchBendMenu + &pitchBendMenu, + &tiltModeMenu, + &tiltCCMenu, + &rollModeMenu, + &rollCCMenu, + &accelModeMenu, + &accelCCMenu, }; -SubMenu<13> controlMenu("CTL SETUP", controlMenuEntries); +SubMenu<19> controlMenu("CTL SETUP", controlMenuEntries); const std::array vibratoMenuEntries = { &vibDepthMenu, @@ -1225,6 +1230,10 @@ void initDisplay() { currentMenu = &statusMenu; } +bool inMenu() { + return currentMenu != &statusMenu; +} + void handleMenu(state_t& state, bool draw) { unsigned long timeNow = millis(); bool wakeUp = false; diff --git a/NuEVI/src/menu.h b/NuEVI/src/menu.h index c1e146e..3f48edd 100644 --- a/NuEVI/src/menu.h +++ b/NuEVI/src/menu.h @@ -38,6 +38,7 @@ class MenuScreen { }; void initDisplay(); +bool inMenu(); void displayOff(state_t &state); void showVersion(); void displayError(const char *error); diff --git a/NuEVI/src/settings.h b/NuEVI/src/settings.h index 3f33955..c121546 100644 --- a/NuEVI/src/settings.h +++ b/NuEVI/src/settings.h @@ -83,12 +83,12 @@ struct preset_t { uint8_t knob3CC = 73; uint8_t knob4CC = 74; - uint8_t icmAccelMode; - uint8_t icmAccelCC; - uint8_t icmTiltMode; - uint8_t icmTiltCC; - uint8_t icmRotationMode; - uint8_t icmRotationCC; + ExtraControl icmAccelMode = ExtraControl::CC; + uint8_t icmAccelCC = 75; + ExtraControl icmTiltMode = ExtraControl::CC; + uint8_t icmTiltCC = 76; + ExtraControl icmRollMode = ExtraControl::CC; + uint8_t icmRollCC = 77; uint8_t breathFilterFreq = 20; uint8_t spikeFilterFreq = 20; diff --git a/NuEVI/src/xEVI.cpp b/NuEVI/src/xEVI.cpp index 8dab21b..5012cf6 100644 --- a/NuEVI/src/xEVI.cpp +++ b/NuEVI/src/xEVI.cpp @@ -231,17 +231,17 @@ int breath() { // send midi cc midiSendControlChange(state.currentPreset->breathCC, breathCCval); } - if (state.currentPreset->breathMode == BreathMode::BREATH_AT - || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT - || state.currentPreset->breathMode == BreathMode::BREATH_ACC_AT) { + if (state.currentPreset->breathMode == BreathMode::BREATH_AT + || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT + || state.currentPreset->breathMode == BreathMode::BREATH_ACC_AT) { // send aftertouch midiSendAfterTouch(breathCCval); } oldbreath = breathCCval; } - if (breathCCvalHires != oldbreathhires - && (state.currentPreset->breathMode == BreathMode::BREATH_LSB || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT)) { + if (breathCCvalHires != oldbreathhires + && (state.currentPreset->breathMode == BreathMode::BREATH_LSB || state.currentPreset->breathMode == BreathMode::BREATH_LSB_AT)) { midiSendControlChange(state.currentPreset->breathCC + 32, breathCCvalFine); } @@ -299,13 +299,13 @@ void pitch_bend() { if (ExtraControl::VIBRATO == state.currentPreset->leverControl) { // lever vibrato vibRead = instrument.leverSignal; if (vibRead > instrument.vibThr) { - instrument.vibSignal = (instrument.vibSignal + - mapConstrain(vibRead, (instrument.vibZero - vibMax), instrument.vibThr, calculatedDepth, 0) - ) / 2; + instrument.vibSignal = (instrument.vibSignal + + mapConstrain(vibRead, (instrument.vibZero - vibMax), instrument.vibThr, calculatedDepth, 0) + ) / 2; } else if (vibRead < instrument.vibThrLo) { - instrument.vibSignal = (instrument.vibSignal + - mapConstrain(vibRead, (instrument.vibZero + vibMax), instrument.vibThr, calculatedDepth, 0) - ) / 2; + instrument.vibSignal = (instrument.vibSignal + + mapConstrain(vibRead, (instrument.vibZero + vibMax), instrument.vibThr, calculatedDepth, 0) + ) / 2; } else { instrument.vibSignal = instrument.vibSignal / 2; } @@ -425,6 +425,52 @@ void sendCC() { } instrument.extraVal = extraVal; } + + if (!inMenu()) { + for (int i = 0; i < 4; i++) { + byte val = constrain((int)state.instrument->knobVals[i] + readKnob(i), 0, 127); + if (state.instrument->knobVals[i] != val) { + switch (i) { + case 0: + midiSendControlChange(state.currentPreset->knob1CC, val); + break; + case 1: + midiSendControlChange(state.currentPreset->knob2CC, val); + break; + case 2: + midiSendControlChange(state.currentPreset->knob3CC, val); + break; + case 3: + midiSendControlChange(state.currentPreset->knob4CC, val); + break; + } + } + + state.instrument->knobVals[i] = val; + } + } + + icm_result_t icmSignal = readICM(); + Serial.print(">roll: "); + Serial.println(icmSignal.roll); + Serial.print(">tilt: "); + Serial.println(icmSignal.tilt); + if (ExtraControl::CC == state.currentPreset->icmRollMode) { + byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0); + if (roll != state.instrument->rollCCVal) { + midiSendControlChange(state.currentPreset->icmRollCC, roll); + state.instrument->rollCCVal = roll; + } + } + + if (ExtraControl::CC == state.currentPreset->icmTiltMode) { + byte tilt = mapConstrain(abs(icmSignal.tilt), -20, 40, 0, 127); + if (tilt != state.instrument->tiltCCVal) { + midiSendControlChange(state.currentPreset->icmTiltCC, tilt); + state.instrument->tiltCCVal = tilt; + } + } + } // Re-zero floating calibration values @@ -444,7 +490,7 @@ void autoCal() { instrument.vibZero = instrument.vibZeroBite = 0; long int bZero = 0; long int bAltZero = 0; - for(int i = 1 ; i <= CALIBRATE_SAMPLE_COUNT; ++i) { + for (int i = 1; i <= CALIBRATE_SAMPLE_COUNT; ++i) { bZero += readPressure(); bAltZero += readAltPressure(); instrument.vibZero += readTouchUtil(leverPin); @@ -464,9 +510,9 @@ void fullAutoCal() { int calReadNext; calibration.breathAltThrValOffset = 5; - calibration.breathAltMaxValOffset = 1500 ; + calibration.breathAltMaxValOffset = 1500; calibration.breathThrValOffset = 5; - calibration.breathMaxValOffset = 1500 ; + calibration.breathMaxValOffset = 1500; autoCal(); // Lever @@ -841,7 +887,7 @@ void setup() { Serial.begin(9600); // debug Serial.println("Debug Startup"); if (CrashReport) { - while (!Serial) ; // wait for serial monitor open + while (!Serial); // wait for serial monitor open Serial.print(CrashReport); } @@ -912,7 +958,7 @@ void loop() { int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT); - if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset-> breathMode == BREATH_ACC_AT) { + if (state.currentPreset->breathMode == BREATH_ACC || state.currentPreset->breathMode == BREATH_ACC_AT) { int delta = breathSignal - instrument.breathZero; if (abs(delta) > state.calibration->breathAltThrValOffset) { instrument.breathSignal = constrain(instrument.breathSignal + delta / 10, instrument.breathZero, instrument.breathMaxVal); @@ -922,18 +968,18 @@ void loop() { } instrument.breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP -/* - Serial.print(">breathThr:"); - Serial.println(instrument.breathThrVal); - Serial.print(">note:"); - Serial.println(state.mainState); - Serial.print(">spike:"); - Serial.println(spikeSignal); - Serial.print(">breath:"); - Serial.println(breathSignal); - Serial.print(">combo:"); - Serial.println(instrument.breathSignal); -*/ + /* + Serial.print(">breathThr:"); + Serial.println(instrument.breathThrVal); + Serial.print(">note:"); + Serial.println(state.mainState); + Serial.print(">spike:"); + Serial.println(spikeSignal); + Serial.print(">breath:"); + Serial.println(breathSignal); + Serial.print(">combo:"); + Serial.println(instrument.breathSignal); + */ runStateMachine(); sendCCs();