Add EINK_DISPLAY_SINGLE_BUFFER_MODE build flag and allow for single buffer rendering
This commit is contained in:
parent
54e6368c01
commit
9536359647
@ -30,12 +30,17 @@ class EInkDisplay {
|
||||
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;
|
||||
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
void swapBuffers();
|
||||
#endif
|
||||
void setFramebuffer(const uint8_t* bwBuffer) const;
|
||||
|
||||
void copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t* msbBuffer);
|
||||
void copyGrayscaleLsbBuffers(const uint8_t* lsbBuffer);
|
||||
void copyGrayscaleMsbBuffers(const uint8_t* msbBuffer);
|
||||
#ifdef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
void cleanupGrayscaleBuffers(const uint8_t* bwBuffer);
|
||||
#endif
|
||||
|
||||
void displayBuffer(RefreshMode mode = FAST_REFRESH);
|
||||
void displayGrayBuffer(bool turnOffScreen = false);
|
||||
@ -65,10 +70,11 @@ class EInkDisplay {
|
||||
|
||||
// Frame buffer (statically allocated)
|
||||
uint8_t frameBuffer0[BUFFER_SIZE];
|
||||
uint8_t frameBuffer1[BUFFER_SIZE];
|
||||
|
||||
uint8_t* frameBuffer;
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
uint8_t frameBuffer1[BUFFER_SIZE];
|
||||
uint8_t* frameBufferActive;
|
||||
#endif
|
||||
|
||||
// SPI settings
|
||||
SPISettings spiSettings;
|
||||
|
||||
@ -115,7 +115,9 @@ EInkDisplay::EInkDisplay(int8_t sclk, int8_t mosi, int8_t cs, int8_t dc, int8_t
|
||||
_rst(rst),
|
||||
_busy(busy),
|
||||
frameBuffer(nullptr),
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
frameBufferActive(nullptr),
|
||||
#endif
|
||||
customLutActive(false) {
|
||||
Serial.printf("[%lu] EInkDisplay: Constructor called\n", millis());
|
||||
Serial.printf("[%lu] SCLK=%d, MOSI=%d, CS=%d, DC=%d, RST=%d, BUSY=%d\n", millis(), sclk, mosi, cs, dc, rst, busy);
|
||||
@ -125,13 +127,19 @@ void EInkDisplay::begin() {
|
||||
Serial.printf("[%lu] EInkDisplay: begin() called\n", millis());
|
||||
|
||||
frameBuffer = frameBuffer0;
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
frameBufferActive = frameBuffer1;
|
||||
#endif
|
||||
|
||||
// Initialize to white
|
||||
memset(frameBuffer0, 0xFF, BUFFER_SIZE);
|
||||
#ifdef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
Serial.printf("[%lu] Static frame buffer (%lu bytes = 48KB)\n", millis(), BUFFER_SIZE);
|
||||
#else
|
||||
memset(frameBuffer1, 0xFF, BUFFER_SIZE);
|
||||
|
||||
Serial.printf("[%lu] Static frame buffers (2 x %lu bytes = 96KB)\n", millis(), BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
Serial.printf("[%lu] Initializing e-ink display driver...\n", millis());
|
||||
|
||||
// Initialize SPI with custom pins
|
||||
@ -351,11 +359,13 @@ void EInkDisplay::setFramebuffer(const uint8_t* bwBuffer) const {
|
||||
memcpy(frameBuffer, bwBuffer, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
void EInkDisplay::swapBuffers() {
|
||||
uint8_t* temp = frameBuffer;
|
||||
frameBuffer = frameBufferActive;
|
||||
frameBufferActive = temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EInkDisplay::grayscaleRevert() {
|
||||
if (!inGrayscaleMode) {
|
||||
@ -386,6 +396,18 @@ void EInkDisplay::copyGrayscaleBuffers(const uint8_t* lsbBuffer, const uint8_t*
|
||||
writeRamBuffer(CMD_WRITE_RAM_RED, msbBuffer, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
#ifdef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
/**
|
||||
* In single buffer mode, this should be called with the previously written BW buffer
|
||||
* to reconstruct the RED buffer for proper differential fast refreshes following a
|
||||
* grayscale display.
|
||||
*/
|
||||
void EInkDisplay::cleanupGrayscaleBuffers(const uint8_t* bwBuffer) {
|
||||
setRamArea(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||
writeRamBuffer(CMD_WRITE_RAM_RED, bwBuffer, BUFFER_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void EInkDisplay::displayBuffer(RefreshMode mode) {
|
||||
if (!isScreenOn) {
|
||||
// Force half refresh if screen is off
|
||||
@ -408,14 +430,22 @@ void EInkDisplay::displayBuffer(RefreshMode mode) {
|
||||
} else {
|
||||
// For fast refresh, write to BW buffer only
|
||||
writeRamBuffer(CMD_WRITE_RAM_BW, frameBuffer, BUFFER_SIZE);
|
||||
// In single buffer mode, the RED RAM should already contain the previous frame
|
||||
// In dual buffer mode, we write back frameBufferActive which is the last frame
|
||||
#ifndef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
writeRamBuffer(CMD_WRITE_RAM_RED, frameBufferActive, BUFFER_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
// swap active buffer for next time
|
||||
swapBuffers();
|
||||
|
||||
// Refresh the display
|
||||
refreshDisplay(mode);
|
||||
|
||||
#ifdef EINK_DISPLAY_SINGLE_BUFFER_MODE
|
||||
// In single buffer mode always sync RED RAM after refresh to prepare for next fast refresh
|
||||
// This ensures RED contains the currently displayed frame for differential comparison
|
||||
setRamArea(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||
writeRamBuffer(CMD_WRITE_RAM_RED, frameBuffer, BUFFER_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void EInkDisplay::displayGrayBuffer(const bool turnOffScreen) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user