## Summary After a silent reboot, there was a small window where the esp32 would listen for button presses but the full refresh would hold the event loop. This gave a UX experience where the silent reboot had completed to the home screen, a user taps select (at any time during the process), and they find themselves unexpectedly in a book. ## Additional Context This must land after https://github.com/crosspoint-reader/community-sdk/pull/11 and will need the submodule SHA changes included in. --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? partially
99 lines
3.5 KiB
C++
99 lines
3.5 KiB
C++
#include <HalDisplay.h>
|
|
#include <HalGPIO.h>
|
|
|
|
// Global HalDisplay instance
|
|
HalDisplay display;
|
|
|
|
#define SD_SPI_MISO 7
|
|
|
|
HalDisplay::HalDisplay() : einkDisplay(EPD_SCLK, EPD_MOSI, EPD_CS, EPD_DC, EPD_RST, EPD_BUSY) {}
|
|
|
|
HalDisplay::~HalDisplay() {}
|
|
|
|
void HalDisplay::begin(bool seamless) {
|
|
// Set X3-specific panel mode before initializing.
|
|
if (gpio.deviceIsX3()) {
|
|
einkDisplay.setDisplayX3();
|
|
}
|
|
|
|
einkDisplay.begin();
|
|
|
|
if (seamless) {
|
|
// Defuse the SDK's X3 _x3InitialFullSyncsRemaining counter (no-op on X4)
|
|
// so the first paint isn't promoted to FULL (~770ms). Skips the wakeup-
|
|
// gated requestResync() below for the same reason.
|
|
einkDisplay.skipInitialResync();
|
|
return;
|
|
}
|
|
// Request resync after specific wakeup events to ensure clean display state.
|
|
const auto wakeupReason = gpio.getWakeupReason();
|
|
if (wakeupReason == HalGPIO::WakeupReason::PowerButton || wakeupReason == HalGPIO::WakeupReason::AfterFlash ||
|
|
wakeupReason == HalGPIO::WakeupReason::Other) {
|
|
einkDisplay.requestResync();
|
|
}
|
|
}
|
|
|
|
void HalDisplay::clearScreen(uint8_t color) const { einkDisplay.clearScreen(color); }
|
|
|
|
void HalDisplay::drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
|
|
bool fromProgmem) const {
|
|
einkDisplay.drawImage(imageData, x, y, w, h, fromProgmem);
|
|
}
|
|
|
|
void HalDisplay::drawImageTransparent(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
|
|
bool fromProgmem) const {
|
|
einkDisplay.drawImageTransparent(imageData, x, y, w, h, fromProgmem);
|
|
}
|
|
|
|
EInkDisplay::RefreshMode convertRefreshMode(HalDisplay::RefreshMode mode) {
|
|
switch (mode) {
|
|
case HalDisplay::FULL_REFRESH:
|
|
return EInkDisplay::FULL_REFRESH;
|
|
case HalDisplay::HALF_REFRESH:
|
|
return EInkDisplay::HALF_REFRESH;
|
|
case HalDisplay::FAST_REFRESH:
|
|
default:
|
|
return EInkDisplay::FAST_REFRESH;
|
|
}
|
|
}
|
|
|
|
void HalDisplay::displayBuffer(HalDisplay::RefreshMode mode, bool turnOffScreen) {
|
|
if (gpio.deviceIsX3() && mode == RefreshMode::HALF_REFRESH) {
|
|
einkDisplay.requestResync(1);
|
|
}
|
|
|
|
einkDisplay.displayBuffer(convertRefreshMode(mode), turnOffScreen);
|
|
}
|
|
|
|
void HalDisplay::refreshDisplay(HalDisplay::RefreshMode mode, bool turnOffScreen) {
|
|
if (gpio.deviceIsX3() && mode == RefreshMode::HALF_REFRESH) {
|
|
einkDisplay.requestResync(1);
|
|
}
|
|
|
|
einkDisplay.refreshDisplay(convertRefreshMode(mode), turnOffScreen);
|
|
}
|
|
|
|
void HalDisplay::deepSleep() { einkDisplay.deepSleep(); }
|
|
|
|
uint8_t* HalDisplay::getFrameBuffer() const { return einkDisplay.getFrameBuffer(); }
|
|
|
|
void HalDisplay::copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer) {
|
|
einkDisplay.copyGrayscaleBuffers(lsbBuffer, msbBuffer);
|
|
}
|
|
|
|
void HalDisplay::copyGrayscaleLsbBuffers(const uint8_t* lsbBuffer) { einkDisplay.copyGrayscaleLsbBuffers(lsbBuffer); }
|
|
|
|
void HalDisplay::copyGrayscaleMsbBuffers(const uint8_t* msbBuffer) { einkDisplay.copyGrayscaleMsbBuffers(msbBuffer); }
|
|
|
|
void HalDisplay::cleanupGrayscaleBuffers(const uint8_t* bwBuffer) { einkDisplay.cleanupGrayscaleBuffers(bwBuffer); }
|
|
|
|
void HalDisplay::displayGrayBuffer(bool turnOffScreen) { einkDisplay.displayGrayBuffer(turnOffScreen); }
|
|
|
|
uint16_t HalDisplay::getDisplayWidth() const { return einkDisplay.getDisplayWidth(); }
|
|
|
|
uint16_t HalDisplay::getDisplayHeight() const { return einkDisplay.getDisplayHeight(); }
|
|
|
|
uint16_t HalDisplay::getDisplayWidthBytes() const { return einkDisplay.getDisplayWidthBytes(); }
|
|
|
|
uint32_t HalDisplay::getBufferSize() const { return einkDisplay.getBufferSize(); }
|