GxEPD2_WS_ESP32_Driver.ino 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  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: these e-papers 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. // GxEPD2_WS_ESP32_Driver : GxEPD2_Example variant for Universal e-Paper Raw Panel Driver Board, ESP32 WiFi / Bluetooth Wireless
  12. // https://www.waveshare.com/product/e-paper-esp32-driver-board.htm
  13. // Supporting Arduino Forum Topics:
  14. // Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
  15. // Good Dispay ePaper for Arduino: https://forum.arduino.cc/index.php?topic=436411.0
  16. // mapping of Waveshare ESP32 Driver Board
  17. // BUSY -> 25, RST -> 26, DC -> 27, CS-> 15, CLK -> 13, DIN -> 14
  18. // NOTE: this board uses "unusual" SPI pins and requires re-mapping of HW SPI to these pins in SPIClass
  19. // this example shows how this can be done easily
  20. // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
  21. // enable or disable GxEPD2_GFX base class
  22. #define ENABLE_GxEPD2_GFX 0
  23. #include <GxEPD2_BW.h>
  24. #include <GxEPD2_3C.h>
  25. #include <Fonts/FreeMonoBold9pt7b.h>
  26. #if defined(ESP32)
  27. // ***** for mapping of Waveshare ESP32 Driver Board *****
  28. // use Board "ESP32 Dev Module" to build with Arduino IDE
  29. // select one, can use full buffer size (full HEIGHT)
  30. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  31. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  32. //GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0213I5F
  33. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  34. //GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW029T5
  35. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  36. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  37. //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  38. // 3-color e-papers
  39. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  40. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  41. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  42. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  43. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  44. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT> display(GxEPD2_750c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  45. #endif
  46. // comment out unused bitmaps to reduce code space used
  47. #include "bitmaps/Bitmaps200x200.h" // 1.54" b/w
  48. #include "bitmaps/Bitmaps128x250.h" // 2.13" b/w
  49. #include "bitmaps/Bitmaps128x296.h" // 2.9" b/w
  50. #include "bitmaps/Bitmaps176x264.h" // 2.7" b/w
  51. #include "bitmaps/Bitmaps400x300.h" // 4.2" b/w
  52. #include "bitmaps/Bitmaps640x384.h" // 7.5" b/w
  53. // 3-color
  54. #include "bitmaps/Bitmaps3c200x200.h" // 1.54" b/w/r
  55. #include "bitmaps/Bitmaps3c104x212.h" // 2.13" b/w/r
  56. #include "bitmaps/Bitmaps3c128x296.h" // 2.9" b/w/r
  57. #include "bitmaps/Bitmaps3c176x264.h" // 2.7" b/w/r
  58. #include "bitmaps/Bitmaps3c400x300.h" // 4.2" b/w/r
  59. void setup()
  60. {
  61. Serial.begin(115200);
  62. Serial.println();
  63. Serial.println("setup");
  64. display.init(115200); // uses standard SPI pins, e.g. SCK(18), MISO(19), MOSI(23), SS(5)
  65. // *** special handling for Waveshare ESP32 Driver board *** //
  66. // ********************************************************* //
  67. SPI.end(); // release standard SPI pins, e.g. SCK(18), MISO(19), MOSI(23), SS(5)
  68. //SPI: void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
  69. SPI.begin(13, 12, 14, 15); // map and init SPI pins SCK(13), MISO(12), MOSI(14), SS(15)
  70. // *** end of special handling for Waveshare ESP32 Driver board *** //
  71. // **************************************************************** //
  72. // first update should be full refresh
  73. helloWorld();
  74. delay(1000);
  75. // partial refresh mode can be used to full screen,
  76. // effective if display panel hasFastPartialUpdate
  77. helloFullScreenPartialMode();
  78. delay(1000);
  79. helloArduino();
  80. delay(1000);
  81. helloEpaper();
  82. delay(1000);
  83. showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b);
  84. delay(1000);
  85. drawBitmaps();
  86. if (display.epd2.hasPartialUpdate)
  87. {
  88. showPartialUpdate();
  89. delay(1000);
  90. } // else // on GDEW0154Z04 only full update available, doesn't look nice
  91. //drawCornerTest();
  92. //showBox(16, 16, 48, 32, false);
  93. //showBox(16, 56, 48, 32, true);
  94. display.powerOff();
  95. deepSleepTest();
  96. Serial.println("setup done");
  97. }
  98. void loop()
  99. {
  100. }
  101. const char HelloWorld[] = "Hello World!";
  102. const char HelloArduino[] = "Hello Arduino!";
  103. const char HelloEpaper[] = "Hello E-Paper!";
  104. void helloWorld()
  105. {
  106. //Serial.println("helloWorld");
  107. display.setRotation(1);
  108. display.setFont(&FreeMonoBold9pt7b);
  109. display.setTextColor(GxEPD_BLACK);
  110. int16_t tbx, tby; uint16_t tbw, tbh;
  111. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  112. uint16_t x = (display.width() - tbw) / 2;
  113. uint16_t y = (display.height() + tbh) / 2; // y is base line!
  114. display.setFullWindow();
  115. display.firstPage();
  116. do
  117. {
  118. display.fillScreen(GxEPD_WHITE);
  119. display.setCursor(x, y);
  120. display.print(HelloWorld);
  121. }
  122. while (display.nextPage());
  123. //Serial.println("helloWorld done");
  124. }
  125. void helloWorldForDummies()
  126. {
  127. //Serial.println("helloWorld");
  128. const char text[] = "Hello World!";
  129. // most e-papers have width < height (portrait) as native orientation, especially the small ones
  130. // in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
  131. // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
  132. display.setRotation(1);
  133. // select a suitable font in Adafruit_GFX
  134. display.setFont(&FreeMonoBold9pt7b);
  135. // on e-papers black on white is more pleasant to read
  136. display.setTextColor(GxEPD_BLACK);
  137. // Adafruit_GFX has a handy method getTextBounds() to determine the boundary box for a text for the actual font
  138. int16_t tbx, tby; uint16_t tbw, tbh; // boundary box window
  139. display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh); // it works for 0, 0, fortunately (negative tby!)
  140. // center the boundary box of the text
  141. uint16_t x = (display.width() - tbw) / 2;
  142. uint16_t y = (display.height() + tbh) / 2; // y is base line!
  143. // full window mode is the initial mode, set it anyway
  144. display.setFullWindow();
  145. // here we use paged drawing, even if the processor has enough RAM for full buffer
  146. // so this can be used with any supported processor board.
  147. // the cost in code overhead and execution time penalty is marginal
  148. // tell the graphics class to use paged drawing mode
  149. display.firstPage();
  150. do
  151. {
  152. // this part of code is executed multiple times, as many as needed,
  153. // in case of full buffer it is executed once
  154. // IMPORTANT: each iteration needs to draw the same, to avoid strange effects
  155. // use a copy of values that might change, don't read e.g. from analog or pins in the loop!
  156. display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
  157. display.setCursor(x, y); // set the postition to start printing text
  158. display.print(text); // print some text
  159. // end of part executed multiple times
  160. }
  161. // tell the graphics class to transfer the buffer content (page) to the controller buffer
  162. // the graphics class will command the controller to refresh to the screen when the last page has been transferred
  163. // returns true if more pages need be drawn and transferred
  164. // returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
  165. // returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
  166. // (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
  167. while (display.nextPage());
  168. //Serial.println("helloWorld done");
  169. }
  170. void helloFullScreenPartialMode()
  171. {
  172. //Serial.println("helloFullScreenPartialMode");
  173. const char fullscreen[] = "full screen update";
  174. const char fpm[] = "fast partial mode";
  175. const char spm[] = "slow partial mode";
  176. const char npm[] = "no partial mode";
  177. display.setPartialWindow(0, 0, display.width(), display.height());
  178. display.setRotation(1);
  179. display.setFont(&FreeMonoBold9pt7b);
  180. display.setTextColor(GxEPD_BLACK);
  181. const char* updatemode;
  182. if (display.epd2.hasFastPartialUpdate)
  183. {
  184. updatemode = fpm;
  185. }
  186. else if (display.epd2.hasPartialUpdate)
  187. {
  188. updatemode = spm;
  189. }
  190. else
  191. {
  192. updatemode = npm;
  193. }
  194. // do this outside of the loop
  195. int16_t tbx, tby; uint16_t tbw, tbh;
  196. // center update text
  197. display.getTextBounds(fullscreen, 0, 0, &tbx, &tby, &tbw, &tbh);
  198. uint16_t utx = (display.width() - tbw) / 2;
  199. // center update mode
  200. display.getTextBounds(updatemode, 0, 0, &tbx, &tby, &tbw, &tbh);
  201. uint16_t umx = (display.width() - tbw) / 2;
  202. // center HelloWorld
  203. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  204. uint16_t hwx = (display.width() - tbw) / 2;
  205. uint16_t y;
  206. display.firstPage();
  207. do
  208. {
  209. display.fillScreen(GxEPD_WHITE);
  210. y = (display.height() + tbh) / 2; // y is base line!
  211. display.setCursor(hwx, y);
  212. display.print(HelloWorld);
  213. y = display.height() / 4 + tbh / 2; // y is base line!
  214. display.setCursor(utx, y);
  215. display.print(fullscreen);
  216. y = display.height() * 3 / 4 + tbh / 2; // y is base line!
  217. display.setCursor(umx, y);
  218. display.print(updatemode);
  219. }
  220. while (display.nextPage());
  221. //Serial.println("helloFullScreenPartialMode done");
  222. }
  223. void helloArduino()
  224. {
  225. //Serial.println("helloArduino");
  226. display.setRotation(1);
  227. display.setFont(&FreeMonoBold9pt7b);
  228. display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
  229. int16_t tbx, tby; uint16_t tbw, tbh;
  230. // align with centered HelloWorld
  231. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  232. uint16_t x = (display.width() - tbw) / 2;
  233. // height might be different
  234. display.getTextBounds(HelloArduino, 0, 0, &tbx, &tby, &tbw, &tbh);
  235. uint16_t y = display.height() / 4 + tbh / 2; // y is base line!
  236. // make the window big enough to cover (overwrite) descenders of previous text
  237. uint16_t wh = FreeMonoBold9pt7b.yAdvance;
  238. display.setPartialWindow(0, y - tbh, display.width(), wh);
  239. display.firstPage();
  240. do
  241. {
  242. display.fillScreen(GxEPD_WHITE);
  243. //display.drawRect(x, y - tbh, tbw, tbh, GxEPD_BLACK);
  244. display.setCursor(x, y);
  245. display.print(HelloArduino);
  246. }
  247. while (display.nextPage());
  248. delay(1000);
  249. //Serial.println("helloArduino done");
  250. }
  251. void helloEpaper()
  252. {
  253. //Serial.println("helloEpaper");
  254. display.setRotation(1);
  255. display.setFont(&FreeMonoBold9pt7b);
  256. display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
  257. int16_t tbx, tby; uint16_t tbw, tbh;
  258. // align with centered HelloWorld
  259. display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
  260. uint16_t x = (display.width() - tbw) / 2;
  261. // height might be different
  262. display.getTextBounds(HelloEpaper, 0, 0, &tbx, &tby, &tbw, &tbh);
  263. uint16_t y = display.height() * 3 / 4 + tbh / 2; // y is base line!
  264. // make the window big enough to cover (overwrite) descenders of previous text
  265. uint16_t wh = FreeMonoBold9pt7b.yAdvance;
  266. display.setPartialWindow(0, y - tbh, display.width(), wh);
  267. display.firstPage();
  268. do
  269. {
  270. display.fillScreen(GxEPD_WHITE);
  271. display.setCursor(x, y);
  272. display.print(HelloEpaper);
  273. }
  274. while (display.nextPage());
  275. //Serial.println("helloEpaper done");
  276. }
  277. void deepSleepTest()
  278. {
  279. //Serial.println("deepSleepTest");
  280. const char hibernating[] = "hibernating ...";
  281. const char wokeup[] = "woke up from deep sleep";
  282. const char again[] = "hibernating again ...";
  283. display.setRotation(1);
  284. display.setFont(&FreeMonoBold9pt7b);
  285. display.setTextColor(GxEPD_BLACK);
  286. int16_t tbx, tby; uint16_t tbw, tbh;
  287. // center text
  288. display.getTextBounds(hibernating, 0, 0, &tbx, &tby, &tbw, &tbh);
  289. uint16_t x = (display.width() - tbw) / 2;
  290. uint16_t y = (display.height() + tbh) / 2; // y is base line!
  291. display.setFullWindow();
  292. display.firstPage();
  293. do
  294. {
  295. display.fillScreen(GxEPD_WHITE);
  296. display.setCursor(x, y);
  297. display.print(hibernating);
  298. }
  299. while (display.nextPage());
  300. display.hibernate();
  301. delay(5000);
  302. display.getTextBounds(wokeup, 0, 0, &tbx, &tby, &tbw, &tbh);
  303. x = (display.width() - tbw) / 2;
  304. display.firstPage();
  305. do
  306. {
  307. display.fillScreen(GxEPD_WHITE);
  308. display.setCursor(x, y);
  309. display.print(wokeup);
  310. }
  311. while (display.nextPage());
  312. delay(5000);
  313. display.getTextBounds(again, 0, 0, &tbx, &tby, &tbw, &tbh);
  314. x = (display.width() - tbw) / 2;
  315. display.firstPage();
  316. do
  317. {
  318. display.fillScreen(GxEPD_WHITE);
  319. display.setCursor(x, y);
  320. display.print(again);
  321. }
  322. while (display.nextPage());
  323. display.hibernate();
  324. //Serial.println("deepSleepTest done");
  325. }
  326. void showBox(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool partial)
  327. {
  328. //Serial.println("showBox");
  329. display.setRotation(1);
  330. if (partial)
  331. {
  332. display.setPartialWindow(x, y, w, h);
  333. }
  334. else
  335. {
  336. display.setFullWindow();
  337. }
  338. display.firstPage();
  339. do
  340. {
  341. display.fillScreen(GxEPD_WHITE);
  342. display.fillRect(x, y, w, h, GxEPD_BLACK);
  343. }
  344. while (display.nextPage());
  345. //Serial.println("showBox done");
  346. }
  347. void drawCornerTest()
  348. {
  349. display.setFullWindow();
  350. display.setFont(&FreeMonoBold9pt7b);
  351. display.setTextColor(GxEPD_BLACK);
  352. for (uint16_t r = 0; r <= 4; r++)
  353. {
  354. display.setRotation(r);
  355. display.firstPage();
  356. do
  357. {
  358. display.fillScreen(GxEPD_WHITE);
  359. display.fillRect(0, 0, 8, 8, GxEPD_BLACK);
  360. display.fillRect(display.width() - 18, 0, 16, 16, GxEPD_BLACK);
  361. display.fillRect(display.width() - 25, display.height() - 25, 24, 24, GxEPD_BLACK);
  362. display.fillRect(0, display.height() - 33, 32, 32, GxEPD_BLACK);
  363. display.setCursor(display.width() / 2, display.height() / 2);
  364. display.print(display.getRotation());
  365. }
  366. while (display.nextPage());
  367. delay(2000);
  368. }
  369. }
  370. void showFont(const char name[], const GFXfont* f)
  371. {
  372. display.setFullWindow();
  373. display.setRotation(0);
  374. display.setTextColor(GxEPD_BLACK);
  375. display.firstPage();
  376. do
  377. {
  378. drawFont(name, f);
  379. }
  380. while (display.nextPage());
  381. }
  382. void drawFont(const char name[], const GFXfont* f)
  383. {
  384. //display.setRotation(0);
  385. display.fillScreen(GxEPD_WHITE);
  386. display.setTextColor(GxEPD_BLACK);
  387. display.setFont(f);
  388. display.setCursor(0, 0);
  389. display.println();
  390. display.println(name);
  391. display.println(" !\"#$%&'()*+,-./");
  392. display.println("0123456789:;<=>?");
  393. display.println("@ABCDEFGHIJKLMNO");
  394. display.println("PQRSTUVWXYZ[\\]^_");
  395. if (display.epd2.hasColor)
  396. {
  397. display.setTextColor(GxEPD_RED);
  398. }
  399. display.println("`abcdefghijklmno");
  400. display.println("pqrstuvwxyz{|}~ ");
  401. }
  402. void showPartialUpdate()
  403. {
  404. // some useful background
  405. helloWorld();
  406. // use asymmetric values for test
  407. uint16_t box_x = 10;
  408. uint16_t box_y = 15;
  409. uint16_t box_w = 70;
  410. uint16_t box_h = 20;
  411. uint16_t cursor_y = box_y + box_h - 6;
  412. float value = 13.95;
  413. uint16_t incr = display.epd2.hasFastPartialUpdate ? 1 : 3;
  414. display.setFont(&FreeMonoBold9pt7b);
  415. display.setTextColor(GxEPD_BLACK);
  416. // show where the update box is
  417. for (uint16_t r = 0; r < 4; r++)
  418. {
  419. display.setRotation(r);
  420. display.setPartialWindow(box_x, box_y, box_w, box_h);
  421. display.firstPage();
  422. do
  423. {
  424. display.fillRect(box_x, box_y, box_w, box_h, GxEPD_BLACK);
  425. //display.fillScreen(GxEPD_BLACK);
  426. }
  427. while (display.nextPage());
  428. delay(2000);
  429. display.firstPage();
  430. do
  431. {
  432. display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);
  433. }
  434. while (display.nextPage());
  435. delay(1000);
  436. }
  437. //return;
  438. // show updates in the update box
  439. for (uint16_t r = 0; r < 4; r++)
  440. {
  441. display.setRotation(r);
  442. display.setPartialWindow(box_x, box_y, box_w, box_h);
  443. for (uint16_t i = 1; i <= 10; i += incr)
  444. {
  445. display.firstPage();
  446. do
  447. {
  448. display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);
  449. display.setCursor(box_x, cursor_y);
  450. display.print(value * i, 2);
  451. }
  452. while (display.nextPage());
  453. delay(500);
  454. }
  455. delay(1000);
  456. display.firstPage();
  457. do
  458. {
  459. display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);
  460. }
  461. while (display.nextPage());
  462. delay(1000);
  463. }
  464. }
  465. void drawBitmaps()
  466. {
  467. display.setFullWindow();
  468. #ifdef _GxBitmaps128x250_H_
  469. drawBitmaps128x250();
  470. #endif
  471. #ifdef _GxBitmaps128x296_H_
  472. drawBitmaps128x296();
  473. #endif
  474. #ifdef _GxBitmaps176x264_H_
  475. drawBitmaps176x264();
  476. #endif
  477. #ifdef _GxBitmaps400x300_H_
  478. drawBitmaps400x300();
  479. #endif
  480. #ifdef _GxBitmaps640x384_H_
  481. drawBitmaps640x384();
  482. #endif
  483. // 3-color
  484. #ifdef _GxBitmaps3c104x212_H_
  485. drawBitmaps3c104x212();
  486. #endif
  487. #ifdef _GxBitmaps3c128x296_H_
  488. drawBitmaps3c128x296();
  489. #endif
  490. #ifdef _GxBitmaps3c176x264_H_
  491. drawBitmaps3c176x264();
  492. #endif
  493. #ifdef _GxBitmaps3c400x300_H_
  494. drawBitmaps3c400x300();
  495. #endif
  496. // show these after the specific bitmaps
  497. #ifdef _GxBitmaps200x200_H_
  498. drawBitmaps200x200();
  499. #endif
  500. // 3-color
  501. #ifdef _GxBitmaps3c200x200_H_
  502. drawBitmaps3c200x200();
  503. #endif
  504. }
  505. #ifdef _GxBitmaps200x200_H_
  506. void drawBitmaps200x200()
  507. {
  508. #if defined(__AVR)
  509. const unsigned char* bitmaps[] =
  510. {
  511. logo200x200, first200x200 //, second200x200, third200x200, fourth200x200, fifth200x200, sixth200x200, senventh200x200, eighth200x200
  512. };
  513. #elif defined(_BOARD_GENERIC_STM32F103C_H_)
  514. const unsigned char* bitmaps[] =
  515. {
  516. logo200x200, first200x200, second200x200, third200x200, fourth200x200, fifth200x200 //, sixth200x200, senventh200x200, eighth200x200
  517. };
  518. #else
  519. const unsigned char* bitmaps[] =
  520. {
  521. logo200x200, first200x200, second200x200, third200x200, fourth200x200, fifth200x200, sixth200x200, senventh200x200, eighth200x200
  522. };
  523. #endif
  524. if (display.epd2.panel == GxEPD2::GDEP015OC1)
  525. {
  526. bool m = display.mirror(true);
  527. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  528. {
  529. display.firstPage();
  530. do
  531. {
  532. display.fillScreen(GxEPD_WHITE);
  533. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  534. }
  535. while (display.nextPage());
  536. delay(2000);
  537. }
  538. display.mirror(m);
  539. }
  540. //else
  541. {
  542. bool mirror_y = (display.epd2.panel != GxEPD2::GDE0213B1);
  543. display.clearScreen(); // use default for white
  544. int16_t x = (int16_t(display.epd2.WIDTH) - 200) / 2;
  545. int16_t y = (int16_t(display.epd2.HEIGHT) - 200) / 2;
  546. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  547. {
  548. display.drawImage(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  549. delay(2000);
  550. }
  551. }
  552. bool mirror_y = (display.epd2.panel != GxEPD2::GDE0213B1);
  553. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  554. {
  555. int16_t x = -60;
  556. int16_t y = -60;
  557. for (uint16_t j = 0; j < 10; j++)
  558. {
  559. display.writeScreenBuffer(); // use default for white
  560. display.writeImage(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  561. display.refresh(true);
  562. if ((display.epd2.hasFastPartialUpdate) && (display.epd2.panel == GxEPD2::GDEW027W3))
  563. {
  564. // for differential update: set previous buffer equal to current (IL91874 doesn't switch on refresh)
  565. // display.writeScreenBuffer(); // above is enough for the other controllers
  566. display.epd2.writeImageAgain(bitmaps[i], x, y, 200, 200, false, mirror_y, true);
  567. }
  568. delay(2000);
  569. x += 40;
  570. y += 40;
  571. if ((x >= int16_t(display.epd2.WIDTH)) || (y >= int16_t(display.epd2.HEIGHT))) break;
  572. }
  573. if (!display.epd2.hasFastPartialUpdate) break; // comment out for full show
  574. break; // comment out for full show
  575. }
  576. display.writeScreenBuffer(); // use default for white
  577. display.writeImage(bitmaps[0], int16_t(0), 0, 200, 200, false, mirror_y, true);
  578. display.writeImage(bitmaps[0], int16_t(int16_t(display.epd2.WIDTH) - 200), int16_t(display.epd2.HEIGHT) - 200, 200, 200, false, mirror_y, true);
  579. display.refresh(true);
  580. delay(2000);
  581. }
  582. #endif
  583. #ifdef _GxBitmaps128x250_H_
  584. void drawBitmaps128x250()
  585. {
  586. #if !defined(__AVR)
  587. const unsigned char* bitmaps[] =
  588. {
  589. Bitmap128x250_1, logo128x250, first128x250, second128x250, third128x250
  590. };
  591. #else
  592. const unsigned char* bitmaps[] =
  593. {
  594. Bitmap128x250_1, logo128x250, first128x250, second128x250, third128x250
  595. };
  596. #endif
  597. if (display.epd2.panel == GxEPD2::GDE0213B1)
  598. {
  599. bool m = display.mirror(true);
  600. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  601. {
  602. display.firstPage();
  603. do
  604. {
  605. display.fillScreen(GxEPD_WHITE);
  606. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  607. }
  608. while (display.nextPage());
  609. delay(2000);
  610. }
  611. display.mirror(m);
  612. }
  613. }
  614. #endif
  615. #ifdef _GxBitmaps128x296_H_
  616. void drawBitmaps128x296()
  617. {
  618. #if !defined(__AVR)
  619. const unsigned char* bitmaps[] =
  620. {
  621. Bitmap128x296_1, logo128x296, first128x296, second128x296, third128x296
  622. };
  623. #else
  624. const unsigned char* bitmaps[] =
  625. {
  626. Bitmap128x296_1, logo128x296 //, first128x296, second128x296, third128x296
  627. };
  628. #endif
  629. if (display.epd2.panel == GxEPD2::GDEH029A1)
  630. {
  631. bool m = display.mirror(true);
  632. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  633. {
  634. display.firstPage();
  635. do
  636. {
  637. display.fillScreen(GxEPD_WHITE);
  638. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  639. }
  640. while (display.nextPage());
  641. delay(2000);
  642. }
  643. display.mirror(m);
  644. }
  645. }
  646. #endif
  647. #ifdef _GxBitmaps176x264_H_
  648. void drawBitmaps176x264()
  649. {
  650. #if !defined(__AVR)
  651. const unsigned char* bitmaps[] =
  652. {
  653. Bitmap176x264_1, Bitmap176x264_2, Bitmap176x264_3, Bitmap176x264_4, Bitmap176x264_5
  654. };
  655. #else
  656. const unsigned char* bitmaps[] =
  657. {
  658. Bitmap176x264_1, Bitmap176x264_2 //, Bitmap176x264_3, Bitmap176x264_4, Bitmap176x264_5
  659. };
  660. #endif
  661. if (display.epd2.panel == GxEPD2::GDEW027W3)
  662. {
  663. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  664. {
  665. display.firstPage();
  666. do
  667. {
  668. display.fillScreen(GxEPD_WHITE);
  669. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  670. }
  671. while (display.nextPage());
  672. delay(2000);
  673. }
  674. }
  675. }
  676. #endif
  677. #ifdef _GxBitmaps400x300_H_
  678. void drawBitmaps400x300()
  679. {
  680. #if !defined(__AVR)
  681. const unsigned char* bitmaps[] =
  682. {
  683. Bitmap400x300_1, Bitmap400x300_2
  684. };
  685. #else
  686. const unsigned char* bitmaps[] = {}; // not enough code space
  687. #endif
  688. if (display.epd2.panel == GxEPD2::GDEW042T2)
  689. {
  690. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  691. {
  692. display.firstPage();
  693. do
  694. {
  695. display.fillScreen(GxEPD_WHITE);
  696. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  697. }
  698. while (display.nextPage());
  699. delay(2000);
  700. }
  701. }
  702. }
  703. #endif
  704. #ifdef _GxBitmaps640x384_H_
  705. void drawBitmaps640x384()
  706. {
  707. #if !defined(__AVR)
  708. const unsigned char* bitmaps[] =
  709. {
  710. Bitmap640x384_1, Bitmap640x384_2
  711. };
  712. #else
  713. const unsigned char* bitmaps[] = {}; // not enough code space
  714. #endif
  715. if ((display.epd2.panel == GxEPD2::GDEW075T8) || (display.epd2.panel == GxEPD2::GDEW075Z09))
  716. {
  717. for (uint16_t i = 0; i < sizeof(bitmaps) / sizeof(char*); i++)
  718. {
  719. display.firstPage();
  720. do
  721. {
  722. display.fillScreen(GxEPD_WHITE);
  723. display.drawInvertedBitmap(0, 0, bitmaps[i], display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  724. }
  725. while (display.nextPage());
  726. delay(2000);
  727. }
  728. }
  729. }
  730. #endif
  731. struct bitmap_pair
  732. {
  733. const unsigned char* black;
  734. const unsigned char* red;
  735. };
  736. #ifdef _GxBitmaps3c200x200_H_
  737. void drawBitmaps3c200x200()
  738. {
  739. bitmap_pair bitmap_pairs[] =
  740. {
  741. //{Bitmap3c200x200_black, Bitmap3c200x200_red},
  742. {WS_Bitmap3c200x200_black, WS_Bitmap3c200x200_red}
  743. };
  744. if (display.epd2.panel == GxEPD2::GDEW0154Z04)
  745. {
  746. display.firstPage();
  747. do
  748. {
  749. display.fillScreen(GxEPD_WHITE);
  750. // Bitmap3c200x200_black has 2 bits per pixel
  751. // taken from Adafruit_GFX.cpp, modified
  752. int16_t byteWidth = (display.epd2.WIDTH + 7) / 8; // Bitmap scanline pad = whole byte
  753. uint8_t byte = 0;
  754. for (int16_t j = 0; j < display.epd2.HEIGHT; j++)
  755. {
  756. for (int16_t i = 0; i < display.epd2.WIDTH; i++)
  757. {
  758. if (i & 3) byte <<= 2;
  759. else
  760. {
  761. #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
  762. byte = pgm_read_byte(&Bitmap3c200x200_black[j * byteWidth * 2 + i / 4]);
  763. #else
  764. byte = Bitmap3c200x200_black[j * byteWidth * 2 + i / 4];
  765. #endif
  766. }
  767. if (!(byte & 0x80))
  768. {
  769. display.drawPixel(i, j, GxEPD_BLACK);
  770. }
  771. }
  772. }
  773. display.drawInvertedBitmap(0, 0, Bitmap3c200x200_red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  774. }
  775. while (display.nextPage());
  776. delay(2000);
  777. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  778. {
  779. display.firstPage();
  780. do
  781. {
  782. display.fillScreen(GxEPD_WHITE);
  783. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  784. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  785. }
  786. while (display.nextPage());
  787. delay(2000);
  788. }
  789. }
  790. if (display.epd2.hasColor)
  791. {
  792. display.clearScreen(); // use default for white
  793. int16_t x = (int16_t(display.epd2.WIDTH) - 200) / 2;
  794. int16_t y = (int16_t(display.epd2.HEIGHT) - 200) / 2;
  795. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  796. {
  797. display.drawImage(bitmap_pairs[i].black, bitmap_pairs[i].red, x, y, 200, 200, false, false, true);
  798. delay(2000);
  799. }
  800. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  801. {
  802. int16_t x = -60;
  803. int16_t y = -60;
  804. for (uint16_t j = 0; j < 10; j++)
  805. {
  806. display.writeScreenBuffer(); // use default for white
  807. display.writeImage(bitmap_pairs[i].black, bitmap_pairs[i].red, x, y, 200, 200, false, false, true);
  808. display.refresh();
  809. delay(2000);
  810. x += 40;
  811. y += 40;
  812. if ((x >= int16_t(display.epd2.WIDTH)) || (y >= int16_t(display.epd2.HEIGHT))) break;
  813. }
  814. }
  815. display.writeScreenBuffer(); // use default for white
  816. display.writeImage(bitmap_pairs[0].black, bitmap_pairs[0].red, 0, 0, 200, 200, false, false, true);
  817. display.writeImage(bitmap_pairs[0].black, bitmap_pairs[0].red, int16_t(display.epd2.WIDTH) - 200, int16_t(display.epd2.HEIGHT) - 200, 200, 200, false, false, true);
  818. display.refresh();
  819. delay(2000);
  820. }
  821. }
  822. #endif
  823. #ifdef _GxBitmaps3c104x212_H_
  824. void drawBitmaps3c104x212()
  825. {
  826. #if !defined(__AVR)
  827. bitmap_pair bitmap_pairs[] =
  828. {
  829. {Bitmap3c104x212_1_black, Bitmap3c104x212_1_red},
  830. {Bitmap3c104x212_2_black, Bitmap3c104x212_2_red},
  831. {WS_Bitmap3c104x212_black, WS_Bitmap3c104x212_red}
  832. };
  833. #else
  834. bitmap_pair bitmap_pairs[] =
  835. {
  836. {Bitmap3c104x212_1_black, Bitmap3c104x212_1_red},
  837. //{Bitmap3c104x212_2_black, Bitmap3c104x212_2_red},
  838. {WS_Bitmap3c104x212_black, WS_Bitmap3c104x212_red}
  839. };
  840. #endif
  841. if (display.epd2.panel == GxEPD2::GDEW0213Z16)
  842. {
  843. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  844. {
  845. display.firstPage();
  846. do
  847. {
  848. display.fillScreen(GxEPD_WHITE);
  849. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  850. if (bitmap_pairs[i].red == WS_Bitmap3c104x212_red)
  851. {
  852. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  853. }
  854. else display.drawBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  855. }
  856. while (display.nextPage());
  857. delay(2000);
  858. }
  859. }
  860. }
  861. #endif
  862. #ifdef _GxBitmaps3c128x296_H_
  863. void drawBitmaps3c128x296()
  864. {
  865. #if !defined(__AVR)
  866. bitmap_pair bitmap_pairs[] =
  867. {
  868. {Bitmap3c128x296_1_black, Bitmap3c128x296_1_red},
  869. {Bitmap3c128x296_2_black, Bitmap3c128x296_2_red},
  870. {WS_Bitmap3c128x296_black, WS_Bitmap3c128x296_red}
  871. };
  872. #else
  873. bitmap_pair bitmap_pairs[] =
  874. {
  875. //{Bitmap3c128x296_1_black, Bitmap3c128x296_1_red},
  876. //{Bitmap3c128x296_2_black, Bitmap3c128x296_2_red},
  877. {WS_Bitmap3c128x296_black, WS_Bitmap3c128x296_red}
  878. };
  879. #endif
  880. if (display.epd2.panel == GxEPD2::GDEW029Z10)
  881. {
  882. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  883. {
  884. display.firstPage();
  885. do
  886. {
  887. display.fillScreen(GxEPD_WHITE);
  888. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  889. if (bitmap_pairs[i].red == WS_Bitmap3c128x296_red)
  890. {
  891. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  892. }
  893. else display.drawBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  894. }
  895. while (display.nextPage());
  896. delay(2000);
  897. }
  898. }
  899. }
  900. #endif
  901. #ifdef _GxBitmaps3c176x264_H_
  902. void drawBitmaps3c176x264()
  903. {
  904. bitmap_pair bitmap_pairs[] =
  905. {
  906. {Bitmap3c176x264_black, Bitmap3c176x264_red}
  907. };
  908. if (display.epd2.panel == GxEPD2::GDEW027C44)
  909. {
  910. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  911. {
  912. display.firstPage();
  913. do
  914. {
  915. display.fillScreen(GxEPD_WHITE);
  916. display.drawBitmap(0, 0, bitmap_pairs[i].black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  917. display.drawBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  918. }
  919. while (display.nextPage());
  920. delay(2000);
  921. }
  922. }
  923. }
  924. #endif
  925. #ifdef _GxBitmaps3c400x300_H_
  926. void drawBitmaps3c400x300()
  927. {
  928. #if !defined(__AVR)
  929. bitmap_pair bitmap_pairs[] =
  930. {
  931. {Bitmap3c400x300_1_black, Bitmap3c400x300_1_red},
  932. {Bitmap3c400x300_2_black, Bitmap3c400x300_2_red},
  933. {WS_Bitmap3c400x300_black, WS_Bitmap3c400x300_red}
  934. };
  935. #else
  936. bitmap_pair bitmap_pairs[] = {}; // not enough code space
  937. #endif
  938. if (display.epd2.panel == GxEPD2::GDEW042Z15)
  939. {
  940. for (uint16_t i = 0; i < sizeof(bitmap_pairs) / sizeof(bitmap_pair); i++)
  941. {
  942. display.firstPage();
  943. do
  944. {
  945. display.fillScreen(GxEPD_WHITE);
  946. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].black, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_BLACK);
  947. display.drawInvertedBitmap(0, 0, bitmap_pairs[i].red, display.epd2.WIDTH, display.epd2.HEIGHT, GxEPD_RED);
  948. }
  949. while (display.nextPage());
  950. delay(2000);
  951. }
  952. }
  953. }
  954. #endif