diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index d48647b3dd3..aced739dc45 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -197,11 +197,10 @@ class HomeScreen : public UIScreen { sensors_nb ++; } sensors_scroll = sensors_nb > UI_RECENT_LIST_SIZE; -#if AUTO_OFF_MILLIS > 0 - next_sensors_refresh = millis() + 5000; // refresh sensor values every 5 sec -#else - next_sensors_refresh = millis() + 60000; // refresh sensor values every 1 min -#endif + if (display.isEink()) // preserve eink displays + next_sensors_refresh = millis() + 60000; // refresh sensor values every 1 min + else + next_sensors_refresh = millis() + 5000; // refresh sensor values every 5 sec } } @@ -703,11 +702,7 @@ class MsgPreviewScreen : public UIScreen { display.translateUTF8ToBlocks(filtered_msg, p->msg, sizeof(filtered_msg)); display.printWordWrap(filtered_msg, display.width()); -#if AUTO_OFF_MILLIS==0 // probably e-ink - return 10000; // 10 s -#else - return 1000; // next render after 1000 ms -#endif + return display.isEink() ? 10000 : 1000; // 10 s for eink } bool handleInput(char c) override { @@ -739,6 +734,9 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no #if defined(PIN_USER_BTN_ANA) analog_btn.begin(); #endif +#if defined(BACKLIGHT_BTN) + backlight_btn.begin(); +#endif _node_prefs = node_prefs; @@ -910,9 +908,11 @@ void UITask::shutdown(bool restart){ if (restart) { _board->reboot(); } else { - display.forceFullRefresh(); - display.clear(); - display.endFrame(); + if (_display->isEink()) { + _display->blankScreen(); + _display->turnOff(); + _display->powerOff(); + } // Power off board including radio, display, GPS and components _board->powerOff(); } @@ -957,7 +957,9 @@ void UITask::loop() { if (ev == BUTTON_EVENT_CLICK) { c = checkDisplayOn(KEY_ENTER); } else if (ev == BUTTON_EVENT_LONG_PRESS) { + display.blankScreen(); display.turnOff(); + display.powerOff(); } else if (ev == BUTTON_EVENT_DOUBLE_CLICK) { c = handleDoubleClick(KEY_SELECT); } else if (ev == BUTTON_EVENT_TRIPLE_CLICK) { @@ -1002,13 +1004,31 @@ void UITask::loop() { #endif #if defined(BACKLIGHT_BTN) if (millis() > next_backlight_btn_check) { - bool touch_state = digitalRead(PIN_BUTTON2); + if (backlight_btn.isPressed()) { + if (!_display->isOn()) { + _display->turnOn(); + _next_refresh = 0; + } + _auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer + backlight_btn_pressed_at = millis(); // still pressed + } + bool touch_state = (millis() - backlight_btn_pressed_at > 5000); + // Backlight button events + int bev = backlight_btn.check(); + if (bev == BUTTON_EVENT_DOUBLE_CLICK) { + _display->forceFullRefresh(); + } else if (bev == BUTTON_EVENT_TRIPLE_CLICK) { + _display->blankScreen(); + _display->turnOff(); + _display->powerOff(); + backlight_btn_pressed_at = 0; + } #if defined(DISP_BACKLIGHT) digitalWrite(DISP_BACKLIGHT, !touch_state); #elif defined(EXP_PIN_BACKLIGHT) expander.digitalWrite(EXP_PIN_BACKLIGHT, !touch_state); #endif - next_backlight_btn_check = millis() + 300; + next_backlight_btn_check = millis() + 100; } #endif @@ -1056,6 +1076,12 @@ void UITask::loop() { } #endif if (millis() > _auto_off) { + #ifdef EINK_SCREENOFF_BLANK + if (curr != msg_preview) { // don't blank if messages are waiting + _display->blankScreen(); + _display->powerOff(); + } + #endif _display->turnOff(); } #endif diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 361b04d0125..4d44bfe1a6e 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -61,7 +61,8 @@ class UITask : public AbstractUITask { unsigned long _alert_expiry; int _msgcount; unsigned long ui_started_at, next_batt_chck; - int next_backlight_btn_check = 0; + unsigned long next_backlight_btn_check = 0; + unsigned long backlight_btn_pressed_at = 0; #ifdef PIN_STATUS_LED int led_state = 0; int next_led_change = 0; diff --git a/src/helpers/ui/DisplayDriver.h b/src/helpers/ui/DisplayDriver.h index 3e9e2dde86f..58147aa0e75 100644 --- a/src/helpers/ui/DisplayDriver.h +++ b/src/helpers/ui/DisplayDriver.h @@ -26,6 +26,8 @@ class DisplayDriver { virtual void forceFullRefresh() {} // next refresh will be full for eink virtual void turnOn() = 0; virtual void turnOff() = 0; + virtual void blankScreen() {} // to cleanly erase screen before turning off + virtual void powerOff() {} virtual void clear() = 0; virtual void startFrame(ColorVal bkg = UIColor::window_bkg) = 0; virtual void setTextSize(int sz) = 0; diff --git a/src/helpers/ui/GxEPDDisplay.cpp b/src/helpers/ui/GxEPDDisplay.cpp index 332157eb8d1..ce09423e11a 100644 --- a/src/helpers/ui/GxEPDDisplay.cpp +++ b/src/helpers/ui/GxEPDDisplay.cpp @@ -75,20 +75,27 @@ void GxEPDDisplay::turnOn() { } } -void GxEPDDisplay::turnOff() { +void GxEPDDisplay::powerOff() { + display.hibernate(); +} + +void GxEPDDisplay::turnOff() { // Only stops refresh #if defined(DISP_BACKLIGHT) && !defined(BACKLIGHT_BTN) digitalWrite(DISP_BACKLIGHT, LOW); #elif defined(EXP_PIN_BACKLIGHT) && !defined(BACKLIGHT_BTN) expander.digitalWrite(EXP_PIN_BACKLIGHT, LOW); #endif _isOn = false; + last_display_crc_value=0; +} + +void GxEPDDisplay::blankScreen() { // do full refresh before powering off to clear screen // no full refresh needed at wakeup display.clearScreen(0xFF); // Clears microcontroller side RAM display.writeScreenBuffer(0xFF); // Forces 0xFF (White) into the display controller's history registers resetPartialRefreshCounter(); last_display_crc_value=0; - display.hibernate(); } void GxEPDDisplay::clear() { diff --git a/src/helpers/ui/GxEPDDisplay.h b/src/helpers/ui/GxEPDDisplay.h index 8a37b72cc69..462744026bd 100644 --- a/src/helpers/ui/GxEPDDisplay.h +++ b/src/helpers/ui/GxEPDDisplay.h @@ -60,6 +60,8 @@ class GxEPDDisplay : public DisplayDriver { void resetPartialRefreshCounter() { _cycles_before_full_refresh = max_partial_refresh; }; void turnOn() override; void turnOff() override; + void blankScreen() override; + void powerOff() override; void clear() override; void startFrame(ColorVal bkg = UIColor::window_bkg) override; void setTextSize(int sz) override; diff --git a/variants/lilygo_techo/platformio.ini b/variants/lilygo_techo/platformio.ini index 81da2e48c3f..eb4a69e284e 100644 --- a/variants/lilygo_techo/platformio.ini +++ b/variants/lilygo_techo/platformio.ini @@ -32,8 +32,12 @@ build_flags = ${nrf52_base.build_flags} -D PIN_GPS_RESET_ACTIVE=LOW -D TELEM_BME280_ADDRESS=0x77 -D DISPLAY_CLASS=GxEPDDisplay + -D EINK_SCREENOFF_BLANK + -D UI_RECENT_LIST_SIZE=9 + -D UI_MSG_PREVIEW_SIZE=165 + -D EINK_MAX_PARTIAL_REFRESH=60 + -D AUTO_OFF_MILLIS=900000 -D BACKLIGHT_BTN=PIN_BUTTON2 - -D AUTO_OFF_MILLIS=0 build_src_filter = ${nrf52_base.build_src_filter} + + @@ -91,7 +95,6 @@ build_flags = -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 - -D UI_RECENT_LIST_SIZE=9 -D UI_SENSORS_PAGE=1 -D UI_GPS_PAGE=1 ; -D MESH_PACKET_LOGGING=1 @@ -116,7 +119,6 @@ build_flags = -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 -D OFFLINE_QUEUE_SIZE=256 - -D UI_RECENT_LIST_SIZE=9 -D UI_SENSORS_PAGE=1 -D AUTO_SHUTDOWN_MILLIVOLTS=3300 -D QSPIFLASH=1 diff --git a/variants/lilygo_techo/target.cpp b/variants/lilygo_techo/target.cpp index 278fc76dad5..12b40d7ee94 100644 --- a/variants/lilygo_techo/target.cpp +++ b/variants/lilygo_techo/target.cpp @@ -23,6 +23,7 @@ EnvironmentSensorManager sensors = EnvironmentSensorManager(); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); + MomentaryButton backlight_btn(BACKLIGHT_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/lilygo_techo/target.h b/variants/lilygo_techo/target.h index 2b8a1783f06..a1668f03187 100644 --- a/variants/lilygo_techo/target.h +++ b/variants/lilygo_techo/target.h @@ -22,6 +22,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; extern MomentaryButton user_btn; + extern MomentaryButton backlight_btn; #endif bool radio_init(); diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini index 89c48403bf5..7c620e2ed6d 100644 --- a/variants/thinknode_m1/platformio.ini +++ b/variants/thinknode_m1/platformio.ini @@ -24,6 +24,18 @@ build_flags = ${nrf52_base.build_flags} -D SX126X_RX_BOOSTED_GAIN=1 -D LORA_TX_POWER=22 -D P_LORA_TX_LED=13 + -D UI_RECENT_LIST_SIZE=9 + -D UI_MSG_PREVIEW_SIZE=165 + -D EINK_MAX_PARTIAL_REFRESH=60 + -D EINK_DISPLAY_MODEL=GxEPD2_154_D67 + -D EINK_SCALE_X=1.5625f + -D EINK_SCALE_Y=1.5625f + -D EINK_X_OFFSET=0 + -D EINK_Y_OFFSET=10 + -D BACKLIGHT_BTN=PIN_BUTTON2 + -D AUTO_OFF_MILLIS=900000 + -D UI_NO_HIBERNATE + -D DISABLE_DIAGNOSTIC_OUTPUT build_src_filter = ${nrf52_base.build_src_filter} + + diff --git a/variants/thinknode_m1/target.cpp b/variants/thinknode_m1/target.cpp index 69306fc0e1e..c430cee00df 100644 --- a/variants/thinknode_m1/target.cpp +++ b/variants/thinknode_m1/target.cpp @@ -17,6 +17,7 @@ ThinkNodeM1SensorManager sensors = ThinkNodeM1SensorManager(nmea); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); + MomentaryButton backlight_btn(BACKLIGHT_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/thinknode_m1/target.h b/variants/thinknode_m1/target.h index ec1297beffc..d2d6aed1d50 100644 --- a/variants/thinknode_m1/target.h +++ b/variants/thinknode_m1/target.h @@ -40,6 +40,7 @@ extern ThinkNodeM1SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; extern MomentaryButton user_btn; + extern MomentaryButton backlight_btn; #endif bool radio_init(); diff --git a/variants/thinknode_m1/variant.h b/variants/thinknode_m1/variant.h index f7f52a6a592..aecf197e62d 100644 --- a/variants/thinknode_m1/variant.h +++ b/variants/thinknode_m1/variant.h @@ -81,7 +81,7 @@ #define BUTTON_PIN PIN_BUTTON1 #define PIN_USER_BTN BUTTON_PIN -#define PIN_BUTTON2 (11) +#define PIN_BUTTON2 (39) #define BUTTON_PIN2 PIN_BUTTON2 #define EXTERNAL_FLASH_DEVICES MX25R1635F @@ -131,6 +131,11 @@ extern const int SCK; #define DISP_BUSY (3) #define DISP_BACKLIGHT (43) +#define PIN_DISPLAY_CS DISP_CS +#define PIN_DISPLAY_DC DISP_DC +#define PIN_DISPLAY_RST DISP_RST +#define PIN_DISPLAY_BUSY DISP_BUSY + //////////////////////////////////////////////////////////////////////////////// // GPS diff --git a/variants/thinknode_m5/platformio.ini b/variants/thinknode_m5/platformio.ini index a3f348b3374..1980575ec66 100644 --- a/variants/thinknode_m5/platformio.ini +++ b/variants/thinknode_m5/platformio.ini @@ -26,8 +26,12 @@ build_flags = ${esp32_base.build_flags} -D EINK_SCALE_Y=1.5625f -D EINK_X_OFFSET=0 -D EINK_Y_OFFSET=10 + -D UI_RECENT_LIST_SIZE=9 + -D UI_MSG_PREVIEW_SIZE=165 + -D EINK_MAX_PARTIAL_REFRESH=60 -D BACKLIGHT_BTN=PIN_BUTTON2 - -D AUTO_OFF_MILLIS=0 + -D AUTO_OFF_MILLIS=900000 + -D UI_NO_HIBERNATE -D DISABLE_DIAGNOSTIC_OUTPUT -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=3.3 @@ -150,7 +154,6 @@ build_flags = -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 -D OFFLINE_QUEUE_SIZE=256 - -D UI_RECENT_LIST_SIZE=9 ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D GPS_NMEA_DEBUG diff --git a/variants/thinknode_m5/target.cpp b/variants/thinknode_m5/target.cpp index be534f67d75..ec524df749f 100644 --- a/variants/thinknode_m5/target.cpp +++ b/variants/thinknode_m5/target.cpp @@ -26,6 +26,7 @@ EnvironmentSensorManager sensors = EnvironmentSensorManager(); #ifdef DISPLAY_CLASS DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); + MomentaryButton backlight_btn(BACKLIGHT_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/thinknode_m5/target.h b/variants/thinknode_m5/target.h index a613e390901..7cce1edbf88 100644 --- a/variants/thinknode_m5/target.h +++ b/variants/thinknode_m5/target.h @@ -24,6 +24,7 @@ extern PCA9557 expander; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; extern MomentaryButton user_btn; + extern MomentaryButton backlight_btn; #endif bool radio_init(); diff --git a/variants/thinknode_m8/platformio.ini b/variants/thinknode_m8/platformio.ini index db19e446644..47d3a3fcd78 100644 --- a/variants/thinknode_m8/platformio.ini +++ b/variants/thinknode_m8/platformio.ini @@ -18,12 +18,16 @@ build_flags = ${nrf52_base.build_flags} -D P_LORA_SCLK=19 -D P_LORA_MISO=22 -D P_LORA_MOSI=20 - -D UI_SHOW_CLOCK=1 + -D DISPLAY_ROTATION=4 -D UI_HAS_ROTARY_INPUT=1 -D UI_HAS_NAV_INPUT=1 -D UI_RECENT_LIST_SIZE=9 -D UI_MSG_PREVIEW_SIZE=165 -D EINK_MAX_PARTIAL_REFRESH=60 + -D AUTO_OFF_MILLIS=900000 + -D BACKLIGHT_BTN=PIN_BUTTON2 + -D UI_SHOW_CLOCK=1 + -D EINK_SCREENOFF_BLANK -D EINK_DISPLAY_MODEL=GxEPD2_154_D67 ; -D EINK_DISPLAY_MODEL=GxEPD2_154_GDEY0154D67 ; -D EINK_DISPLAY_MODEL=GxEPD2_150_BN @@ -92,10 +96,7 @@ build_flags = -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 # -D BLE_DEBUG_LOGGING=1 - -D DISPLAY_ROTATION=4 -D DISPLAY_CLASS=GxEPDDisplay - -D BACKLIGHT_BTN=PIN_BUTTON2 - -D AUTO_OFF_MILLIS=0 -D OFFLINE_QUEUE_SIZE=256 -D PIN_BUZZER=33 -D AUTO_SHUTDOWN_MILLIVOLTS=3300 @@ -133,8 +134,6 @@ build_flags = -D DISPLAY_ROTATION=4 -D QSPIFLASH=1 -D DISPLAY_CLASS=GxEPDDisplay - -D BACKLIGHT_BTN=PIN_BUTTON2 - -D AUTO_OFF_MILLIS=0 -D OFFLINE_QUEUE_SIZE=256 -D PIN_BUZZER=6 -D AUTO_SHUTDOWN_MILLIVOLTS=3300 diff --git a/variants/thinknode_m8/target.cpp b/variants/thinknode_m8/target.cpp index ac4ac100edc..69f3cc52604 100644 --- a/variants/thinknode_m8/target.cpp +++ b/variants/thinknode_m8/target.cpp @@ -23,6 +23,7 @@ EnvironmentSensorManager sensors = EnvironmentSensorManager(); DISPLAY_CLASS display; MomentaryButton user_btn(PIN_USER_BTN, 1000, true); RotaryInputGPIO rotary_input(PIN_BUTTON1_A, PIN_BUTTON1_B); + MomentaryButton backlight_btn(BACKLIGHT_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/thinknode_m8/target.h b/variants/thinknode_m8/target.h index c3402a01a7e..39928506585 100644 --- a/variants/thinknode_m8/target.h +++ b/variants/thinknode_m8/target.h @@ -23,6 +23,7 @@ extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; extern MomentaryButton user_btn; + extern MomentaryButton backlight_btn; extern RotaryInputGPIO rotary_input; #endif