GxEPD2_PagedDisplayUsingCallback.ino 24 KB

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