17#ifndef ENABLE_GxEPD2_GFX
19#define ENABLE_GxEPD2_GFX 0
24#define GxEPD2_GFX_BASE_CLASS GxEPD2_GFX
26#define GxEPD2_GFX_BASE_CLASS GFX
28#include <Adafruit_GFX.h>
29#define GxEPD2_GFX_BASE_CLASS Adafruit_GFX
53template<
typename GxEPD2_Type, const u
int16_t page_height>
59 GxEPD2_3C(GxEPD2_Type epd2_instance) : GxEPD2_GFX_BASE_CLASS(
epd2, GxEPD2_Type::WIDTH_VISIBLE, GxEPD2_Type::HEIGHT),
epd2(epd2_instance)
61 GxEPD2_3C(GxEPD2_Type epd2_instance) : GxEPD2_GFX_BASE_CLASS(GxEPD2_Type::WIDTH_VISIBLE, GxEPD2_Type::HEIGHT),
epd2(epd2_instance)
64 _page_height = page_height;
65 _pages = (HEIGHT / _page_height) + ((HEIGHT % _page_height) > 0);
67 _using_partial_mode =
false;
88 void drawPixel(int16_t x, int16_t y, uint16_t color)
90 if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
return;
91 if (_mirror) x = width() - x - 1;
93 switch (getRotation())
112 if ((x < 0) || (x >= int16_t(_pw_w)) || (y < 0) || (y >= int16_t(_pw_h)))
return;
114 y -= _current_page * _page_height;
116 if ((y < 0) || (y >= int16_t(_page_height)))
return;
117 uint16_t i = x / 8 + y * (_pw_w / 8);
118 _black_buffer[i] = (_black_buffer[i] | (1 << (7 - x % 8)));
119 _color_buffer[i] = (_color_buffer[i] | (1 << (7 - x % 8)));
121 else if (color ==
GxEPD_BLACK) _black_buffer[i] = (_black_buffer[i] & (0xFF ^ (1 << (7 - x % 8))));
122 else if ((color ==
GxEPD_RED) || (color ==
GxEPD_YELLOW)) _color_buffer[i] = (_color_buffer[i] & (0xFF ^ (1 << (7 - x % 8))));
125 void init(uint32_t serial_diag_bitrate = 0)
127 epd2.init(serial_diag_bitrate);
128 _using_partial_mode =
false;
138 void init(uint32_t serial_diag_bitrate,
bool initial, uint16_t reset_duration = 20,
bool pulldown_rst_mode =
false)
140 epd2.init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode);
141 _using_partial_mode =
false;
149 void init(uint32_t serial_diag_bitrate,
bool initial, uint16_t reset_duration,
bool pulldown_rst_mode, SPIClass& spi, SPISettings spi_settings)
151 epd2.selectSPI(spi, spi_settings);
152 epd2.init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode);
153 _using_partial_mode =
false;
160 uint8_t black = 0xFF;
165 for (uint16_t x = 0; x <
sizeof(_black_buffer); x++)
167 _black_buffer[x] = black;
168 _color_buffer[x] = red;
173 void display(
bool partial_update_mode =
false)
175 epd2.writeImage(_black_buffer, _color_buffer, 0, 0, GxEPD2_Type::WIDTH, _page_height);
176 epd2.refresh(partial_update_mode);
177 if (!partial_update_mode)
epd2.powerOff();
188 x = gx_uint16_min(x, width());
189 y = gx_uint16_min(y, height());
190 w = gx_uint16_min(w, width() - x);
191 h = gx_uint16_min(h, height() - y);
193 epd2.writeImagePart(_black_buffer, _color_buffer, x, y, GxEPD2_Type::WIDTH, _page_height, x, y, w, h);
194 epd2.refresh(x, y, w, h);
199 x = gx_uint16_min(x, width());
200 y = gx_uint16_min(y, height());
201 w = gx_uint16_min(w, width() - x);
202 h = gx_uint16_min(h, height() - y);
204 epd2.writeImagePartNew(_black_buffer, x, y, GxEPD2_Type::WIDTH, _page_height, x, y, w, h);
205 epd2.refresh_bw(x, y, w, h);
206 epd2.writeImagePartPrevious(_black_buffer, x, y, GxEPD2_Type::WIDTH, _page_height, x, y, w, h);
211 _using_partial_mode =
false;
214 _pw_w = GxEPD2_Type::WIDTH;
225 if (!
epd2.hasPartialUpdate)
return;
226 _pw_x = gx_uint16_min(x, width());
227 _pw_y = gx_uint16_min(y, height());
228 _pw_w = gx_uint16_min(w, width() - _pw_x);
229 _pw_h = gx_uint16_min(h, height() - _pw_y);
230 _rotate(_pw_x, _pw_y, _pw_w, _pw_h);
231 _using_partial_mode =
true;
234 if (_pw_w % 8 > 0) _pw_w += 8 - _pw_w % 8;
242 _second_phase =
false;
248 uint16_t page_ys = _current_page * _page_height;
249 if (_using_partial_mode)
253 uint16_t page_ye = _current_page < int16_t(_pages - 1) ? page_ys + _page_height : HEIGHT;
254 uint16_t dest_ys = _pw_y + page_ys;
255 uint16_t dest_ye = gx_uint16_min(_pw_y + _pw_h, _pw_y + page_ye);
256 if (dest_ye > dest_ys)
260 epd2.writeImage(_black_buffer, _color_buffer, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
269 if (_current_page == int16_t(_pages))
274 epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
275 if (
epd2.hasFastPartialUpdate)
277 _second_phase =
true;
288 epd2.writeImage(_black_buffer, _color_buffer, 0, page_ys, GxEPD2_Type::WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
290 if (_current_page == int16_t(_pages))
298 _second_phase =
true;
302 else epd2.refresh(
true);
303 }
else epd2.refresh(
false);
316 if (_using_partial_mode)
318 epd2.writeImageNew(_black_buffer, _pw_x, _pw_y, _pw_w, _pw_h);
319 epd2.refresh_bw(_pw_x, _pw_y, _pw_w, _pw_h);
320 epd2.writeImagePrevious(_black_buffer, _pw_x, _pw_y, _pw_w, _pw_h);
324 epd2.writeImage(_black_buffer, 0, 0, GxEPD2_Type::WIDTH, HEIGHT);
326 epd2.writeImagePrevious(_black_buffer, 0, 0, GxEPD2_Type::WIDTH, HEIGHT);
331 uint16_t page_ys = _current_page * _page_height;
332 if (_using_partial_mode)
336 uint16_t page_ye = _current_page < (_pages - 1) ? page_ys + _page_height : HEIGHT;
337 uint16_t dest_ys = _pw_y + page_ys;
338 uint16_t dest_ye = gx_uint16_min(_pw_y + _pw_h, _pw_y + page_ye);
339 if (dest_ye > dest_ys)
343 if (!_second_phase)
epd2.writeImageNew(_black_buffer, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
344 else epd2.writeImagePrevious(_black_buffer, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
353 if (_current_page == _pages)
358 epd2.refresh_bw(_pw_x, _pw_y, _pw_w, _pw_h);
359 _second_phase =
true;
370 if (!_second_phase)
epd2.writeImage(_black_buffer, 0, page_ys, GxEPD2_Type::WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
371 else epd2.writeImagePrevious(_black_buffer, 0, page_ys, GxEPD2_Type::WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
373 if (_current_page == _pages)
379 _second_phase =
true;
392 void drawPaged(
void (*drawCallback)(
const void*),
const void* pv)
394 if (_using_partial_mode)
396 for (_current_page = 0; _current_page < _pages; _current_page++)
398 uint16_t page_ys = _current_page * _page_height;
399 uint16_t page_ye = _current_page < (_pages - 1) ? page_ys + _page_height : HEIGHT;
400 uint16_t dest_ys = _pw_y + page_ys;
401 uint16_t dest_ye = gx_uint16_min(_pw_y + _pw_h, _pw_y + page_ye);
402 if (dest_ye > dest_ys)
406 epd2.writeImage(_black_buffer, _color_buffer, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
409 epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
414 for (_current_page = 0; _current_page < _pages; _current_page++)
416 uint16_t page_ys = _current_page * _page_height;
419 epd2.writeImage(_black_buffer, _color_buffer, 0, page_ys, GxEPD2_Type::WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
423 for (_current_page = 0; _current_page < _pages; _current_page++)
425 uint16_t page_ys = _current_page * _page_height;
428 epd2.writeImage(_black_buffer, _color_buffer, 0, page_ys, GxEPD2_Type::WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
437 void drawInvertedBitmap(int16_t x, int16_t y,
const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
440 int16_t byteWidth = (w + 7) / 8;
442 for (int16_t j = 0; j < h; j++)
444 for (int16_t i = 0; i < w; i++ )
446 if (i & 7)
byte <<= 1;
449#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
450 byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
452 byte = bitmap[j * byteWidth + i / 8];
466 epd2.clearScreen(value);
470 epd2.writeScreenBuffer(value);
473 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)
475 epd2.writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
477 void writeImagePart(
const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
478 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert =
false,
bool mirror_y =
false,
bool pgm =
false)
480 epd2.writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
482 void 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)
484 epd2.writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
486 void writeImage(
const uint8_t* black,
const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h)
488 epd2.writeImage(black, color, x, y, w, h,
false,
false,
false);
490 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,
491 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert,
bool mirror_y,
bool pgm)
493 epd2.writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
495 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,
496 int16_t x, int16_t y, int16_t w, int16_t h)
498 epd2.writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h,
false,
false,
false);
501 void 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)
503 epd2.writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
506 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)
508 epd2.drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
510 void drawImagePart(
const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
511 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert =
false,
bool mirror_y =
false,
bool pgm =
false)
513 epd2.drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
515 void 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)
517 epd2.drawImage(black, color, x, y, w, h, invert, mirror_y, pgm);
519 void drawImage(
const uint8_t* black,
const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h)
521 epd2.drawImage(black, color, x, y, w, h,
false,
false,
false);
523 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,
524 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert,
bool mirror_y,
bool pgm)
526 epd2.drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
528 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,
529 int16_t x, int16_t y, int16_t w, int16_t h)
531 epd2.drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h,
false,
false,
false);
534 void 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)
536 epd2.drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
538 void refresh(
bool partial_update_mode =
false)
540 epd2.refresh(partial_update_mode);
541 if (!partial_update_mode)
epd2.powerOff();
543 void refresh(int16_t x, int16_t y, int16_t w, int16_t h)
545 epd2.refresh(x, y, w, h);
558 template <
typename T>
static inline void
565 static inline uint16_t gx_uint16_min(uint16_t a, uint16_t b)
567 return (a < b ? a : b);
569 static inline uint16_t gx_uint16_max(uint16_t a, uint16_t b)
571 return (a > b ? a : b);
573 void _rotate(uint16_t& x, uint16_t& y, uint16_t& w, uint16_t& h)
575 switch (getRotation())
594 uint8_t _black_buffer[(GxEPD2_Type::WIDTH / 8) * page_height];
595 uint8_t _color_buffer[(GxEPD2_Type::WIDTH / 8) * page_height];
596 bool _using_partial_mode, _second_phase, _mirror;
597 uint16_t _width_bytes, _pixel_bytes;
598 int16_t _current_page;
599 uint16_t _pages, _page_height;
600 uint16_t _pw_x, _pw_y, _pw_w, _pw_h;
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 displayWindowBW(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
void display(bool partial_update_mode=false)
void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration=20, bool pulldown_rst_mode=false)
void 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)
void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
void refresh(int16_t x, int16_t y, int16_t w, int16_t h)
void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode, SPIClass &spi, SPISettings spi_settings)
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 drawImage(const uint8_t *black, const uint8_t *color, int16_t x, int16_t y, int16_t w, int16_t h)
void writeScreenBuffer(uint8_t value=0xFF)
GxEPD2_3C(GxEPD2_Type epd2_instance)
void clearScreen(uint8_t value=0xFF)
void drawPixel(int16_t x, int16_t y, uint16_t color)
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)
void 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)
void drawInvertedBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
void refresh(bool partial_update_mode=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, bool mirror_y, bool pgm)
void writeImage(const uint8_t *black, const uint8_t *color, int16_t x, int16_t y, int16_t w, int16_t h)
void fillScreen(uint16_t color)
void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
void 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)
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 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 init(uint32_t serial_diag_bitrate=0)
void 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)
void drawPaged(void(*drawCallback)(const void *), const void *pv)
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)
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, bool mirror_y, bool pgm)