USE_EPD (e-ink parallel display)

This commit is contained in:
Manuel
2025-10-28 17:41:38 +01:00
parent 109fd627a4
commit f4c0ca11fc
5 changed files with 28 additions and 17 deletions

View File

@@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "configuration.h" #include "configuration.h"
#include "meshUtils.h" #include "meshUtils.h"
#if HAS_SCREEN #if HAS_SCREEN
#include "EInkParallelDisplay.h"
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include "DisplayFormatters.h" #include "DisplayFormatters.h"
@@ -154,7 +155,7 @@ void Screen::showSimpleBanner(const char *message, uint32_t durationMs)
// Called to trigger a banner with custom message and duration // Called to trigger a banner with custom message and duration
void Screen::showOverlayBanner(BannerOverlayOptions banner_overlay_options) void Screen::showOverlayBanner(BannerOverlayOptions banner_overlay_options)
{ {
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus
#endif #endif
// Store the message and set the expiration timestamp // Store the message and set the expiration timestamp
@@ -178,7 +179,7 @@ void Screen::showOverlayBanner(BannerOverlayOptions banner_overlay_options)
// Called to trigger a banner with custom message and duration // Called to trigger a banner with custom message and duration
void Screen::showNodePicker(const char *message, uint32_t durationMs, std::function<void(uint32_t)> bannerCallback) void Screen::showNodePicker(const char *message, uint32_t durationMs, std::function<void(uint32_t)> bannerCallback)
{ {
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus
#endif #endif
nodeDB->pause_sort(true); nodeDB->pause_sort(true);
@@ -201,7 +202,7 @@ void Screen::showNodePicker(const char *message, uint32_t durationMs, std::funct
void Screen::showNumberPicker(const char *message, uint32_t durationMs, uint8_t digits, void Screen::showNumberPicker(const char *message, uint32_t durationMs, uint8_t digits,
std::function<void(uint32_t)> bannerCallback) std::function<void(uint32_t)> bannerCallback)
{ {
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Skip full refresh for all overlay menus
#endif #endif
// Store the message and set the expiration timestamp // Store the message and set the expiration timestamp
@@ -378,6 +379,8 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
#elif defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY) #elif defined(USE_EINK) && defined(USE_EINK_DYNAMICDISPLAY)
dispdev = new EInkDynamicDisplay(address.address, -1, -1, geometry, dispdev = new EInkDynamicDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EPD)
dispdev = new EInkParallelDisplay(EPD_WIDTH, EPD_HEIGHT, EInkParallelDisplay::EPD_ROT_PORTRAIT);
#elif defined(USE_ST7567) #elif defined(USE_ST7567)
dispdev = new ST7567Wire(address.address, -1, -1, geometry, dispdev = new ST7567Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
@@ -414,7 +417,7 @@ Screen::~Screen()
*/ */
void Screen::doDeepSleep() void Screen::doDeepSleep()
{ {
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
setOn(false, graphics::UIRenderer::drawDeepSleepFrame); setOn(false, graphics::UIRenderer::drawDeepSleepFrame);
#else #else
// Without E-Ink display: // Without E-Ink display:
@@ -472,7 +475,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
runASAP = true; runASAP = true;
} else { } else {
powerMon->clearState(meshtastic_PowerMon_State_Screen_On); powerMon->clearState(meshtastic_PowerMon_State_Screen_On);
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
// eInkScreensaver parameter is usually NULL (default argument), default frame used instead // eInkScreensaver parameter is usually NULL (default argument), default frame used instead
setScreensaverFrames(einkScreensaver); setScreensaverFrames(einkScreensaver);
#endif #endif
@@ -624,7 +627,7 @@ void Screen::setup()
handleSetOn(true); handleSetOn(true);
determineResolution(dispdev->height(), dispdev->width()); determineResolution(dispdev->height(), dispdev->width());
ui->update(); ui->update();
#ifndef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
ui->update(); // Some SSD1306 clones drop the first draw, so run twice ui->update(); // Some SSD1306 clones drop the first draw, so run twice
#endif #endif
serialSinceMsec = millis(); serialSinceMsec = millis();
@@ -676,7 +679,7 @@ void Screen::setOn(bool on, FrameCallback einkScreensaver)
void Screen::forceDisplay(bool forceUiUpdate) void Screen::forceDisplay(bool forceUiUpdate)
{ {
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup. // Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
// If requested, make sure queued commands are run, and UI has rendered a new frame // If requested, make sure queued commands are run, and UI has rendered a new frame
if (forceUiUpdate) { if (forceUiUpdate) {
// Force a display refresh, in addition to the UI update // Force a display refresh, in addition to the UI update
@@ -705,7 +708,11 @@ void Screen::forceDisplay(bool forceUiUpdate)
} }
// Tell EInk class to update the display // Tell EInk class to update the display
#if defined(USE_EINK)
static_cast<EInkDisplay *>(dispdev)->forceDisplay(); static_cast<EInkDisplay *>(dispdev)->forceDisplay();
#elif defined(USE_EPD)
static_cast<EInkParallelDisplay *>(dispdev)->forceDisplay();
#endif
#else #else
// No delay between UI frame rendering // No delay between UI frame rendering
if (forceUiUpdate) { if (forceUiUpdate) {
@@ -800,7 +807,7 @@ int32_t Screen::runOnce()
showingNormalScreen = false; showingNormalScreen = false;
NotificationRenderer::pauseBanner = true; NotificationRenderer::pauseBanner = true;
alertFrames[0] = alertFrame; alertFrames[0] = alertFrame;
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?) handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
@@ -887,7 +894,7 @@ void Screen::setSSLFrames()
} }
} }
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
/// Determine which screensaver frame to use, then set the FrameCallback /// Determine which screensaver frame to use, then set the FrameCallback
void Screen::setScreensaverFrames(FrameCallback einkScreensaver) void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
{ {
@@ -924,7 +931,11 @@ void Screen::setScreensaverFrames(FrameCallback einkScreensaver)
// Old EInkDisplay class // Old EInkDisplay class
#if !defined(USE_EINK_DYNAMICDISPLAY) #if !defined(USE_EINK_DYNAMICDISPLAY)
#if defined(USE_EINK)
static_cast<EInkDisplay *>(dispdev)->forceDisplay(0); // Screen::forceDisplay(), but override rate-limit static_cast<EInkDisplay *>(dispdev)->forceDisplay(0); // Screen::forceDisplay(), but override rate-limit
#elif defined(USE_EPD)
static_cast<EInkParallelDisplay *>(dispdev)->forceDisplay(0); // Screen::forceDisplay(), but override rate-limit
#endif
#endif #endif
// Prepare now for next frame, shown when display wakes // Prepare now for next frame, shown when display wakes
@@ -1005,7 +1016,7 @@ void Screen::setFrames(FrameFocus focus)
#endif #endif
// Show detailed node views only on E-Ink builds // Show detailed node views only on E-Ink builds
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
if (!hiddenFrames.nodelist_lastheard) { if (!hiddenFrames.nodelist_lastheard) {
fsi.positions.nodelist_lastheard = numframes; fsi.positions.nodelist_lastheard = numframes;
normalFrames[numframes++] = graphics::NodeListRenderer::drawLastHeardScreen; normalFrames[numframes++] = graphics::NodeListRenderer::drawLastHeardScreen;
@@ -1197,7 +1208,7 @@ void Screen::toggleFrameVisibility(const std::string &frameName)
hiddenFrames.nodelist = !hiddenFrames.nodelist; hiddenFrames.nodelist = !hiddenFrames.nodelist;
} }
#endif #endif
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
if (frameName == "nodelist_lastheard") { if (frameName == "nodelist_lastheard") {
hiddenFrames.nodelist_lastheard = !hiddenFrames.nodelist_lastheard; hiddenFrames.nodelist_lastheard = !hiddenFrames.nodelist_lastheard;
} }

View File

@@ -593,7 +593,7 @@ class Screen : public concurrency::OSThread
void toggleFrameVisibility(const std::string &frameName); void toggleFrameVisibility(const std::string &frameName);
bool isFrameHidden(const std::string &frameName) const; bool isFrameHidden(const std::string &frameName) const;
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
/// Draw an image to remain on E-Ink display after screen off /// Draw an image to remain on E-Ink display after screen off
void setScreensaverFrames(FrameCallback einkScreensaver = NULL); void setScreensaverFrames(FrameCallback einkScreensaver = NULL);
#endif #endif
@@ -682,7 +682,7 @@ class Screen : public concurrency::OSThread
#ifndef USE_EINK #ifndef USE_EINK
bool nodelist = false; bool nodelist = false;
#endif #endif
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
bool nodelist_lastheard = false; bool nodelist_lastheard = false;
bool nodelist_hopsignal = false; bool nodelist_hopsignal = false;
bool nodelist_distance = false; bool nodelist_distance = false;

View File

@@ -513,7 +513,7 @@ void drawDynamicNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state,
} }
#endif #endif
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
const char *title = "Last Heard"; const char *title = "Last Heard";
@@ -522,7 +522,7 @@ void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void drawHopSignalScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
const char *title = "Hops/Sig"; const char *title = "Hops/Sig";
#else #else

View File

@@ -852,7 +852,7 @@ bool UIRenderer::haveGlyphs(const char *str)
return have; return have;
} }
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
/// Used on eink displays while in deep sleep /// Used on eink displays while in deep sleep
void UIRenderer::drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void UIRenderer::drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {

View File

@@ -72,7 +72,7 @@ class UIRenderer
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#endif #endif
#ifdef USE_EINK #if defined(USE_EINK) || defined(USE_EPD)
/// Used on eink displays while in deep sleep /// Used on eink displays while in deep sleep
static void drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); static void drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);