From c726e5f331fb02f7452bccd1bec141fd63230bdb Mon Sep 17 00:00:00 2001 From: geeksville Date: Wed, 12 Feb 2020 09:58:46 -0800 Subject: [PATCH] leave screen off most of the time - press to wake --- TODO.md | 4 ++- src/MeshRadio.h | 3 +- src/configuration.h | 2 +- src/mesh.pb.c | 1 + src/mesh.pb.h | 9 ++++++ src/screen.cpp | 74 +++++++++++++++++++++++++++++++-------------- 6 files changed, 67 insertions(+), 26 deletions(-) diff --git a/TODO.md b/TODO.md index 302ddfb3..a1ffd2e5 100644 --- a/TODO.md +++ b/TODO.md @@ -4,9 +4,9 @@ * make debug info screen show real data (including battery level & charging) * make real implementation of getNumOnlineNodes * very occasionally send our position and user packet based on the schedule in the radio info (if for nothing else so that other nodes update last_seen) -* make screen advance only when a new node update arrives, a new text arrives or the user presses a button * show real text info on the text screen * retest BLE software update for both board types +* turn on screen when a new update arrives # Medium priority @@ -122,3 +122,5 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w * reported altitude is crap * good tips on which bands might be more free https://github.com/TheThingsNetwork/ttn/issues/119 * finish power measurements (GPS on during sleep vs LCD on during sleep vs LORA on during sleep) and est battery life +* make screen sleep behavior work +* make screen advance only when a new node update arrives, a new text arrives or the user presses a button, turn off screen after a while diff --git a/src/MeshRadio.h b/src/MeshRadio.h index 9d2a4368..c79cfade 100644 --- a/src/MeshRadio.h +++ b/src/MeshRadio.h @@ -11,12 +11,11 @@ // US channel settings #define CH0_US 903.08f // MHz #define CH_SPACING_US 2.16f // MHz -#define NUM_CHANNELS_US 13 // FIXME add defs for other regions and use them here #define CH0 CH0_US #define CH_SPACING CH_SPACING_US -#define NUM_CHANNELS NUM_CHANNELS_US +#define NUM_CHANNELS Constants_NumChannels #define MAX_TX_QUEUE 8 // max number of packets which can be waiting for transmission diff --git a/src/configuration.h b/src/configuration.h index cb0c5482..46ef06b6 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -62,7 +62,7 @@ along with this program. If not, see . // If not defined, we will wait for lock forever -#define MINWAKE_MSECS (30 * 1000) // stay awake a long time (30 mins) for debugging +#define MINWAKE_MSECS (60 * 1000) // stay awake a long time (30 mins) for debugging // #define MINWAKE_MSECS (30 * 1000) // Wait after every boot for GPS lock (may need longer than 5s because we turned the gps off during deep sleep) // ----------------------------------------------------------------------------- diff --git a/src/mesh.pb.c b/src/mesh.pb.c index 5e406196..822e04ee 100644 --- a/src/mesh.pb.c +++ b/src/mesh.pb.c @@ -49,6 +49,7 @@ PB_BIND(ToRadio, ToRadio, AUTO) + #ifndef PB_CONVERT_DOUBLE_FLOAT /* On some platforms (such as AVR), double is really float. * To be able to encode/decode double on these platforms, you need. diff --git a/src/mesh.pb.h b/src/mesh.pb.h index 2c016c0f..01bbd63d 100644 --- a/src/mesh.pb.h +++ b/src/mesh.pb.h @@ -14,6 +14,11 @@ extern "C" { #endif /* Enum definitions */ +typedef enum _Constants { + Constants_Unused = 0, + Constants_NumChannels = 13 +} Constants; + typedef enum _Data_Type { Data_Type_SIGNAL_OPAQUE = 0, Data_Type_CLEAR_TEXT = 1, @@ -141,6 +146,10 @@ typedef struct _ToRadio { /* Helper constants for enums */ +#define _Constants_MIN Constants_Unused +#define _Constants_MAX Constants_NumChannels +#define _Constants_ARRAYSIZE ((Constants)(Constants_NumChannels+1)) + #define _Data_Type_MIN Data_Type_SIGNAL_OPAQUE #define _Data_Type_MAX Data_Type_CLEAR_READACK #define _Data_Type_ARRAYSIZE ((Data_Type)(Data_Type_CLEAR_READACK+1)) diff --git a/src/screen.cpp b/src/screen.cpp index a5f04fe6..b6881911 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -43,6 +43,7 @@ SSD1306Wire dispdev(SSD1306_ADDRESS, 0, 0); // fake values to keep build happy, #endif bool disp; // true if we are using display +bool screenOn; // true if the display is currently powered OLEDDisplayUi ui(&dispdev); @@ -320,7 +321,7 @@ void drawDebugInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i // This array keeps function pointers to all frames // frames are the single views that slide in -FrameCallback bootFrames[] = {drawBootScreen, drawTextMessageFrame, drawDebugInfo}; +FrameCallback bootFrames[] = {drawBootScreen}; // Overlays are statically drawn on top of a frame eg. a clock OverlayCallback overlays[] = {/* msOverlay */}; @@ -359,6 +360,7 @@ void screen_off() return; dispdev.displayOff(); + screenOn = false; } void screen_on() @@ -367,6 +369,7 @@ void screen_on() return; dispdev.displayOn(); + screenOn = true; } static void screen_print(const char *text, uint8_t x, uint8_t y, uint8_t alignment) @@ -428,11 +431,15 @@ void screen_setup() // Scroll buffer dispdev.setLogBuffer(3, 32); + screen_on(); // update our screenOn bool + #ifdef BICOLOR_DISPLAY dispdev.flipScreenVertically(); // looks better without this on lora32 #endif // dispdev.setFont(Custom_ArialMT_Plain_10); + + ui.disableAutoTransition(); // we now require presses #endif } @@ -441,10 +448,15 @@ static bool showingBluetooth; /// If set to true (possibly from an ISR), we should turn on the screen the next time our idle loop runs. static bool wakeScreen; +uint32_t lastPressMs; + +/// Turn off the screen this many ms after last press or wake +#define SCREEN_SLEEP_MS (60 * 1000) + uint32_t screen_loop() { - if (!disp) - return 30 * 1000; + if (!disp) // If we don't have a screen, don't ever spend any CPU for us + return UINT32_MAX; if (wakeScreen) { @@ -452,27 +464,41 @@ uint32_t screen_loop() wakeScreen = false; } - static bool showingBootScreen = true; + if(!screenOn) // If we didn't just wake and the screen is still off, then bail + return UINT32_MAX; + + static bool showingBootScreen = true; // start by showing the bootscreen ui.update(); - // Once we finish showing the bootscreen, remove it from the loop - if (showingBootScreen && !showingBluetooth) + // While showing the bluetooth pair screen all of our standard screen switching is stopped + if (!showingBluetooth) { - if (ui.getUiState()->currentFrame == 1) + // Once we finish showing the bootscreen, remove it from the loop + if (showingBootScreen) { - showingBootScreen = false; - screen_set_frames(); + if (millis() > 5 * 1000) // we show the boot screen for a few seconds only + { + showingBootScreen = false; + screen_set_frames(); + } } - } + else // standard screen loop handling ehre + { + // If the # nodes changes, we need to regen our list of screens + static size_t oldnumnodes = 0; + size_t numnodes = nodeDB.getNumNodes(); + if (numnodes != oldnumnodes) + { + oldnumnodes = numnodes; + screen_set_frames(); + } - static size_t oldnumnodes = 0; - size_t numnodes = nodeDB.getNumNodes(); - if (numnodes != oldnumnodes) - { - // If the # nodes changes, we need to regen our list of screens - oldnumnodes = numnodes; - screen_set_frames(); + if(millis() - lastPressMs > SCREEN_SLEEP_MS) { + DEBUG_MSG("screen timeout, turn it off for now...\n"); + screen_off(); + } + } } // If we are scrolling do 30fps, otherwise just 1 fps (to save CPU) @@ -490,8 +516,7 @@ void screen_start_bluetooth(uint32_t pin) showingBluetooth = true; wakeScreen = true; - ui.disableAutoTransition(); // we now require presses - ui.setFrames(btFrames, 1); // Just show the bluetooth frame + ui.setFrames(btFrames, 1); // Just show the bluetooth frame // we rely on our main loop to show this screen (because we are invoked deep inside of bluetooth callbacks) // ui.update(); // manually draw once, because I'm not sure if loop is getting called } @@ -516,12 +541,17 @@ void screen_set_frames() showingBluetooth = false; } + + /// handle press of the button void screen_press() { // screen_start_bluetooth(123456); - // Once the user presses a button, stop auto scrolling between screens - ui.disableAutoTransition(); // we now require presses - ui.nextFrame(); + lastPressMs = millis(); + wakeScreen = true; + + // If screen was off, just wake it, otherwise advance to next frame + if(screenOn) + ui.nextFrame(); } \ No newline at end of file