From 640abd9b99dff5ce42127372ed7e6eb40b039689 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Tue, 12 May 2026 22:14:19 +0200 Subject: [PATCH] Try more conditioning passes on x3 before sleepscreen to get rid of ghosting --- lib/hal/HalDisplay.cpp | 16 ++++++++++++++-- lib/hal/HalDisplay.h | 5 +++++ src/activities/boot_sleep/SleepActivity.cpp | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/hal/HalDisplay.cpp b/lib/hal/HalDisplay.cpp index 665df535..dbe8fefb 100644 --- a/lib/hal/HalDisplay.cpp +++ b/lib/hal/HalDisplay.cpp @@ -50,18 +50,30 @@ EInkDisplay::RefreshMode convertRefreshMode(HalDisplay::RefreshMode mode) { } } +void HalDisplay::requestResync(uint8_t settlePasses) { + if (gpio.deviceIsX3() && settlePasses > pendingX3SettlePasses) { + pendingX3SettlePasses = settlePasses; + } +} + void HalDisplay::displayBuffer(HalDisplay::RefreshMode mode, bool turnOffScreen) { if (gpio.deviceIsX3() && mode == RefreshMode::HALF_REFRESH) { - einkDisplay.requestResync(1); + einkDisplay.requestResync(pendingX3SettlePasses > 1 ? pendingX3SettlePasses : 1); + } else if (pendingX3SettlePasses > 0) { + einkDisplay.requestResync(pendingX3SettlePasses); } + pendingX3SettlePasses = 0; einkDisplay.displayBuffer(convertRefreshMode(mode), turnOffScreen); } void HalDisplay::refreshDisplay(HalDisplay::RefreshMode mode, bool turnOffScreen) { if (gpio.deviceIsX3() && mode == RefreshMode::HALF_REFRESH) { - einkDisplay.requestResync(1); + einkDisplay.requestResync(pendingX3SettlePasses > 1 ? pendingX3SettlePasses : 1); + } else if (pendingX3SettlePasses > 0) { + einkDisplay.requestResync(pendingX3SettlePasses); } + pendingX3SettlePasses = 0; einkDisplay.refreshDisplay(convertRefreshMode(mode), turnOffScreen); } diff --git a/lib/hal/HalDisplay.h b/lib/hal/HalDisplay.h index a0a7f920..0015cb88 100644 --- a/lib/hal/HalDisplay.h +++ b/lib/hal/HalDisplay.h @@ -36,6 +36,10 @@ class HalDisplay { void displayBuffer(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); + // Request extra X3 ghost-clearing on the next display refresh. + // No-op on non-X3 panels. Consumed by the next displayBuffer/refreshDisplay call. + void requestResync(uint8_t settlePasses = 0); + // Power management void deepSleep(); @@ -57,6 +61,7 @@ class HalDisplay { private: EInkDisplay einkDisplay; + uint8_t pendingX3SettlePasses = 0; }; extern HalDisplay display; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index dd583e3e..cbc4b27e 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -357,6 +357,10 @@ void SleepActivity::onEnter() { if (SETTINGS.sleepScreen != CrossPointSettings::SLEEP_SCREEN_MODE::OVERLAY) { GUI.drawPopup(renderer, tr(STR_ENTERING_SLEEP)); } + // X3 panels need extra settle passes to fully clear ghosting from the previous reader page + // before showing the static sleep image. No-op on other panels. Placed after the popup so + // its own displayBuffer doesn't consume the request. + display.requestResync(2); switch (SETTINGS.sleepScreen) { case (CrossPointSettings::SLEEP_SCREEN_MODE::BLANK):