#pragma once #include #include class HalDisplay { public: // Constructor with pin configuration HalDisplay(); // Destructor ~HalDisplay(); // Refresh modes enum RefreshMode { FULL_REFRESH, // Full refresh with complete waveform HALF_REFRESH, // Half refresh (1720ms) - balanced quality and speed FAST_REFRESH // Fast refresh using custom LUT }; // Initialize the display hardware and driver. // When seamless=true, skip the on-wake resync so existing panel content is preserved // (used by Quick Resume to bring back the last reader page without a boot screen). void begin(bool seamless = false); // Display dimensions static constexpr uint16_t DISPLAY_WIDTH = EInkDisplay::DISPLAY_WIDTH; static constexpr uint16_t DISPLAY_HEIGHT = EInkDisplay::DISPLAY_HEIGHT; static constexpr uint16_t DISPLAY_WIDTH_BYTES = DISPLAY_WIDTH / 8; static constexpr uint32_t BUFFER_SIZE = DISPLAY_WIDTH_BYTES * DISPLAY_HEIGHT; // Frame buffer operations void clearScreen(uint8_t color = 0xFF) const; void drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool fromProgmem = false) const; void drawImageTransparent(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool fromProgmem = false) const; 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(); // Access to frame buffer uint8_t* getFrameBuffer() const; void copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer); void copyGrayscaleLsbBuffers(const uint8_t* lsbBuffer); void copyGrayscaleMsbBuffers(const uint8_t* msbBuffer); void cleanupGrayscaleBuffers(const uint8_t* bwBuffer); void displayGrayBuffer(bool turnOffScreen = false); // Tiled grayscale: stream one band of a plane (lsbPlane selects LSB/MSB RAM) // straight to the controller; supportsStripGrayscale() gates the path. See // EInkDisplay::writeGrayscalePlaneStrip. void writeGrayscalePlaneStrip(bool lsbPlane, const uint8_t* rows, uint16_t yStart, uint16_t numRows); bool supportsStripGrayscale() const; // X3-only knob: pick between the OEM 53-frame grayscale LUT (default, slow // and accurate) and the 7-frame community LUT (fast, slightly darker // mid-tones). No effect on X4. See EInkDisplay::setFastGrayscaleLut. void setFastGrayscaleLut(bool fast); bool getFastGrayscaleLut() const; // Runtime geometry passthrough uint16_t getDisplayWidth() const; uint16_t getDisplayHeight() const; uint16_t getDisplayWidthBytes() const; uint32_t getBufferSize() const; private: EInkDisplay einkDisplay; uint8_t pendingX3SettlePasses = 0; }; extern HalDisplay display;