mirror of https://github.com/sqfmi/Watchy.git
Implement new showMainMenu() functionality and state handling
parent
ef0534e92b
commit
0c0fc8949b
353
src/Watchy.cpp
353
src/Watchy.cpp
|
@ -5,7 +5,7 @@ GxEPD2_BW<WatchyDisplay, WatchyDisplay::HEIGHT> 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue