From 5b59b4cd0fdf5af4cd67334bd72e2a5187445605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikael=20Degerf=C3=A4lt?= Date: Sun, 23 Jun 2019 16:55:25 +0200 Subject: [PATCH] Final push to unify all menu states All states are now handled by the new menu system, although some are flagged to have a custom handler that does everything by itself. I replaced most reference parameters to pointers to be able to typecast in a nicer way. Key input is not passed as a parameter to the menu functions instead of having global variables they all access. I think I broke one thing by doing this, since there is no way to propagate key input changes to the next frame. --- NuEVI/adjustmenu.cpp | 6 +- NuEVI/menu.cpp | 631 +++++++++++++++++++++++-------------------- NuEVI/menu.h | 20 +- NuEVI/numenu.h | 21 +- 4 files changed, 364 insertions(+), 314 deletions(-) diff --git a/NuEVI/adjustmenu.cpp b/NuEVI/adjustmenu.cpp index 310d6f7..500c503 100644 --- a/NuEVI/adjustmenu.cpp +++ b/NuEVI/adjustmenu.cpp @@ -274,12 +274,14 @@ static bool updateAdjustCursor(uint32_t timeNow) { return false; } -int updateAdjustMenu(uint32_t timeNow, uint8_t buttons, bool firstRun, bool drawSensor) { +int updateAdjustMenu(uint32_t timeNow, KeyState &input, bool firstRun, bool drawSensor) { bool redraw = false; int result = 0; const AdjustMenuEntry *currentMenu = adjustMenuEntries[adjustOption]; + uint8_t buttons = input.changed ? input.current : 0; + if(firstRun || refreshScreen) { adjustCurrent = 0; refreshScreen = false; @@ -294,7 +296,6 @@ int updateAdjustMenu(uint32_t timeNow, uint8_t buttons, bool firstRun, bool draw redraw |= updateAdjustCursor(timeNow); bool save = false; - if( buttons == BTN_DOWN ) { adjustOption += 1; refreshScreen = 1; @@ -357,3 +358,4 @@ int updateAdjustMenu(uint32_t timeNow, uint8_t buttons, bool firstRun, bool draw return result; } + diff --git a/NuEVI/menu.cpp b/NuEVI/menu.cpp index 014ade3..59f9a80 100644 --- a/NuEVI/menu.cpp +++ b/NuEVI/menu.cpp @@ -11,11 +11,6 @@ #include "settings.h" #include "numenu.h" -static uint8_t lastDeumButtons = 0; -static uint8_t deumButtonState = 0; -static byte buttonPressedAndNotUsed = 0; - - enum CursorIdx { EMain, EBreath, @@ -44,15 +39,13 @@ const unsigned long cursorBlinkInterval = 300; // the cursor blink toggle int const unsigned long patchViewTimeUp = 2000; // ms until patch view shuts off const unsigned long menuTimeUp = 60000; // menu shuts off after one minute of button inactivity -static unsigned long lastDebounceTime = 0; // the last time the output pin was toggled -static unsigned long buttonRepeatTime = 0; -static unsigned long buttonPressedTime = 0; + static unsigned long menuTime = 0; static unsigned long patchViewTime = 0; unsigned long cursorBlinkTime = 0; // the last time the cursor was toggled //Display state -static byte state = DISPLAYOFF_IDL; +static byte menuState= DISPLAYOFF_IDL; static byte stateFirstRun = 1; // The external function of subSquelch has been broken, @@ -205,10 +198,10 @@ static void plotSubOption(const char* label, int color) { display.println(label); } -static bool drawSubMenu(const MenuPage &page, int color) { - int index = cursors[page.cursor]; +static bool drawSubMenu(const MenuPage *page, int color) { + int index = cursors[page->cursor]; // TODO: Null check subMenuFunc - const MenuEntry* subEntry = page.entries[index]; + const MenuEntry* subEntry = page->entries[index]; switch(subEntry->type) { case MenuType::ESub: { @@ -245,7 +238,7 @@ static void clearSubValue() { display.fillRect(65, 24, 60, 37, BLACK); } -static bool updateSubMenuCursor(const MenuPage &page, uint32_t timeNow) +static bool updateSubMenuCursor(const MenuPage *page, uint32_t timeNow) { if ((timeNow - cursorBlinkTime) > cursorBlinkInterval) { cursorBlinkTime = timeNow; @@ -260,35 +253,42 @@ static bool updateSubMenuCursor(const MenuPage &page, uint32_t timeNow) return false; } -static void plotMenuEntries(const MenuPage &page, bool clear = false) { +static void plotMenuEntries(const MenuPage *page, bool clear = false) { int row = 0; if(clear) { display.fillRect( 0, MENU_HEADER_OFFSET, 56, 64-MENU_HEADER_OFFSET, BLACK ); } - for(int item = offsets[page.cursor]; (item < page.numEntries) && (row < MENU_NUM_ROWS); item++, row++) { + for(int item = offsets[page->cursor]; (item < page->numEntries) && (row < MENU_NUM_ROWS); item++, row++) { int rowPixel = (row)*MENU_ROW_HEIGHT + MENU_HEADER_OFFSET; - const char* lineText = page.entries[item]->title; + const char* lineText = page->entries[item]->title; display.setCursor(0,rowPixel); display.println(lineText); } } -static void drawMenu(const MenuPage &page, const char* customTitle = nullptr) { +typedef void (*MenuTitleGetFunc)(char*out); + +static void drawMenu(const MenuPage *page) { //Initialize display and draw menu header + line display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); - if(customTitle) - display.println(customTitle); - else - display.println(page.title); + + if(page->flags & EMenuCustomTitle) { + // This is a bit hacky, but we are reusing the title pointer as a function pointer + MenuTitleGetFunc func = (MenuTitleGetFunc)page->title; + char buffer[23]; + func(buffer); + display.println(buffer); + } else + display.println(page->title); display.drawLine(0, MENU_ROW_HEIGHT, 127, MENU_ROW_HEIGHT, WHITE); plotMenuEntries(page); } -static void drawMenuScreen() { +static void mainTitleGetStr(char* out) { //Construct the title including voltage reading. //Involves intricate splicing of the title string with battery voltage char menuTitle[] = "MENU XXX Y.YV"; //Allocate string buffer of appropriate size with some placeholders @@ -304,7 +304,7 @@ static void drawMenuScreen() { splice2[0] = (voltage/10)+'0'; splice2[2] = (voltage%10)+'0'; } - drawMenu(mainMenuPage, menuTitle); + strncpy(out, menuTitle, 22); } static void drawTrills(){ @@ -471,8 +471,8 @@ const MenuEntry* mainMenuEntries[] = { }; const MenuPage mainMenuPage = { - nullptr, - EMenuPageRoot, + (const char*)mainTitleGetStr, + EMenuPageRoot | EMenuCustomTitle, CursorIdx::EMain, DISPLAYOFF_IDL, ARR_LEN(mainMenuEntries), mainMenuEntries @@ -806,24 +806,41 @@ const MenuPage vibratoMenuPage = { ARR_LEN(vibratorMenuEntries), vibratorMenuEntries }; +//*********************************************************** + +static bool patchPageUpdate(KeyState& __unused input, uint32_t __unused timeNow); +static bool idlePageUpdate(KeyState& __unused input, uint32_t __unused timeNow); + +const MenuPageCustom adjustMenuPage = { + nullptr, EMenuPageCustom, adjustPageUpdate, +}; + +const MenuPageCustom patchMenuPage = { + nullptr, EMenuPageCustom, patchPageUpdate, +}; + +const MenuPageCustom idleMenuPage = { + nullptr, EMenuPageCustom, idlePageUpdate, +}; + //*********************************************************** -static bool selectMenuOption(const MenuPage &page) { - int cursorPosition = cursors[page.cursor]; - const MenuEntry* menuEntry = page.entries[cursorPosition]; +static bool selectMenuOption(const MenuPage *page) { + int cursorPosition = cursors[page->cursor]; + const MenuEntry* menuEntry = page->entries[cursorPosition]; cursorBlinkTime = millis(); switch(menuEntry->type) { case MenuType::ESub: - activeSub[page.cursor] = cursorPosition+1; + activeSub[page->cursor] = cursorPosition+1; drawMenuCursor(cursorPosition, WHITE); drawSubBox( ((const MenuEntrySub*)menuEntry)->subTitle); drawSubMenu(page, WHITE); return true; case MenuType::EStateChange: - state = ((const MenuEntryStateCh*)menuEntry)->state; + menuState= ((const MenuEntryStateCh*)menuEntry)->state; stateFirstRun = 1; break; } @@ -831,25 +848,22 @@ static bool selectMenuOption(const MenuPage &page) { return false; } - //*********************************************************** -static bool updateSubMenu(const MenuPage &page, uint32_t timeNow) { +static bool updateSubMenu(const MenuPage *page, KeyState &input, uint32_t timeNow) { bool redraw = false; bool redrawSubValue = false; - if (buttonPressedAndNotUsed) { - buttonPressedAndNotUsed = 0; - - int current_sub = activeSub[page.cursor] -1; + if (input.changed) { + int current_sub = activeSub[page->cursor] -1; if( current_sub < 0) return false; - auto sub = (const MenuEntrySub*)page.entries[current_sub]; + auto sub = (const MenuEntrySub*)page->entries[current_sub]; uint16_t currentVal = *sub->valuePtr; - switch (deumButtonState){ + switch (input.current){ case BTN_DOWN: if(currentVal > sub->min) { currentVal -= 1; @@ -870,16 +884,16 @@ static bool updateSubMenu(const MenuPage &page, uint32_t timeNow) { if(sub->flags & EMenuEntryEnterHandler) { bool result = sub->onEnterFunc(); if(result) { - activeSub[page.cursor] = 0; + activeSub[page->cursor] = 0; } } else { - activeSub[page.cursor] = 0; + activeSub[page->cursor] = 0; sub->applyFunc(*sub); } break; case BTN_MENU: - activeSub[page.cursor] = 0; + activeSub[page->cursor] = 0; sub->applyFunc(*sub); break; } @@ -899,16 +913,14 @@ static bool updateSubMenu(const MenuPage &page, uint32_t timeNow) { return redraw; } -static bool updateMenuPage( const MenuPage &page, uint32_t timeNow ) { - byte cursorPos = cursors[page.cursor]; +static bool updateMenuPage(const MenuPage *page, KeyState &input, uint32_t timeNow) { + byte cursorPos = cursors[page->cursor]; byte newPos = cursorPos; bool redraw = false; - if (buttonPressedAndNotUsed) { - int lastEntry = page.numEntries-1; - - buttonPressedAndNotUsed = 0; - switch (deumButtonState) { + if (input.changed) { + int lastEntry = page->numEntries-1; + switch (input.current) { case BTN_DOWN: if (cursorPos < lastEntry) newPos = cursorPos+1; @@ -924,7 +936,8 @@ static bool updateMenuPage( const MenuPage &page, uint32_t timeNow ) { break; case BTN_MENU: - state = page.parentPage; + Serial.print("back to parent..."); + menuState= page->parentPage; stateFirstRun = 1; break; } @@ -935,7 +948,7 @@ static bool updateMenuPage( const MenuPage &page, uint32_t timeNow ) { cursorNow = BLACK; clearSub(); redraw = true; - cursors[page.cursor] = newPos; + cursors[page->cursor] = newPos; } } else if ((timeNow - cursorBlinkTime) > cursorBlinkInterval) { // Only need to update cursor blink if no buttons were pressed @@ -948,60 +961,44 @@ static bool updateMenuPage( const MenuPage &page, uint32_t timeNow ) { return redraw; } -static bool updatePage(const MenuPage &page, uint32_t timeNow) { +static void checkForPatchView(int buttons); + + +static bool updatePage(const MenuPage *page, KeyState &input, uint32_t timeNow) { + if(page->flags & EMenuPageCustom) { + auto custom = (const MenuPageCustom*)page; + return custom->menuUpdateFunc(input, timeNow); + } + + bool redraw = false; + if (stateFirstRun) { drawMenu(page); stateFirstRun = 0; } - if (activeSub[page.cursor]) { - return updateSubMenu(page, timeNow); + if (activeSub[page->cursor]) { + redraw = updateSubMenu(page, input, timeNow); } else { - return updateMenuPage(page, timeNow); - } -} + redraw = updateMenuPage(page, input, timeNow); - - - -static bool updateSensorPixelsFlag = false; -void drawSensorPixels() { - updateSensorPixelsFlag = true; -} - -bool adjustPageUpdate(uint16_t buttonChanges, uint32_t timeNow) { - // This is a hack to update touch_Thr is it was changed.. - int old_thr = ctouchThrVal; - int result = updateAdjustMenu(timeNow, buttonChanges, stateFirstRun, updateSensorPixelsFlag); - bool redraw = false; - - updateSensorPixelsFlag = false; - stateFirstRun = 0; - buttonPressedAndNotUsed = 0; - - if(result < 0) { - // Go back to main menu - state = MAIN_MENU; - stateFirstRun = true; - } else { - redraw = result; + if((page->flags & EMenuPageRoot) && input.changed) + checkForPatchView(input.current); } - if( old_thr != ctouchThrVal) { - touch_Thr = map(ctouchThrVal,ctouchHiLimit,ctouchLoLimit,ttouchLoLimit,ttouchHiLimit); - } + return redraw; } + + //*********************************************************** + static void checkForPatchView(int buttons) { int trills = readTrills(); - switch (buttons){ - case BTN_MENU+BTN_DOWN: - break; - + switch (buttons) { case BTN_MENU+BTN_ENTER: if (trills) { - state = PATCH_VIEW; + menuState= PATCH_VIEW; stateFirstRun = 1; setFPS(trills, patch); } @@ -1009,14 +1006,16 @@ static void checkForPatchView(int buttons) { case BTN_MENU+BTN_UP: if (trills) { - state = PATCH_VIEW; + menuState= PATCH_VIEW; stateFirstRun = 1; clearFPS(trills); } break; + default: break; } } +//*********************************************************** // This should be moved to a separate file/process that handles only led static void statusBlink() { digitalWrite(statusLedPin,LOW); @@ -1030,12 +1029,219 @@ static void statusBlink() { //*********************************************************** -void menu() { - unsigned long timeNow = millis(); - const MenuPage *currentPage = nullptr; - bool redraw = stateFirstRun; - // read the state of the switches +static bool updateSensorPixelsFlag = false; +void drawSensorPixels() { + updateSensorPixelsFlag = true; +} + +//*********************************************************** + + +bool adjustPageUpdate(KeyState &input, uint32_t timeNow) { + // This is a hack to update touch_Thr is it was changed.. + int old_thr = ctouchThrVal; + int result = updateAdjustMenu(timeNow, input, stateFirstRun, updateSensorPixelsFlag); + bool redraw = false; + + updateSensorPixelsFlag = false; + stateFirstRun = 0; + + if(result < 0) { + // Go back to main menu + menuState= MAIN_MENU; + stateFirstRun = true; + } else { + redraw = result; + } + + if( old_thr != ctouchThrVal) { + touch_Thr = map(ctouchThrVal,ctouchHiLimit,ctouchLoLimit,ttouchLoLimit,ttouchHiLimit); + } + return redraw; +} + + +static bool patchPageUpdate(KeyState& input, uint32_t timeNow) { + bool redraw = false; + + if (stateFirstRun) { + display.ssd1306_command(SSD1306_DISPLAYON); + drawPatchView(); + patchViewTime = timeNow; + stateFirstRun = 0; + } + if ((timeNow - patchViewTime) > patchViewTimeUp) { + menuState= DISPLAYOFF_IDL; + stateFirstRun = 1; + doPatchUpdate = 1; + FPD = 0; + writeSetting(PATCH_ADDR,patch); + } + if (input.changed) { + patchViewTime = timeNow; + int trills = readTrills(); + switch (input.current){ + case BTN_DOWN: + // down + if (trills && (fastPatch[trills-1] > 0)){ + patch = fastPatch[trills-1]; + activePatch = 0; + doPatchUpdate = 1; + FPD = 1; + writeSetting(PATCH_ADDR,patch); + } else if (!trills){ + if (patch > 1){ + patch--; + } else patch = 128; + activePatch = 0; + doPatchUpdate = 1; + FPD = 0; + } + drawPatchView(); + redraw = true; + break; + case BTN_ENTER: + // enter + if (trills && (fastPatch[trills-1] > 0)){ + patch = fastPatch[trills-1]; + activePatch = 0; + doPatchUpdate = 1; + FPD = 1; + drawPatchView(); + redraw = true; + } + break; + case BTN_UP: + // up + if (trills && (fastPatch[trills-1] > 0)){ + patch = fastPatch[trills-1]; + activePatch = 0; + doPatchUpdate = 1; + FPD = 1; + writeSetting(PATCH_ADDR,patch); + } else if (!trills){ + if (patch < 128){ + patch++; + } else patch = 1; + activePatch = 0; + doPatchUpdate = 1; + FPD = 0; + } + drawPatchView(); + redraw = true; + break; + + case BTN_MENU: + if (FPD < 2){ + menuState= DISPLAYOFF_IDL; + stateFirstRun = 1; + doPatchUpdate = 1; + } + writeSetting(PATCH_ADDR,patch); + FPD = 0; + break; + + case BTN_MENU+BTN_ENTER: + midiPanic(); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(2); + display.setCursor(35,15); + display.println("DON'T"); + display.setCursor(35,30); + display.println("PANIC"); + redraw = true; + break; + + case BTN_MENU+BTN_ENTER+BTN_UP+BTN_DOWN: + //all keys depressed, reboot to programming mode + _reboot_Teensyduino_(); + } + } + + return redraw; +} + + +static bool idlePageUpdate(KeyState& __unused input, uint32_t __unused timeNow) { + bool redraw = false; + if (stateFirstRun) { + display.ssd1306_command(SSD1306_DISPLAYOFF); + display.clearDisplay(); + redraw = true; + stateFirstRun = 0; + } + if (input.changed) { + int trills = readTrills(); + switch (input.current){ + case BTN_UP: // fallthrough + case BTN_DOWN: + if (trills && (fastPatch[trills-1] > 0)){ + patch = fastPatch[trills-1]; + activePatch = 0; + doPatchUpdate = 1; + FPD = 1; + } // else if (!trills) buttonPressedAndNotUsed = 1; // <- TODO: this is now broken, all input is consumed... solve in another way. + menuState= PATCH_VIEW; + stateFirstRun = 1; + break; + + case BTN_ENTER: + if (trills && (fastPatch[trills-1] > 0)){ + patch = fastPatch[trills-1]; + activePatch = 0; + doPatchUpdate = 1; + FPD = 1; + } + menuState= PATCH_VIEW; + stateFirstRun = 1; + break; + + case BTN_MENU: + if (pinkyKey && (exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch breath activated legacy settings on/off + legacyBrAct = !legacyBrAct; + dipSwBits = dipSwBits ^ (1<<2); + writeSetting(DIPSW_BITS_ADDR,dipSwBits); + statusBlink(); + } else if ((exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch pb pad activated legacy settings control on/off + legacy = !legacy; + dipSwBits = dipSwBits ^ (1<<1); + writeSetting(DIPSW_BITS_ADDR,dipSwBits); + statusBlink(); + } else if (pinkyKey && !specialKey){ //hold pinky key for rotator menu, and if too high touch sensing blocks regular menu, touching special key helps + display.ssd1306_command(SSD1306_DISPLAYON); + menuState= ROTATOR_MENU; + stateFirstRun = 1; + } else { + display.ssd1306_command(SSD1306_DISPLAYON); + menuState= MAIN_MENU; + stateFirstRun = 1; + } + break; + + case BTN_UP | BTN_DOWN | BTN_ENTER | BTN_MENU: + //all keys depressed, reboot to programming mode + _reboot_Teensyduino_(); + } + } + return redraw; +} + + +//*********************************************************** + +static KeyState readInput(uint32_t timeNow) { + + static uint32_t lastDebounceTime = 0; // the last time the output pin was toggled + static uint32_t buttonRepeatTime = 0; + static uint32_t buttonPressedTime = 0; + static uint8_t lastDeumButtons = 0; + static uint8_t deumButtonState = 0; + + + KeyState keys = { deumButtonState, 0 }; + uint8_t deumButtons = 0x0f ^(digitalRead(dPin) | (digitalRead(ePin) << 1) | (digitalRead(uPin) << 2) | (digitalRead(mPin)<<3)); // check to see if you just pressed the button @@ -1048,230 +1254,65 @@ void menu() { lastDebounceTime = timeNow; } + if ((timeNow - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer than the debounce // delay, so take it as the actual current state: // if the button state has changed: if (deumButtons != deumButtonState) { + keys.current = deumButtons; + keys.changed = deumButtonState ^ deumButtons; + deumButtonState = deumButtons; menuTime = timeNow; - buttonPressedAndNotUsed = 1; buttonPressedTime = timeNow; } - if (((deumButtons == 1) || (deumButtons == 4)) && (timeNow - buttonPressedTime > buttonRepeatDelay) && (timeNow - buttonRepeatTime > buttonRepeatInterval)){ - buttonPressedAndNotUsed = 1; + if (((deumButtons == BTN_DOWN) || (deumButtons == BTN_UP)) && (timeNow - buttonPressedTime > buttonRepeatDelay) && (timeNow - buttonRepeatTime > buttonRepeatInterval)){ buttonRepeatTime = timeNow; + keys.changed = deumButtons; // Key repeat } } // save the reading. Next time through the loop, it'll be the lastButtonState: lastDeumButtons = deumButtons; - // shut off menu system if not used for a while (changes not stored by exiting a setting manually will not be stored in EEPROM) - if (state && ((timeNow - menuTime) > menuTimeUp)) { - state = DISPLAYOFF_IDL; - stateFirstRun = 1; + return keys; +} +void menu() { + unsigned long timeNow = millis(); + + bool redraw = stateFirstRun; + + KeyState input = readInput(timeNow); + // read the state of the switches + + // shut off menu system if not used for a while (changes not stored by exiting a setting manually will not be stored in EEPROM) + if (menuState&& ((timeNow - menuTime) > menuTimeUp)) { + menuState= DISPLAYOFF_IDL; + stateFirstRun = 1; subVibSquelch = 0; memset(activeSub, 0, sizeof(activeSub)); } - if (state == DISPLAYOFF_IDL) { - if (stateFirstRun) { - display.ssd1306_command(SSD1306_DISPLAYOFF); - stateFirstRun = 0; - } - if (buttonPressedAndNotUsed) { - buttonPressedAndNotUsed = 0; - int trills = readTrills(); - switch (deumButtonState){ - case BTN_UP: // fallthrough - case BTN_DOWN: - if (trills && (fastPatch[trills-1] > 0)){ - patch = fastPatch[trills-1]; - activePatch = 0; - doPatchUpdate = 1; - FPD = 1; - } else if (!trills) buttonPressedAndNotUsed = 1; - state = PATCH_VIEW; - stateFirstRun = 1; - break; - - case BTN_ENTER: - if (trills && (fastPatch[trills-1] > 0)){ - patch = fastPatch[trills-1]; - activePatch = 0; - doPatchUpdate = 1; - FPD = 1; - } - state = PATCH_VIEW; - stateFirstRun = 1; - break; - - case BTN_MENU: - if (pinkyKey && (exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch breath activated legacy settings on/off - legacyBrAct = !legacyBrAct; - dipSwBits = dipSwBits ^ (1<<2); - writeSetting(DIPSW_BITS_ADDR,dipSwBits); - statusBlink(); - } else if ((exSensor >= ((extracThrVal+extracMaxVal)/2))) { // switch pb pad activated legacy settings control on/off - legacy = !legacy; - dipSwBits = dipSwBits ^ (1<<1); - writeSetting(DIPSW_BITS_ADDR,dipSwBits); - statusBlink(); - } else if (pinkyKey && !specialKey){ //hold pinky key for rotator menu, and if too high touch sensing blocks regular menu, touching special key helps - display.ssd1306_command(SSD1306_DISPLAYON); - state = ROTATOR_MENU; - stateFirstRun = 1; - } else { - display.ssd1306_command(SSD1306_DISPLAYON); - state = MAIN_MENU; - stateFirstRun = 1; - } - break; - - case 15: - //all keys depressed, reboot to programming mode - _reboot_Teensyduino_(); - } - } - } else if (state == PATCH_VIEW) { - if (stateFirstRun) { - display.ssd1306_command(SSD1306_DISPLAYON); - drawPatchView(); - patchViewTime = timeNow; - stateFirstRun = 0; - } - if ((timeNow - patchViewTime) > patchViewTimeUp) { - state = DISPLAYOFF_IDL; - stateFirstRun = 1; - doPatchUpdate = 1; - FPD = 0; - writeSetting(PATCH_ADDR,patch); - } - if (buttonPressedAndNotUsed){ - buttonPressedAndNotUsed = 0; - patchViewTime = timeNow; - int trills = readTrills(); - switch (deumButtonState){ - case BTN_DOWN: - // down - if (trills && (fastPatch[trills-1] > 0)){ - patch = fastPatch[trills-1]; - activePatch = 0; - doPatchUpdate = 1; - FPD = 1; - writeSetting(PATCH_ADDR,patch); - } else if (!trills){ - if (patch > 1){ - patch--; - } else patch = 128; - activePatch = 0; - doPatchUpdate = 1; - FPD = 0; - } - drawPatchView(); - redraw = true; - break; - case BTN_ENTER: - // enter - if (trills && (fastPatch[trills-1] > 0)){ - patch = fastPatch[trills-1]; - activePatch = 0; - doPatchUpdate = 1; - FPD = 1; - drawPatchView(); - redraw = true; - } - break; - case BTN_UP: - // up - if (trills && (fastPatch[trills-1] > 0)){ - patch = fastPatch[trills-1]; - activePatch = 0; - doPatchUpdate = 1; - FPD = 1; - writeSetting(PATCH_ADDR,patch); - } else if (!trills){ - if (patch < 128){ - patch++; - } else patch = 1; - activePatch = 0; - doPatchUpdate = 1; - FPD = 0; - } - drawPatchView(); - redraw = true; - break; - - case BTN_MENU: - if (FPD < 2){ - state = DISPLAYOFF_IDL; - stateFirstRun = 1; - doPatchUpdate = 1; - } - writeSetting(PATCH_ADDR,patch); - FPD = 0; - break; - - case BTN_MENU+BTN_ENTER: - midiPanic(); - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(2); - display.setCursor(35,15); - display.println("DON'T"); - display.setCursor(35,30); - display.println("PANIC"); - redraw = true; - break; - - case BTN_MENU+BTN_ENTER+BTN_UP+BTN_DOWN: - //all keys depressed, reboot to programming mode - _reboot_Teensyduino_(); - } - } - } else if (state == MAIN_MENU) { // MAIN MENU HERE <<<<<<<<<<<<<<< - currentPage = &mainMenuPage; - if (stateFirstRun) { - drawMenuScreen(); - stateFirstRun = 0; - } - - if(activeSub[currentPage->cursor]) { - redraw |= updateSubMenu(*currentPage, timeNow); - } else { - bool hadButtons = buttonPressedAndNotUsed; - redraw |= updateMenuPage(*currentPage, timeNow); - if (hadButtons) - checkForPatchView(deumButtonState); - } - } else if (state == ROTATOR_MENU) { // ROTATOR MENU HERE <<<<<<<<<<<<<<< - currentPage = &rotatorMenuPage; - if (stateFirstRun) { - drawMenu(*currentPage); - stateFirstRun = 0; - } - if(activeSub[currentPage->cursor]) { - redraw |= updateSubMenu(*currentPage, timeNow); - } else { - bool hadButtons = buttonPressedAndNotUsed; - redraw |= updateMenuPage(*currentPage, timeNow); - if (hadButtons) - checkForPatchView(deumButtonState); - } - // end rotator menu - - } else if (state == ADJUST_MENU) { - adjustPageUpdate(buttonPressedAndNotUsed ? deumButtonState : 0, timeNow); - } else if (state == SETUP_BR_MENU) { // SETUP BREATH MENU HERE <<<<<<<<<<<<<< - redraw |= updatePage(breathMenuPage, timeNow); - } else if (state == SETUP_CT_MENU) { // SETUP CONTROLLERS MENU HERE <<<<<<<<<<<<< - redraw |= updatePage(controlMenuPage, timeNow); - } else if (state == VIBRATO_MENU) { // VIBRATO MENU HERE <<<<<<<<<<<<< - redraw |= updatePage(vibratoMenuPage, timeNow); + if (menuState== DISPLAYOFF_IDL) { + redraw |= updatePage((const MenuPage*)&idleMenuPage, input, timeNow); + } else if (menuState== PATCH_VIEW) { + redraw |= updatePage((const MenuPage*)&patchMenuPage, input, timeNow); + } else if (menuState== MAIN_MENU) { + redraw |= updatePage(&mainMenuPage, input, timeNow); + } else if (menuState== ROTATOR_MENU) { + redraw |= updatePage(&rotatorMenuPage, input, timeNow); + } else if (menuState== ADJUST_MENU) { + redraw |= updatePage((const MenuPage*)&adjustMenuPage, input, timeNow); + } else if (menuState== SETUP_BR_MENU) { + redraw |= updatePage(&breathMenuPage, input, timeNow); + } else if (menuState== SETUP_CT_MENU) { + redraw |= updatePage(&controlMenuPage, input, timeNow); + } else if (menuState== VIBRATO_MENU) { + redraw |= updatePage(&vibratoMenuPage, input, timeNow); } if(redraw) { diff --git a/NuEVI/menu.h b/NuEVI/menu.h index 16bbbf5..0d70a90 100644 --- a/NuEVI/menu.h +++ b/NuEVI/menu.h @@ -2,6 +2,7 @@ #define __MENU_H #include "Wiring.h" +#include "numenu.h" #define MENU_ROW_HEIGHT 9 #define MENU_HEADER_OFFSET 12 @@ -11,11 +12,11 @@ #define DISPLAYOFF_IDL 0 #define MAIN_MENU 1 #define PATCH_VIEW 2 -#define ADJUST_MENU 70 -#define SETUP_BR_MENU 80 -#define SETUP_CT_MENU 90 -#define ROTATOR_MENU 100 -#define VIBRATO_MENU 110 +#define ADJUST_MENU 3 +#define SETUP_BR_MENU 4 +#define SETUP_CT_MENU 5 +#define ROTATOR_MENU 6 +#define VIBRATO_MENU 7 #define ARR_LEN(a) (sizeof (a) / sizeof (a[0])) @@ -25,7 +26,6 @@ #define BTN_MENU 8 - extern const unsigned long debounceDelay; // the debounce time; increase if the output flickers extern const unsigned long buttonRepeatInterval; extern const unsigned long buttonRepeatDelay; @@ -33,9 +33,7 @@ extern const unsigned long cursorBlinkInterval; // the cursor blink toggle in extern const unsigned long patchViewTimeUp; // ms until patch view shuts off extern const unsigned long menuTimeUp; // menu shuts off after one minute of button inactivity - - -extern byte subVibSquelch; +extern byte subVibSquelch; // TODO: This is broken <- subVibSquelch is never set, we need another way to expose what menu is open. void initDisplay(); void showVersion(); @@ -44,7 +42,7 @@ void drawSensorPixels(); unsigned short readSetting(byte address); void writeSetting(byte address, unsigned short value); -int updateAdjustMenu(uint32_t timeNow, uint8_t buttons, bool firstRun, bool updateSensor); -bool adjustPageUpdate(uint16_t buttonChanges, uint32_t timeNow); +int updateAdjustMenu(uint32_t timeNow, KeyState &input, bool firstRun, bool drawSensor); +bool adjustPageUpdate(KeyState &input, uint32_t timeNow); #endif diff --git a/NuEVI/numenu.h b/NuEVI/numenu.h index c7d8de1..525d2cc 100644 --- a/NuEVI/numenu.h +++ b/NuEVI/numenu.h @@ -1,6 +1,15 @@ #ifndef __NUMENU_H #define __NUMENU_H +#include + +//*********************************************************** + +struct KeyState { + uint8_t current; + uint8_t changed; +}; + //*********************************************************** enum MenuType { @@ -18,6 +27,7 @@ enum MenuEntryFlags { enum MenuPageFlags { EMenuPageCustom = (1u<<0), EMenuPageRoot = (1u<<1), + EMenuCustomTitle = (1u << 2), }; @@ -45,22 +55,22 @@ struct MenuEntrySub { struct MenuEntryStateCh { enum MenuType type; const char* title; - byte state; + uint8_t state; }; struct MenuPage { const char* title; uint16_t flags; - byte cursor; - byte parentPage; - byte numEntries; + uint8_t cursor; + uint8_t parentPage; + uint8_t numEntries; const MenuEntry** entries; }; struct MenuPageCustom { const char* title; uint16_t flags; - bool (*menuUpdateFunc)(void); + bool (*menuUpdateFunc)(KeyState &input, uint32_t timeNow); }; //*********************************************************** @@ -77,5 +87,4 @@ struct AdjustMenuEntry { void (*saveFunc)(const AdjustMenuEntry&); }; - #endif