diff --git a/src/Watchy.cpp b/src/Watchy.cpp index dc25287..6596b88 100644 --- a/src/Watchy.cpp +++ b/src/Watchy.cpp @@ -5,7 +5,7 @@ GxEPD2_BW Watchy::display( WatchyDisplay(DISPLAY_CS, DISPLAY_DC, DISPLAY_RES, DISPLAY_BUSY)); RTC_DATA_ATTR int guiState; -RTC_DATA_ATTR int menuIndex; +RTC_DATA_ATTR int mainMenuIndex = 0; RTC_DATA_ATTR BMA423 sensor; RTC_DATA_ATTR bool WIFI_CONFIGURED; RTC_DATA_ATTR bool BLE_CONFIGURED; @@ -13,7 +13,6 @@ RTC_DATA_ATTR weatherData currentWeather; RTC_DATA_ATTR int weatherIntervalCounter = -1; RTC_DATA_ATTR bool displayFullInit = true; RTC_DATA_ATTR long gmtOffset = 0; -RTC_DATA_ATTR bool alreadyInMenu = true; void Watchy::init(String datetime) { esp_sleep_wakeup_cause_t wakeup_reason; @@ -30,25 +29,12 @@ void Watchy::init(String datetime) { switch (wakeup_reason) { case ESP_SLEEP_WAKEUP_EXT0: // RTC Alarm RTC.read(currentTime); - switch (guiState) { - case WATCHFACE_STATE: - showWatchFace(true); // partial updates on tick - if (settings.vibrateOClock) { - if (currentTime.Minute == 0) { - // The RTC wakes us up once per minute - vibMotor(75, 4); - } + showWatchFace(true); // partial updates on tick + if (settings.vibrateOClock) { + if (currentTime.Minute == 0) { + // The RTC wakes us up once per minute + vibMotor(75, 4); } - break; - case MAIN_MENU_STATE: - // Return to watchface if in menu for more than one tick - if (alreadyInMenu) { - guiState = WATCHFACE_STATE; - showWatchFace(false); - } else { - alreadyInMenu = true; - } - break; } break; case ESP_SLEEP_WAKEUP_EXT1: // button Press @@ -96,159 +82,62 @@ void Watchy::deepSleep() { void Watchy::handleButtonPress() { uint64_t wakeupBit = esp_sleep_get_ext1_wakeup_status(); - // Menu Button + + // Wake up only from menu button if (wakeupBit & MENU_BTN_MASK) { - if (guiState == - WATCHFACE_STATE) { // enter menu state if coming from watch face - showMenu(menuIndex, false); - } else if (guiState == - MAIN_MENU_STATE) { // if already in menu, then select menu item - switch (menuIndex) { - case 0: - showAbout(); - break; - case 1: - showBuzz(); - break; - case 2: - showAccelerometer(); - break; - case 3: - setTime(); - break; - case 4: - setupWifi(); - break; - case 5: - showUpdateFW(); - break; - case 6: - showSyncNTP(); - break; - default: - break; - } - } else if (guiState == FW_UPDATE_STATE) { - updateFWBegin(); - } - } - // Back Button - else if (wakeupBit & BACK_BTN_MASK) { - if (guiState == MAIN_MENU_STATE) { // exit to watch face if already in menu - RTC.read(currentTime); - showWatchFace(false); - } else if (guiState == APP_STATE) { - showMenu(menuIndex, false); // exit to menu if already in app - } else if (guiState == FW_UPDATE_STATE) { - showMenu(menuIndex, false); // exit to menu if already in app - } else if (guiState == WATCHFACE_STATE) { - return; - } - } - // Up Button - else if (wakeupBit & UP_BTN_MASK) { - if (guiState == MAIN_MENU_STATE) { // increment menu index - menuIndex--; - if (menuIndex < 0) { - menuIndex = MENU_LENGTH - 1; - } - showMenu(menuIndex, true); - } else if (guiState == WATCHFACE_STATE) { - return; - } - } - // Down Button - else if (wakeupBit & DOWN_BTN_MASK) { - if (guiState == MAIN_MENU_STATE) { // decrement menu index - menuIndex++; - if (menuIndex > MENU_LENGTH - 1) { - menuIndex = 0; - } - showMenu(menuIndex, true); - } else if (guiState == WATCHFACE_STATE) { - return; - } - } - - /***************** fast menu *****************/ - bool timeout = false; - long lastTimeout = millis(); - pinMode(MENU_BTN_PIN, INPUT); - pinMode(BACK_BTN_PIN, INPUT); - pinMode(UP_BTN_PIN, INPUT); - pinMode(DOWN_BTN_PIN, INPUT); - while (!timeout) { - if (millis() - lastTimeout > 5000) { - timeout = true; + if (guiState == WATCHFACE_STATE) { // enter menu state if coming from watch face + showMainMenu(); } else { - if (digitalRead(MENU_BTN_PIN) == 1) { - lastTimeout = millis(); - if (guiState == - MAIN_MENU_STATE) { // if already in menu, then select menu item - switch (menuIndex) { - case 0: - showAbout(); - break; - case 1: - showBuzz(); - break; - case 2: - showAccelerometer(); - break; - case 3: - setTime(); - break; - case 4: - setupWifi(); - break; - case 5: - showUpdateFW(); - break; - case 6: - showSyncNTP(); - break; - default: - break; - } - } else if (guiState == FW_UPDATE_STATE) { - updateFWBegin(); - } - } else if (digitalRead(BACK_BTN_PIN) == 1) { - lastTimeout = millis(); - if (guiState == - MAIN_MENU_STATE) { // exit to watch face if already in menu - RTC.read(currentTime); - showWatchFace(false); - break; // leave loop - } else if (guiState == APP_STATE) { - showMenu(menuIndex, false); // exit to menu if already in app - } else if (guiState == FW_UPDATE_STATE) { - showMenu(menuIndex, false); // exit to menu if already in app - } - } else if (digitalRead(UP_BTN_PIN) == 1) { - lastTimeout = millis(); - if (guiState == MAIN_MENU_STATE) { // increment menu index - menuIndex--; - if (menuIndex < 0) { - menuIndex = MENU_LENGTH - 1; - } - showFastMenu(menuIndex); - } - } else if (digitalRead(DOWN_BTN_PIN) == 1) { - lastTimeout = millis(); - if (guiState == MAIN_MENU_STATE) { // decrement menu index - menuIndex++; - if (menuIndex > MENU_LENGTH - 1) { - menuIndex = 0; - } - showFastMenu(menuIndex); - } - } + return; } } } -void Watchy::showMenu(byte menuIndex, bool partialRefresh) { +void Watchy::showMainMenu() { + guiState = MAIN_MENU_STATE; + + const char *menuItems[] = { + "About Watchy", "Vibrate Motor", "Show Accelerometer", + "Set Time", "Setup WiFi", "Update Firmware", + "Sync NTP"}; + + int idx = getMenuSelection(menuItems, 7, mainMenuIndex, 6000); + switch (idx) { + case 0: + showAbout(); + break; + case 1: + showBuzz(); + break; + case 2: + showAccelerometer(); + break; + case 3: + setTime(); + break; + case 4: + setupWifi(); + break; + case 5: + showUpdateFW(); + break; + case 6: + showSyncNTP(); + break; + default: + break; + } + + if (guiState == MAIN_MENU_STATE) { // Getting out of main menu because of timeout or back button + RTC.read(currentTime); + showWatchFace(false); + } else { // Coming back to main menu from APP_STATE + mainMenuIndex = idx; + showMainMenu(); + } +} + +int Watchy::getMenuSelection(const char* menuItems[], int menuLength, int selectionStartIndex, int timeOut) { display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -257,63 +146,50 @@ void Watchy::showMenu(byte menuIndex, bool partialRefresh) { uint16_t w, h; int16_t yPos; - const char *menuItems[] = { - "About Watchy", "Vibrate Motor", "Show Accelerometer", - "Set Time", "Setup WiFi", "Update Firmware", - "Sync NTP"}; - for (int i = 0; i < MENU_LENGTH; i++) { - yPos = MENU_HEIGHT + (MENU_HEIGHT * i); - display.setCursor(0, yPos); - if (i == menuIndex) { - display.getTextBounds(menuItems[i], 0, yPos, &x1, &y1, &w, &h); - display.fillRect(x1 - 1, y1 - 10, 200, h + 15, GxEPD_WHITE); - display.setTextColor(GxEPD_BLACK); - display.println(menuItems[i]); - } else { - display.setTextColor(GxEPD_WHITE); - display.println(menuItems[i]); + int currentIndex = selectionStartIndex; + long lastTimeActive = millis(); + while (millis() - lastTimeActive < timeOut) { + for (int i = 0; i < menuLength; i++) { + yPos = MENU_HEIGHT + (MENU_HEIGHT * i); + display.setCursor(0, yPos); + if (i == currentIndex) { + display.getTextBounds(menuItems[i], 0, yPos, &x1, &y1, &w, &h); + display.fillRect(x1 - 1, y1 - 10, 200, h + 15, GxEPD_WHITE); + display.setTextColor(GxEPD_BLACK); + display.println(menuItems[i]); + } else { + display.setTextColor(GxEPD_WHITE); + display.println(menuItems[i]); + } + } + display.display(true); // partial refresh + + if (digitalRead(MENU_BTN_PIN) == 1) { + return currentIndex; + + } else if (digitalRead(BACK_BTN_PIN) == 1) { + return menuLength; + } else if (digitalRead(UP_BTN_PIN) == 1) { + lastTimeActive = millis(); + currentIndex--; + if (currentIndex < 0) { + currentIndex = menuLength - 1; + } + display.fillScreen(GxEPD_BLACK); + } else if (digitalRead(DOWN_BTN_PIN) == 1) { + lastTimeActive = millis(); + currentIndex++; + if (currentIndex > menuLength - 1) { + currentIndex = 0; + } + display.fillScreen(GxEPD_BLACK); } } - - display.display(partialRefresh); - - guiState = MAIN_MENU_STATE; - alreadyInMenu = false; -} - -void Watchy::showFastMenu(byte menuIndex) { - display.setFullWindow(); - display.fillScreen(GxEPD_BLACK); - display.setFont(&FreeMonoBold9pt7b); - - int16_t x1, y1; - uint16_t w, h; - int16_t yPos; - - const char *menuItems[] = { - "About Watchy", "Vibrate Motor", "Show Accelerometer", - "Set Time", "Setup WiFi", "Update Firmware", - "Sync NTP"}; - for (int i = 0; i < MENU_LENGTH; i++) { - yPos = MENU_HEIGHT + (MENU_HEIGHT * i); - display.setCursor(0, yPos); - if (i == menuIndex) { - display.getTextBounds(menuItems[i], 0, yPos, &x1, &y1, &w, &h); - display.fillRect(x1 - 1, y1 - 10, 200, h + 15, GxEPD_WHITE); - display.setTextColor(GxEPD_BLACK); - display.println(menuItems[i]); - } else { - display.setTextColor(GxEPD_WHITE); - display.println(menuItems[i]); - } - } - - display.display(true); - - guiState = MAIN_MENU_STATE; + return menuLength; } void Watchy::showAbout() { + guiState = APP_STATE; display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -332,12 +208,17 @@ void Watchy::showAbout() { display.print(voltage); display.println("V"); - display.display(false); // full refresh + display.display(true); // partial refresh - guiState = APP_STATE; + while (1) { + if (digitalRead(BACK_BTN_PIN) == 1 || digitalRead(MENU_BTN_PIN) == 1) { + break; + } + } } void Watchy::showBuzz() { + guiState = APP_STATE; display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -346,7 +227,6 @@ void Watchy::showBuzz() { display.println("Buzz!"); display.display(false); // full refresh vibMotor(); - showMenu(menuIndex, false); } void Watchy::vibMotor(uint8_t intervalMs, uint8_t length) { @@ -360,7 +240,6 @@ void Watchy::vibMotor(uint8_t intervalMs, uint8_t length) { } void Watchy::setTime() { - guiState = APP_STATE; RTC.read(currentTime); @@ -511,11 +390,10 @@ void Watchy::setTime() { tm.Second = 0; RTC.set(tm); - - showMenu(menuIndex, false); } void Watchy::showAccelerometer() { + guiState = APP_STATE; display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -526,8 +404,6 @@ void Watchy::showAccelerometer() { long previousMillis = 0; long interval = 200; - guiState = APP_STATE; - pinMode(BACK_BTN_PIN, INPUT); while (1) { @@ -580,11 +456,9 @@ void Watchy::showAccelerometer() { break; } } - display.display(true); // full refresh + display.display(true); // partial refresh } } - - showMenu(menuIndex, false); } void Watchy::showWatchFace(bool partialRefresh) { @@ -792,6 +666,7 @@ void Watchy::_bmaConfig() { } void Watchy::setupWifi() { + guiState = APP_STATE; display.epd2.setBusyCallback(0); // temporarily disable lightsleep on busy WiFiManager wifiManager; wifiManager.resetSettings(); @@ -812,9 +687,7 @@ void Watchy::setupWifi() { // turn off radios WiFi.mode(WIFI_OFF); btStop(); - display.epd2.setBusyCallback(displayBusyCallback); // enable lightsleep on - // busy - guiState = APP_STATE; + display.epd2.setBusyCallback(displayBusyCallback); // enable lightsleep on busy } void Watchy::_configModeCallback(WiFiManager *myWiFiManager) { @@ -851,6 +724,7 @@ bool Watchy::connectWiFi() { } void Watchy::showUpdateFW() { + guiState = APP_STATE; display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -867,7 +741,15 @@ void Watchy::showUpdateFW() { display.println("Keep USB powered"); display.display(false); // full refresh - guiState = FW_UPDATE_STATE; + while (1) { + if (digitalRead(MENU_BTN_PIN) == 1) { + updateFWBegin(); + break; + } + if (digitalRead(BACK_BTN_PIN) == 1) { + break; + } + } } void Watchy::updateFWBegin() { @@ -953,10 +835,10 @@ void Watchy::updateFWBegin() { // turn off radios WiFi.mode(WIFI_OFF); btStop(); - showMenu(menuIndex, false); } void Watchy::showSyncNTP() { + guiState = APP_STATE; display.setFullWindow(); display.fillScreen(GxEPD_BLACK); display.setFont(&FreeMonoBold9pt7b); @@ -997,7 +879,6 @@ void Watchy::showSyncNTP() { } display.display(true); // full refresh delay(3000); - showMenu(menuIndex, false); } bool Watchy::syncNTP() { // NTP sync - call after connecting to WiFi and diff --git a/src/Watchy.h b/src/Watchy.h index 77cc5e2..bc5829b 100644 --- a/src/Watchy.h +++ b/src/Watchy.h @@ -56,8 +56,7 @@ public: void vibMotor(uint8_t intervalMs = 100, uint8_t length = 20); void handleButtonPress(); - void showMenu(byte menuIndex, bool partialRefresh); - void showFastMenu(byte menuIndex); + void showMainMenu(); void showAbout(); void showBuzz(); void showAccelerometer(); @@ -75,10 +74,10 @@ public: void updateFWBegin(); void showWatchFace(bool partialRefresh); - virtual void drawWatchFace(); // override this method for different watch - // faces + virtual void drawWatchFace(); // override this method for different watch faces private: + int getMenuSelection(const char* menuItems[], int menuLength, int selectionStartIndex, int timeOut); void _bmaConfig(); static void _configModeCallback(WiFiManager *myWiFiManager); static uint16_t _readRegister(uint8_t address, uint8_t reg, uint8_t *data, @@ -88,7 +87,7 @@ private: }; extern RTC_DATA_ATTR int guiState; -extern RTC_DATA_ATTR int menuIndex; +extern RTC_DATA_ATTR int mainMenuIndex; extern RTC_DATA_ATTR BMA423 sensor; extern RTC_DATA_ATTR bool WIFI_CONFIGURED; extern RTC_DATA_ATTR bool BLE_CONFIGURED; diff --git a/src/config.h b/src/config.h index 4d84fa7..8c2a372 100644 --- a/src/config.h +++ b/src/config.h @@ -57,9 +57,7 @@ #define WATCHFACE_STATE -1 #define MAIN_MENU_STATE 0 #define APP_STATE 1 -#define FW_UPDATE_STATE 2 #define MENU_HEIGHT 25 -#define MENU_LENGTH 7 // set time #define SET_HOUR 0 #define SET_MINUTE 1