From e757ebc88543cc0530d5172b2dd9dbbd3b89134c Mon Sep 17 00:00:00 2001 From: Brian Hrebec Date: Wed, 30 Aug 2023 22:50:55 -0500 Subject: [PATCH] Additional br tweaking --- NuEVI/src/TODO | 2 -- NuEVI/src/config.h | 2 +- NuEVI/src/globals.h | 6 ++--- NuEVI/src/hardware.cpp | 4 +-- NuEVI/src/led.cpp | 38 +++++++++++++++++++++++++-- NuEVI/src/menu.cpp | 11 +++++--- NuEVI/src/settings.cpp | 4 +++ NuEVI/src/settings.h | 9 ++++--- NuEVI/src/xEVI.cpp | 59 ++++++++++++++++++++++++------------------ 9 files changed, 91 insertions(+), 44 deletions(-) diff --git a/NuEVI/src/TODO b/NuEVI/src/TODO index 1bf51bd..47e69d1 100644 --- a/NuEVI/src/TODO +++ b/NuEVI/src/TODO @@ -1,11 +1,9 @@ 1. LED abstraction code -4. Refactor note play behavior into module 5. Refactor CV behavior into module 6. 9dof sensor code 7. Alternate fingerings 8. Encoder midi - Lever mode: pb -- Breath mode: relative - Breath suck control? - \ No newline at end of file diff --git a/NuEVI/src/config.h b/NuEVI/src/config.h index 9f1e640..f2c3f90 100644 --- a/NuEVI/src/config.h +++ b/NuEVI/src/config.h @@ -57,6 +57,6 @@ #define LEVER_LO_LIMIT 500 #define LEVER_HI_LIMIT 1000 #define SPIKE_LO_LIMIT 0 -#define SPIKE_HI_LIMIT 100 +#define SPIKE_HI_LIMIT 200 #endif diff --git a/NuEVI/src/globals.h b/NuEVI/src/globals.h index 3421502..07fc732 100644 --- a/NuEVI/src/globals.h +++ b/NuEVI/src/globals.h @@ -18,9 +18,6 @@ // A note is sounding #define NOTE_ON 3 -// We turned the note off due to a HF spike -#define SPIKE_HOLD 4 - enum PinkyMode : uint8_t { PBD = 12, GLD = 25, @@ -54,6 +51,8 @@ enum BreathMode : uint8_t { BREATH_LSB = 1, BREATH_AT = 2, BREATH_LSB_AT = 3, + BREATH_ACC = 4, + BREATH_ACC_AT = 5, }; enum ExtraControl : uint8_t { @@ -89,7 +88,6 @@ struct instrument_state_t { // Raw sensor signals int16_t breathSignal = 0; // breath level (smoothed) not mapped to CC value int16_t breathAltSignal = 0; - int16_t spikeSignal = 0; // breath level (smoothed) not mapped to CC value int16_t biteSignal = 0; // capacitance data from bite sensor, for midi cc and threshold checks int16_t leverSignal = 0; int16_t pbUpSignal = 0; diff --git a/NuEVI/src/hardware.cpp b/NuEVI/src/hardware.cpp index cbe9f75..e94a686 100644 --- a/NuEVI/src/hardware.cpp +++ b/NuEVI/src/hardware.cpp @@ -120,9 +120,9 @@ int readKnob(uint8_t n) { static unsigned long lastOutTime = 0; int out = 0; int32_t val = knobs[n].read(); - if (val > (lastOut < 0) ? 3 : 4) { + if (val > ((lastOut < 0) ? 3 : 4)) { out = val / 4; - } else if (val < (lastOut > 0) ? -3 : -4) { + } else if ((val < (lastOut > 0) ? -3 : -4)) { out = val / 4; } diff --git a/NuEVI/src/led.cpp b/NuEVI/src/led.cpp index b07ab02..9e632e5 100644 --- a/NuEVI/src/led.cpp +++ b/NuEVI/src/led.cpp @@ -6,7 +6,36 @@ void singleLED(int n, int color) { } +// 0000 0001 +// 0000 0010 +// 0000 0011 +// 0000 0100 +// ... +// 0111 0000 +// 0111 1111 +// >> 4 == 0111 + +// 127 -> 255, 255, 255, 255, 255, 255, 255, 255 +// 64 -> 255, 255, 255, 255, 0, 0, 0, 0 +// 64 -> 255, 255, 255, 255, 0, 0, 0, 0 +// 32 -> 255, 255, 0, 0, 0, 0, 0, 0 +// 24 -> 255, 127, 0, 0, 0, 0, 0, 0 +// 16 -> 255, 0, 0, 0, 0, 0, 0, 0 +// 8 -> 127, 0, 0, 0, 0, 0, 0, 0 +// 0 -> 0, 0, 0, 0, 0, 0, 0, 0 + void ledFullMeter(byte indicatedValue, int color){ + int scaledVal = indicatedValue; + ledStrip.setBrightness(1); + for (int i = 0; i < 8; i++) { + if (scaledVal > 0) { + ledStrip.setPixel(i, color); + } else { + ledStrip.setPixel(i, 0); + } + scaledVal -= 16; + } + ledStrip.show(); } void ledHalfMeter(int n, byte indicatedValue, int color){ @@ -32,9 +61,15 @@ void statusLedFlip() { } void statusLedFlash(uint16_t delayTime) { + for (int i = 0; i < 8; i++) { + ledStrip.setPixel(i, 0x000400); + } + ledStrip.show(); statusLedOff(); delay(delayTime/2); statusLedOn(); + ledStrip.clear(); + ledStrip.show(); delay(delayTime/2); } @@ -44,6 +79,5 @@ void statusLedBlink() { } void updateSensorLEDs(instrument_state_t &state) { - ledHalfMeter(1, state.breathCCVal, 0x00FF00); - ledQuarterMeter(3, state.biteVal, 0x0000FF); + ledFullMeter(state.breathCCVal, 0x0000FF); } diff --git a/NuEVI/src/menu.cpp b/NuEVI/src/menu.cpp index 96d3185..82326ba 100644 --- a/NuEVI/src/menu.cpp +++ b/NuEVI/src/menu.cpp @@ -941,7 +941,6 @@ private: std::array adjustValues = { { {"BREATH", &instrument_state_t::breathSignal, &calibration_t::breathThrValOffset, &calibration_t::breathMaxValOffset, BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathZero}, - {"TRIGGER", &instrument_state_t::spikeSignal, &calibration_t::spikeThrVal, &calibration_t::spikeThrVal, SPIKE_LO_LIMIT, SPIKE_HI_LIMIT, NULL}, {"BR ALT", &instrument_state_t::breathAltSignal, &calibration_t::breathAltThrValOffset, &calibration_t::breathAltMaxValOffset, BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathAltZero}, {"BITE",&instrument_state_t::biteSignal, &calibration_t::biteThrVal, &calibration_t::biteMaxVal, BITE_LO_LIMIT, BITE_HI_LIMIT, NULL}, @@ -956,7 +955,7 @@ AdjustMenuScreen<9> adjustMenu("ADJUST", adjustValues); //*********************************************************** -ChoiceMenu<4, BreathMode> breathModeMenu("BR MODE", &preset_t::breathMode, { { BREATH_STD, BREATH_LSB, BREATH_AT, BREATH_LSB_AT} }, { { "STD", "LSB", "AT", "AT+" } }); +ChoiceMenu<6, BreathMode> breathModeMenu("BR MODE", &preset_t::breathMode, { { BREATH_STD, BREATH_LSB, BREATH_AT, BREATH_LSB_AT, BREATH_ACC, BREATH_ACC_AT} }, { { "STD", "LSB", "AT", "AT+", "ACC", "ACC+AT" } }); PresetValueMenu<128, uint8_t> breathCCMenu("BREATH CC", &preset_t::breathCC, 0, 127, true, CC_NAMES); PresetValueMenu<1, uint8_t> velocityMenu("VELOCITY", &preset_t::fixedVelocity, 0, 127, true, { { "DYN" } }); CurveValueMenu<0, uint8_t> curveMenu("CURVE", &preset_t::breathCurve, 0, 12); @@ -965,6 +964,8 @@ PresetValueMenu<1, uint8_t> velBiasMenu("VEL BOOST", &preset_t::velBias, 0, 30, PresetValueMenu<0, uint8_t> breathIntervalMenu("BR INTV", &preset_t::breathInterval, 0, 30, true, {}, "ms"); PresetValueMenu<0, uint8_t> filterMenu("FILTER CT", &preset_t::breathFilterFreq, 1, 100, false, {}, "hz"); PresetValueMenu<1, uint8_t> spikeFilterMenu("FILTER TRG", &preset_t::spikeFilterFreq, 0, 100, false, {"OFF"}, "hz"); +PresetValueMenu<0, int8_t> spikeOnFactorMenu("TRG ON MUL", &preset_t::spikeOnFactor, -25, 25, false, {}, "x"); +PresetValueMenu<0, int8_t> spikeOffFactorMenu("TRG OFF MUL", &preset_t::spikeOffFactor, -25, 25, false, {}, "x"); PresetValueMenu<0, int8_t> trill3Menu("TRILL3", &preset_t::trill3_interval, 3, 4, true, {}); PresetValueMenu<0, int8_t> cvTuneMenu("CV Tune", &preset_t::cvTune, -100, 100, false, {}); PresetValueMenu<0, uint8_t> cvVibMenu("CV LFO", &preset_t::cvVibRate, 0, 8, false, {}); @@ -1049,7 +1050,7 @@ FuncMenu saveAllPresetsMenu("SAVE PRESETS", [](state_t &state, InputState& input writePresets(); }); -std::array breathMenuEntries = { +std::array breathMenuEntries = { &breathModeMenu, &breathCCMenu, &velocityMenu, @@ -1059,8 +1060,10 @@ std::array breathMenuEntries = { &breathIntervalMenu, &filterMenu, &spikeFilterMenu, + &spikeOnFactorMenu, + &spikeOffFactorMenu, }; -SubMenu<9> breathMenu("BR SETUP", breathMenuEntries); +SubMenu<11> breathMenu("BR SETUP", breathMenuEntries); const std::array controlMenuEntries = { &fingeringMenu, diff --git a/NuEVI/src/settings.cpp b/NuEVI/src/settings.cpp index 76be4aa..5b287b4 100644 --- a/NuEVI/src/settings.cpp +++ b/NuEVI/src/settings.cpp @@ -343,6 +343,10 @@ void readEEPROM(const bool factoryReset, calibration_t &calibration) { presets[i].breathFilterFreq = 20; presets[i].spikeFilterFreq = 20; } + if (settings_version < 4) { + presets[i].spikeOnFactor = 5; + presets[i].spikeOffFactor = 5; + } } writePresets(); diff --git a/NuEVI/src/settings.h b/NuEVI/src/settings.h index 6a6325a..3f33955 100644 --- a/NuEVI/src/settings.h +++ b/NuEVI/src/settings.h @@ -5,7 +5,7 @@ #include "globals.h" -#define EEPROM_VERSION 3 +#define EEPROM_VERSION 4 #define EEPROM_VERSION_ADDR 0 #define SETTINGS_OFFSET 2 #define PRESET_MAX_SIZE 128 // Leave extra space for future settings @@ -35,8 +35,7 @@ struct calibration_t { int16_t extraThrVal = 850; int16_t extraMaxVal = 1000; int16_t ctouchThrVal = 900; - int16_t spikeThrVal= 25; - uint8_t _reserved[22]; + uint8_t _reserved[24]; }; static_assert(sizeof(calibration_t) == CALIBRATION_MAX_SIZE, "calibration data wrong size"); @@ -93,8 +92,10 @@ struct preset_t { uint8_t breathFilterFreq = 20; uint8_t spikeFilterFreq = 20; + int8_t spikeOnFactor = 5; + int8_t spikeOffFactor = 5; - uint8_t _reserved[85]; + uint8_t _reserved[83]; }; static_assert(sizeof(preset_t) == PRESET_MAX_SIZE, "preset_t must be 128 bytes"); diff --git a/NuEVI/src/xEVI.cpp b/NuEVI/src/xEVI.cpp index c618534..8dab21b 100644 --- a/NuEVI/src/xEVI.cpp +++ b/NuEVI/src/xEVI.cpp @@ -231,7 +231,9 @@ int breath() { // send midi cc midiSendControlChange(state.currentPreset->breathCC, breathCCval); } - if (state.currentPreset->breathMode == BreathMode::BREATH_AT || state.currentPreset->breathMode == BreathMode::BREATH_LSB_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); } @@ -245,6 +247,7 @@ int breath() { oldbreathhires = breathCCvalHires; + state.instrument->breathCCVal = breathCCval; return breathCCval; } @@ -790,16 +793,6 @@ void sendCCs() { void runStateMachine() { static unsigned long breath_on_time = 0L; // Time when breath sensor value went over the ON threshold static int initial_breath_value = 0; // The breath value at the time we observed the transition - - Serial.print(">breath:"); - Serial.println(instrument.breathSignal); - Serial.print(">breathThr:"); - Serial.println(instrument.breathThrVal); - Serial.print(">spike:"); - Serial.println(instrument.spikeSignal); - Serial.print(">note:"); - Serial.println(state.mainState); - int fingeredNote = noteValueCheck(readSwitches() + readOctave()); if (state.mainState == NOTE_OFF) { handleOffStateActions(); @@ -823,10 +816,7 @@ void runStateMachine() { state.mainState = NOTE_OFF; } } else if (state.mainState == NOTE_ON) { - if (state.currentPreset->spikeFilterFreq && instrument.spikeSignal < -calibration.spikeThrVal) { - midiSendNoteOff(instrument.activeNote); // send Note Off message - state.mainState = SPIKE_HOLD; - } else if (instrument.breathSignal < instrument.breathThrVal) { + if (instrument.breathSignal < instrument.breathThrVal) { // Value has fallen below threshold - turn the note off midiSendNoteOff(instrument.activeNote); // send Note Off message instrument.breathSignal = 0; @@ -842,14 +832,6 @@ void runStateMachine() { instrument.activeNote = fingeredNote; } } - } else if (state.mainState == SPIKE_HOLD) { - if (state.currentPreset->spikeFilterFreq && instrument.spikeSignal > calibration.spikeThrVal) { - noteOn(fingeredNote, instrument.breathSignal, initial_breath_value); - state.mainState = NOTE_ON; - instrument.activeNote = fingeredNote; - } else if ((instrument.breathSignal < instrument.breathThrVal)) { - state.mainState = NOTE_OFF; - } } } @@ -908,8 +890,12 @@ void setup() { //_______________________________________________________________________________________________ MAIN LOOP void loop() { + static unsigned long lastUpdate = millis(); static unsigned long pixelUpdateTime = 0; static const unsigned long pixelUpdateInterval = 80; + unsigned long time = millis(); + unsigned long deltaTime = time - lastUpdate; + lastUpdate = time; // If in config mgmt loop, do that and nothing else if (configManagementMode) { @@ -922,9 +908,32 @@ void loop() { return; } - instrument.breathSignal = constrain(readPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP + int16_t breathSignal = constrain(readPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP + int16_t spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT); + + + 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); + } + } else { + instrument.breathSignal = breathSignal + (spikeSignal > 0 ? spikeSignal * state.currentPreset->spikeOnFactor : spikeSignal * state.currentPreset->spikeOffFactor); + } instrument.breathAltSignal = constrain(readAltPressure(), BREATH_LO_LIMIT, BREATH_HI_LIMIT); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP - instrument.spikeSignal = constrain(readSpikePressure(), -SPIKE_HI_LIMIT, SPIKE_HI_LIMIT); + +/* + 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();