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.
This commit is contained in:
Mikael Degerfält 2019-06-23 16:55:25 +02:00
parent 9a595c0ffc
commit 5b59b4cd0f
4 changed files with 364 additions and 314 deletions

View file

@ -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;
}

View file

@ -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,114 +1029,42 @@ static void statusBlink() {
//***********************************************************
void menu() {
unsigned long timeNow = millis();
const MenuPage *currentPage = nullptr;
bool redraw = stateFirstRun;
// read the state of the switches
uint8_t deumButtons = 0x0f ^(digitalRead(dPin) | (digitalRead(ePin) << 1) | (digitalRead(uPin) << 2) | (digitalRead(mPin)<<3));
static bool updateSensorPixelsFlag = false;
void drawSensorPixels() {
updateSensorPixelsFlag = true;
}
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
//***********************************************************
// If the switch changed, due to noise or pressing:
if (deumButtons != lastDeumButtons) {
// reset the debouncing timer
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:
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;
// if the button state has changed:
if (deumButtons != deumButtonState) {
deumButtonState = deumButtons;
menuTime = timeNow;
buttonPressedAndNotUsed = 1;
buttonPressedTime = timeNow;
}
if (((deumButtons == 1) || (deumButtons == 4)) && (timeNow - buttonPressedTime > buttonRepeatDelay) && (timeNow - buttonRepeatTime > buttonRepeatInterval)){
buttonPressedAndNotUsed = 1;
buttonRepeatTime = timeNow;
}
}
// 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;
subVibSquelch = 0;
memset(activeSub, 0, sizeof(activeSub));
}
if (state == DISPLAYOFF_IDL) {
if (stateFirstRun) {
display.ssd1306_command(SSD1306_DISPLAYOFF);
updateSensorPixelsFlag = false;
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;
if(result < 0) {
// Go back to main menu
menuState= MAIN_MENU;
stateFirstRun = true;
} else {
display.ssd1306_command(SSD1306_DISPLAYON);
state = MAIN_MENU;
stateFirstRun = 1;
redraw = result;
}
break;
case 15:
//all keys depressed, reboot to programming mode
_reboot_Teensyduino_();
if( old_thr != ctouchThrVal) {
touch_Thr = map(ctouchThrVal,ctouchHiLimit,ctouchLoLimit,ttouchLoLimit,ttouchHiLimit);
}
}
} else if (state == PATCH_VIEW) {
return redraw;
}
static bool patchPageUpdate(KeyState& input, uint32_t timeNow) {
bool redraw = false;
if (stateFirstRun) {
display.ssd1306_command(SSD1306_DISPLAYON);
drawPatchView();
@ -1145,17 +1072,16 @@ void menu() {
stateFirstRun = 0;
}
if ((timeNow - patchViewTime) > patchViewTimeUp) {
state = DISPLAYOFF_IDL;
menuState= DISPLAYOFF_IDL;
stateFirstRun = 1;
doPatchUpdate = 1;
FPD = 0;
writeSetting(PATCH_ADDR,patch);
}
if (buttonPressedAndNotUsed){
buttonPressedAndNotUsed = 0;
if (input.changed) {
patchViewTime = timeNow;
int trills = readTrills();
switch (deumButtonState){
switch (input.current){
case BTN_DOWN:
// down
if (trills && (fastPatch[trills-1] > 0)){
@ -1208,7 +1134,7 @@ void menu() {
case BTN_MENU:
if (FPD < 2){
state = DISPLAYOFF_IDL;
menuState= DISPLAYOFF_IDL;
stateFirstRun = 1;
doPatchUpdate = 1;
}
@ -1233,45 +1159,160 @@ void menu() {
_reboot_Teensyduino_();
}
}
} else if (state == MAIN_MENU) { // MAIN MENU HERE <<<<<<<<<<<<<<<
currentPage = &mainMenuPage;
return redraw;
}
static bool idlePageUpdate(KeyState& __unused input, uint32_t __unused timeNow) {
bool redraw = false;
if (stateFirstRun) {
drawMenuScreen();
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;
if(activeSub[currentPage->cursor]) {
redraw |= updateSubMenu(*currentPage, timeNow);
} else {
bool hadButtons = buttonPressedAndNotUsed;
redraw |= updateMenuPage(*currentPage, timeNow);
if (hadButtons)
checkForPatchView(deumButtonState);
case BTN_ENTER:
if (trills && (fastPatch[trills-1] > 0)){
patch = fastPatch[trills-1];
activePatch = 0;
doPatchUpdate = 1;
FPD = 1;
}
} 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
menuState= PATCH_VIEW;
stateFirstRun = 1;
break;
} 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);
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
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (deumButtons != lastDeumButtons) {
// reset the debouncing timer
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;
buttonPressedTime = timeNow;
}
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;
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 (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) {

View file

@ -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

View file

@ -1,6 +1,15 @@
#ifndef __NUMENU_H
#define __NUMENU_H
#include <stdint.h>
//***********************************************************
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