From b0837c10c6d964af17a41e293807a6ca3ff46cd3 Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Fri, 16 Oct 2020 10:53:55 +0800 Subject: [PATCH] eink display improvements --- bin/install-eink.sh | 22 ++++++++++++++++++++++ src/graphics/EInkDisplay.cpp | 3 +-- src/graphics/EInkDisplay.h | 6 +++--- src/graphics/Screen.cpp | 35 ++++++++++++++++++++++------------- src/graphics/Screen.h | 3 +++ 5 files changed, 51 insertions(+), 18 deletions(-) create mode 100755 bin/install-eink.sh diff --git a/bin/install-eink.sh b/bin/install-eink.sh new file mode 100755 index 00000000..5bfb6f1a --- /dev/null +++ b/bin/install-eink.sh @@ -0,0 +1,22 @@ +# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board + +set -e + +BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader + +nrfjprog --eraseall -f nrf52 + +# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid +# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000 +# first 4 bytes should be 0x01 to indicate valid app image +# second 4 bytes should be 0x00 to indicate no CRC required for image +echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin +srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel + +echo Generating merged hex file +mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-125-gf38f8f4-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex + +echo Telling bootloader app region is valid and telling CPU to run +nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset + +# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less diff --git a/src/graphics/EInkDisplay.cpp b/src/graphics/EInkDisplay.cpp index 4b296a2d..0d5e8307 100644 --- a/src/graphics/EInkDisplay.cpp +++ b/src/graphics/EInkDisplay.cpp @@ -102,8 +102,7 @@ void EInkDisplay::display(void) // at least one forceDisplay() keyframe. This prevents flashing when we should the critical // bootscreen (that we want to look nice) if (lastDrawMsec) - if (forceDisplay(slowUpdateMsec)) // Show the first screen a few seconds after boot, then slower - slowUpdateMsec = 5 * 60 * 1000; + forceDisplay(slowUpdateMsec); // Show the first screen a few seconds after boot, then slower } // Send a command to the display (low level function) diff --git a/src/graphics/EInkDisplay.h b/src/graphics/EInkDisplay.h index a36c1a77..18b90030 100644 --- a/src/graphics/EInkDisplay.h +++ b/src/graphics/EInkDisplay.h @@ -14,9 +14,9 @@ */ class EInkDisplay : public OLEDDisplay { - /// How often should we update the display, at first we do an update 5 secs after boot, + /// How often should we update the display /// thereafter we do once per 5 minutes - uint32_t slowUpdateMsec = 5 * 1000; + uint32_t slowUpdateMsec = 5 * 60 * 1000; public: /* constructor @@ -32,7 +32,7 @@ class EInkDisplay : public OLEDDisplay * * @return true if we did draw the screen */ - bool forceDisplay(uint32_t msecLimit = 2000); + bool forceDisplay(uint32_t msecLimit = 1000); protected: // the header size of the buffer used, e.g. for the SPI command header diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index a5c15f49..e08b50d6 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -681,7 +681,8 @@ int32_t Screen::runOnce() // Show boot screen for first 3 seconds, then switch to normal operation. static bool showingBootScreen = true; - if (showingBootScreen && (millis() > 3000)) { + if (showingBootScreen && (millis() > 5000)) { + DEBUG_MSG("Done with boot screen...\n"); stopBootScreen(); showingBootScreen = false; } @@ -727,6 +728,10 @@ int32_t Screen::runOnce() return 0; } + // this must be before the frameState == FIXED check, because we always + // want to draw at least one FIXED frame before doing forceDisplay + ui.update(); + // Switch to a low framerate (to save CPU) when we are not in transition // but we should only call setTargetFPS when framestate changes, because // otherwise that breaks animations. @@ -744,8 +749,6 @@ int32_t Screen::runOnce() // standard screen loop handling here } - ui.update(); - // DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate, // ui.getUiState()->frameState); If we are scrolling we need to be called // soon, otherwise just 1 fps (to save CPU) We also ask to be called twice @@ -812,6 +815,8 @@ void Screen::setFrames() prevFrame = -1; // Force drawNodeInfo to pick a new node (because our list // just changed) + + setFastFramerate(); // Draw ASAP } void Screen::handleStartBluetoothPinScreen(uint32_t pin) @@ -825,12 +830,13 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin) ui.disableAllIndicators(); ui.setFrames(btFrames, 1); + setFastFramerate(); } void Screen::handlePrint(const char *text) { DEBUG_MSG("Screen: %s", text); - if (!useDisplay) + if (!useDisplay || !showingNormalScreen) return; dispdev.print(text); @@ -841,17 +847,22 @@ void Screen::handleOnPress() // If screen was off, just wake it, otherwise advance to next frame // If we are in a transition, the press must have bounced, drop it. if (ui.getUiState()->frameState == FIXED) { - setInterval(0); // redraw ASAP ui.nextFrame(); - DEBUG_MSG("Setting fast framerate\n"); - - // We are about to start a transition so speed up fps - targetFramerate = TRANSITION_FRAMERATE; - ui.setTargetFPS(targetFramerate); + setFastFramerate(); } } +void Screen::setFastFramerate() +{ + DEBUG_MSG("Setting fast framerate\n"); + + // We are about to start a transition so speed up fps + targetFramerate = TRANSITION_FRAMERATE; + ui.setTargetFPS(targetFramerate); + setInterval(0); // redraw ASAP +} + void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { displayedNodeNum = 0; // Not currently showing a node pane @@ -1100,9 +1111,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg) switch (arg->getStatusType()) { case STATUS_TYPE_NODE: if (nodeDB.updateTextMessage || nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) { - setFrames(); // Regen the list of screens - prevFrame = -1; // Force a GUI update - setInterval(0); // Update the screen right away + setFrames(); // Regen the list of screens } nodeDB.updateGUI = false; nodeDB.updateTextMessage = false; diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 7c8d3435..b2f90e84 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -219,6 +219,9 @@ class Screen : public concurrency::OSThread /// Rebuilds our list of frames (screens) to default ones. void setFrames(); + /// Try to start drawing ASAP + void setFastFramerate(); + /// Called when debug screen is to be drawn, calls through to debugInfo.drawFrame. static void drawDebugInfoTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);