From 6114b80e5d9e89afd7886becb66eadd0c68251db Mon Sep 17 00:00:00 2001 From: Justin Mitchell Date: Fri, 13 Feb 2026 15:27:13 -0500 Subject: [PATCH] adds x3 commands for refresh types --- lib/GfxRenderer/GfxRenderer.h | 1 + lib/hal/HalDisplay.cpp | 2 ++ lib/hal/HalDisplay.h | 3 +++ src/activities/reader/EpubReaderActivity.cpp | 23 +++++++++++++------- src/activities/reader/ReaderActivity.cpp | 4 ++++ src/main.cpp | 20 ++++++++++++++++- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/lib/GfxRenderer/GfxRenderer.h b/lib/GfxRenderer/GfxRenderer.h index 63cbc36b8..b2d3054aa 100644 --- a/lib/GfxRenderer/GfxRenderer.h +++ b/lib/GfxRenderer/GfxRenderer.h @@ -70,6 +70,7 @@ class GfxRenderer { // Screen ops int getScreenWidth() const; int getScreenHeight() const; + void requestResync(uint8_t settlePasses = 0) const { display.requestResync(settlePasses); } void displayBuffer(HalDisplay::RefreshMode refreshMode = HalDisplay::FAST_REFRESH) const; // EXPERIMENTAL: Windowed update - display only a rectangular region // void displayWindow(int x, int y, int width, int height) const; diff --git a/lib/hal/HalDisplay.cpp b/lib/hal/HalDisplay.cpp index 6bc372175..76481df9d 100644 --- a/lib/hal/HalDisplay.cpp +++ b/lib/hal/HalDisplay.cpp @@ -38,6 +38,8 @@ void HalDisplay::refreshDisplay(HalDisplay::RefreshMode mode, bool turnOffScreen einkDisplay.refreshDisplay(convertRefreshMode(mode), turnOffScreen); } +void HalDisplay::requestResync(uint8_t settlePasses) { einkDisplay.requestResync(settlePasses); } + void HalDisplay::deepSleep() { einkDisplay.deepSleep(); } uint8_t* HalDisplay::getFrameBuffer() const { return einkDisplay.getFrameBuffer(); } diff --git a/lib/hal/HalDisplay.h b/lib/hal/HalDisplay.h index a113f8e38..1b33e1b73 100644 --- a/lib/hal/HalDisplay.h +++ b/lib/hal/HalDisplay.h @@ -36,6 +36,9 @@ class HalDisplay { void displayBuffer(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false); + // Hint the display driver to perform a one-shot full resync on next update. + // Optional settle passes are used by X3 only. + void requestResync(uint8_t settlePasses = 0); // Power management void deepSleep(); diff --git a/src/activities/reader/EpubReaderActivity.cpp b/src/activities/reader/EpubReaderActivity.cpp index 8b2e47e28..d68f7ab85 100644 --- a/src/activities/reader/EpubReaderActivity.cpp +++ b/src/activities/reader/EpubReaderActivity.cpp @@ -33,6 +33,12 @@ int clampPercent(int percent) { return percent; } +bool isX3DisplayGeometry(const GfxRenderer& renderer) { + const int w = renderer.getScreenWidth(); + const int h = renderer.getScreenHeight(); + return (w == 792 && h == 528) || (w == 528 && h == 792); +} + // Apply the logical reader orientation to the renderer. // This centralizes orientation mapping so we don't duplicate switch logic elsewhere. void applyReaderOrientation(GfxRenderer& renderer, const uint8_t orientation) { @@ -682,12 +688,13 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or pagesUntilFullRefresh--; } - // Save bw buffer to reset buffer state after grayscale data sync - renderer.storeBwBuffer(); + const bool useGrayscaleAA = SETTINGS.textAntiAliasing && !isX3DisplayGeometry(renderer); + if (useGrayscaleAA) { + // Save BW buffer only when we actually run grayscale passes. + renderer.storeBwBuffer(); - // grayscale rendering - // TODO: Only do this if font supports it - if (SETTINGS.textAntiAliasing) { + // grayscale rendering + // TODO: Only do this if font supports it renderer.clearScreen(0x00); renderer.setRenderMode(GfxRenderer::GRAYSCALE_LSB); page->render(renderer, SETTINGS.getReaderFontId(), orientedMarginLeft, orientedMarginTop); @@ -702,10 +709,10 @@ void EpubReaderActivity::renderContents(std::unique_ptr page, const int or // display grayscale part renderer.displayGrayBuffer(); renderer.setRenderMode(GfxRenderer::BW); - } - // restore the bw data - renderer.restoreBwBuffer(); + // restore the bw data + renderer.restoreBwBuffer(); + } } void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const int orientedMarginBottom, diff --git a/src/activities/reader/ReaderActivity.cpp b/src/activities/reader/ReaderActivity.cpp index dd3ea2e9d..bf0951109 100644 --- a/src/activities/reader/ReaderActivity.cpp +++ b/src/activities/reader/ReaderActivity.cpp @@ -1,5 +1,6 @@ #include "ReaderActivity.h" +#include #include #include "Epub.h" @@ -83,6 +84,7 @@ void ReaderActivity::onGoToEpubReader(std::unique_ptr epub) { const auto epubPath = epub->getPath(); currentBookPath = epubPath; exitActivity(); + renderer.requestResync(1); enterNewActivity(new EpubReaderActivity( renderer, mappedInput, std::move(epub), [this, epubPath] { goToLibrary(epubPath); }, [this] { onGoBack(); })); } @@ -91,6 +93,7 @@ void ReaderActivity::onGoToXtcReader(std::unique_ptr xtc) { const auto xtcPath = xtc->getPath(); currentBookPath = xtcPath; exitActivity(); + renderer.requestResync(1); enterNewActivity(new XtcReaderActivity( renderer, mappedInput, std::move(xtc), [this, xtcPath] { goToLibrary(xtcPath); }, [this] { onGoBack(); })); } @@ -99,6 +102,7 @@ void ReaderActivity::onGoToTxtReader(std::unique_ptr txt) { const auto txtPath = txt->getPath(); currentBookPath = txtPath; exitActivity(); + renderer.requestResync(1); enterNewActivity(new TxtReaderActivity( renderer, mappedInput, std::move(txt), [this, txtPath] { goToLibrary(txtPath); }, [this] { onGoBack(); })); } diff --git a/src/main.cpp b/src/main.cpp index cbf3e3c14..9d78fd1a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -129,6 +129,12 @@ EpdFontFamily ui12FontFamily(&ui12RegularFont, &ui12BoldFont); unsigned long t1 = 0; unsigned long t2 = 0; +inline void requestResyncIfX3(uint8_t settlePasses = 0) { + if (gpio.getDeviceType() == HalGPIO::DeviceType::X3) { + display.requestResync(settlePasses); + } +} + void exitActivity() { if (currentActivity) { currentActivity->onExit(); @@ -199,6 +205,7 @@ void enterDeepSleep() { APP_STATE.lastSleepFromReader = currentActivity && currentActivity->isReaderActivity(); APP_STATE.saveToFile(); exitActivity(); + requestResyncIfX3(0); enterNewActivity(new SleepActivity(renderer, mappedInputManager)); display.deepSleep(); @@ -248,6 +255,12 @@ void onGoToBrowser() { } void onGoHome() { + const bool returningFromReader = currentActivity && currentActivity->isReaderActivity(); + if (returningFromReader && (gpio.getDeviceType() == HalGPIO::DeviceType::X3)) { + // Force Home's first frame to run a full resync on X3. + // Avoid doing a blocking scrub refresh before activity transition. + display.requestResync(1); + } exitActivity(); enterNewActivity(new HomeActivity(renderer, mappedInputManager, onGoToReader, onGoToMyLibrary, onGoToRecentBooks, onGoToSettings, onGoToFileTransfer, onGoToBrowser)); @@ -316,7 +329,8 @@ void setup() { UITheme::getInstance().reload(); ButtonNavigator::setMappedInputManager(mappedInputManager); - switch (gpio.getWakeupReason()) { + const auto wakeupReason = gpio.getWakeupReason(); + switch (wakeupReason) { case HalGPIO::WakeupReason::PowerButton: // For normal wakeups, verify power button press duration Serial.printf("[%lu] [ ] Verifying power button press duration\n", millis()); @@ -338,6 +352,10 @@ void setup() { Serial.printf("[%lu] [ ] Starting CrossPoint version " CROSSPOINT_VERSION "\n", millis()); setupDisplayAndFonts(); + if (wakeupReason == HalGPIO::WakeupReason::PowerButton || wakeupReason == HalGPIO::WakeupReason::AfterFlash || + wakeupReason == HalGPIO::WakeupReason::Other) { + requestResyncIfX3(0); + } exitActivity(); enterNewActivity(new BootActivity(renderer, mappedInputManager));