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
35template<
typename GxEPD2_Type, const u
int16_t page_height>
41 GxEPD2_7C(GxEPD2_Type epd2_instance) : GxEPD2_GFX_BASE_CLASS(
epd2, GxEPD2_Type::WIDTH, GxEPD2_Type::HEIGHT),
epd2(epd2_instance)
43 GxEPD2_7C(GxEPD2_Type epd2_instance) : GxEPD2_GFX_BASE_CLASS(GxEPD2_Type::WIDTH, GxEPD2_Type::HEIGHT),
epd2(epd2_instance)
46 _page_height = page_height;
47 _pages = (HEIGHT / _page_height) + ((HEIGHT % _page_height) > 0);
49 _using_partial_mode =
false;
70 void drawPixel(int16_t x, int16_t y, uint16_t color)
72 if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
return;
73 if (_mirror) x = width() - x - 1;
75 switch (getRotation())
94 if ((x < 0) || (x >= int16_t(_pw_w)) || (y < 0) || (y >= int16_t(_pw_h)))
return;
96 y -= _current_page * _page_height;
98 if ((y < 0) || (y >= int16_t(_page_height)))
return;
99 uint32_t i = x / 2 + uint32_t(y) * (_pw_w / 2);
100 uint8_t pv = color7(color);
101 if (x & 1) _pixel_buffer[i] = (_pixel_buffer[i] & 0xF0) | pv;
102 else _pixel_buffer[i] = (_pixel_buffer[i] & 0x0F) | (pv << 4);
105 void init(uint32_t serial_diag_bitrate = 0)
107 epd2.init(serial_diag_bitrate);
108 _using_partial_mode =
false;
118 void init(uint32_t serial_diag_bitrate,
bool initial, uint16_t reset_duration = 20,
bool pulldown_rst_mode =
false)
120 epd2.init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode);
121 _using_partial_mode =
false;
129 void init(uint32_t serial_diag_bitrate,
bool initial, uint16_t reset_duration,
bool pulldown_rst_mode, SPIClass& spi, SPISettings spi_settings)
131 epd2.selectSPI(spi, spi_settings);
132 epd2.init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode);
133 _using_partial_mode =
false;
140 uint8_t pv = color7(color);
141 uint8_t pv2 = pv | pv << 4;
142 for (uint32_t x = 0; x <
sizeof(_pixel_buffer); x++)
144 _pixel_buffer[x] = pv2;
149 void display(
bool partial_update_mode =
false)
151 epd2.writeNative(_pixel_buffer, 0, 0, 0, WIDTH, _page_height);
152 epd2.refresh(partial_update_mode);
153 if (!partial_update_mode)
epd2.powerOff();
164 x = gx_uint16_min(x, width());
165 y = gx_uint16_min(y, height());
166 w = gx_uint16_min(w, width() - x);
167 h = gx_uint16_min(h, height() - y);
169 epd2.writeNativePart(_pixel_buffer, 0, x, y, WIDTH, _page_height, x, y, w, h);
170 epd2.refresh(x, y, w, h);
175 _using_partial_mode =
false;
189 if (!
epd2.hasPartialUpdate)
return;
190 _pw_x = gx_uint16_min(x, width());
191 _pw_y = gx_uint16_min(y, height());
192 _pw_w = gx_uint16_min(w, width() - _pw_x);
193 _pw_h = gx_uint16_min(h, height() - _pw_y);
194 _rotate(_pw_x, _pw_y, _pw_w, _pw_h);
195 _using_partial_mode =
true;
198 if (_pw_w % 2 > 0) _pw_w += 2 - _pw_w % 2;
206 _second_phase =
false;
212 uint16_t page_ys = _current_page * _page_height;
213 if (_using_partial_mode)
217 uint16_t page_ye = _current_page < int16_t(_pages - 1) ? page_ys + _page_height : HEIGHT;
218 uint16_t dest_ys = _pw_y + page_ys;
219 uint16_t dest_ye = gx_uint16_min(_pw_y + _pw_h, _pw_y + page_ye);
220 if (dest_ye > dest_ys)
224 epd2.writeNative(_pixel_buffer, 0, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
233 if (_current_page == int16_t(_pages))
238 epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
239 if (
epd2.hasFastPartialUpdate)
241 _second_phase =
true;
252 epd2.writeNative(_pixel_buffer, 0, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
254 if (_current_page == int16_t(_pages))
262 _second_phase =
true;
266 else epd2.refresh(
true);
267 }
else epd2.refresh(
false);
277 void drawPaged(
void (*drawCallback)(
const void*),
const void* pv)
279 if (_using_partial_mode)
281 for (_current_page = 0; _current_page < _pages; _current_page++)
283 uint16_t page_ys = _current_page * _page_height;
284 uint16_t page_ye = _current_page < (_pages - 1) ? page_ys + _page_height : HEIGHT;
285 uint16_t dest_ys = _pw_y + page_ys;
286 uint16_t dest_ye = gx_uint16_min(_pw_y + _pw_h, _pw_y + page_ye);
287 if (dest_ye > dest_ys)
291 epd2.writeNative(_pixel_buffer, 0, _pw_x, dest_ys, _pw_w, dest_ye - dest_ys);
294 epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
299 for (_current_page = 0; _current_page < _pages; _current_page++)
301 uint16_t page_ys = _current_page * _page_height;
304 epd2.writeNative(_pixel_buffer, 0, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
312 void drawInvertedBitmap(int16_t x, int16_t y,
const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)
315 int16_t byteWidth = (w + 7) / 8;
317 for (int16_t j = 0; j < h; j++)
319 for (int16_t i = 0; i < w; i++ )
321 if (i & 7)
byte <<= 1;
324#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
325 byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
327 byte = bitmap[j * byteWidth + i / 8];
341 epd2.clearScreen(value);
345 epd2.writeScreenBuffer(value);
348 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)
350 epd2.writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
352 void writeImagePart(
const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
353 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert =
false,
bool mirror_y =
false,
bool pgm =
false)
355 epd2.writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
357 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)
359 epd2.writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
361 void writeImage(
const uint8_t* black,
const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h)
363 epd2.writeImage(black, color, x, y, w, h,
false,
false,
false);
365 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,
366 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert,
bool mirror_y,
bool pgm)
368 epd2.writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
370 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,
371 int16_t x, int16_t y, int16_t w, int16_t h)
373 epd2.writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h,
false,
false,
false);
376 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)
378 epd2.writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
381 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)
383 epd2.drawImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
385 void drawImagePart(
const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
386 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert =
false,
bool mirror_y =
false,
bool pgm =
false)
388 epd2.drawImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
390 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)
392 epd2.drawImage(black, color, x, y, w, h, invert, mirror_y, pgm);
394 void drawImage(
const uint8_t* black,
const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h)
396 epd2.drawImage(black, color, x, y, w, h,
false,
false,
false);
398 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,
399 int16_t x, int16_t y, int16_t w, int16_t h,
bool invert,
bool mirror_y,
bool pgm)
401 epd2.drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
403 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,
404 int16_t x, int16_t y, int16_t w, int16_t h)
406 epd2.drawImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h,
false,
false,
false);
409 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)
411 epd2.drawNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
413 void refresh(
bool partial_update_mode =
false)
415 epd2.refresh(partial_update_mode);
416 if (!partial_update_mode)
epd2.powerOff();
418 void refresh(int16_t x, int16_t y, int16_t w, int16_t h)
420 epd2.refresh(x, y, w, h);
433 template <
typename T>
static inline void
440 static inline uint16_t gx_uint16_min(uint16_t a, uint16_t b)
442 return (a < b ? a : b);
444 static inline uint16_t gx_uint16_max(uint16_t a, uint16_t b)
446 return (a > b ? a : b);
448 void _rotate(uint16_t& x, uint16_t& y, uint16_t& w, uint16_t& h)
450 switch (getRotation())
468 uint8_t color7(uint16_t color)
471 static uint8_t _prev_color7 = 0x00;
472 if (color == _prev_color)
return _prev_color7;
485 uint16_t red = color & 0xF800;
486 uint16_t green = (color & 0x07E0) << 5;
487 uint16_t blue = (color & 0x001F) << 11;
488 if ((red < 0x8000) && (green < 0x8000) && (blue < 0x8000)) cv7 = 0x00;
489 else if ((red >= 0x8000) && (green >= 0x8000) && (blue >= 0x8000)) cv7 = 0x01;
490 else if ((red >= 0x8000) && (blue >= 0x8000)) cv7 = red > blue ? 0x04 : 0x03;
491 else if ((green >= 0x8000) && (blue >= 0x8000)) cv7 = green > blue ? 0x02 : 0x03;
492 else if ((red >= 0x8000) && (green >= 0x8000))
495 cv7 = green > y2o_lim ? 0x05 : 0x06;
497 else if (red >= 0x8000) cv7 = 0x04;
498 else if (green >= 0x8000) cv7 = 0x02;
507 uint8_t _pixel_buffer[(GxEPD2_Type::WIDTH / 2) * page_height];
508 bool _using_partial_mode, _second_phase, _mirror;
509 uint16_t _width_bytes, _pixel_bytes;
510 int16_t _current_page;
511 uint16_t _pages, _page_height;
512 uint16_t _pw_x, _pw_y, _pw_w, _pw_h;
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 writeImage(const uint8_t *black, const uint8_t *color, 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 display(bool partial_update_mode=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 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 refresh(int16_t x, int16_t y, int16_t w, int16_t h)
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 fillScreen(uint16_t color)
void drawImage(const uint8_t *black, const uint8_t *color, 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=20, bool pulldown_rst_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)
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 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)
void init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode, SPIClass &spi, SPISettings spi_settings)
void drawPixel(int16_t x, int16_t y, uint16_t color)
void refresh(bool partial_update_mode=false)
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)
GxEPD2_7C(GxEPD2_Type epd2_instance)
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, bool invert, bool mirror_y, bool pgm)
void writeScreenBuffer(uint8_t value=0xFF)
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 displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_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)
void init(uint32_t serial_diag_bitrate=0)
void clearScreen(uint8_t value=0xFF)
void drawInvertedBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color)