#pragma once #include "configuration.h" #ifdef USE_EINK_PARALLELDISPLAY #include #include #include #include class FASTEPD; /** * Adapter for E-Ink 8-bit parallel displays (EPD), specifically devices supported by FastEPD library */ class EInkParallelDisplay : public OLEDDisplay { public: enum EpdRotation { EPD_ROT_LANDSCAPE = 0, EPD_ROT_PORTRAIT = 90, EPD_ROT_INVERTED_LANDSCAPE = 180, EPD_ROT_INVERTED_PORTRAIT = 270, }; EInkParallelDisplay(uint16_t width, uint16_t height, EpdRotation rotation); virtual ~EInkParallelDisplay(); // OLEDDisplay virtuals bool connect() override; void sendCommand(uint8_t com) override; int getBufferOffset(void) override { return 0; } void display(void) override; bool forceDisplay(uint32_t msecLimit = 1000); void endUpdate(); protected: uint32_t lastDrawMsec = 0; FASTEPD *epaper; private: // Async full-refresh support std::atomic asyncFullRunning{false}; TaskHandle_t asyncTaskHandle = nullptr; void startAsyncFullUpdate(int clearMode); static void asyncFullUpdateTask(void *pvParameters); #ifdef EINK_LIMIT_GHOSTING_PX // helpers void resetGhostPixelTracking(); void markDirtyBits(const uint8_t *prevBuf, uint32_t pos, uint8_t mask, uint8_t out); void countGhostPixelsAndMaybePromote(int &newTop, int &newBottom, bool &forceFull); // per-bit dirty buffer (same format as epaper buffers): one bit == one pixel uint8_t *dirtyPixels = nullptr; size_t dirtyPixelsSize = 0; uint32_t ghostPixelCount = 0; uint32_t ghostPixelLimit = EINK_LIMIT_GHOSTING_PX; #endif EpdRotation rotation; uint32_t previousImageHash = 0; uint32_t lastUpdateMs = 0; int fastRefreshCount = 0; }; #endif