From a2f2fb260dd821e667f7524354157db22ac02a95 Mon Sep 17 00:00:00 2001 From: Brian Hrebec Date: Sat, 9 Nov 2024 11:39:35 -0600 Subject: [PATCH] Improved menu status display Added ability to adjust key params from status and load preset --- NuEVI/src/hardware.cpp | 2 +- NuEVI/src/icm.cpp | 14 ++-- NuEVI/src/menu.cpp | 157 ++++++++++++++++++++++++++++++++++------- NuEVI/src/menu.h | 3 + NuEVI/src/xEVI.cpp | 73 +++++++------------ 5 files changed, 165 insertions(+), 84 deletions(-) diff --git a/NuEVI/src/hardware.cpp b/NuEVI/src/hardware.cpp index 6b5b927..598511e 100644 --- a/NuEVI/src/hardware.cpp +++ b/NuEVI/src/hardware.cpp @@ -145,7 +145,7 @@ int readKnob(uint8_t n) { lastOut = out; if (time - lastOutTime < KNOB_CURVE_THRESHOLD) { - out *= constrain(KNOB_CURVE_THRESHOLD / time - lastOutTime, 1, KNOB_CURVE_MAX_MULTIPLIER); + out *= constrain(KNOB_CURVE_THRESHOLD / (time - lastOutTime), 1, KNOB_CURVE_MAX_MULTIPLIER); } lastOutTime = time; } diff --git a/NuEVI/src/icm.cpp b/NuEVI/src/icm.cpp index 342b312..5cf995c 100644 --- a/NuEVI/src/icm.cpp +++ b/NuEVI/src/icm.cpp @@ -3,25 +3,19 @@ void checkICM(state_t &state) { icm_result_t icmSignal = readICM(); - /* - Serial.print(">roll: "); - Serial.println(icmSignal.roll); - Serial.print(">tilt: "); - Serial.println(icmSignal.tilt); -*/ + byte roll = mapConstrain(abs(icmSignal.roll), 0, 40, 127, 0); 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; } } + state.instrument->rollCCVal = roll; + byte tilt = mapConstrain(abs(icmSignal.tilt), -20, 40, 0, 127); 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; } } + state.instrument->tiltCCVal = tilt; } \ No newline at end of file diff --git a/NuEVI/src/menu.cpp b/NuEVI/src/menu.cpp index 6833b6d..2c6b5bb 100644 --- a/NuEVI/src/menu.cpp +++ b/NuEVI/src/menu.cpp @@ -295,8 +295,8 @@ static void drawAdjustValues(state_t& state, const AdjustValue& value, AdjustDra maxV += zero; } - char buffer[16]; - snprintf(buffer, 16, "%d>%d<%d", thrV, state.instrument->*value.value, maxV); + char buffer[21]; + snprintf(buffer, 21, "% 5d>% 5d<% 5d", thrV, state.instrument->*value.value, maxV); display.setTextSize(1); display.setCursor(128 - 6 * strlen(buffer), drawing.row - 9); display.println(buffer); @@ -458,6 +458,10 @@ public: redraw = true; } + if (input.changed && (input.btnVal1 || input.btnVal2)) { + displayOff(state); + } + if (redraw) { drawHeader(state); plotMenuEntries(_entries, _cursorPos); @@ -534,6 +538,10 @@ public: } }; + void exit() { + _focused = false; + } + const char* title() { return _title; } @@ -603,6 +611,17 @@ public: draw(state, redraw); } } + + const char* summary(state_t& state) { + size_t label_idx = *value(state) - _min; + if (_labels.size() > 0 && label_idx >= 0 && label_idx < _labels.size()) { + return _labels[label_idx]; + } else { + snprintf(buffer, 12, "%+d", *value(state)); + return buffer; + } + } + const char* title() { return _title; } @@ -614,6 +633,7 @@ protected: const bool _wrap; const std::array _labels; const char* _unit; + char buffer[12]; void drawFrame(bool redraw) { if (!redraw) { @@ -633,7 +653,6 @@ protected: display.setTextColor(WHITE, BLACK); drawFrame(redraw); - char buffer[12]; snprintf(buffer, 12, "%+d", *value(state)); size_t label_idx = *value(state) - _min; if (_labels.size() > 0 && label_idx >= 0 && label_idx < _labels.size()) { @@ -747,6 +766,15 @@ public: draw(state, redraw, it - _choices.begin()); } } + const char* summary(state_t& state) { + int label_idx = (state.currentPreset)->*_value; + if (_labels.size() > 0 && label_idx >= 0 && label_idx <= _labels.size()) { + return _labels[label_idx]; + } else { + snprintf(buffer, 12, "%+d", state.currentPreset->*_value); + return buffer; + } + } const char* title() { return _title; } @@ -755,6 +783,7 @@ private: T preset_t::*const _value; const std::array _choices; const std::array _labels; + char buffer[12]; void draw(state_t& state, bool redraw, size_t label_idx) { if (redraw) { @@ -769,7 +798,6 @@ private: display.fillRect(64, 33, 62, 29, BLACK); } - char buffer[12]; snprintf(buffer, 12, "%+d", state.currentPreset->*_value); if (_labels.size() > 0 && label_idx >= 0 && label_idx <= _labels.size()) { plotSubOption(_labels[label_idx]); @@ -779,20 +807,6 @@ private: } }; -class StatusMenu : public MenuScreen { -public: - StatusMenu(MenuScreen& mainMenu) : _mainMenu(mainMenu) { } - void update(state_t& state, InputState& input, bool redraw) { - InputState nullinput; - if (input.changed && input.btnMenu) { - currentMenu = &_mainMenu; - currentMenu->update(state, nullinput, true); - } - }; -private: - MenuScreen& _mainMenu; -}; - class ExitMenu : public MenuScreen { public: ExitMenu() {} @@ -940,17 +954,17 @@ private: std::array adjustValues = { { - {"BREATH", &instrument_state_t::breathSignal, &calibration_t::breathThrValOffset, &calibration_t::breathMaxValOffset, + {"BRTH", &instrument_state_t::breathSignal, &calibration_t::breathThrValOffset, &calibration_t::breathMaxValOffset, BREATH_LO_LIMIT, BREATH_HI_LIMIT, &instrument_state_t::breathZero}, {"BITE",&instrument_state_t::biteSignal, &calibration_t::biteThrVal, &calibration_t::biteMaxVal, BITE_LO_LIMIT, BITE_HI_LIMIT, NULL}, {"PB",&instrument_state_t::pbSignal, &calibration_t::pbMinVal, &calibration_t::pbMaxVal, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL}, - {"PB Z/DZ",&instrument_state_t::pbSignal, &calibration_t::pbCenterVal, &calibration_t::pbDeadzone, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL}, + {"PBDZ",&instrument_state_t::pbSignal, &calibration_t::pbCenterVal, &calibration_t::pbDeadzone, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL}, {"PB Y",&instrument_state_t::pbYSignal, &calibration_t::pbYMinVal, &calibration_t::pbYMaxVal, PITCHB_LO_LIMIT, PITCHB_HI_LIMIT, NULL}, - {"EXTRA", &instrument_state_t::extraSignal, &calibration_t::extraMinVal, &calibration_t::extraMaxVal, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT, NULL}, - {"LEVER", &instrument_state_t::leverSignal, &calibration_t::leverMinVal, &calibration_t::leverMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, - {"STICK X", &instrument_state_t::stickXSignal, &calibration_t::stickXMinVal, &calibration_t::stickXMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, - {"STICK Y", &instrument_state_t::stickYSignal, &calibration_t::stickYMinVal, &calibration_t::stickYMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, - {"TOUCH", &instrument_state_t::avgCTouchSignal, &calibration_t::ctouchThrVal, &calibration_t::ctouchThrVal, CTOUCH_LO_LIMIT, CTOUCH_HI_LIMIT, NULL}, + {"EXRA", &instrument_state_t::extraSignal, &calibration_t::extraMinVal, &calibration_t::extraMaxVal, EXTRA_LO_LIMIT, EXTRA_HI_LIMIT, NULL}, + {"LEVR", &instrument_state_t::leverSignal, &calibration_t::leverMinVal, &calibration_t::leverMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, + {"ST X", &instrument_state_t::stickXSignal, &calibration_t::stickXMinVal, &calibration_t::stickXMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, + {"ST Y", &instrument_state_t::stickYSignal, &calibration_t::stickYMinVal, &calibration_t::stickYMaxVal, LEVER_LO_LIMIT, LEVER_HI_LIMIT, NULL}, + {"TCH", &instrument_state_t::avgCTouchSignal, &calibration_t::ctouchThrVal, &calibration_t::ctouchThrVal, CTOUCH_LO_LIMIT, CTOUCH_HI_LIMIT, NULL}, }}; AdjustMenuScreen<10> adjustMenu("ADJUST", adjustValues); @@ -1172,6 +1186,96 @@ const std::array mainMenuEntries = { &exitMenu, }; MainMenu<10> mainMenu(mainMenuEntries); + +class StatusMenu : public MenuScreen { +public: + StatusMenu(MenuScreen& mainMenu) : _mainMenu(mainMenu) { } + void update(state_t& state, InputState& input, bool redraw) { + InputState nullinput; + if (input.changed && input.btnMenu) { + currentMenu = &_mainMenu; + currentMenu->update(state, nullinput, true); + return; + } + + if (input.changed && input.knobPreset && !redraw) { + state.currentPresetIdx = constrain((int)state.currentPresetIdx + input.knobPreset, 0, PRESET_COUNT - 1); + state.currentPreset = &presets[state.currentPresetIdx]; + _showValues = false; + } + if (input.changed && input.knobVal2 && !redraw) { + // adjust midi channel + state.currentPreset->MIDIchannel = constrain(state.currentPreset->MIDIchannel + input.knobVal2, 1, 16); + _showValues = false; + } + if (input.changed && input.knobVal1 && !redraw) { + // adjust octave + state.instrument->octave = constrain(state.instrument->octave + input.knobVal1, -3, 3); + _showValues = false; + } + if (input.changed && input.knobMenu && !redraw) { + // adjust transpose + state.instrument->transpose = constrain(state.instrument->transpose + input.knobMenu, -12, 12); + _showValues = false; + } + if (input.changed && input.btnVal1 && !redraw) { + // Toggle display if we didn't just wake up + _showValues = !_showValues; + } + + draw(state); + }; + void exit() { + _showValues = false; + } +private: + bool _showValues = false; + MenuScreen& _mainMenu; + void draw(state_t& state) { + display.clearDisplay(); + display.setTextSize(1); + display.setCursor(0, 0); + if (!_showValues) { + display.print(" PRESET "); + display.println(state.currentPresetIdx + 1); + drawMenuSummary(state, midiMenu); + drawMenuSummary(state, octaveMenu); + drawMenuSummary(state, transposeMenu); + drawMenuSummary(state, breathModeMenu); + drawMenuSummary(state, fingeringMenu); + drawMenuSummary(state, polyMenu); + drawMenuSummary(state, rollModeMenu); + } else { + drawVal("BRTH: ", state.instrument->breathCCVal); + drawVal("BITE: ", state.instrument->biteVal); + drawVal("PORT: ", state.instrument->portamentoVal); + drawVal("EXRA: ", state.instrument->extraVal); + drawVal("LEVR: ", state.instrument->leverVal); + drawVal("PB : ", state.instrument->pbVal); + drawVal("PB Y: ", state.instrument->pbYVal); + display.setCursor(42, 0); + drawVal("ST X: ", state.instrument->stickXSignal); + drawVal("ST Y: ", state.instrument->stickYSignal); + drawVal("K1 : ", state.instrument->knobVals[0]); + drawVal("K2 : ", state.instrument->knobVals[1]); + drawVal("K3 : ", state.instrument->knobVals[2]); + drawVal("K4 : ", state.instrument->knobVals[3]); + display.setCursor(84, 0); + drawVal("ROLL: ", state.instrument->rollCCVal); + drawVal("TILT: ", state.instrument->tiltCCVal); + } + } + void drawVal(const char *name, int val) { + display.print(name); + display.println(val); + } + void drawMenuSummary(state_t& state, MenuScreen &menu) { + display.printf("%12s", menu.title()); + display.print(": "); + display.println(menu.summary(state)); + } +}; + StatusMenu statusMenu = StatusMenu(mainMenu); //*********************************************************** @@ -1238,6 +1342,7 @@ void displayOff(state_t &state) { display.clearDisplay(); display.display(); display.ssd1306_command(SSD1306_DISPLAYOFF); + currentMenu->exit(); currentMenu = &statusMenu; displayOn = false; } @@ -1278,7 +1383,7 @@ void initDisplay() { } bool inMenu() { - return currentMenu != &statusMenu; + return displayOn; } void handleMenu(state_t& state, bool draw) { diff --git a/NuEVI/src/menu.h b/NuEVI/src/menu.h index 3f48edd..a9ede8f 100644 --- a/NuEVI/src/menu.h +++ b/NuEVI/src/menu.h @@ -33,7 +33,10 @@ class MenuScreen { public: MenuScreen() {}; virtual const char *title() { return ""; }; + virtual const char* summary(state_t& state) { return ""; }; virtual void update(state_t &state, InputState &input, bool redraw) = 0; + + virtual void exit() { }; virtual ~MenuScreen() {}; }; diff --git a/NuEVI/src/xEVI.cpp b/NuEVI/src/xEVI.cpp index 490f8b4..13b1795 100644 --- a/NuEVI/src/xEVI.cpp +++ b/NuEVI/src/xEVI.cpp @@ -419,68 +419,47 @@ void portamento_() { //*********************************************************** void sendCC() { - if (ExtraControl::CC == state.currentPreset->biteControl) { - int biteVal = mapConstrain(instrument.biteSignal, calibration.biteThrVal, calibration.biteMaxVal, 127, 0); - - if (biteVal != instrument.biteVal) { - midiSendControlChange(state.currentPreset->biteCC, biteVal); - } - instrument.biteVal = biteVal; + int biteVal = mapConstrain(instrument.biteSignal, calibration.biteThrVal, calibration.biteMaxVal, 127, 0); + if (ExtraControl::CC == state.currentPreset->biteControl && biteVal != instrument.biteVal) { + midiSendControlChange(state.currentPreset->biteCC, biteVal); } + instrument.biteVal = biteVal; - if (ExtraControl::CC == state.currentPreset->extraControl) { - int extraVal = mapConstrain(instrument.extraSignal, calibration.extraMinVal, calibration.extraMaxVal, 0, 127); - - if (extraVal != instrument.extraVal) { - midiSendControlChange(state.currentPreset->extraCC, extraVal); - } - instrument.extraVal = extraVal; + int extraVal = mapConstrain(instrument.extraSignal, calibration.extraMinVal, calibration.extraMaxVal, 0, 127); + if (ExtraControl::CC == state.currentPreset->extraControl && extraVal != instrument.extraVal) { + midiSendControlChange(state.currentPreset->extraCC, extraVal); } + instrument.extraVal = extraVal; int leverVal = mapConstrain(instrument.leverSignal, calibration.leverMinVal, calibration.leverMaxVal, 0, 127); - if (ExtraControl::CC == state.currentPreset->leverControl) { - if (leverVal != instrument.leverVal) { - midiSendControlChange(state.currentPreset->leverCC, leverVal); - } + if (ExtraControl::CC == state.currentPreset->leverControl && leverVal != instrument.leverVal) { + midiSendControlChange(state.currentPreset->leverCC, leverVal); } instrument.leverVal = leverVal; - if (ExtraControl::CC == state.currentPreset->pbControl) { - int pbVal = mapConstrain(instrument.pbSignal, calibration.pbMinVal, calibration.pbMaxVal, 0, 127); - - if (pbVal != instrument.pbVal) { - midiSendControlChange(state.currentPreset->pbCC, pbVal); - } - instrument.pbVal = pbVal; + int pbVal = mapConstrain(instrument.pbSignal, calibration.pbMinVal, calibration.pbMaxVal, 0, 127); + if (ExtraControl::CC == state.currentPreset->pbControl && pbVal != instrument.pbVal) { + midiSendControlChange(state.currentPreset->pbCC, pbVal); } + instrument.pbVal = pbVal; - if (state.currentPreset->pbYCC) { - int pbYVal = mapConstrain(instrument.pbYSignal, calibration.pbYMinVal, calibration.pbYMaxVal, 0, 127); - - if (pbYVal != instrument.pbYVal) { - midiSendControlChange(state.currentPreset->pbYCC, pbYVal); - } - instrument.pbYVal = pbYVal; + int pbYVal = mapConstrain(instrument.pbYSignal, calibration.pbYMinVal, calibration.pbYMaxVal, 0, 127); + if (state.currentPreset->pbYCC && pbYVal != instrument.pbYVal) { + midiSendControlChange(state.currentPreset->pbYCC, pbYVal); } + instrument.pbYVal = pbYVal; - if (state.currentPreset->stickXCC) { - int stickXVal = mapConstrain(instrument.stickXSignal, calibration.stickXMinVal, calibration.stickXMaxVal, 0, 127); - - if (stickXVal != instrument.stickXVal) { - midiSendControlChange(state.currentPreset->stickXCC, stickXVal); - } - instrument.stickXVal = stickXVal; + int stickXVal = mapConstrain(instrument.stickXSignal, calibration.stickXMinVal, calibration.stickXMaxVal, 0, 127); + if (state.currentPreset->stickXCC && stickXVal != instrument.stickXVal) { + midiSendControlChange(state.currentPreset->stickXCC, stickXVal); } + instrument.stickXVal = stickXVal; - if (state.currentPreset->stickYCC) { - int stickYVal = mapConstrain(instrument.stickYSignal, calibration.stickYMinVal, calibration.stickYMaxVal, 0, 127); - - if (stickYVal != instrument.stickYVal) { - midiSendControlChange(state.currentPreset->stickYCC, stickYVal); - } - instrument.stickYVal = stickYVal; + int stickYVal = mapConstrain(instrument.stickYSignal, calibration.stickYMinVal, calibration.stickYMaxVal, 0, 127); + if (state.currentPreset->stickYCC && stickYVal != instrument.stickYVal) { + midiSendControlChange(state.currentPreset->stickYCC, stickYVal); } - + instrument.stickYVal = stickYVal; if (!inMenu()) { for (int i = 0; i < 4; i++) {