Adds a basic implementation of `displayWindow` which displays a subset of the current frame buffer to the screen. It is significantly less performant than a full screen reload, so it shouldn't be used unless the underlying content is hard to get/rerender. I've also spotted a little bit of ghosting, but it's not fully clear as to why that is. My only thought it the LUT and grayscale mode isn't fully disengaged or the RED RAM buffer isn't correctly setup (but afaict it should be populated correctly). Going to merge this to continue testing this feature out in the wild, but consider it experimental.
EInkDisplay library
This is a focused low-level interaction library for the X4 display.
It's best paried with a higher-level GFX library to help with rendering shapes, text, and images. Along with dealing with display orientation.
See the SSD1677 guide for details on the implemention.
Usage
Setup
// Display SPI pins (custom pins for XteinkX4, not hardware SPI defaults)
#define EPD_SCLK 8 // SPI Clock
#define EPD_MOSI 10 // SPI MOSI (Master Out Slave In)
#define EPD_CS 21 // Chip Select
#define EPD_DC 4 // Data/Command
#define EPD_RST 5 // Reset
#define EPD_BUSY 6 // Busy
EInkDisplay display(EPD_SCLK, EPD_MOSI, EPD_CS, EPD_DC, EPD_RST, EPD_BUSY);
display.begin();
Rendering black and white frames
// First frame
display.clearScreen();
uint8_t* frameBuffer = einkDisplay.getFrameBuffer();
// ... your drawing code here, writing to frameBuffer, a 0 bit is black, a 1 bit is white ...
display.displayBuffer(FAST_REFRESH);
// Next frame
display.clearScreen();
uint8_t* frameBuffer = einkDisplay.getFrameBuffer();
// ... your drawing code here, writing to frameBuffer, a 0 bit is black, a 1 bit is white ...
// Using fash refresh for fast updates
display.displayBuffer(FAST_REFRESH);
Rendering greyscale frames
display.clearScreen();
uint8_t* frameBuffer = einkDisplay.getFrameBuffer();
// ... regular drawing code from before, all gray pixels should also be marked as black ...
display.displayBuffer(FAST_REFRESH);
// Grayscale rendering
// Refetch the frame buffer to ensure it's up to date
frameBuffer = einkDisplay.getFrameBuffer();
// Dark gray rendering
// Clear the screen with 0, all 0 bits are considered out of bounds for grayscale rendering
// Only mark the bits you want to be gray as 1
display.clearScreen(0x00);
// ... exact same screen content as before, but only mark the **dark** grays pixels with `1`, rest leave as `0`
display.copyGrayscaleLsbBuffers(frameBuffer);
display.clearScreen(0x00);
// ... exact same screen content as before, but mark the **light and dark** grays pixels with `1`, rest leave as `0`
display.copyGrayscaleMsbBuffers(frameBuffer);
display.displayGrayBuffer();
// All done :)
Power off
To ensure the display locks the image in, it's important to power off the display before exiting the program.
display.deepSleep();