Files
meshtastic_firmware/src/graphics/niche/InkHUD/Applets/System/Logo/LogoApplet.cpp
T
todd-herbertandGitHub bd2d2981c9 Add InkHUD driver for WeAct Studio 4.2" display module (#6384)
* chore: todo.txt

* chore: InkHUD documentation
Word salad for maintainers

* refactor: don't init system applets using onActivate
System applets cannot be deactivated, so we will avoid using onActivate / onDeactivate methods entirely.

* chore: update the example applets

* fix: SSD16XX reset pulse
Allow time for controller IC to wake. Aligns with manufacturer's suggestions.
T-Echo button timing adjusted to prevent bouncing as a result(?) of slightly faster refreshes.

* fix: allow timeout if display update fails
Result is not graceful, but avoids total display lockup requiring power cycle.
Typical cause of failure is poor wiring / power supply.

* fix: improve display health on shutdown
Two extra full refreshes, masquerading as a "shutting down" screen. One is drawn white-on-black, to really shake the pixels up.

* feat: driver for display HINK_E042A87
As of Feb. 2025, these panels are used for "WeActStudio 4.2in B&W" display modules.

* fix: inkhud rotation should default to 0

* Revert "chore: todo.txt"

This reverts commit bea7df44a7cbf2f92e8c67c965e53d26a7885b11.

* fix: more generous timeout for display updates
Previously this was tied to the expected duration of the update, but this didn't account for any delay if our polling thread got held up by an unrelated firmware task.

* fix: don't use the full shutdown screen during reboot

* fix: cooldown period during the display shutdown display sequence
Observed to prevent border pixels from being locked in place with some residual charge?
2025-03-31 09:17:24 +02:00

132 lines
3.7 KiB
C++

#ifdef MESHTASTIC_INCLUDE_INKHUD
#include "./LogoApplet.h"
#include "mesh/NodeDB.h"
using namespace NicheGraphics;
InkHUD::LogoApplet::LogoApplet() : concurrency::OSThread("LogoApplet")
{
OSThread::setIntervalFromNow(8 * 1000UL);
OSThread::enabled = true;
textLeft = "";
textRight = "";
textTitle = xstr(APP_VERSION_SHORT);
fontTitle = fontSmall;
bringToForeground();
// This is then drawn with a FULL refresh by Renderer::begin
}
void InkHUD::LogoApplet::onRender()
{
// Size of the region which the logo should "scale to fit"
uint16_t logoWLimit = X(0.8);
uint16_t logoHLimit = Y(0.5);
// Get the max width and height we can manage within the region, while still maintaining aspect ratio
uint16_t logoW = getLogoWidth(logoWLimit, logoHLimit);
uint16_t logoH = getLogoHeight(logoWLimit, logoHLimit);
// Where to place the center of the logo
int16_t logoCX = X(0.5);
int16_t logoCY = Y(0.5 - 0.05);
// 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);
printAt(0, 0, textLeft, LEFT, TOP);
}
if (!textRight.empty()) {
setFont(fontSmall);
printAt(X(1), 0, textRight, RIGHT, TOP);
}
if (!textTitle.empty()) {
int16_t logoB = logoCY + (logoH / 2); // Bottom of the logo
setFont(fontTitle);
printAt(X(0.5), logoB + Y(0.1), textTitle, CENTER, TOP);
}
}
void InkHUD::LogoApplet::onForeground()
{
SystemApplet::lockRendering = true;
SystemApplet::lockRequests = true;
SystemApplet::handleInput = true; // We don't actually use this input. Just blocking other applets from using it.
}
void InkHUD::LogoApplet::onBackground()
{
SystemApplet::lockRendering = false;
SystemApplet::lockRequests = false;
SystemApplet::handleInput = false;
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
// 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);
delay(1000); // Cooldown. Back to back updates aren't great for health.
inverted = false;
inkhud->forceUpdate(Drivers::EInk::FULL, false);
delay(1000); // Cooldown
// 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;
// This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update, after InkHUD's flash write is complete
}
void InkHUD::LogoApplet::onReboot()
{
bringToForeground();
textLeft = "";
textRight = "";
textTitle = "Rebooting...";
fontTitle = fontSmall;
inkhud->forceUpdate(Drivers::EInk::FULL, false);
// Perform the update right now, waiting here until complete
}
int32_t InkHUD::LogoApplet::runOnce()
{
sendToBackground();
return OSThread::disable();
}
#endif