diff --git a/src/graphics/niche/InkHUD/Applet.cpp b/src/graphics/niche/InkHUD/Applet.cpp index 9fda9a87e..b896d9a5c 100644 --- a/src/graphics/niche/InkHUD/Applet.cpp +++ b/src/graphics/niche/InkHUD/Applet.cpp @@ -799,7 +799,7 @@ uint16_t InkHUD::Applet::getLogoHeight(uint16_t limitWidth, uint16_t limitHeight // // \\ */ -void InkHUD::Applet::drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height) +void InkHUD::Applet::drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height, Color color) { struct Point { int x; @@ -905,24 +905,24 @@ void InkHUD::Applet::drawLogo(int16_t centerX, int16_t centerY, uint16_t width, Point aq2{a2.x - fromPath.x, a2.y - fromPath.y}; Point aq3{a2.x + fromPath.x, a2.y + fromPath.y}; Point aq4{a1.x + fromPath.x, a1.y + fromPath.y}; - fillTriangle(aq1.x, aq1.y, aq2.x, aq2.y, aq3.x, aq3.y, BLACK); - fillTriangle(aq1.x, aq1.y, aq3.x, aq3.y, aq4.x, aq4.y, BLACK); + fillTriangle(aq1.x, aq1.y, aq2.x, aq2.y, aq3.x, aq3.y, color); + fillTriangle(aq1.x, aq1.y, aq3.x, aq3.y, aq4.x, aq4.y, color); // Make the path thick: path b becomes quad b Point bq1{b1.x - fromPath.x, b1.y - fromPath.y}; Point bq2{b2.x - fromPath.x, b2.y - fromPath.y}; Point bq3{b2.x + fromPath.x, b2.y + fromPath.y}; Point bq4{b1.x + fromPath.x, b1.y + fromPath.y}; - fillTriangle(bq1.x, bq1.y, bq2.x, bq2.y, bq3.x, bq3.y, BLACK); - fillTriangle(bq1.x, bq1.y, bq3.x, bq3.y, bq4.x, bq4.y, BLACK); + fillTriangle(bq1.x, bq1.y, bq2.x, bq2.y, bq3.x, bq3.y, color); + fillTriangle(bq1.x, bq1.y, bq3.x, bq3.y, bq4.x, bq4.y, color); // Make the path thick: path c becomes quad c Point cq1{c1.x - fromPath.x, c1.y + fromPath.y}; Point cq2{c2.x - fromPath.x, c2.y + fromPath.y}; Point cq3{c2.x + fromPath.x, c2.y - fromPath.y}; Point cq4{c1.x + fromPath.x, c1.y - fromPath.y}; - fillTriangle(cq1.x, cq1.y, cq2.x, cq2.y, cq3.x, cq3.y, BLACK); - fillTriangle(cq1.x, cq1.y, cq3.x, cq3.y, cq4.x, cq4.y, BLACK); + fillTriangle(cq1.x, cq1.y, cq2.x, cq2.y, cq3.x, cq3.y, color); + fillTriangle(cq1.x, cq1.y, cq3.x, cq3.y, cq4.x, cq4.y, color); // Radius the intersection of quad b and quad c /* @@ -941,7 +941,7 @@ void InkHUD::Applet::drawLogo(int16_t centerX, int16_t centerY, uint16_t width, // The radius for the cap *should* be the same as logoTh, but it's not, due to accumulated rounding // We get better results just re-deriving it int16_t capRad = sqrt(pow(fromPath.x, 2) + pow(fromPath.y, 2)); - fillCircle(b2.x, b2.y, capRad, BLACK); + fillCircle(b2.x, b2.y, capRad, color); } } diff --git a/src/graphics/niche/InkHUD/Applet.h b/src/graphics/niche/InkHUD/Applet.h index 028b24f9c..8f4466647 100644 --- a/src/graphics/niche/InkHUD/Applet.h +++ b/src/graphics/niche/InkHUD/Applet.h @@ -130,7 +130,8 @@ class Applet : public GFX static constexpr float LOGO_ASPECT_RATIO = 1.9; // Width:Height for drawing the Meshtastic logo uint16_t getLogoWidth(uint16_t limitWidth, uint16_t limitHeight); // Size Meshtastic logo to fit within region uint16_t getLogoHeight(uint16_t limitWidth, uint16_t limitHeight); // Size Meshtastic logo to fit within region - void drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height); // Draw the meshtastic logo + void drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height, + Color color = BLACK); // Draw the Meshtastic logo std::string hexifyNodeNum(NodeNum num); // Style as !0123abdc SignalStrength getSignalStrength(float snr, float rssi); // Interpret SNR and RSSI, as an easy to understand value diff --git a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp index 24c2d88a4..4c8b0755f 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp +++ b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp @@ -34,7 +34,15 @@ void InkHUD::LogoApplet::onRender() int16_t logoCX = X(0.5); int16_t logoCY = Y(0.5 - 0.05); - drawLogo(logoCX, logoCY, logoW, logoH); + // Invert colors if black-on-white + // Used during shutdown, to resport display health + // Todo: handle this in InkHUD::Renderer instead + if (inverted) { + fillScreen(BLACK); + setTextColor(WHITE); + } + + drawLogo(logoCX, logoCY, logoW, logoH, inverted ? WHITE : BLACK); if (!textLeft.empty()) { setFont(fontSmall); @@ -74,13 +82,30 @@ void InkHUD::LogoApplet::onBackground() // Begin displaying the screen which is shown at shutdown void InkHUD::LogoApplet::onShutdown() { + bringToForeground(); + + textLeft = ""; + textRight = ""; + textTitle = "Shutting Down..."; + fontTitle = fontSmall; + + // Draw a shutting down screen, twice. + // Once white on black, once black on white. + // Intention is to restore display health. + + inverted = true; + inkhud->forceUpdate(Drivers::EInk::FULL, false); + inverted = false; + inkhud->forceUpdate(Drivers::EInk::FULL, false); + + // Prepare for the powered-off screen now + // We can change these values because the initial "shutting down" screen has already rendered at this point textLeft = ""; textRight = ""; textTitle = owner.short_name; fontTitle = fontLarge; - bringToForeground(); - // This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update + // This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update, after InkHUD's flash write is complete } int32_t InkHUD::LogoApplet::runOnce() diff --git a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.h b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.h index b55d4a2d9..cc12bd1ba 100644 --- a/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.h +++ b/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.h @@ -33,6 +33,7 @@ class LogoApplet : public SystemApplet, public concurrency::OSThread std::string textRight; std::string textTitle; AppletFont fontTitle; + bool inverted = false; // Invert colors. Used during shutdown, to restore display health. }; } // namespace NicheGraphics::InkHUD diff --git a/src/graphics/niche/InkHUD/Events.cpp b/src/graphics/niche/InkHUD/Events.cpp index 10072b302..666dff1e4 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -70,6 +70,9 @@ void InkHUD::Events::onButtonLong() // Returns 0 to signal that we agree to sleep now int InkHUD::Events::beforeDeepSleep(void *unused) { + // If a previous display update is in progress, wait for it to complete. + inkhud->awaitUpdate(); + // Notify all applets that we're shutting down for (Applet *ua : inkhud->userApplets) { ua->onDeactivate(); @@ -87,8 +90,10 @@ int InkHUD::Events::beforeDeepSleep(void *unused) inkhud->persistence->saveSettings(); inkhud->persistence->saveLatestMessage(); - // LogoApplet::onShutdown will have requested an update, to draw the shutdown screen - // Draw that now, and wait here until the update is complete + // LogoApplet::onShutdown attempted to heal the display by drawing a "shutting down" screen twice, + // then prepared a final powered-off screen for us, which shows device shortname. + // We're updating to show that one now. + inkhud->forceUpdate(Drivers::EInk::UpdateTypes::FULL, false); return 0; // We agree: deep sleep now