Something went wrong. Try again.
A fork of https://github.com/crosspoint-reader/crosspoint-reader
Something went wrong. Try again.
6.1 kB · 133 lines
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134#pragma once#include <Arduino.h>#include <BoardConfig.h>#include <EInkDisplay.h>
class HalDisplay { public: using Controller = BoardConfig::DisplayController; Controller getController() const;
using GrayscaleMode = freeink::GrayscaleMode; using GrayscaleCapabilities = freeink::GrayscaleCapabilities; using GrayscaleBase = freeink::GrayscaleBase; using GrayscaleEncoding = freeink::GrayscaleEncoding;
GrayscaleCapabilities grayscaleCapabilities(GrayscaleMode mode = GrayscaleMode::Overlay) const;
// 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 };
// Pass seamless=true on any path where the panel already shows the // content it should after begin() returns (silent reboot's popup, // sleep-wake with a restored buffer). Skips the wakeup-gated // requestResync() and defuses the SDK's X3 _x3InitialFullSyncsRemaining // counter; otherwise the first two paints get promoted to FULL // (~770ms each on X3). 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); // Non-blocking refresh (shadow-free): starts the panel waveform and returns // while the panel refreshes on its own. The framebuffer must stay untouched // until waitRefreshComplete(), and the caller must rebuild the differential // baseline before the next differential update (the tiled grayscale cleanup // does). Panels without deferral fall back to a blocking refresh. void displayBufferAsync(RefreshMode mode = RefreshMode::FAST_REFRESH); // Block until a pending deferred refresh completes (no-op when none is). void waitRefreshComplete(); // True when displayBufferAsync() genuinely overlaps (panel driver defers); // false where it falls back to a blocking refresh. bool supportsAsyncRefresh() const; // True when an ordinary deferred B/W refresh is suitable as the base for a // grayscale pass. X3 needs its controller-specific grayscale base waveform. bool supportsAsyncGrayscaleBase() const; void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false);
// Output polarity. The framebuffer remains in normal polarity; inversion is // applied by the display driver while sending it to the panel. void setInverted(bool inverted); bool toggleInverted(); bool isInverted() const;
// Power management void deepSleep();
// Access to frame buffer uint8_t* getFrameBuffer() const;
// Lend the framebuffer's ~48 KB STORAGE to a memory-hungry phase (chapter // builds) without freeing it: the allocation never moves, so repeated loans // cannot fragment the heap (free+realloc measurably did). No display calls // between lend and return; the panel keeps its last refreshed image. The // buffer comes back white — redraw fully. Returns nullptr if already lent. uint8_t* lendFrameBufferStorage(uint32_t* sizeOut); void returnFrameBufferStorage();
// X3 grayscale preconditioning (OEM "AA-pre-BW(mid)" settle pass), windowed // to the gray region in physical panel coordinates (no-arg = full frame). // Call after the BW base frame is displayed and before the grayscale planes // are written; no-op on X4. See EInkDisplay::preconditionGrayscale. void preconditionGrayscale(); void preconditionGrayscale(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
// Display the framebuffer as the base frame for a grayscale overlay that // follows. On X3, HALF fallback first requests a resync to match // displayBuffer(HALF); FAST fallback keeps the OEM differential base waveform // ("AA-pre-BW(mid)"). Other panels display normally with `fallback` mode. void displayGrayscaleBase(RefreshMode fallback = HALF_REFRESH, bool turnOffScreen = false); bool displayGrayscaleBase(GrayscaleMode mode, RefreshMode fallback = HALF_REFRESH, bool turnOffScreen = false);
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;
// True when displayGrayscaleBase() defers the base activation so the gray // planes join it in a single waveform (Paper Mono). Callers should then route // the base of a grayscale page through displayGrayscaleBase() instead of // displayBuffer(): a separate B/W refresh first makes the gray pass re-drive // the whole text body (a visible flash). bool combinesGrayscaleBase() const;
// Runtime geometry passthrough uint16_t getDisplayWidth() const; uint16_t getDisplayHeight() const; uint16_t getDisplayWidthBytes() const; uint32_t getBufferSize() const;
private: EInkDisplay einkDisplay;};
extern HalDisplay display;