mirror of https://github.com/sqfmi/Watchy.git
* This change implements certain speed improvements on top of upstream GxEPD2 that are not fully accepted by the upstream maintainer. * The change Adds a new WatchyDisplay class and implements the mods in there. * Using transactions for SPI communication * Remove extra delays for yield() * Remove 10ms active waits in resets * This reduces (874ms -> 657ms) the display update. Making it more responsive and Saving 21mJ/update or 2.6mAh/daypull/178/head
parent
3e3a8859a9
commit
5c27f4721f
4 changed files with 506 additions and 3 deletions
@ -0,0 +1,416 @@ |
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// based on Demo Example from Good Display, available here: http://www.e-paper-display.com/download_detail/downloadsId=806.html
|
||||
// Panel: GDEH0154D67 : http://www.e-paper-display.com/products_detail/productId=455.html
|
||||
// Controller : SSD1681 : http://www.e-paper-display.com/download_detail/downloadsId=825.html
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
//
|
||||
// The original code from the author has been slightly modified to improve the performance for Watchy Project:
|
||||
// Link: https://github.com/sqfmi/Watchy
|
||||
|
||||
#include "Display.h" |
||||
|
||||
WatchyDisplay::WatchyDisplay(int16_t cs, int16_t dc, int16_t rst, int16_t busy) : |
||||
GxEPD2_EPD(cs, dc, rst, busy, HIGH, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate) |
||||
{ |
||||
selectSPI(SPI, SPISettings(20000000, MSBFIRST, SPI_MODE0)); // Set SPI to 20Mhz (default is 4Mhz)
|
||||
} |
||||
|
||||
void WatchyDisplay::clearScreen(uint8_t value) |
||||
{ |
||||
writeScreenBuffer(value); |
||||
refresh(true); |
||||
writeScreenBufferAgain(value); |
||||
} |
||||
|
||||
void WatchyDisplay::writeScreenBuffer(uint8_t value) |
||||
{ |
||||
if (!_using_partial_mode) _Init_Part(); |
||||
if (_initial_write) _writeScreenBuffer(0x26, value); // set previous
|
||||
_writeScreenBuffer(0x24, value); // set current
|
||||
_initial_write = false; // initial full screen buffer clean done
|
||||
} |
||||
|
||||
void WatchyDisplay::writeScreenBufferAgain(uint8_t value) |
||||
{ |
||||
if (!_using_partial_mode) _Init_Part(); |
||||
_writeScreenBuffer(0x24, value); // set current
|
||||
} |
||||
|
||||
void WatchyDisplay::_writeScreenBuffer(uint8_t command, uint8_t value) |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(command); |
||||
for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++) |
||||
{ |
||||
_transfer(value); |
||||
} |
||||
_endTransfer(); |
||||
} |
||||
|
||||
void WatchyDisplay::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
_writeImage(0x24, bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
_writeImage(0x26, bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
_writeImage(0x24, bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
_writeImage(0x24, bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
|
||||
#if defined(ESP8266) || defined(ESP32) |
||||
yield(); // avoid wdt
|
||||
#endif |
||||
int16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
|
||||
x -= x % 8; // byte boundary
|
||||
w = wb * 8; // byte boundary
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
|
||||
int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
|
||||
int16_t dx = x1 - x; |
||||
int16_t dy = y1 - y; |
||||
w1 -= dx; |
||||
h1 -= dy; |
||||
if ((w1 <= 0) || (h1 <= 0)) return; |
||||
if (!_using_partial_mode) _Init_Part(); |
||||
_setPartialRamArea(x1, y1, w1, h1); |
||||
_startTransfer(); |
||||
_transferCommand(command); |
||||
for (int16_t i = 0; i < h1; i++) |
||||
{ |
||||
for (int16_t j = 0; j < w1 / 8; j++) |
||||
{ |
||||
uint8_t data; |
||||
// use wb, h of bitmap for index!
|
||||
int16_t idx = mirror_y ? j + dx / 8 + ((h - 1 - (i + dy))) * wb : j + dx / 8 + (i + dy) * wb; |
||||
if (pgm) |
||||
{ |
||||
#if defined(__AVR) || defined(ESP8266) || defined(ESP32) |
||||
data = pgm_read_byte(&bitmap[idx]); |
||||
#else |
||||
data = bitmap[idx]; |
||||
#endif |
||||
} |
||||
else |
||||
{ |
||||
data = bitmap[idx]; |
||||
} |
||||
if (invert) data = ~data; |
||||
_transfer(data); |
||||
} |
||||
} |
||||
_endTransfer(); |
||||
#if defined(ESP8266) || defined(ESP32) |
||||
yield(); // avoid wdt
|
||||
#endif |
||||
} |
||||
|
||||
void WatchyDisplay::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
_writeImagePart(0x24, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
_writeImagePart(0x24, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::_writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
|
||||
#if defined(ESP8266) || defined(ESP32) |
||||
yield(); // avoid wdt
|
||||
#endif |
||||
if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return; |
||||
if ((x_part < 0) || (x_part >= w_bitmap)) return; |
||||
if ((y_part < 0) || (y_part >= h_bitmap)) return; |
||||
int16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
|
||||
x_part -= x_part % 8; // byte boundary
|
||||
w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
|
||||
h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
|
||||
x -= x % 8; // byte boundary
|
||||
w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
|
||||
int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
|
||||
int16_t dx = x1 - x; |
||||
int16_t dy = y1 - y; |
||||
w1 -= dx; |
||||
h1 -= dy; |
||||
if ((w1 <= 0) || (h1 <= 0)) return; |
||||
if (!_using_partial_mode) _Init_Part(); |
||||
_setPartialRamArea(x1, y1, w1, h1); |
||||
_startTransfer(); |
||||
_transferCommand(command); |
||||
for (int16_t i = 0; i < h1; i++) |
||||
{ |
||||
for (int16_t j = 0; j < w1 / 8; j++) |
||||
{ |
||||
uint8_t data; |
||||
// use wb_bitmap, h_bitmap of bitmap for index!
|
||||
int16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + ((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + (y_part + i + dy) * wb_bitmap; |
||||
if (pgm) |
||||
{ |
||||
#if defined(__AVR) || defined(ESP8266) || defined(ESP32) |
||||
data = pgm_read_byte(&bitmap[idx]); |
||||
#else |
||||
data = bitmap[idx]; |
||||
#endif |
||||
} |
||||
else |
||||
{ |
||||
data = bitmap[idx]; |
||||
} |
||||
if (invert) data = ~data; |
||||
_transfer(data); |
||||
} |
||||
} |
||||
_endTransfer(); |
||||
#if defined(ESP8266) || defined(ESP32) |
||||
yield(); // avoid wdt
|
||||
#endif |
||||
} |
||||
|
||||
void WatchyDisplay::writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (black) |
||||
{ |
||||
writeImage(black, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (black) |
||||
{ |
||||
writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (data1) |
||||
{ |
||||
writeImage(data1, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
refresh(x, y, w, h); |
||||
writeImageAgain(bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
refresh(x, y, w, h); |
||||
writeImagePartAgain(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
|
||||
void WatchyDisplay::drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (black) |
||||
{ |
||||
drawImage(black, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (black) |
||||
{ |
||||
drawImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm) |
||||
{ |
||||
if (data1) |
||||
{ |
||||
drawImage(data1, x, y, w, h, invert, mirror_y, pgm); |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::refresh(bool partial_update_mode) |
||||
{ |
||||
if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT); |
||||
else |
||||
{ |
||||
if (_using_partial_mode) _Init_Full(); |
||||
_Update_Full(); |
||||
_initial_refresh = false; // initial full update done
|
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::refresh(int16_t x, int16_t y, int16_t w, int16_t h) |
||||
{ |
||||
if (_initial_refresh) return refresh(false); // initial update needs be full update
|
||||
// intersection with screen
|
||||
int16_t w1 = x < 0 ? w + x : w; // reduce
|
||||
int16_t h1 = y < 0 ? h + y : h; // reduce
|
||||
int16_t x1 = x < 0 ? 0 : x; // limit
|
||||
int16_t y1 = y < 0 ? 0 : y; // limit
|
||||
w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit
|
||||
h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit
|
||||
if ((w1 <= 0) || (h1 <= 0)) return;
|
||||
// make x1, w1 multiple of 8
|
||||
w1 += x1 % 8; |
||||
if (w1 % 8 > 0) w1 += 8 - w1 % 8; |
||||
x1 -= x1 % 8; |
||||
if (!_using_partial_mode) _Init_Part(); |
||||
_setPartialRamArea(x1, y1, w1, h1); |
||||
_Update_Part(); |
||||
} |
||||
|
||||
void WatchyDisplay::powerOff() |
||||
{ |
||||
_PowerOff(); |
||||
} |
||||
|
||||
void WatchyDisplay::hibernate() |
||||
{ |
||||
//_PowerOff(); // Not needed before entering deep sleep
|
||||
if (_rst >= 0) |
||||
{ |
||||
_writeCommand(0x10); // deep sleep mode
|
||||
_writeData(0x1); // enter deep sleep
|
||||
_hibernating = true; |
||||
} |
||||
} |
||||
|
||||
void WatchyDisplay::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h) |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(0x11); // set ram entry mode
|
||||
_transfer(0x03); // x increase, y increase : normal mode
|
||||
_transferCommand(0x44); |
||||
_transfer(x / 8); |
||||
_transfer((x + w - 1) / 8); |
||||
_transferCommand(0x45); |
||||
_transfer(y % 256); |
||||
_transfer(y / 256); |
||||
_transfer((y + h - 1) % 256); |
||||
_transfer((y + h - 1) / 256); |
||||
_transferCommand(0x4e); |
||||
_transfer(x / 8); |
||||
_transferCommand(0x4f); |
||||
_transfer(y % 256); |
||||
_transfer(y / 256); |
||||
_endTransfer(); |
||||
} |
||||
|
||||
void WatchyDisplay::_PowerOn() |
||||
{ |
||||
if (!_power_is_on) |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(0x22); |
||||
_transfer(0xf8); |
||||
_transferCommand(0x20); |
||||
_endTransfer(); |
||||
_waitWhileBusy("_PowerOn", power_on_time); |
||||
} |
||||
_power_is_on = true; |
||||
} |
||||
|
||||
void WatchyDisplay::_PowerOff() |
||||
{ |
||||
if (_power_is_on) |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(0x22); |
||||
_transfer(0x83); |
||||
_transferCommand(0x20); |
||||
_endTransfer(); |
||||
_waitWhileBusy("_PowerOff", power_off_time); |
||||
} |
||||
_power_is_on = false; |
||||
_using_partial_mode = false; |
||||
} |
||||
|
||||
void WatchyDisplay::_InitDisplay() |
||||
{ |
||||
if (_hibernating) _reset(); |
||||
_writeCommand(0x12); // soft reset
|
||||
_waitWhileBusy("_SoftReset", 10); // 10ms max according to specs
|
||||
|
||||
_startTransfer(); |
||||
_transferCommand(0x01); // Driver output control
|
||||
_transfer(0xC7); |
||||
_transfer(0x00); |
||||
_transfer(0x00); |
||||
_transferCommand(0x3C); // BorderWavefrom
|
||||
_transfer(darkBorder ? 0x02 : 0x05); |
||||
_transferCommand(0x18); // Read built-in temperature sensor
|
||||
_transfer(0x80); |
||||
_endTransfer(); |
||||
|
||||
_setPartialRamArea(0, 0, WIDTH, HEIGHT); |
||||
} |
||||
|
||||
void WatchyDisplay::_Init_Full() |
||||
{ |
||||
_InitDisplay(); |
||||
_PowerOn(); |
||||
_using_partial_mode = false; |
||||
} |
||||
|
||||
void WatchyDisplay::_Init_Part() |
||||
{ |
||||
_InitDisplay(); |
||||
_PowerOn(); |
||||
_using_partial_mode = true; |
||||
} |
||||
|
||||
void WatchyDisplay::_Update_Full() |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(0x22); |
||||
_transfer(0xf4); |
||||
_transferCommand(0x20); |
||||
_endTransfer(); |
||||
_waitWhileBusy("_Update_Full", full_refresh_time); |
||||
} |
||||
|
||||
void WatchyDisplay::_Update_Part() |
||||
{ |
||||
_startTransfer(); |
||||
_transferCommand(0x22); |
||||
//_transfer(0xcc); // skip temperature load (-5ms)
|
||||
_transfer(0xfc); |
||||
_transferCommand(0x20); |
||||
_endTransfer(); |
||||
_waitWhileBusy("_Update_Part", partial_refresh_time); |
||||
} |
||||
|
||||
void WatchyDisplay::_transferCommand(uint8_t value) |
||||
{ |
||||
if (_dc >= 0) digitalWrite(_dc, LOW); |
||||
SPI.transfer(value); |
||||
if (_dc >= 0) digitalWrite(_dc, HIGH); |
||||
} |
@ -0,0 +1,86 @@ |
||||
// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
|
||||
// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
|
||||
//
|
||||
// based on Demo Example from Good Display, available here: http://www.e-paper-display.com/download_detail/downloadsId=806.html
|
||||
// Panel: GDEH0154D67 : http://www.e-paper-display.com/products_detail/productId=455.html
|
||||
// Controller : SSD1681 : http://www.e-paper-display.com/download_detail/downloadsId=825.html
|
||||
//
|
||||
// Author: Jean-Marc Zingg
|
||||
//
|
||||
// Version: see library.properties
|
||||
//
|
||||
// Library: https://github.com/ZinggJM/GxEPD2
|
||||
//
|
||||
// The original code from the author has been slightly modified to improve the performance for Watchy Project:
|
||||
// Link: https://github.com/sqfmi/Watchy
|
||||
|
||||
#pragma once |
||||
|
||||
#include <GxEPD2_EPD.h> |
||||
|
||||
class WatchyDisplay : public GxEPD2_EPD |
||||
{ |
||||
public: |
||||
// attributes
|
||||
static const uint16_t WIDTH = 200; |
||||
static const uint16_t HEIGHT = 200; |
||||
static const GxEPD2::Panel panel = GxEPD2::GDEH0154D67; |
||||
static const bool hasColor = false; |
||||
static const bool hasPartialUpdate = true; |
||||
static const bool hasFastPartialUpdate = true; |
||||
static const uint16_t power_on_time = 100; // ms, e.g. 95583us
|
||||
static const uint16_t power_off_time = 150; // ms, e.g. 140621us
|
||||
static const uint16_t full_refresh_time = 2600; // ms, e.g. 2509602us
|
||||
static const uint16_t partial_refresh_time = 500; // ms, e.g. 457282us
|
||||
// constructor
|
||||
WatchyDisplay(int16_t cs, int16_t dc, int16_t rst, int16_t busy); |
||||
// methods (virtual)
|
||||
// Support for Bitmaps (Sprites) to Controller Buffer and to Screen
|
||||
void clearScreen(uint8_t value = 0xFF); // init controller memory and screen (default white)
|
||||
void writeScreenBuffer(uint8_t value = 0xFF); // init controller memory (default white)
|
||||
void writeScreenBufferAgain(uint8_t value = 0xFF); // init previous buffer controller memory (default white)
|
||||
// write to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
// for differential update: set current and previous buffers equal (for fast partial update to work correctly)
|
||||
void writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
// write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8
|
||||
void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
// write to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
// write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8
|
||||
void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void refresh(bool partial_update_mode = false); // screen refresh from controller memory to full screen
|
||||
void refresh(int16_t x, int16_t y, int16_t w, int16_t h); // screen refresh from controller memory, partial screen
|
||||
void powerOff(); // turns off generation of panel driving voltages, avoids screen fading over time
|
||||
void hibernate(); // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
|
||||
|
||||
bool darkBorder = false; // adds a dark border outside the normal screen area
|
||||
private: |
||||
void _writeScreenBuffer(uint8_t command, uint8_t value); |
||||
void _writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void _writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, |
||||
int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false); |
||||
void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h); |
||||
void _PowerOn(); |
||||
void _PowerOff(); |
||||
void _InitDisplay(); |
||||
void _Init_Full(); |
||||
void _Init_Part(); |
||||
void _Update_Full(); |
||||
void _Update_Part(); |
||||
|
||||
void _transferCommand(uint8_t command); |
||||
}; |
Loading…
Reference in new issue