GxEPD2_PagedDisplayUsingCallback.ino 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. // Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
  2. // Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
  3. //
  4. // Display Library based on Demo Example from Good Display: https://www.good-display.com/companyfile/32/
  5. //
  6. // Author: Jean-Marc Zingg
  7. //
  8. // Version: see library.properties
  9. //
  10. // Library: https://github.com/ZinggJM/GxEPD2
  11. // Supporting Arduino Forum Topics (closed, read only):
  12. // Good Display ePaper for Arduino: https://forum.arduino.cc/t/good-display-epaper-for-arduino/419657
  13. // Waveshare e-paper displays with SPI: https://forum.arduino.cc/t/waveshare-e-paper-displays-with-spi/467865
  14. //
  15. // Add new topics in https://forum.arduino.cc/c/using-arduino/displays/23 for new questions and issues
  16. // see GxEPD2_wiring_examples.h for wiring suggestions and examples
  17. // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
  18. // enable or disable GxEPD2_GFX base class
  19. #define ENABLE_GxEPD2_GFX 0
  20. // uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX
  21. //#include <GFX.h>
  22. // Note: if you use this with ENABLE_GxEPD2_GFX 1:
  23. // uncomment it in GxEPD2_GFX.h too, or add #include <GFX.h> before any #include <GxEPD2_GFX.h>
  24. #include <GxEPD2_BW.h>
  25. #include <GxEPD2_3C.h>
  26. #include <GxEPD2_7C.h>
  27. #include <GxEPD2_BW_SHM.h>
  28. #include <Fonts/FreeMonoBold9pt7b.h>
  29. // select the display class and display driver class in the following file (new style):
  30. #include "GxEPD2_display_selection_new_style.h"
  31. #if !defined(__AVR) && !defined(_BOARD_GENERIC_STM32F103C_H_)
  32. // note 16.11.2019: the compiler may exclude code based on constant if statements (display.epd2.panel == constant),
  33. // therefore bitmaps may get optimized out by the linker
  34. // comment out unused bitmaps to reduce code space used
  35. #include "bitmaps/Bitmaps152x152.h" // 1.54" b/w
  36. #include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
  37. #include "bitmaps/Bitmaps104x212.h" // 2.13" b/w flexible GDEW0213I5F
  38. #include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
  39. #include "bitmaps/Bitmaps128x296.h" // 2.9" b/w
  40. #include "bitmaps/Bitmaps152x296.h" // 2.6" b/w
  41. #include "bitmaps/Bitmaps176x264.h" // 2.7" b/w
  42. #include "bitmaps/Bitmaps240x416.h" // 3.71" b/w
  43. #include "bitmaps/Bitmaps400x300.h" // 4.2" b/w
  44. #include "bitmaps/Bitmaps648x480.h" // 5.38" b/w
  45. #include "bitmaps/Bitmaps640x384.h" // 7.5" b/w
  46. #include "bitmaps/Bitmaps800x480.h" // 7.5" b/w
  47. // 3-color
  48. #include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r
  49. #include "bitmaps/Bitmaps3c104x212.h" // 2.13" b/w/r
  50. #include "bitmaps/Bitmaps3c128x296.h" // 2.9" b/w/r
  51. #include "bitmaps/Bitmaps3c176x264.h" // 2.7" b/w/r
  52. #include "bitmaps/Bitmaps3c400x300.h" // 4.2" b/w/r
  53. #if defined(ESP8266) || defined(ESP32)
  54. #include "bitmaps/Bitmaps3c800x480.h" // 7.5" b/w/r
  55. #include "bitmaps/Bitmaps3c880x528.h" // 7.5" b/w/r
  56. #include "bitmaps/WS_Bitmaps800x600.h" // 6.0" grey
  57. #include "bitmaps/WS_Bitmaps7c192x143.h" // 5.65" 7-color
  58. #endif
  59. #if defined(ESP32)
  60. #include "bitmaps/Bitmaps1304x984.h" // 12.48" b/w
  61. #endif
  62. #else
  63. // select only one to fit in code space
  64. //#include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
  65. //#include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
  66. //#include "bitmaps/Bitmaps128x296.h" // 2.9" b/w
  67. //#include "bitmaps/Bitmaps176x264.h" // 2.7" b/w
  68. ////#include "bitmaps/Bitmaps400x300.h" // 4.2" b/w // not enough code space
  69. ////#include "bitmaps/Bitmaps640x384.h" // 7.5" b/w // not enough code space
  70. // 3-color
  71. //#include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r
  72. //#include "bitmaps/Bitmaps3c104x212.h" // 2.13" b/w/r
  73. //#include "bitmaps/Bitmaps3c128x296.h" // 2.9" b/w/r
  74. //#include "bitmaps/Bitmaps3c176x264.h" // 2.7" b/w/r
  75. ////#include "bitmaps/Bitmaps3c400x300.h" // 4.2" b/w/r // not enough code space
  76. #endif
  77. // for handling alternative SPI pins (ESP32, RP2040) see example GxEPD2_Example.ino
  78. void setup()
  79. {
  80. Serial.begin(115200);
  81. Serial.println();
  82. Serial.println("setup");
  83. if (display.epd2.panel == GxEPD2::GDEH0576T81) display.epd2.enableRead(SCK, MOSI); // enable read temperature, uses SW SPI
  84. //display.init(115200); // default 10ms reset pulse, e.g. for bare panels with DESPI-C02
  85. display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
  86. // first update should be full refresh
  87. helloWorld();
  88. delay(1000);
  89. // partial refresh mode can be used to full screen,
  90. // effective if display panel hasFastPartialUpdate
  91. helloFullScreenPartialMode();
  92. delay(1000);
  93. helloArduino();
  94. delay(1000);
  95. helloEpaper();
  96. delay(1000);
  97. showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b);
  98. delay(1000);
  99. drawBitmaps();
  100. if (display.epd2.hasPartialUpdate)
  101. {
  102. showPartialUpdate();
  103. delay(1000);
  104. } // else // on GDEW0154Z04 only full update available, doesn't look nice
  105. //drawCornerTest();
  106. //showBox(16, 16, 48, 32, false);
  107. //showBox(16, 56, 48, 32, true);
  108. display.powerOff();
  109. Serial.println("setup done");
  110. }
  111. void loop()
  112. {
  113. }
  114. const char HelloWorld[] = "Hello World!";
  115. const char HelloArduino[] = "Hello Arduino!";
  116. const char HelloEpaper[] = "Hello E-Paper!";
  117. struct coordinates
  118. {
  119. uint16_t x;
  120. uint16_t y;
  121. };
  122. void helloWorldCallback(const void* p)
  123. {
  124. const coordinates& where(*reinterpret_cast<const coordinates*>(p));
  125. display.setCursor(where.x, where.y);
  126. display.print(HelloWorld);
  127. }
  128. void helloWorld()
  129. {
  130. //Serial.println("helloWorld");
  131. coordinates cursor;
  132. display.setRotation(1);
  133. display.setFont(&FreeMonoBold9pt7b);
  134. if (display.epd2.WIDTH < 104) display.setFont(0);
  135. display.setTextColor(GxEPD_BLACK);
  136. int16_t tbx, tby; uint16_t tbw, tbh;
  137. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  138. // center bounding box by transposition of origin:
  139. cursor.x = ((display.width() - tbw) / 2) - tbx;
  140. cursor.y = ((display.height() - tbh) / 2) - tby;
  141. display.setFullWindow();
  142. display.drawPaged(helloWorldCallback, &cursor);
  143. //Serial.println("helloWorld done");
  144. }
  145. struct text_at
  146. {
  147. const char* text;
  148. coordinates where;
  149. };
  150. void helloFullScreenPartialModeCallback(const void* p)
  151. {
  152. const text_at* what(reinterpret_cast<const text_at*>(p));
  153. display.fillScreen(GxEPD_WHITE);
  154. display.setCursor(what[0].where.x, what[0].where.y);
  155. display.print(what[0].text);
  156. display.setCursor(what[1].where.x, what[1].where.y);
  157. display.print(what[1].text);
  158. display.setCursor(what[2].where.x, what[2].where.y);
  159. display.print(what[2].text);
  160. }
  161. void helloFullScreenPartialMode()
  162. {
  163. //Serial.println("helloFullScreenPartialMode");
  164. const char fullscreen[] = "full screen update";
  165. const char fpm[] = "fast partial mode";
  166. const char spm[] = "slow partial mode";
  167. const char npm[] = "no partial mode";
  168. text_at what[3];
  169. display.setPartialWindow(0, 0, display.width(), display.height());
  170. display.setRotation(1);
  171. display.setFont(&FreeMonoBold9pt7b);
  172. if (display.epd2.WIDTH < 104) display.setFont(0);
  173. display.setTextColor(GxEPD_BLACK);
  174. const char* updatemode;
  175. if (display.epd2.hasFastPartialUpdate)
  176. {
  177. updatemode = fpm;
  178. }
  179. else if (display.epd2.hasPartialUpdate)
  180. {
  181. updatemode = spm;
  182. }
  183. else
  184. {
  185. updatemode = npm;
  186. }
  187. int16_t tbx, tby; uint16_t tbw, tbh;
  188. // center update text
  189. display.getTextBounds(fullscreen, 0, 0, &tbx, &tby, &tbw, &tbh);
  190. what[0].text = fullscreen;
  191. what[0].where.x = ((display.width() - tbw) / 2) - tbx;
  192. what[0].where.y = ((display.height() / 4) - tbh / 2) - tby;
  193. // center update mode
  194. display.getTextBounds(updatemode, 0, 0, &tbx, &tby, &tbw, &tbh);
  195. what[1].text = updatemode;
  196. what[1].where.x = ((display.width() - tbw) / 2) - tbx;
  197. what[1].where.y = ((display.height() * 3 / 4) - tbh / 2) - tby;
  198. // center HelloWorld
  199. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  200. what[2].text = HelloWorld;
  201. what[2].where.x = ((display.width() - tbw) / 2) - tbx;
  202. what[2].where.y = ((display.height() - tbh) / 2) - tby;
  203. display.drawPaged(helloFullScreenPartialModeCallback, &what);
  204. //Serial.println("helloFullScreenPartialMode done");
  205. }
  206. void helloArduinoCallback(const void* p)
  207. {
  208. const coordinates& where(*reinterpret_cast<const coordinates*>(p));
  209. display.setCursor(where.x, where.y);
  210. display.print(HelloArduino);
  211. }
  212. void helloArduino()
  213. {
  214. //Serial.println("helloArduino");
  215. coordinates cursor;
  216. display.setRotation(1);
  217. display.setFont(&FreeMonoBold9pt7b);
  218. if (display.epd2.WIDTH < 104) display.setFont(0);
  219. display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
  220. int16_t tbx, tby; uint16_t tbw, tbh;
  221. // align with centered HelloWorld
  222. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  223. cursor.x = ((display.width() - tbw) / 2) - tbx;
  224. // height might be different
  225. display.getTextBounds(HelloArduino, 0, 0, &tbx, &tby, &tbw, &tbh);
  226. cursor.y = ((display.height() / 4) - tbh / 2) - tby; // y is base line!
  227. // make the window big enough to cover (overwrite) descenders of previous text
  228. uint16_t wh = FreeMonoBold9pt7b.yAdvance;
  229. uint16_t wy = (display.height() / 4) - wh / 2;
  230. display.setPartialWindow(0, wy, display.width(), wh);
  231. display.drawPaged(helloArduinoCallback, &cursor);
  232. delay(1000);
  233. //Serial.println("helloArduino done");
  234. }
  235. void helloEpaperCallback(const void* p)
  236. {
  237. const coordinates& where(*reinterpret_cast<const coordinates*>(p));
  238. display.setCursor(where.x, where.y);
  239. display.print(HelloEpaper);
  240. }
  241. void helloEpaper()
  242. {
  243. //Serial.println("helloEpaper");
  244. coordinates cursor;
  245. display.setRotation(1);
  246. display.setFont(&FreeMonoBold9pt7b);
  247. if (display.epd2.WIDTH < 104) display.setFont(0);
  248. display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
  249. int16_t tbx, tby; uint16_t tbw, tbh;
  250. // align with centered HelloWorld
  251. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  252. cursor.x = ((display.width() - tbw) / 2) - tbx;
  253. // height might be different
  254. display.getTextBounds(HelloEpaper, 0, 0, &tbx, &tby, &tbw, &tbh);
  255. cursor.y = ((display.height() * 3 / 4) - tbh / 2) - tby; // y is base line!
  256. // make the window big enough to cover (overwrite) descenders of previous text
  257. uint16_t wh = FreeMonoBold9pt7b.yAdvance;
  258. uint16_t wy = (display.height() * 3 / 4) - wh / 2;
  259. display.setPartialWindow(0, wy, display.width(), wh);
  260. display.drawPaged(helloEpaperCallback, &cursor);
  261. //Serial.println("helloEpaper done");
  262. }
  263. struct DrawFontParameters
  264. {
  265. const char* name;
  266. const GFXfont* f;
  267. };
  268. void showFont(const char name[], const GFXfont* f)
  269. {
  270. DrawFontParameters fontParameters{name, f};
  271. display.setFullWindow();
  272. display.setRotation(0);
  273. display.setTextColor(GxEPD_BLACK);
  274. display.drawPaged(drawFontCallback, &fontParameters);
  275. }
  276. void drawFontCallback(const void* parameters)
  277. {
  278. const DrawFontParameters* p = reinterpret_cast<const DrawFontParameters*>(parameters);
  279. //display.setRotation(0);
  280. display.fillScreen(GxEPD_WHITE);
  281. display.setTextColor(GxEPD_BLACK);
  282. display.setFont(p->f);
  283. display.setCursor(0, 0);
  284. display.println();
  285. display.println(p->name);
  286. display.println(" !\"#$%&'()*+,-./");
  287. display.println("0123456789:;<=>?");
  288. display.println("@ABCDEFGHIJKLMNO");
  289. display.println("PQRSTUVWXYZ[\\]^_");
  290. if (display.epd2.hasColor)
  291. {
  292. display.setTextColor(GxEPD_RED);
  293. }
  294. display.println("`abcdefghijklmno");
  295. display.println("pqrstuvwxyz{|}~ ");
  296. }
  297. struct ShowBoxParameters
  298. {
  299. uint16_t x, y, w, h;
  300. uint16_t color;
  301. };
  302. struct ShowValueParameters
  303. {
  304. uint16_t x, y, w, h, cursor_y;
  305. float value;
  306. };
  307. void showBoxCallback(const void* parameters)
  308. {
  309. const ShowBoxParameters* p = reinterpret_cast<const ShowBoxParameters*>(parameters);
  310. display.fillRect(p->x, p->y, p->w, p->h, p->color);
  311. }
  312. void showValueBoxCallback(const void* parameters)
  313. {
  314. const ShowValueParameters* p = reinterpret_cast<const ShowValueParameters*>(parameters);
  315. display.fillRect(p->x, p->y, p->w, p->h, GxEPD_WHITE);
  316. display.setCursor(p->x, p->cursor_y);
  317. display.print(p->value);
  318. }
  319. void showPartialUpdate()
  320. {
  321. // some useful background
  322. helloWorld();
  323. // use asymmetric values for test
  324. ShowBoxParameters boxParameters{10, 15, 70, 20, GxEPD_WHITE};
  325. ShowValueParameters valueParameters{10, 15, 70, 20, 0, 13.95};
  326. valueParameters.cursor_y = valueParameters.y + valueParameters.h - 6;
  327. float value = 13.95;
  328. uint16_t incr = display.epd2.hasFastPartialUpdate ? 1 : 3;
  329. display.setFont(&FreeMonoBold9pt7b);
  330. display.setTextColor(GxEPD_BLACK);
  331. // show where the update box is
  332. for (uint16_t r = 0; r < 4; r++)
  333. {
  334. display.setRotation(r);
  335. display.setPartialWindow(boxParameters.x, boxParameters.y, boxParameters.w, boxParameters.h);
  336. boxParameters.color = GxEPD_BLACK;
  337. display.drawPaged(showBoxCallback, &boxParameters);
  338. delay(2000);
  339. boxParameters.color = GxEPD_WHITE;
  340. display.drawPaged(showBoxCallback, &boxParameters);
  341. while (display.nextPage());
  342. delay(1000);
  343. }
  344. // show updates in the update box
  345. for (uint16_t r = 0; r < 4; r++)
  346. {
  347. display.setRotation(r);
  348. display.setPartialWindow(boxParameters.x, boxParameters.y, boxParameters.w, boxParameters.h);
  349. for (uint16_t i = 1; i <= 10; i += incr)
  350. {
  351. valueParameters.value = value * i;
  352. display.drawPaged(showValueBoxCallback, &valueParameters);
  353. delay(500);
  354. }
  355. delay(1000);
  356. boxParameters.color = GxEPD_WHITE;
  357. display.drawPaged(showBoxCallback, &boxParameters);
  358. delay(1000);
  359. }
  360. }
  361. void showBox(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool partial)
  362. {
  363. //Serial.println("showBox");
  364. ShowBoxParameters boxParameters{x, y, w, h, GxEPD_BLACK};
  365. display.setRotation(1);
  366. if (partial)
  367. {
  368. display.setPartialWindow(x, y, w, h);
  369. }
  370. else
  371. {
  372. display.setFullWindow();
  373. }
  374. display.drawPaged(showBoxCallback, &boxParameters);
  375. //Serial.println("showBox done");
  376. }
  377. void drawCornerTestCallback(const void*)
  378. {
  379. display.fillScreen(GxEPD_WHITE);
  380. display.fillRect(0, 0, 8, 8, GxEPD_BLACK);
  381. display.fillRect(display.width() - 18, 0, 16, 16, GxEPD_BLACK);
  382. display.fillRect(display.width() - 25, display.height() - 25, 24, 24, GxEPD_BLACK);
  383. display.fillRect(0, display.height() - 33, 32, 32, GxEPD_BLACK);
  384. display.setCursor(display.width() / 2, display.height() / 2);
  385. display.print(display.getRotation());
  386. }
  387. void drawCornerTest()
  388. {
  389. display.setFullWindow();
  390. display.setFont(&FreeMonoBold9pt7b);
  391. display.setTextColor(GxEPD_BLACK);
  392. for (uint16_t r = 0; r <= 4; r++)
  393. {
  394. display.setRotation(r);
  395. display.drawPaged(drawCornerTestCallback, 0);
  396. delay(2000);
  397. }
  398. }
  399. void drawBitmaps()
  400. {
  401. display.setFullWindow();
  402. #ifdef _GxBitmaps128x250_H_
  403. drawBitmaps128x250();
  404. #endif
  405. #ifdef _GxBitmaps128x296_H_
  406. drawBitmaps128x296();
  407. #endif
  408. #ifdef _GxBitmaps176x264_H_
  409. drawBitmaps176x264();
  410. #endif
  411. #ifdef _GxBitmaps400x300_H_
  412. drawBitmaps400x300();
  413. #endif
  414. #ifdef _GxBitmaps640x384_H_
  415. drawBitmaps640x384();
  416. #endif
  417. // 3-color
  418. #ifdef _GxBitmaps3c104x212_H_
  419. drawBitmaps3c104x212();
  420. #endif
  421. #ifdef _GxBitmaps3c128x296_H_
  422. drawBitmaps3c128x296();
  423. #endif
  424. #ifdef _GxBitmaps3c176x264_H_
  425. drawBitmaps3c176x264();
  426. #endif
  427. #ifdef _GxBitmaps3c400x300_H_
  428. drawBitmaps3c400x300();
  429. #endif
  430. // show these after the specific bitmaps
  431. #ifdef _GxBitmaps200x200_H_
  432. drawBitmaps200x200();
  433. #endif
  434. // 3-color
  435. #ifdef _GxBitmaps3c200x200_H_
  436. drawBitmaps3c200x200();
  437. #endif
  438. }
  439. void drawInvertedBitmapCallback(const void* parameter)
  440. {
  441. const uint8_t* bitmap = reinterpret_cast<const uint8_t*>(parameter);
  442. display.fillScreen(GxEPD_WHITE);
  443. display.drawInvertedBitmap(0, 0, bitmap, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  444. }
  445. #ifdef _GxBitmaps200x200_H_
  446. void drawBitmaps200x200()
  447. {
  448. #if defined(__AVR)
  449. const unsigned char* bitmaps[] =
  450. {
  451. logo200x200, first200x200 //, second200x200, third200x200, fourth200x200, fifth200x200, sixth200x200, senventh200x200, eighth200x200
  452. };
  453. #else
  454. const unsigned char* bitmaps[] =
  455. {
  456. logo200x200, first200x200, second200x200, third200x200, fourth200x200, fifth200x200, sixth200x200, senventh200x200, eighth200x200
  457. };
  458. #endif
  459. if ((display.epd2.panel == GxEPD2::GDEP015OC1) || (display.epd2.panel == GxEPD2::GDEH0154D67))
  460. {
  461. bool m = display.mirror(true);
  462. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  463. {
  464. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  465. delay(2000);
  466. }
  467. display.mirror(m);
  468. }
  469. //else
  470. {
  471. bool mirror_y = (display.epd2.panel != GxEPD2::GDE0213B1);
  472. display.clearScreen(); // use default for white
  473. uint16_t x = (display.epd2.WIDTH - 200) / 2;
  474. uint16_t y = (display.epd2.HEIGHT - 200) / 2;
  475. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  476. {
  477. display.drawImage(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  478. delay(2000);
  479. }
  480. }
  481. bool mirror_y = (display.epd2.panel != GxEPD2::GDE0213B1);
  482. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  483. {
  484. int16_t x = -60;
  485. int16_t y = -60;
  486. for (uint16_t j = 0; j < 10; j++)
  487. {
  488. display.writeScreenBuffer(); // use default for white
  489. display.writeImage(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  490. display.refresh(true);
  491. if (display.epd2.hasFastPartialUpdate)
  492. {
  493. // for differential update: set previous buffer equal to current buffer in controller
  494. display.epd2.writeScreenBufferAgain(); // use default for white
  495. display.epd2.writeImageAgain(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  496. }
  497. delay(2000);
  498. x += 40;
  499. y += 40;
  500. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) break;
  501. }
  502. if (!display.epd2.hasFastPartialUpdate) break; // comment out for full show
  503. break; // comment out for full show
  504. }
  505. display.writeScreenBuffer(); // use default for white
  506. display.writeImage(bitmaps[0], 0, 0, 200, 200, false, mirror_y, true);
  507. display.writeImage(bitmaps[0], display.epd2.WIDTH - 200, display.epd2.HEIGHT - 200, 200, 200, false, mirror_y, true);
  508. display.refresh(true);
  509. delay(2000);
  510. }
  511. #endif
  512. #ifdef _GxBitmaps128x250_H_
  513. void drawBitmaps128x250()
  514. {
  515. const unsigned char* bitmaps[] =
  516. {
  517. Bitmap128x250_1, logo128x250, first128x250, second128x250, third128x250
  518. };
  519. if (display.epd2.panel == GxEPD2::GDE0213B1)
  520. {
  521. bool m = display.mirror(true);
  522. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  523. {
  524. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  525. delay(2000);
  526. }
  527. display.mirror(m);
  528. }
  529. }
  530. #endif
  531. #ifdef _GxBitmaps128x296_H_
  532. void drawBitmaps128x296()
  533. {
  534. #if !defined(__AVR)
  535. const unsigned char* bitmaps[] =
  536. {
  537. Bitmap128x296_1, logo128x296, first128x296, second128x296, third128x296
  538. };
  539. #else
  540. const unsigned char* bitmaps[] =
  541. {
  542. Bitmap128x296_1, logo128x296 //, first128x296, second128x296, third128x296
  543. };
  544. #endif
  545. if (display.epd2.panel == GxEPD2::GDEH029A1)
  546. {
  547. bool m = display.mirror(true);
  548. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  549. {
  550. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  551. delay(2000);
  552. }
  553. display.mirror(m);
  554. }
  555. }
  556. #endif
  557. #ifdef _GxBitmaps176x264_H_
  558. void drawBitmaps176x264()
  559. {
  560. const unsigned char* bitmaps[] =
  561. {
  562. Bitmap176x264_1, Bitmap176x264_2
  563. };
  564. if (display.epd2.panel == GxEPD2::GDEW027W3)
  565. {
  566. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  567. {
  568. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  569. delay(2000);
  570. }
  571. }
  572. }
  573. #endif
  574. #ifdef _GxBitmaps400x300_H_
  575. void drawBitmaps400x300()
  576. {
  577. const unsigned char* bitmaps[] =
  578. {
  579. Bitmap400x300_1, Bitmap400x300_2
  580. };
  581. if (display.epd2.panel == GxEPD2::GDEW042T2)
  582. {
  583. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  584. {
  585. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  586. delay(2000);
  587. }
  588. }
  589. }
  590. #endif
  591. #ifdef _GxBitmaps640x384_H_
  592. void drawBitmaps640x384()
  593. {
  594. const unsigned char* bitmaps[] =
  595. {
  596. Bitmap640x384_1, Bitmap640x384_2
  597. };
  598. if (display.epd2.panel == GxEPD2::GDEW075T8)
  599. {
  600. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  601. {
  602. display.drawPaged(drawInvertedBitmapCallback, bitmaps[i]);
  603. delay(2000);
  604. }
  605. }
  606. }
  607. #endif
  608. struct bitmap_pair
  609. {
  610. const unsigned char* black;
  611. const unsigned char* red;
  612. };
  613. void drawBitmapPairCallback(const void* parameters)
  614. {
  615. const bitmap_pair* bitmaps = reinterpret_cast<const bitmap_pair*>(parameters);
  616. display.fillScreen(GxEPD_WHITE);
  617. display.drawBitmap(0, 0, bitmaps->black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  618. display.drawBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  619. }
  620. void drawInvertedBitmapPairCallback(const void* parameters)
  621. {
  622. const bitmap_pair* bitmaps = reinterpret_cast<const bitmap_pair*>(parameters);
  623. display.fillScreen(GxEPD_WHITE);
  624. display.drawInvertedBitmap(0, 0, bitmaps->black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  625. display.drawInvertedBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  626. }
  627. void drawSpecialBitmapPairCallback(const void* parameters)
  628. {
  629. const bitmap_pair* bitmaps = reinterpret_cast<const bitmap_pair*>(parameters);
  630. display.fillScreen(GxEPD_WHITE);
  631. // Bitmap3c200x200_black has 2 bits per pixel
  632. // taken from Adafruit_GFX.cpp, modified
  633. int16_t byteWidth = (display.epd2.WIDTH + 7) / 8; // Bitmap scanline pad = whole byte
  634. uint8_t byte = 0;
  635. for (int16_t j = 0; j < display.epd2.HEIGHT; j++)
  636. {
  637. for (int16_t i = 0; i < display.epd2.WIDTH; i++)
  638. {
  639. if (i & 3) byte <<= 2;
  640. else
  641. {
  642. #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
  643. byte = pgm_read_byte(&bitmaps->black[j * byteWidth * 2 + i / 4]);
  644. #else
  645. byte = bitmaps->black[j * byteWidth * 2 + i / 4];
  646. #endif
  647. }
  648. if (!(byte & 0x80))
  649. {
  650. display.drawPixel(i, j, GxEPD_BLACK);
  651. }
  652. }
  653. }
  654. display.drawInvertedBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  655. }
  656. #ifdef _GxBitmaps3c200x200_H_
  657. void drawBitmaps3c200x200()
  658. {
  659. bitmap_pair bitmap_pairs[] =
  660. {
  661. //{Bitmap3c200x200_black, Bitmap3c200x200_red}, // special
  662. {WS_Bitmap3c200x200_black, WS_Bitmap3c200x200_red}
  663. };
  664. bitmap_pair special_bitmap{Bitmap3c200x200_black, Bitmap3c200x200_red};
  665. if (display.epd2.panel == GxEPD2::GDEW0154Z04)
  666. {
  667. display.drawPaged(drawSpecialBitmapPairCallback, &special_bitmap);
  668. delay(2000);
  669. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  670. {
  671. display.drawPaged(drawInvertedBitmapPairCallback, &bitmap_pairs[i]);
  672. delay(2000);
  673. }
  674. }
  675. if (display.epd2.hasColor)
  676. {
  677. display.clearScreen(); // use default for white
  678. uint16_t x = (display.epd2.WIDTH - 200) / 2;
  679. uint16_t y = (display.epd2.HEIGHT - 200) / 2;
  680. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  681. {
  682. display.drawImage(bitmap_pairs[i].black, bitmap_pairs[i].red, x, y, 200, 200, false, false, true);
  683. delay(2000);
  684. }
  685. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  686. {
  687. int16_t x = -60;
  688. int16_t y = -60;
  689. for (uint16_t j = 0; j < 10; j++)
  690. {
  691. display.writeScreenBuffer(); // use default for white
  692. display.writeImage(bitmap_pairs[i].black, bitmap_pairs[i].red, x, y, 200, 200, false, false, true);
  693. display.refresh();
  694. delay(2000);
  695. x += 40;
  696. y += 40;
  697. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) break;
  698. }
  699. }
  700. display.writeScreenBuffer(); // use default for white
  701. display.writeImage(bitmap_pairs[0].black, bitmap_pairs[0].red, 0, 0, 200, 200, false, false, true);
  702. display.writeImage(bitmap_pairs[0].black, bitmap_pairs[0].red, display.epd2.WIDTH - 200, display.epd2.HEIGHT - 200, 200, 200, false, false, true);
  703. display.refresh();
  704. delay(2000);
  705. }
  706. }
  707. #endif
  708. #ifdef _GxBitmaps3c104x212_H_
  709. void drawBitmapPairCallback3c104x212(const void* parameters)
  710. {
  711. const bitmap_pair* bitmaps = reinterpret_cast<const bitmap_pair*>(parameters);
  712. display.fillScreen(GxEPD_WHITE);
  713. display.drawInvertedBitmap(0, 0, bitmaps->black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  714. if (bitmaps->red == WS_Bitmap3c104x212_red)
  715. {
  716. display.drawInvertedBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  717. }
  718. else display.drawBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  719. }
  720. void drawBitmaps3c104x212()
  721. {
  722. #if !defined(__AVR)
  723. bitmap_pair bitmap_pairs[] =
  724. {
  725. {Bitmap3c104x212_1_black, Bitmap3c104x212_1_red},
  726. {Bitmap3c104x212_2_black, Bitmap3c104x212_2_red},
  727. {WS_Bitmap3c104x212_black, WS_Bitmap3c104x212_red}
  728. };
  729. #else
  730. bitmap_pair bitmap_pairs[] =
  731. {
  732. {Bitmap3c104x212_1_black, Bitmap3c104x212_1_red},
  733. //{Bitmap3c104x212_2_black, Bitmap3c104x212_2_red},
  734. {WS_Bitmap3c104x212_black, WS_Bitmap3c104x212_red}
  735. };
  736. #endif
  737. if (display.epd2.panel == GxEPD2::GDEW0213Z16)
  738. {
  739. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  740. {
  741. display.drawPaged(drawBitmapPairCallback3c104x212, &bitmap_pairs[i]);
  742. delay(2000);
  743. }
  744. }
  745. }
  746. #endif
  747. #ifdef _GxBitmaps3c128x296_H_
  748. void drawBitmapPairCallback3c128x296(const void* parameters)
  749. {
  750. const bitmap_pair* bitmaps = reinterpret_cast<const bitmap_pair*>(parameters);
  751. display.fillScreen(GxEPD_WHITE);
  752. display.drawInvertedBitmap(0, 0, bitmaps->black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  753. if (bitmaps->red == WS_Bitmap3c128x296_red)
  754. {
  755. display.drawInvertedBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  756. }
  757. else display.drawBitmap(0, 0, bitmaps->red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  758. }
  759. void drawBitmaps3c128x296()
  760. {
  761. #if !defined(__AVR)
  762. bitmap_pair bitmap_pairs[] =
  763. {
  764. {Bitmap3c128x296_1_black, Bitmap3c128x296_1_red},
  765. {Bitmap3c128x296_2_black, Bitmap3c128x296_2_red},
  766. {WS_Bitmap3c128x296_black, WS_Bitmap3c128x296_red}
  767. };
  768. #else
  769. bitmap_pair bitmap_pairs[] =
  770. {
  771. //{Bitmap3c128x296_1_black, Bitmap3c128x296_1_red},
  772. //{Bitmap3c128x296_2_black, Bitmap3c128x296_2_red},
  773. {WS_Bitmap3c128x296_black, WS_Bitmap3c128x296_red}
  774. };
  775. #endif
  776. if (display.epd2.panel == GxEPD2::GDEW029Z10)
  777. {
  778. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  779. {
  780. display.drawPaged(drawBitmapPairCallback3c128x296, &bitmap_pairs[i]);
  781. delay(2000);
  782. }
  783. }
  784. }
  785. #endif
  786. #ifdef _GxBitmaps3c176x264_H_
  787. void drawBitmaps3c176x264()
  788. {
  789. bitmap_pair bitmap_pairs[] =
  790. {
  791. {Bitmap3c176x264_black, Bitmap3c176x264_red}
  792. };
  793. if (display.epd2.panel == GxEPD2::GDEW027C44)
  794. {
  795. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  796. {
  797. display.drawPaged(drawBitmapPairCallback, &bitmap_pairs[i]);
  798. delay(2000);
  799. }
  800. }
  801. }
  802. #endif
  803. #ifdef _GxBitmaps3c400x300_H_
  804. void drawBitmaps3c400x300()
  805. {
  806. #if !defined(__AVR)
  807. bitmap_pair bitmap_pairs[] =
  808. {
  809. {Bitmap3c400x300_1_black, Bitmap3c400x300_1_red},
  810. {Bitmap3c400x300_2_black, Bitmap3c400x300_2_red},
  811. {WS_Bitmap3c400x300_black, WS_Bitmap3c400x300_red}
  812. };
  813. #else
  814. bitmap_pair bitmap_pairs[] = {}; // not enough code space
  815. #endif
  816. if (display.epd2.panel == GxEPD2::GDEW042Z15)
  817. {
  818. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  819. {
  820. display.drawPaged(drawInvertedBitmapPairCallback, &bitmap_pairs[i]);
  821. delay(2000);
  822. }
  823. }
  824. }
  825. #endif