From e55799f8a5ae71c6a3646a01626b165a5b9b34c9 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:41:03 +1100 Subject: [PATCH] tdpro settings screen updates and ui changes; gps baudrate selector kept to settings screen only; firmware version and build date updated --- examples/companion_radio/MyMesh.h | 2 +- .../companion_radio/ui-new/Settingsscreen.h | 302 +++++++++++------- examples/companion_radio/ui-new/UITask.cpp | 37 +-- 3 files changed, 202 insertions(+), 139 deletions(-) diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index eb593b38..47e13176 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -12,7 +12,7 @@ #endif #ifndef FIRMWARE_VERSION -#define FIRMWARE_VERSION "Meck v1.0.1" +#define FIRMWARE_VERSION "Meck v1.1" #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) diff --git a/examples/companion_radio/ui-new/Settingsscreen.h b/examples/companion_radio/ui-new/Settingsscreen.h index 999346df..9716c31c 100644 --- a/examples/companion_radio/ui-new/Settingsscreen.h +++ b/examples/companion_radio/ui-new/Settingsscreen.h @@ -51,6 +51,25 @@ extern MyMesh the_mesh; // --------------------------------------------------------------------------- #include "RadioPresets.h" +// --------------------------------------------------------------------------- +// GPS baud rate options (shared with UITask GPS home page overlay) +// --------------------------------------------------------------------------- +static const uint32_t GPS_BAUD_OPTIONS[] = { 0, 4800, 9600, 19200, 38400, 57600, 115200 }; +#define GPS_BAUD_OPTION_COUNT 7 + +static inline const char* gpsBaudLabel(uint32_t baud, char* buf, int bufLen) { + if (baud == 0) return "Default (38400)"; + snprintf(buf, bufLen, "%lu", (unsigned long)baud); + return buf; +} + +static inline int findGpsBaudIndex(uint32_t baud) { + for (int i = 0; i < GPS_BAUD_OPTION_COUNT; i++) { + if (GPS_BAUD_OPTIONS[i] == baud) return i; + } + return 0; +} + // --------------------------------------------------------------------------- // Settings row types // --------------------------------------------------------------------------- @@ -64,10 +83,11 @@ enum SettingsRowType : uint8_t { ROW_TX_POWER, // TX power (1-20 dBm) ROW_UTC_OFFSET, // UTC offset (-12 to +14) ROW_MSG_NOTIFY, // Keyboard flash on new msg toggle - ROW_DARK_MODE, // Dark mode toggle (inverted display) #if defined(LilyGo_T5S3_EPaper_Pro) + ROW_DARK_MODE, // Dark mode toggle (inverted display) ROW_PORTRAIT_MODE, // Portrait orientation toggle #endif + ROW_GPS_BAUD, // GPS baud rate picker (requires reboot) ROW_PATH_HASH_SIZE, // Path hash size (1, 2, or 3 bytes per hop) #ifdef MECK_WIFI_COMPANION ROW_WIFI_SETUP, // WiFi SSID/password configuration @@ -84,6 +104,8 @@ enum SettingsRowType : uint8_t { ROW_AUTOADD_ROOM, // Toggle: auto-add Room Servers ROW_AUTOADD_SENSOR, // Toggle: auto-add Sensors ROW_AUTOADD_OVERWRITE, // Toggle: overwrite oldest non-favourite when full + ROW_CONTACTS_SUBMENU, // Folder row → enters Contacts sub-screen + ROW_CHANNELS_SUBMENU, // Folder row → enters Channels sub-screen ROW_CH_HEADER, // "--- Channels ---" separator ROW_CHANNEL, // A channel entry (dynamic, index stored separately) ROW_ADD_CHANNEL, // "+ Add Hashtag Channel" @@ -111,6 +133,15 @@ enum EditMode : uint8_t { #endif }; +// --------------------------------------------------------------------------- +// Settings sub-screens (collapsible sections) +// --------------------------------------------------------------------------- +enum SubScreen : uint8_t { + SUB_NONE, // Top-level settings list + SUB_CONTACTS, // Contacts settings sub-screen + SUB_CHANNELS, // Channels management sub-screen +}; + // Max rows in the settings list (increased for contact sub-toggles + WiFi) #if defined(HAS_4G_MODEM) && defined(MECK_WIFI_COMPANION) #define SETTINGS_MAX_ROWS 56 // Extra rows for IMEI, Carrier, APN, contacts, WiFi @@ -153,6 +184,10 @@ private: // Onboarding mode bool _onboarding; + // Sub-screen navigation + SubScreen _subScreen; + int _savedTopCursor; // cursor position to restore when leaving sub-screen + // Dirty flag for radio params — prompt to apply bool _radioChanged; @@ -240,66 +275,68 @@ private: void rebuildRows() { _numRows = 0; - addRow(ROW_NAME); - addRow(ROW_RADIO_PRESET); - addRow(ROW_FREQ); - addRow(ROW_BW); - addRow(ROW_SF); - addRow(ROW_CR); - addRow(ROW_TX_POWER); - addRow(ROW_UTC_OFFSET); - addRow(ROW_MSG_NOTIFY); - addRow(ROW_PATH_HASH_SIZE); - addRow(ROW_DARK_MODE); -#if defined(LilyGo_T5S3_EPaper_Pro) - addRow(ROW_PORTRAIT_MODE); -#endif - #ifdef MECK_WIFI_COMPANION - addRow(ROW_WIFI_SETUP); - addRow(ROW_WIFI_TOGGLE); - #endif - #ifdef HAS_4G_MODEM - addRow(ROW_MODEM_TOGGLE); - // addRow(ROW_RINGTONE); - #endif - - // --- Contacts section --- - addRow(ROW_CONTACT_HEADER); - addRow(ROW_CONTACT_MODE); - - // Show per-type sub-toggles only in Custom mode - if (getContactMode() == CONTACT_MODE_CUSTOM) { - addRow(ROW_AUTOADD_CHAT); - addRow(ROW_AUTOADD_REPEATER); - addRow(ROW_AUTOADD_ROOM); - addRow(ROW_AUTOADD_SENSOR); - addRow(ROW_AUTOADD_OVERWRITE); - } - - // --- Channels section --- - addRow(ROW_CH_HEADER); - - // Enumerate current channels - for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) { - ChannelDetails ch; - if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') { - addRow(ROW_CHANNEL, i); - } else { - break; // channels are contiguous + if (_subScreen == SUB_CONTACTS) { + // --- Contacts sub-screen: only contact-related rows --- + addRow(ROW_CONTACT_MODE); + if (getContactMode() == CONTACT_MODE_CUSTOM) { + addRow(ROW_AUTOADD_CHAT); + addRow(ROW_AUTOADD_REPEATER); + addRow(ROW_AUTOADD_ROOM); + addRow(ROW_AUTOADD_SENSOR); + addRow(ROW_AUTOADD_OVERWRITE); } + } else if (_subScreen == SUB_CHANNELS) { + // --- Channels sub-screen: only channel-related rows --- + for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) { + ChannelDetails ch; + if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') { + addRow(ROW_CHANNEL, i); + } else { + break; + } + } + addRow(ROW_ADD_CHANNEL); + } else { + // --- Top-level settings list --- + addRow(ROW_NAME); + addRow(ROW_RADIO_PRESET); + addRow(ROW_FREQ); + addRow(ROW_BW); + addRow(ROW_SF); + addRow(ROW_CR); + addRow(ROW_TX_POWER); + addRow(ROW_UTC_OFFSET); + addRow(ROW_MSG_NOTIFY); + addRow(ROW_GPS_BAUD); + addRow(ROW_PATH_HASH_SIZE); +#if defined(LilyGo_T5S3_EPaper_Pro) + addRow(ROW_DARK_MODE); + addRow(ROW_PORTRAIT_MODE); +#endif + #ifdef MECK_WIFI_COMPANION + addRow(ROW_WIFI_SETUP); + addRow(ROW_WIFI_TOGGLE); + #endif + #ifdef HAS_4G_MODEM + addRow(ROW_MODEM_TOGGLE); + #endif + + // Folder rows for sub-screens + addRow(ROW_CONTACTS_SUBMENU); + addRow(ROW_CHANNELS_SUBMENU); + + // Info section (stays at top level) + addRow(ROW_INFO_HEADER); + addRow(ROW_PUB_KEY); + addRow(ROW_FIRMWARE); + + #ifdef HAS_4G_MODEM + addRow(ROW_IMEI); + addRow(ROW_OPERATOR_INFO); + addRow(ROW_APN); + #endif } - addRow(ROW_ADD_CHANNEL); - addRow(ROW_INFO_HEADER); - addRow(ROW_PUB_KEY); - addRow(ROW_FIRMWARE); - - #ifdef HAS_4G_MODEM - addRow(ROW_IMEI); - addRow(ROW_OPERATOR_INFO); - addRow(ROW_APN); - #endif - // Clamp cursor if (_cursor >= _numRows) _cursor = _numRows - 1; if (_cursor < 0) _cursor = 0; @@ -321,7 +358,7 @@ private: #ifdef HAS_4G_MODEM && t != ROW_IMEI && t != ROW_OPERATOR_INFO #endif - ; + ; // ROW_CONTACTS_SUBMENU and ROW_CHANNELS_SUBMENU ARE selectable } void skipNonSelectable(int dir) { @@ -439,12 +476,15 @@ public: _numRows(0), _cursor(0), _scrollTop(0), _editMode(EDIT_NONE), _editPos(0), _editPickerIdx(0), _editFloat(0), _editInt(0), _confirmAction(0), - _onboarding(false), _radioChanged(false) { + _onboarding(false), _subScreen(SUB_NONE), _savedTopCursor(0), + _radioChanged(false) { memset(_editBuf, 0, sizeof(_editBuf)); } void enter() { _editMode = EDIT_NONE; + _subScreen = SUB_NONE; + _savedTopCursor = 0; _cursor = 0; _scrollTop = 0; _radioChanged = false; @@ -477,42 +517,6 @@ public: bool isEditing() const { return _editMode != EDIT_NONE; } bool hasRadioChanges() const { return _radioChanged; } - // Returns true when cursor is on a non-public channel row (deletable) - bool isCursorOnDeletableChannel() const { - if (_cursor < 0 || _cursor >= _numRows) return false; - return _rows[_cursor].type == ROW_CHANNEL && _rows[_cursor].param > 0 - && _editMode == EDIT_NONE; - } - - // T5S3 VKB integration for text editing (channel name, device name, freq, APN) - bool isEditingText() const { return _editMode == EDIT_TEXT; } - bool isEditingNumOrPicker() const { return _editMode == EDIT_NUMBER || _editMode == EDIT_PICKER; } - const char* getEditBuf() const { return _editBuf; } - - // Get a suitable VKB label for the current text edit field - const char* getEditLabel() const { - if (_cursor < 0 || _cursor >= _numRows) return "Edit"; - switch (_rows[_cursor].type) { - case ROW_NAME: return "Device Name"; - case ROW_ADD_CHANNEL: return "Add Channel"; - case ROW_FREQ: return "Frequency"; - #ifdef HAS_4G_MODEM - case ROW_APN: return "Edit APN"; - #endif - default: return "Edit"; - } - } - - // Fill edit buffer with VKB result and confirm via Enter - void submitEditText(const char* text) { - int len = strlen(text); - if (len >= SETTINGS_TEXT_BUF) len = SETTINGS_TEXT_BUF - 1; - memcpy(_editBuf, text, len); - _editBuf[len] = '\0'; - _editPos = len; - handleKeyInput('\r'); // trigger existing confirm logic - } - // --------------------------------------------------------------------------- // WiFi scan helpers // --------------------------------------------------------------------------- @@ -664,6 +668,10 @@ public: display.setCursor(0, 0); if (_onboarding) { display.print("Welcome! Setup"); + } else if (_subScreen == SUB_CONTACTS) { + display.print("Settings > Contacts"); + } else if (_subScreen == SUB_CHANNELS) { + display.print("Settings > Channels"); } else { display.print("Settings"); } @@ -809,13 +817,26 @@ public: display.print(tmp); break; + case ROW_GPS_BAUD: { + char baudStr[16]; + if (editing && _editMode == EDIT_PICKER) { + snprintf(tmp, sizeof(tmp), "< GPS Baud: %s > *", + gpsBaudLabel(GPS_BAUD_OPTIONS[_editPickerIdx], baudStr, sizeof(baudStr))); + } else { + snprintf(tmp, sizeof(tmp), "GPS Baud: %s *", + gpsBaudLabel(_prefs->gps_baudrate, baudStr, sizeof(baudStr))); + } + display.print(tmp); + break; + } + +#if defined(LilyGo_T5S3_EPaper_Pro) case ROW_DARK_MODE: snprintf(tmp, sizeof(tmp), "Dark Mode: %s", _prefs->dark_mode ? "ON" : "OFF"); display.print(tmp); break; -#if defined(LilyGo_T5S3_EPaper_Pro) case ROW_PORTRAIT_MODE: snprintf(tmp, sizeof(tmp), "Portrait Mode: %s", _prefs->portrait_mode ? "ON" : "OFF"); @@ -853,6 +874,17 @@ public: // break; #endif + // --- Submenu folder rows --- + case ROW_CONTACTS_SUBMENU: + display.setColor(selected ? DisplayDriver::DARK : DisplayDriver::GREEN); + display.print("Contacts >>"); + break; + + case ROW_CHANNELS_SUBMENU: + display.setColor(selected ? DisplayDriver::DARK : DisplayDriver::GREEN); + display.print("Channels >>"); + break; + // --- Contacts section --- case ROW_CONTACT_HEADER: display.setColor(DisplayDriver::YELLOW); @@ -917,11 +949,7 @@ public: snprintf(tmp, sizeof(tmp), " %s", ch.name); if (selected) { // Show delete hint on right -#if defined(LilyGo_T5S3_EPaper_Pro) - const char* hint = "Hold:Delete"; -#else const char* hint = "Del:X"; -#endif int hintW = display.getTextWidth(hint); display.setCursor(display.width() - hintW - 2, y); display.print(hint); @@ -1035,11 +1063,7 @@ public: } else if (_confirmAction == 2) { display.drawTextCentered(display.width() / 2, by + 4, "Apply radio changes?"); } -#if defined(LilyGo_T5S3_EPaper_Pro) - display.drawTextCentered(display.width() / 2, by + bh - 14, "Tap:Yes Boot:No"); -#else display.drawTextCentered(display.width() / 2, by + bh - 14, "Enter:Yes Q:No"); -#endif display.setTextSize(1); } @@ -1137,10 +1161,17 @@ public: #if defined(LilyGo_T5S3_EPaper_Pro) if (_editMode == EDIT_NONE) { - display.print("Swipe:Scroll"); - const char* r = "Tap:Toggle Hold:Edit"; - display.setCursor(display.width() - display.getTextWidth(r) - 2, footerY); - display.print(r); + if (_subScreen != SUB_NONE) { + display.print("Boot:Back"); + const char* r = "Tap:Toggle Hold:Edit"; + display.setCursor(display.width() - display.getTextWidth(r) - 2, footerY); + display.print(r); + } else { + display.print("Swipe:Scroll"); + const char* r = "Tap:Toggle Hold:Edit"; + display.setCursor(display.width() - display.getTextWidth(r) - 2, footerY); + display.print(r); + } } else if (_editMode == EDIT_NUMBER) { display.print("Swipe:Adjust"); const char* r = "Tap:OK Boot:Cancel"; @@ -1199,7 +1230,11 @@ public: } else if (_editMode == EDIT_CONFIRM) { // Footer already covered by overlay } else { - display.print("Q:Bck"); + if (_subScreen != SUB_NONE) { + display.print("Q:Back"); + } else { + display.print("Q:Bck"); + } const char* r = "W/S:Up/Dwn Entr:Chng"; display.setCursor(display.width() - display.getTextWidth(r) - 2, footerY); display.print(r); @@ -1426,6 +1461,9 @@ public: if (type == ROW_CONTACT_MODE) { _editPickerIdx--; if (_editPickerIdx < 0) _editPickerIdx = CONTACT_MODE_COUNT - 1; + } else if (type == ROW_GPS_BAUD) { + _editPickerIdx--; + if (_editPickerIdx < 0) _editPickerIdx = GPS_BAUD_OPTION_COUNT - 1; } else { // Radio preset _editPickerIdx--; @@ -1437,6 +1475,9 @@ public: if (type == ROW_CONTACT_MODE) { _editPickerIdx++; if (_editPickerIdx >= CONTACT_MODE_COUNT) _editPickerIdx = 0; + } else if (type == ROW_GPS_BAUD) { + _editPickerIdx++; + if (_editPickerIdx >= GPS_BAUD_OPTION_COUNT) _editPickerIdx = 0; } else { // Radio preset _editPickerIdx++; @@ -1448,6 +1489,12 @@ public: if (type == ROW_CONTACT_MODE) { applyContactMode(_editPickerIdx); _editMode = EDIT_NONE; + } else if (type == ROW_GPS_BAUD) { + _prefs->gps_baudrate = GPS_BAUD_OPTIONS[_editPickerIdx]; + the_mesh.savePrefs(); + _editMode = EDIT_NONE; + Serial.printf("Settings: GPS baud set to %lu (reboot to apply)\n", + (unsigned long)_prefs->gps_baudrate); } else { // Apply radio preset if (_editPickerIdx >= 0 && _editPickerIdx < (int)NUM_RADIO_PRESETS) { @@ -1627,13 +1674,16 @@ public: case ROW_PATH_HASH_SIZE: startEditInt(_prefs->path_hash_mode + 1); // display as 1-3 break; + case ROW_GPS_BAUD: + startEditPicker(findGpsBaudIndex(_prefs->gps_baudrate)); + break; +#if defined(LilyGo_T5S3_EPaper_Pro) case ROW_DARK_MODE: _prefs->dark_mode = _prefs->dark_mode ? 0 : 1; the_mesh.savePrefs(); Serial.printf("Settings: Dark mode = %s\n", _prefs->dark_mode ? "ON" : "OFF"); break; -#if defined(LilyGo_T5S3_EPaper_Pro) case ROW_PORTRAIT_MODE: _prefs->portrait_mode = _prefs->portrait_mode ? 0 : 1; the_mesh.savePrefs(); @@ -1748,6 +1798,24 @@ public: (_prefs->autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) ? "ON" : "OFF"); break; + // --- Submenu folder rows --- + case ROW_CONTACTS_SUBMENU: + _savedTopCursor = _cursor; + _subScreen = SUB_CONTACTS; + _cursor = 0; + _scrollTop = 0; + rebuildRows(); + Serial.println("Settings: entered Contacts sub-screen"); + break; + case ROW_CHANNELS_SUBMENU: + _savedTopCursor = _cursor; + _subScreen = SUB_CHANNELS; + _cursor = 0; + _scrollTop = 0; + rebuildRows(); + Serial.println("Settings: entered Channels sub-screen"); + break; + case ROW_ADD_CHANNEL: startEditText(""); break; @@ -1771,8 +1839,18 @@ public: } } - // Q: back — if radio changed, prompt to apply first + // Q: back -- if in sub-screen, return to top level; else exit settings if (c == 'q' || c == 'Q') { + if (_subScreen != SUB_NONE) { + // Return to top-level settings list + _subScreen = SUB_NONE; + rebuildRows(); + _cursor = _savedTopCursor; + if (_cursor >= _numRows) _cursor = _numRows - 1; + skipNonSelectable(1); + Serial.println("Settings: back to top level"); + return true; + } if (_radioChanged) { _editMode = EDIT_CONFIRM; _confirmAction = 2; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index a5251b38..7080667f 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -138,6 +138,7 @@ class HomeScreen : public UIScreen { unsigned long _shutdown_at; // earliest time to proceed with shutdown (after e-ink refresh) bool _editing_utc; int8_t _saved_utc_offset; // for cancel/undo + AdvertPath recent[UI_RECENT_LIST_SIZE]; @@ -254,7 +255,7 @@ public: _shutdown_init(false), _shutdown_at(0), _editing_utc(false), _saved_utc_offset(0), sensors_lpp(200) { } bool isEditingUTC() const { return _editing_utc; } - void cancelEditUTC() { + void cancelEditing() { if (_editing_utc) { _node_prefs->utc_offset_hours = _saved_utc_offset; _editing_utc = false; @@ -666,7 +667,9 @@ public: display.drawTextLeftAlign(0, y, "time(U)"); display.drawTextRightAlign(display.width()-1, y, "no sync"); } + y = y + 12; } + // UTC offset editor overlay if (_editing_utc) { // Draw background box @@ -686,6 +689,7 @@ public: display.drawTextCentered(display.width() / 2, by + bh - 10, "W/S:adj Enter:ok Q:cancel"); display.setTextSize(1); } + #endif #if UI_SENSORS_PAGE == 1 } else if (_page == HomePage::SENSORS) { @@ -842,11 +846,7 @@ public: #endif } } -#if defined(LilyGo_T5S3_EPaper_Pro) - return _editing_utc ? 700 : 2000; // Faster refresh for touch-only (no key to force update) -#else - return _editing_utc ? 700 : 5000; // match e-ink refresh cycle while editing UTC -#endif + return _editing_utc ? 700 : 5000; } bool handleInput(char c) override { @@ -1179,11 +1179,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no map_screen = nullptr; #endif - // Apply saved dark mode preference before first render +#if defined(LilyGo_T5S3_EPaper_Pro) + // Apply saved display preferences before first render if (_node_prefs->dark_mode) { ::display.setDarkMode(true); } -#if defined(LilyGo_T5S3_EPaper_Pro) if (_node_prefs->portrait_mode) { ::display.setPortraitMode(true); } @@ -1278,16 +1278,9 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i #endif if (_display != NULL) { -#if defined(LilyGo_T5S3_EPaper_Pro) - // E-ink: always wake — no backlight cost, and stale image shows wrong MSG count - if (!_display->isOn()) { - _display->turnOn(); - } -#else if (!_display->isOn() && !hasConnection()) { _display->turnOn(); } -#endif if (_display->isOn()) { _auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer _next_refresh = 100; // trigger refresh @@ -1552,11 +1545,11 @@ if (curr) curr->poll(); if (_display != NULL && _display->isOn()) { if (millis() >= _next_refresh && curr) { - // Sync dark mode with prefs (settings toggle takes effect here) +#if defined(LilyGo_T5S3_EPaper_Pro) + // Sync display modes with prefs (settings toggles take effect here) if (_node_prefs && display.isDarkMode() != (_node_prefs->dark_mode != 0)) { display.setDarkMode(_node_prefs->dark_mode != 0); } -#if defined(LilyGo_T5S3_EPaper_Pro) if (_node_prefs && display.isPortraitMode() != (_node_prefs->portrait_mode != 0)) { display.setPortraitMode(_node_prefs->portrait_mode != 0); // Text reader layout depends on orientation — force recalculation @@ -1839,14 +1832,6 @@ void UITask::onVKBSubmit() { if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB); break; } - case VKB_SETTINGS_TEXT: { - SettingsScreen* ss = (SettingsScreen*)settings_screen; - if (ss) { - ss->submitEditText(text); // Fills buffer + triggers Enter confirm - } - if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB); - break; - } case VKB_NOTES: { NotesScreen* notes = (NotesScreen*)getNotesScreen(); if (notes && strlen(text) > 0) { @@ -2006,7 +1991,7 @@ void UITask::injectKey(char c) { void UITask::gotoHomeScreen() { // Cancel any active editing state when navigating to home - ((HomeScreen *) home)->cancelEditUTC(); + ((HomeScreen *) home)->cancelEditing(); setCurrScreen(home); if (_display != NULL && !_display->isOn()) { _display->turnOn();