GxEPD2_WiFi_Example.ino 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. // GxEPD2_WiFi_Example : 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. // BMP handling code extracts taken from: https://github.com/prenticedavid/MCUFRIEND_kbv/tree/master/examples/showBMP_kbv_Uno
  7. //
  8. // Author: Jean-Marc Zingg
  9. //
  10. // Version: see library.properties
  11. //
  12. // Library: https://github.com/ZinggJM/GxEPD2
  13. //
  14. // note that BMP bitmaps are drawn at physical position in physical orientation of the screen
  15. // Supporting Arduino Forum Topics:
  16. // Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
  17. // Good Display ePaper for Arduino: https://forum.arduino.cc/index.php?topic=436411.0
  18. // mapping suggestion from Waveshare SPI e-Paper to Wemos D1 mini
  19. // BUSY -> D2, RST -> D4, DC -> D3, CS -> D8, CLK -> D5, DIN -> D7, GND -> GND, 3.3V -> 3.3V
  20. // NOTE: connect 3.3k pull-down from D8 to GND if your board or shield has level converters
  21. // NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, use different pin in case, or 4k7 pull-down
  22. // mapping suggestion from Waveshare SPI e-Paper to generic ESP8266
  23. // BUSY -> GPIO4, RST -> GPIO2, DC -> GPIO0, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
  24. // NOTE: connect 3.3k pull-down from GPIO15 to GND if your board or shield has level converters
  25. // NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, use different pin in case, or 3.3k pull-down
  26. // mapping of Waveshare e-Paper ESP8266 Driver Board, new version (see GxEPD2_boards_added.h for old version)
  27. // BUSY -> GPIO5, RST -> GPIO2, DC -> GPIO4, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
  28. // NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, add a 3.3k pull-down in case
  29. // the e-Paper ESP8266 Driver Board should have no boot mode issue, as it doesn't use level converters
  30. // mapping suggestion for ESP32, e.g. LOLIN32, see .../variants/.../pins_arduino.h for your board
  31. // NOTE: there are variants with different pins for SPI ! CHECK SPI PINS OF YOUR BOARD
  32. // BUSY -> 4, RST -> 16, DC -> 17, CS -> SS(5), CLK -> SCK(18), DIN -> MOSI(23), GND -> GND, 3.3V -> 3.3V
  33. // mapping of Waveshare ESP32 Driver Board
  34. // BUSY -> 25, RST -> 26, DC -> 27, CS-> 15, CLK -> 13, DIN -> 14
  35. // NOTE: this board uses "unusual" SPI pins and requires re-mapping of HW SPI to these pins in SPIClass
  36. // see example GxEPD2_WS_ESP32_Driver.ino, it shows how this can be done easily
  37. // new mapping suggestion for STM32F1, e.g. STM32F103C8T6 "BluePill"
  38. // BUSY -> A1, RST -> A2, DC -> A3, CS-> A4, CLK -> A5, DIN -> A7
  39. // mapping suggestion for AVR, UNO, NANO etc.
  40. // BUSY -> 7, RST -> 9, DC -> 8, CS-> 10, CLK -> 13, DIN -> 11
  41. // mapping of Waveshare Universal e-Paper Raw Panel Driver Shield for Arduino / NUCLEO
  42. // BUSY -> 7, RST -> 8, DC -> 9, CS-> 10, CLK -> 13, DIN -> 11
  43. // mapping suggestion for Arduino MEGA
  44. // BUSY -> 7, RST -> 9, DC -> 8, CS-> 53, CLK -> 52, DIN -> 51
  45. // base class GxEPD2_GFX can be used to pass references or pointers to the display instance as parameter, uses ~1.2k more code
  46. // enable or disable GxEPD2_GFX base class
  47. #define ENABLE_GxEPD2_GFX 0
  48. // uncomment next line to use class GFX of library GFX_Root instead of Adafruit_GFX
  49. //#include <GFX.h>
  50. // Note: if you use this with ENABLE_GxEPD2_GFX 1:
  51. // uncomment it in GxEPD2_GFX.h too, or add #include <GFX.h> before any #include <GxEPD2_GFX.h>
  52. #include <GxEPD2_BW.h>
  53. #include <GxEPD2_3C.h>
  54. #include <GxEPD2_7C.h>
  55. #if defined (ESP8266)
  56. #define MAX_DISPLAY_BUFFER_SIZE (81920ul-34000ul-34000ul) // ~34000 base use, WiFiClientSecure seems to need about 34k more to work
  57. #define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))
  58. #define MAX_HEIGHT_3C(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE / 2) / (EPD::WIDTH / 8))
  59. #define MAX_HEIGHT_7C(EPD) (EPD::HEIGHT <= (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2) ? EPD::HEIGHT : (MAX_DISPLAY_BUFFER_SIZE) / (EPD::WIDTH / 2))
  60. // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
  61. //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEP015OC1 no longer available
  62. //GxEPD2_BW<GxEPD2_154_D67, MAX_HEIGHT(GxEPD2_154_D67)> display(GxEPD2_154_D67(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0154D67
  63. //GxEPD2_BW<GxEPD2_154_T8, MAX_HEIGHT(GxEPD2_154_T8)> display(GxEPD2_154_T8(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0154T8 152x152
  64. //GxEPD2_BW<GxEPD2_154_M09, MAX_HEIGHT(GxEPD2_154_M09)> display(GxEPD2_154_M09(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0154M09 200x200
  65. //GxEPD2_BW<GxEPD2_154_M10, MAX_HEIGHT(GxEPD2_154_M10)> display(GxEPD2_154_M10(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0154M10 152x152
  66. //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDE0213B1, phased out
  67. //GxEPD2_BW<GxEPD2_213_B72, MAX_HEIGHT(GxEPD2_213_B72)> display(GxEPD2_213_B72(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0213B72
  68. //GxEPD2_BW<GxEPD2_213_B73, MAX_HEIGHT(GxEPD2_213_B73)> display(GxEPD2_213_B73(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0213B73
  69. //GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0213I5F
  70. //GxEPD2_BW<GxEPD2_213_M21, MAX_HEIGHT(GxEPD2_213_M21)> display(GxEPD2_213_M21(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0213M21
  71. //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  72. //GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW029T5
  73. //GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display(GxEPD2_290_M06(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW029M06
  74. //GxEPD2_BW<GxEPD2_260, MAX_HEIGHT(GxEPD2_260)> display(GxEPD2_260(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  75. //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  76. //GxEPD2_BW<GxEPD2_371, MAX_HEIGHT(GxEPD2_371)> display(GxEPD2_371(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  77. //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  78. //GxEPD2_BW<GxEPD2_420_M01, MAX_HEIGHT(GxEPD2_420_M01)> display(GxEPD2_420_M01(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW042M01
  79. //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  80. //GxEPD2_BW<GxEPD2_583_T8, MAX_HEIGHT(GxEPD2_583_T8)> display(GxEPD2_583_T8(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  81. //GxEPD2_BW<GxEPD2_750, MAX_HEIGHT(GxEPD2_750)> display(GxEPD2_750(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  82. //GxEPD2_BW<GxEPD2_750_T7, MAX_HEIGHT(GxEPD2_750_T7)> display(GxEPD2_750_T7(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW075T7 800x480
  83. // 3-color e-papers
  84. //GxEPD2_3C<GxEPD2_154c, MAX_HEIGHT_3C(GxEPD2_154c)> display(GxEPD2_154c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0154Z04 no longer available
  85. //GxEPD2_3C<GxEPD2_154_Z90c, MAX_HEIGHT_3C(GxEPD2_154_Z90c)> display(GxEPD2_154_Z90c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0154Z90
  86. //GxEPD2_3C<GxEPD2_213c, MAX_HEIGHT_3C(GxEPD2_213c)> display(GxEPD2_213c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  87. //GxEPD2_3C<GxEPD2_290c, MAX_HEIGHT_3C(GxEPD2_290c)> display(GxEPD2_290c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  88. //GxEPD2_3C<GxEPD2_270c, MAX_HEIGHT_3C(GxEPD2_270c)> display(GxEPD2_270c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  89. //GxEPD2_3C<GxEPD2_420c, MAX_HEIGHT_3C(GxEPD2_420c)> display(GxEPD2_420c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  90. //GxEPD2_3C<GxEPD2_583c, MAX_HEIGHT_3C(GxEPD2_583c)> display(GxEPD2_583c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  91. //GxEPD2_3C<GxEPD2_750c, MAX_HEIGHT_3C(GxEPD2_750c)> display(GxEPD2_750c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
  92. //GxEPD2_3C<GxEPD2_750c_Z08, MAX_HEIGHT_3C(GxEPD2_750c_Z08)> display(GxEPD2_750c_Z08(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW075Z08 800x480
  93. //GxEPD2_3C<GxEPD2_750c_Z90, MAX_HEIGHT_3C(GxEPD2_750c_Z90)> display(GxEPD2_750c_Z90(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH075Z90 880x528
  94. // 7-color e-paper
  95. //GxEPD2_3C<GxEPD2_565c, MAX_HEIGHT_7C(GxEPD2_565c)> display(GxEPD2_565c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // Waveshare 5.65" 7-color (3C graphics)
  96. //GxEPD2_7C<GxEPD2_565c, MAX_HEIGHT_7C(GxEPD2_565c)> display(GxEPD2_565c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // Waveshare 5.65" 7-color
  97. // grey levels parallel IF e-papers on Waveshare e-Paper IT8951 Driver HAT
  98. // HRDY -> 4, RST -> 2, CS -> SS(15), SCK -> SCK(14), MOSI -> MOSI(D7(13)), MISO -> MISO(D6(12)), GND -> GND, 5V -> 5V
  99. // note: 5V supply needs to be exact and strong; 5V pin of USB powered Wemos D1 mini doesn't work!
  100. //GxEPD2_BW<GxEPD2_it60, MAX_HEIGHT(GxEPD2_it60)> display(GxEPD2_it60(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 4));
  101. //GxEPD2_BW<GxEPD2_it60_1448x1072, MAX_HEIGHT(GxEPD2_it60_1448x1072)> display(GxEPD2_it60_1448x1072(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 4));
  102. // ***** for mapping of Waveshare e-Paper ESP8266 Driver Board *****
  103. // select one , can use full buffer size (full HEIGHT)
  104. //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEP015OC1 no longer available
  105. //GxEPD2_BW<GxEPD2_154_D67, MAX_HEIGHT(GxEPD2_154_D67)> display(GxEPD2_154_D67(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEH0154D67
  106. //GxEPD2_BW<GxEPD2_154_T8, MAX_HEIGHT(GxEPD2_154_T8)> display(GxEPD2_154_T8(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0154T8 152x152
  107. //GxEPD2_BW<GxEPD2_154_M09, MAX_HEIGHT(GxEPD2_154_M09)> display(GxEPD2_154_M09(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0154M09 200x200
  108. //GxEPD2_BW<GxEPD2_154_M10, MAX_HEIGHT(GxEPD2_154_M10)> display(GxEPD2_154_M10(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0154M10 152x152
  109. //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDE0213B1, phased out
  110. //GxEPD2_BW<GxEPD2_213_B72, MAX_HEIGHT(GxEPD2_213_B72)> display(GxEPD2_213_B72(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEH0213B72
  111. //GxEPD2_BW<GxEPD2_213_B73, MAX_HEIGHT(GxEPD2_213_B73)> display(GxEPD2_213_B73(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEH0213B73
  112. //GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0213I5F
  113. //GxEPD2_BW<GxEPD2_213_M21, MAX_HEIGHT(GxEPD2_213_M21)> display(GxEPD2_213_M21(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0213M21
  114. //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  115. //GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW029T5
  116. //GxEPD2_BW<GxEPD2_290_M06, MAX_HEIGHT(GxEPD2_290_M06)> display(GxEPD2_290_M06(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW029M06
  117. //GxEPD2_BW<GxEPD2_260, MAX_HEIGHT(GxEPD2_260)> display(GxEPD2_260(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  118. //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  119. //GxEPD2_BW<GxEPD2_371, MAX_HEIGHT(GxEPD2_371)> display(GxEPD2_371(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  120. //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  121. //GxEPD2_BW<GxEPD2_420_M01, MAX_HEIGHT(GxEPD2_420_M01)> display(GxEPD2_420_M01(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW042M01
  122. //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  123. //GxEPD2_BW<GxEPD2_583_T8, MAX_HEIGHT(GxEPD2_583_T8)> display(GxEPD2_583_T8(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  124. //GxEPD2_BW<GxEPD2_750, MAX_HEIGHT(GxEPD2_750)> display(GxEPD2_750(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  125. //GxEPD2_BW<GxEPD2_750_T7, MAX_HEIGHT(GxEPD2_750_T7)> display(GxEPD2_750_T7(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW075T7 800x480
  126. // 3-color e-papers
  127. //GxEPD2_3C<GxEPD2_154c, MAX_HEIGHT_3C(GxEPD2_154c)> display(GxEPD2_154c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW0154Z04 no longer available
  128. //GxEPD2_3C<GxEPD2_154_Z90c, MAX_HEIGHT_3C(GxEPD2_154_Z90c)> display(GxEPD2_154_Z90c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEH0154Z90
  129. //GxEPD2_3C<GxEPD2_213c, MAX_HEIGHT_3C(GxEPD2_213c)> display(GxEPD2_213c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  130. //GxEPD2_3C<GxEPD2_290c, MAX_HEIGHT_3C(GxEPD2_290c)> display(GxEPD2_290c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  131. //GxEPD2_3C<GxEPD2_270c, MAX_HEIGHT_3C(GxEPD2_270c)> display(GxEPD2_270c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  132. //GxEPD2_3C<GxEPD2_420c, MAX_HEIGHT_3C(GxEPD2_420c)> display(GxEPD2_420c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  133. //GxEPD2_3C<GxEPD2_583c, MAX_HEIGHT_3C(GxEPD2_583c)> display(GxEPD2_583c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  134. //GxEPD2_3C<GxEPD2_750c, MAX_HEIGHT_3C(GxEPD2_750c)> display(GxEPD2_750c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5));
  135. //GxEPD2_3C<GxEPD2_750c_Z08, MAX_HEIGHT_3C(GxEPD2_750c_Z08)> display(GxEPD2_750c_Z08(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEW075Z08 800x480
  136. //GxEPD2_3C<GxEPD2_750c_Z90, MAX_HEIGHT_3C(GxEPD2_750c_Z90)> display(GxEPD2_750c_Z90(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // GDEH075Z90 880x528
  137. // 7-color e-paper
  138. //GxEPD2_7C<GxEPD2_565c, MAX_HEIGHT_7C(GxEPD2_565c)> display(GxEPD2_565c(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=2*/ 2, /*BUSY=5*/ 5)); // Waveshare 5.65" 7-color
  139. #endif
  140. #if defined(ESP32)
  141. // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
  142. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEP015OC1 no longer available
  143. //GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH0154D67
  144. //GxEPD2_BW<GxEPD2_154_T8, GxEPD2_154_T8::HEIGHT> display(GxEPD2_154_T8(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0154T8 152x152
  145. //GxEPD2_BW<GxEPD2_154_M09, GxEPD2_154_M09::HEIGHT> display(GxEPD2_154_M09(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0154M09 200x200
  146. //GxEPD2_BW<GxEPD2_154_M10, GxEPD2_154_M10::HEIGHT> display(GxEPD2_154_M10(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0154M10 152x152
  147. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDE0213B1, phased out
  148. //GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display(GxEPD2_213_B72(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH0213B72
  149. //GxEPD2_BW<GxEPD2_213_B73, GxEPD2_213_B73::HEIGHT> display(GxEPD2_213_B73(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH0213B73
  150. //GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0213I5F
  151. //GxEPD2_BW<GxEPD2_213_M21, GxEPD2_213_M21::HEIGHT> display(GxEPD2_213_M21(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0213M21
  152. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  153. //GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW029T5
  154. //GxEPD2_BW<GxEPD2_290_M06, GxEPD2_290_M06::HEIGHT> display(GxEPD2_290_M06(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW029M06
  155. //GxEPD2_BW<GxEPD2_260, GxEPD2_260::HEIGHT> display(GxEPD2_260(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  156. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  157. //GxEPD2_BW<GxEPD2_371, GxEPD2_371::HEIGHT> display(GxEPD2_371(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  158. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  159. //GxEPD2_BW<GxEPD2_420_M01, GxEPD2_420_M01::HEIGHT> display(GxEPD2_420_M01(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW042M01
  160. //GxEPD2_BW<GxEPD2_583, GxEPD2_583::HEIGHT> display(GxEPD2_583(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  161. //GxEPD2_BW<GxEPD2_583_T8, GxEPD2_583_T8::HEIGHT> display(GxEPD2_583_T8(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  162. //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  163. //GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW075T7 800x480
  164. // 3-color e-papers
  165. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0154Z04 no longer available
  166. //GxEPD2_3C<GxEPD2_154_Z90c, GxEPD2_154_Z90c::HEIGHT> display(GxEPD2_154_Z90c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH0154Z90
  167. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  168. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  169. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  170. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  171. //GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT> display(GxEPD2_583c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  172. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT> display(GxEPD2_750c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  173. //GxEPD2_3C<GxEPD2_750c_Z08, GxEPD2_750c_Z08::HEIGHT> display(GxEPD2_750c_Z08(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW075Z08 800x480
  174. //GxEPD2_3C<GxEPD2_750c_Z90, GxEPD2_750c_Z90::HEIGHT / 2> display(GxEPD2_750c_Z90(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH075Z90 880x528
  175. // 7-color e-paper
  176. //GxEPD2_3C < GxEPD2_565c, GxEPD2_565c::HEIGHT / 2 > display(GxEPD2_565c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // Waveshare 5.65" 7-color (3C graphics)
  177. //GxEPD2_7C < GxEPD2_565c, GxEPD2_565c::HEIGHT / 2 > display(GxEPD2_565c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // Waveshare 5.65" 7-color
  178. // grey levels parallel IF e-papers on Waveshare e-Paper IT8951 Driver HAT
  179. // HRDY -> 4, RST -> 16, CS -> SS(5), SCK -> SCK(18), MOSI -> MOSI(23), MISO -> MISO(19), GND -> GND, 5V -> 5V
  180. // note: 5V supply needs to be exact and strong; 5V over diode from USB (e.g. Wemos D1 mini) doesn't work!
  181. //GxEPD2_BW<GxEPD2_it60, GxEPD2_it60::HEIGHT> display(GxEPD2_it60(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  182. //GxEPD2_BW < GxEPD2_it60_1448x1072, GxEPD2_it60_1448x1072::HEIGHT / 4 > display(GxEPD2_it60_1448x1072(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
  183. // Waveshare 12.48 b/w SPI display board and frame or Good Display 12.48 b/w panel GDEW1248T3
  184. // general constructor for use with all parameters, e.g. for Waveshare ESP32 driver board mounted on connection board
  185. //GxEPD2_BW < GxEPD2_1248, GxEPD2_1248::HEIGHT / 4 >
  186. //display(GxEPD2_1248(/*sck=*/ 13, /*miso=*/ 12, /*mosi=*/ 14, /*cs_m1=*/ 23, /*cs_s1=*/ 22, /*cs_m2=*/ 16, /*cs_s2=*/ 19,
  187. // /*dc1=*/ 25, /*dc2=*/ 17, /*rst1=*/ 33, /*rst2=*/ 5, /*busy_m1=*/ 32, /*busy_s1=*/ 26, /*busy_m2=*/ 18, /*busy_s2=*/ 4));
  188. // ***** for mapping of Waveshare ESP32 Driver Board *****
  189. // use Board "ESP32 Dev Module" to build with Arduino IDE
  190. // >>> uncomment next line to remap SPI pins used by the e-paper connector <<<
  191. //#define REMAP_SPI_FOR_WAVESHARE_ESP32_DRIVER_BOARD
  192. // select one, can use full buffer size (full HEIGHT)
  193. //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEP015OC1 no longer available
  194. //GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEH0154D67
  195. //GxEPD2_BW<GxEPD2_154_T8, GxEPD2_154_T8::HEIGHT> display(GxEPD2_154_T8(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0154T8 152x152
  196. //GxEPD2_BW<GxEPD2_154_M09, GxEPD2_154_M09::HEIGHT> display(GxEPD2_154_M09(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0154M09 200x200
  197. //GxEPD2_BW<GxEPD2_154_M10, GxEPD2_154_M10::HEIGHT> display(GxEPD2_154_M10(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0154M10 152x152
  198. //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDE0213B1, phased out
  199. //GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display(GxEPD2_213_B72(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEH0213B72
  200. //GxEPD2_BW<GxEPD2_213_B73, GxEPD2_213_B73::HEIGHT> display(GxEPD2_213_B73(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEH0213B73
  201. //GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0213I5F
  202. //GxEPD2_BW<GxEPD2_213_M21, GxEPD2_213_M21::HEIGHT> display(GxEPD2_213_M21(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0213M21
  203. //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  204. //GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW029T5
  205. //GxEPD2_BW<GxEPD2_290_M06, GxEPD2_290_M06::HEIGHT> display(GxEPD2_290_M06(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW029M06
  206. //GxEPD2_BW<GxEPD2_260, GxEPD2_260::HEIGHT> display(GxEPD2_260(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  207. //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  208. //GxEPD2_BW<GxEPD2_371, GxEPD2_371::HEIGHT> display(GxEPD2_371(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  209. //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  210. //GxEPD2_BW<GxEPD2_420_M01, GxEPD2_420_M01::HEIGHT> display(GxEPD2_420_M01(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW042M01
  211. //GxEPD2_BW<GxEPD2_583, GxEPD2_583::HEIGHT> display(GxEPD2_583(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  212. //GxEPD2_BW<GxEPD2_583_T8, GxEPD2_583_T8::HEIGHT> display(GxEPD2_583_T8(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  213. //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  214. //GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW075T7 800x480
  215. // 3-color e-papers
  216. //GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW0154Z04 no longer available
  217. //GxEPD2_3C<GxEPD2_154_Z90c, GxEPD2_154_Z90c::HEIGHT> display(GxEPD2_154_Z90c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEH0154Z90
  218. //GxEPD2_3C<GxEPD2_213c, GxEPD2_213c::HEIGHT> display(GxEPD2_213c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  219. //GxEPD2_3C<GxEPD2_290c, GxEPD2_290c::HEIGHT> display(GxEPD2_290c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  220. //GxEPD2_3C<GxEPD2_270c, GxEPD2_270c::HEIGHT> display(GxEPD2_270c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  221. //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT> display(GxEPD2_420c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  222. //GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT> display(GxEPD2_583c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  223. //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT> display(GxEPD2_750c(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25));
  224. //GxEPD2_3C<GxEPD2_750c_Z08, GxEPD2_750c_Z08::HEIGHT> display(GxEPD2_750c_Z08(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEW075Z08 800x480
  225. //GxEPD2_3C<GxEPD2_750c_Z90, GxEPD2_750c_Z90::HEIGHT / 2> display(GxEPD2_750c_Z90(/*CS=*/ 15, /*DC=*/ 27, /*RST=*/ 26, /*BUSY=*/ 25)); // GDEH075Z90 880x528
  226. #endif
  227. #if defined (ESP8266)
  228. #include <ESP8266WiFi.h>
  229. #define USE_BearSSL true
  230. #endif
  231. #include <WiFiClient.h>
  232. #include <WiFiClientSecure.h>
  233. const char* ssid = "........";
  234. const char* password = "........";
  235. const int httpPort = 80;
  236. const int httpsPort = 443;
  237. const char* fp_api_github_com = "df b2 29 c6 a6 38 1a 59 9d c9 ad 92 2d 26 f5 3c 83 8f a5 87"; // as of 25.11.2020
  238. const char* fp_github_com = "5f 3f 7a c2 56 9f 50 a4 66 76 47 c6 a1 8c a0 07 aa ed bb 8e"; // as of 25.11.2020
  239. const char* fp_rawcontent = "70 94 de dd e6 c4 69 48 3a 92 70 a1 48 56 78 2d 18 64 e0 b7"; // as of 25.11.2020
  240. // how to find the certificate was not easy. finally I found it using Mozilla Firefox.
  241. // opened one of the bitmaps, e.g. https://raw.githubusercontent.com/ZinggJM/GxEPD2/master/extras/bitmaps/logo200x200.bmp
  242. // clicked the lock symbol, Connection secure clicked >, show connection details, clicked More Information, clicked View Certificate, clicked Download PEM (chain),
  243. // selected Open with Notepad. Copied the middle certificate and editted to the following format:
  244. // the number of characters per line is of no importance, but the 3 \n are needed
  245. const char* certificate_rawcontent =
  246. "-----BEGIN CERTIFICATE-----\n"
  247. "MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln"
  248. "aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBS"
  249. "b290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu"
  250. "YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3VyYW5jZSBTZXJ2ZXIg"
  251. "Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC24C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+U"
  252. "DlqUH1VWtMICKq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1itrSxwUfqJfJ3KSxgoQtxq2l"
  253. "nMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaSc"
  254. "us0Xsh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcftbZvySC/zA/WiaJJTL17jAgMBAAGjggFJ"
  255. "MIIBRTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYI"
  256. "KwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDov"
  257. "L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIGBFUdIAAwKjAo"
  258. "BggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYD"
  259. "VR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwdaOpKj4PWUS+Na0QWnqxj"
  260. "9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNHE+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJ"
  261. "qvIni5ly/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zuxICaEnL6VpPX/78whQYwvwt/Tv9X"
  262. "BZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0AecPUeybQ=\n"
  263. "-----END CERTIFICATE-----\n";
  264. const char* host_rawcontent = "raw.githubusercontent.com";
  265. const char* path_rawcontent = "/ZinggJM/GxEPD2/master/extras/bitmaps/";
  266. const char* path_prenticedavid = "/prenticedavid/MCUFRIEND_kbv/master/extras/bitmaps/";
  267. const char* path_waveshare_c = "/waveshare/e-Paper/master/RaspberryPi_JetsonNano/c/pic/";
  268. const char* path_waveshare_py = "/waveshare/e-Paper/master/RaspberryPi_JetsonNano/python/pic/";
  269. // note that BMP bitmaps are drawn at physical position in physical orientation of the screen
  270. void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color = true);
  271. void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color = true,
  272. const char* certificate = certificate_rawcontent);
  273. // draws BMP bitmap according to set orientation
  274. void showBitmapFrom_HTTP_Buffered(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color = true);
  275. void showBitmapFrom_HTTPS_Buffered(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color = true,
  276. const char* certificate = certificate_rawcontent);
  277. void setup()
  278. {
  279. Serial.begin(115200);
  280. Serial.println();
  281. Serial.println("GxEPD2_WiFi_Example");
  282. display.init(115200);
  283. #ifdef REMAP_SPI_FOR_WAVESHARE_ESP32_DRIVER_BOARD
  284. SPI.end(); // release standard SPI pins, e.g. SCK(18), MISO(19), MOSI(23), SS(5)
  285. //SPI: void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
  286. SPI.begin(13, 12, 14, 15); // map and init SPI pins SCK(13), MISO(12), MOSI(14), SS(15)
  287. #endif
  288. #ifdef RE_INIT_NEEDED
  289. WiFi.persistent(true);
  290. WiFi.mode(WIFI_STA); // switch off AP
  291. WiFi.setAutoConnect(true);
  292. WiFi.setAutoReconnect(true);
  293. WiFi.disconnect();
  294. #endif
  295. if (!WiFi.getAutoConnect() || ( WiFi.getMode() != WIFI_STA) || ((WiFi.SSID() != ssid) && String(ssid) != "........"))
  296. {
  297. Serial.println();
  298. Serial.print("WiFi.getAutoConnect()=");
  299. Serial.println(WiFi.getAutoConnect());
  300. Serial.print("WiFi.SSID()=");
  301. Serial.println(WiFi.SSID());
  302. WiFi.mode(WIFI_STA); // switch off AP
  303. Serial.print("Connecting to ");
  304. Serial.println(ssid);
  305. WiFi.begin(ssid, password);
  306. }
  307. int ConnectTimeout = 30; // 15 seconds
  308. while (WiFi.status() != WL_CONNECTED)
  309. {
  310. delay(500);
  311. Serial.print(".");
  312. Serial.print(WiFi.status());
  313. if (--ConnectTimeout <= 0)
  314. {
  315. Serial.println();
  316. Serial.println("WiFi connect timeout");
  317. return;
  318. }
  319. }
  320. Serial.println();
  321. Serial.println("WiFi connected");
  322. // Print the IP address
  323. Serial.println(WiFi.localIP());
  324. if ((display.epd2.panel == GxEPD2::GDEW0154Z04) || (display.epd2.panel == GxEPD2::ACeP565) || false)
  325. {
  326. drawBitmapsBuffered_200x200();
  327. drawBitmapsBuffered_other();
  328. drawBitmapsBuffered_7C();
  329. }
  330. else
  331. {
  332. drawBitmaps_200x200();
  333. drawBitmaps_other();
  334. }
  335. //drawBitmaps_test();
  336. //drawBitmapsBuffered_test();
  337. Serial.println("GxEPD2_WiFi_Example done");
  338. }
  339. void loop(void)
  340. {
  341. }
  342. void drawBitmaps_200x200()
  343. {
  344. int16_t x = (display.width() - 200) / 2;
  345. int16_t y = (display.height() - 200) / 2;
  346. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "logo200x200.bmp", fp_rawcontent, x, y);
  347. delay(2000);
  348. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "first200x200.bmp", fp_rawcontent, x, y);
  349. delay(2000);
  350. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "second200x200.bmp", fp_rawcontent, x, y);
  351. delay(2000);
  352. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "third200x200.bmp", fp_rawcontent, x, y);
  353. delay(2000);
  354. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fourth200x200.bmp", fp_rawcontent, x, y);
  355. delay(2000);
  356. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "fifth200x200.bmp", fp_rawcontent, x, y);
  357. delay(2000);
  358. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "sixth200x200.bmp", fp_rawcontent, x, y);
  359. delay(2000);
  360. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "seventh200x200.bmp", fp_rawcontent, x, y);
  361. delay(2000);
  362. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "eighth200x200.bmp", fp_rawcontent, x, y);
  363. delay(2000);
  364. }
  365. void drawBitmaps_other()
  366. {
  367. int16_t w2 = display.width() / 2;
  368. int16_t h2 = display.height() / 2;
  369. showBitmapFrom_HTTP("www.packescape.com", "/img/assets/", "IniciMenusTV2.bmp", w2 - 200, h2 - 150, false);
  370. delay(2000);
  371. showBitmapFrom_HTTP("www.squix.org", "/blog/wunderground/", "chanceflurries.bmp", w2 - 50, h2 - 50, false);
  372. delay(2000);
  373. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_1.bmp", fp_rawcontent, w2 - 100, h2 - 160);
  374. delay(2000);
  375. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
  376. delay(2000);
  377. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "marilyn_240x240x8.bmp", fp_rawcontent, w2 - 120, h2 - 120);
  378. delay(2000);
  379. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "miniwoof.bmp", fp_rawcontent, w2 - 60, h2 - 80);
  380. delay(2000);
  381. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "test.bmp", fp_rawcontent, w2 - 120, h2 - 160);
  382. delay(2000);
  383. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger.bmp", fp_rawcontent, w2 - 160, h2 - 120);
  384. delay(2000);
  385. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_178x160x4.bmp", fp_rawcontent, w2 - 89, h2 - 80);
  386. delay(2000);
  387. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_240x317x4.bmp", fp_rawcontent, w2 - 120, h2 - 160);
  388. delay(2000);
  389. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger_320x200x24.bmp", fp_rawcontent, w2 - 160, h2 - 100);
  390. delay(2000);
  391. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "tiger16T.bmp", fp_rawcontent, w2 - 160, h2 - 100);
  392. delay(2000);
  393. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "woof.bmp", fp_rawcontent, w2 - 100, h2 - 100);
  394. delay(2000);
  395. }
  396. void drawBitmaps_test()
  397. {
  398. int16_t w2 = display.width() / 2;
  399. int16_t h2 = display.height() / 2;
  400. showBitmapFrom_HTTPS(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
  401. delay(2000);
  402. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "output5.bmp", fp_rawcontent, 0, 0);
  403. delay(2000);
  404. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "output6.bmp", fp_rawcontent, 0, 0);
  405. delay(2000);
  406. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_1.bmp", fp_rawcontent, 0, 0);
  407. delay(2000);
  408. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_4.bmp", fp_rawcontent, 0, 0);
  409. delay(2000);
  410. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_8.bmp", fp_rawcontent, 0, 0);
  411. delay(2000);
  412. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_11.bmp", fp_rawcontent, 0, 0);
  413. delay(2000);
  414. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_44.bmp", fp_rawcontent, 0, 0);
  415. delay(2000);
  416. showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "tractor_88.bmp", fp_rawcontent, 0, 0);
  417. delay(2000);
  418. //showBitmapFrom_HTTPS(host_rawcontent, path_rawcontent, "liberato640x384.bmp", fp_rawcontent, 0, 0);
  419. //delay(2000);
  420. }
  421. void drawBitmapsBuffered_200x200()
  422. {
  423. int16_t x = (display.width() - 200) / 2;
  424. int16_t y = (display.height() - 200) / 2;
  425. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "logo200x200.bmp", fp_rawcontent, x, y);
  426. delay(2000);
  427. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "first200x200.bmp", fp_rawcontent, x, y);
  428. delay(2000);
  429. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "second200x200.bmp", fp_rawcontent, x, y);
  430. delay(2000);
  431. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "third200x200.bmp", fp_rawcontent, x, y);
  432. delay(2000);
  433. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "fourth200x200.bmp", fp_rawcontent, x, y);
  434. delay(2000);
  435. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "fifth200x200.bmp", fp_rawcontent, x, y);
  436. delay(2000);
  437. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "sixth200x200.bmp", fp_rawcontent, x, y);
  438. delay(2000);
  439. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "seventh200x200.bmp", fp_rawcontent, x, y);
  440. delay(2000);
  441. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_rawcontent, "eighth200x200.bmp", fp_rawcontent, x, y);
  442. delay(2000);
  443. }
  444. void drawBitmapsBuffered_other()
  445. {
  446. int16_t w2 = display.width() / 2;
  447. int16_t h2 = display.height() / 2;
  448. showBitmapFrom_HTTP_Buffered("www.squix.org", "/blog/wunderground/", "chanceflurries.bmp", w2 - 50, h2 - 50, false);
  449. delay(2000);
  450. //showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "betty_1.bmp", fp_rawcontent, w2 - 100, h2 - 160);
  451. delay(2000);
  452. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
  453. delay(2000);
  454. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "marilyn_240x240x8.bmp", fp_rawcontent, w2 - 120, h2 - 120);
  455. delay(2000);
  456. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "miniwoof.bmp", fp_rawcontent, w2 - 60, h2 - 80);
  457. delay(2000);
  458. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "test.bmp", fp_rawcontent, w2 - 120, h2 - 160);
  459. delay(2000);
  460. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "tiger.bmp", fp_rawcontent, w2 - 160, h2 - 120);
  461. delay(2000);
  462. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "tiger_178x160x4.bmp", fp_rawcontent, w2 - 89, h2 - 80);
  463. delay(2000);
  464. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "tiger_240x317x4.bmp", fp_rawcontent, w2 - 120, h2 - 160);
  465. delay(2000);
  466. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "tiger_320x200x24.bmp", fp_rawcontent, w2 - 160, h2 - 100);
  467. delay(2000);
  468. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "tiger16T.bmp", fp_rawcontent, w2 - 160, h2 - 100);
  469. delay(2000);
  470. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "woof.bmp", fp_rawcontent, w2 - 100, h2 - 100);
  471. delay(2000);
  472. }
  473. void drawBitmapsBuffered_7C()
  474. {
  475. if (display.epd2.panel == GxEPD2::ACeP565)
  476. {
  477. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_c, "5in65f.bmp", fp_rawcontent, 0, 0);
  478. delay(2000);
  479. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_c, "5in65f2.bmp", fp_rawcontent, 0, 0);
  480. delay(2000);
  481. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_c, "5in65f3.bmp", fp_rawcontent, 0, 0);
  482. delay(2000);
  483. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_c, "5in65f4.bmp", fp_rawcontent, 0, 0);
  484. delay(2000);
  485. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_py, "5in65f4.bmp", fp_rawcontent, 0, 0);
  486. delay(2000);
  487. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_waveshare_py, "N-Color1.bmp", fp_rawcontent, 0, 0);
  488. delay(2000);
  489. }
  490. }
  491. void drawBitmapsBuffered_test()
  492. {
  493. int16_t w2 = display.width() / 2;
  494. int16_t h2 = display.height() / 2;
  495. showBitmapFrom_HTTPS_Buffered(host_rawcontent, path_prenticedavid, "betty_4.bmp", fp_rawcontent, w2 - 102, h2 - 126);
  496. delay(2000);
  497. }
  498. static const uint16_t input_buffer_pixels = 800; // may affect performance
  499. static const uint16_t max_row_width = 1448; // for up to 6" display 1448x1072
  500. static const uint16_t max_palette_pixels = 256; // for depth <= 8
  501. uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24
  502. uint8_t output_row_mono_buffer[max_row_width / 8]; // buffer for at least one row of b/w bits
  503. uint8_t output_row_color_buffer[max_row_width / 8]; // buffer for at least one row of color bits
  504. uint8_t mono_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 b/w
  505. uint8_t color_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 c/w
  506. uint16_t rgb_palette_buffer[max_palette_pixels]; // palette buffer for depth <= 8 for buffered graphics, needed for 7-color display
  507. void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
  508. {
  509. WiFiClient client;
  510. bool connection_ok = false;
  511. bool valid = false; // valid format to be handled
  512. bool flip = true; // bitmap is stored bottom-to-top
  513. uint32_t startTime = millis();
  514. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) return;
  515. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  516. Serial.print("connecting to "); Serial.println(host);
  517. if (!client.connect(host, httpPort))
  518. {
  519. Serial.println("connection failed");
  520. return;
  521. }
  522. Serial.print("requesting URL: ");
  523. Serial.println(String("http://") + host + path + filename);
  524. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  525. "Host: " + host + "\r\n" +
  526. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  527. "Connection: close\r\n\r\n");
  528. Serial.println("request sent");
  529. while (client.connected())
  530. {
  531. String line = client.readStringUntil('\n');
  532. if (!connection_ok)
  533. {
  534. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  535. if (connection_ok) Serial.println(line);
  536. //if (!connection_ok) Serial.println(line);
  537. }
  538. if (!connection_ok) Serial.println(line);
  539. //Serial.println(line);
  540. if (line == "\r")
  541. {
  542. Serial.println("headers received");
  543. break;
  544. }
  545. }
  546. if (!connection_ok) return;
  547. // Parse BMP header
  548. if (read16(client) == 0x4D42) // BMP signature
  549. {
  550. uint32_t fileSize = read32(client);
  551. uint32_t creatorBytes = read32(client);
  552. uint32_t imageOffset = read32(client); // Start of image data
  553. uint32_t headerSize = read32(client);
  554. uint32_t width = read32(client);
  555. uint32_t height = read32(client);
  556. uint16_t planes = read16(client);
  557. uint16_t depth = read16(client); // bits per pixel
  558. uint32_t format = read32(client);
  559. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  560. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  561. {
  562. Serial.print("File size: "); Serial.println(fileSize);
  563. Serial.print("Image Offset: "); Serial.println(imageOffset);
  564. Serial.print("Header size: "); Serial.println(headerSize);
  565. Serial.print("Bit Depth: "); Serial.println(depth);
  566. Serial.print("Image size: ");
  567. Serial.print(width);
  568. Serial.print('x');
  569. Serial.println(height);
  570. // BMP rows are padded (if needed) to 4-byte boundary
  571. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  572. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  573. if (height < 0)
  574. {
  575. height = -height;
  576. flip = false;
  577. }
  578. uint16_t w = width;
  579. uint16_t h = height;
  580. if ((x + w - 1) >= display.epd2.WIDTH) w = display.epd2.WIDTH - x;
  581. if ((y + h - 1) >= display.epd2.HEIGHT) h = display.epd2.HEIGHT - y;
  582. if (w <= max_row_width) // handle with direct drawing
  583. {
  584. valid = true;
  585. uint8_t bitmask = 0xFF;
  586. uint8_t bitshift = 8 - depth;
  587. uint16_t red, green, blue;
  588. bool whitish, colored;
  589. if (depth == 1) with_color = false;
  590. if (depth <= 8)
  591. {
  592. if (depth < 8) bitmask >>= depth;
  593. //bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
  594. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  595. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  596. {
  597. blue = client.read();
  598. green = client.read();
  599. red = client.read();
  600. client.read();
  601. bytes_read += 4;
  602. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  603. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  604. if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
  605. mono_palette_buffer[pn / 8] |= whitish << pn % 8;
  606. if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
  607. color_palette_buffer[pn / 8] |= colored << pn % 8;
  608. }
  609. }
  610. display.clearScreen();
  611. uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
  612. //Serial.print("skip "); Serial.println(rowPosition - bytes_read);
  613. bytes_read += skip(client, rowPosition - bytes_read);
  614. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  615. {
  616. if (!connection_ok || !(client.connected() || client.available())) break;
  617. delay(1); // yield() to avoid WDT
  618. uint32_t in_remain = rowSize;
  619. uint32_t in_idx = 0;
  620. uint32_t in_bytes = 0;
  621. uint8_t in_byte = 0; // for depth <= 8
  622. uint8_t in_bits = 0; // for depth <= 8
  623. uint8_t out_byte = 0xFF; // white (for w%8!=0 border)
  624. uint8_t out_color_byte = 0xFF; // white (for w%8!=0 border)
  625. uint32_t out_idx = 0;
  626. for (uint16_t col = 0; col < w; col++) // for each pixel
  627. {
  628. yield();
  629. if (!connection_ok || !(client.connected() || client.available())) break;
  630. // Time to read more pixel data?
  631. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  632. {
  633. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  634. uint32_t got = read8n(client, input_buffer, get);
  635. while ((got < get) && connection_ok)
  636. {
  637. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  638. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  639. got += gotmore;
  640. connection_ok = gotmore > 0;
  641. }
  642. in_bytes = got;
  643. in_remain -= got;
  644. bytes_read += got;
  645. }
  646. if (!connection_ok)
  647. {
  648. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  649. break;
  650. }
  651. switch (depth)
  652. {
  653. case 24:
  654. blue = input_buffer[in_idx++];
  655. green = input_buffer[in_idx++];
  656. red = input_buffer[in_idx++];
  657. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  658. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  659. break;
  660. case 16:
  661. {
  662. uint8_t lsb = input_buffer[in_idx++];
  663. uint8_t msb = input_buffer[in_idx++];
  664. if (format == 0) // 555
  665. {
  666. blue = (lsb & 0x1F) << 3;
  667. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  668. red = (msb & 0x7C) << 1;
  669. }
  670. else // 565
  671. {
  672. blue = (lsb & 0x1F) << 3;
  673. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  674. red = (msb & 0xF8);
  675. }
  676. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  677. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  678. }
  679. break;
  680. case 1:
  681. case 4:
  682. case 8:
  683. {
  684. if (0 == in_bits)
  685. {
  686. in_byte = input_buffer[in_idx++];
  687. in_bits = 8;
  688. }
  689. uint16_t pn = (in_byte >> bitshift) & bitmask;
  690. whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
  691. colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
  692. in_byte <<= depth;
  693. in_bits -= depth;
  694. }
  695. break;
  696. }
  697. if (whitish)
  698. {
  699. // keep white
  700. }
  701. else if (colored && with_color)
  702. {
  703. out_color_byte &= ~(0x80 >> col % 8); // colored
  704. }
  705. else
  706. {
  707. out_byte &= ~(0x80 >> col % 8); // black
  708. }
  709. if ((7 == col % 8) || (col == w - 1)) // write that last byte! (for w%8!=0 border)
  710. {
  711. output_row_color_buffer[out_idx] = out_color_byte;
  712. output_row_mono_buffer[out_idx++] = out_byte;
  713. out_byte = 0xFF; // white (for w%8!=0 border)
  714. out_color_byte = 0xFF; // white (for w%8!=0 border)
  715. }
  716. } // end pixel
  717. int16_t yrow = y + (flip ? h - row - 1 : row);
  718. display.writeImage(output_row_mono_buffer, output_row_color_buffer, x, yrow, w, 1);
  719. } // end line
  720. Serial.print("downloaded in ");
  721. Serial.print(millis() - startTime);
  722. Serial.println(" ms");
  723. display.refresh();
  724. }
  725. Serial.print("bytes read "); Serial.println(bytes_read);
  726. }
  727. }
  728. client.stop();
  729. if (!valid)
  730. {
  731. Serial.println("bitmap format not handled.");
  732. }
  733. }
  734. void drawBitmapFrom_HTTP_ToBuffer(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
  735. {
  736. WiFiClient client;
  737. bool connection_ok = false;
  738. bool valid = false; // valid format to be handled
  739. bool flip = true; // bitmap is stored bottom-to-top
  740. bool has_multicolors = display.epd2.panel == GxEPD2::ACeP565;
  741. uint32_t startTime = millis();
  742. if ((x >= display.width()) || (y >= display.height())) return;
  743. display.fillScreen(GxEPD_WHITE);
  744. Serial.print("connecting to "); Serial.println(host);
  745. if (!client.connect(host, httpPort))
  746. {
  747. Serial.println("connection failed");
  748. return;
  749. }
  750. Serial.print("requesting URL: ");
  751. Serial.println(String("http://") + host + path + filename);
  752. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  753. "Host: " + host + "\r\n" +
  754. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  755. "Connection: close\r\n\r\n");
  756. Serial.println("request sent");
  757. while (client.connected())
  758. {
  759. String line = client.readStringUntil('\n');
  760. if (!connection_ok)
  761. {
  762. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  763. if (connection_ok) Serial.println(line);
  764. //if (!connection_ok) Serial.println(line);
  765. }
  766. if (!connection_ok) Serial.println(line);
  767. //Serial.println(line);
  768. if (line == "\r")
  769. {
  770. Serial.println("headers received");
  771. break;
  772. }
  773. }
  774. if (!connection_ok) return;
  775. // Parse BMP header
  776. if (read16(client) == 0x4D42) // BMP signature
  777. {
  778. uint32_t fileSize = read32(client);
  779. uint32_t creatorBytes = read32(client);
  780. uint32_t imageOffset = read32(client); // Start of image data
  781. uint32_t headerSize = read32(client);
  782. uint32_t width = read32(client);
  783. uint32_t height = read32(client);
  784. uint16_t planes = read16(client);
  785. uint16_t depth = read16(client); // bits per pixel
  786. uint32_t format = read32(client);
  787. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  788. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  789. {
  790. Serial.print("File size: "); Serial.println(fileSize);
  791. Serial.print("Image Offset: "); Serial.println(imageOffset);
  792. Serial.print("Header size: "); Serial.println(headerSize);
  793. Serial.print("Bit Depth: "); Serial.println(depth);
  794. Serial.print("Image size: ");
  795. Serial.print(width);
  796. Serial.print('x');
  797. Serial.println(height);
  798. // BMP rows are padded (if needed) to 4-byte boundary
  799. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  800. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  801. if (height < 0)
  802. {
  803. height = -height;
  804. flip = false;
  805. }
  806. uint16_t w = width;
  807. uint16_t h = height;
  808. if ((x + w - 1) >= display.width()) w = display.width() - x;
  809. if ((y + h - 1) >= display.height()) h = display.height() - y;
  810. //if (w <= max_row_width) // handle with direct drawing
  811. {
  812. valid = true;
  813. uint8_t bitmask = 0xFF;
  814. uint8_t bitshift = 8 - depth;
  815. uint16_t red, green, blue;
  816. bool whitish, colored;
  817. if (depth == 1) with_color = false;
  818. if (depth <= 8)
  819. {
  820. if (depth < 8) bitmask >>= depth;
  821. //bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
  822. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  823. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  824. {
  825. blue = client.read();
  826. green = client.read();
  827. red = client.read();
  828. client.read();
  829. bytes_read += 4;
  830. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  831. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  832. if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
  833. mono_palette_buffer[pn / 8] |= whitish << pn % 8;
  834. if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
  835. color_palette_buffer[pn / 8] |= colored << pn % 8;
  836. //Serial.print("0x00"); Serial.print(red, HEX); Serial.print(green, HEX); Serial.print(blue, HEX);
  837. //Serial.print(" : "); Serial.print(whitish); Serial.print(", "); Serial.println(colored);
  838. rgb_palette_buffer[pn] = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  839. }
  840. }
  841. uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
  842. //Serial.print("skip "); Serial.println(rowPosition - bytes_read);
  843. bytes_read += skip(client, rowPosition - bytes_read);
  844. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  845. {
  846. if (!connection_ok || !(client.connected() || client.available())) break;
  847. delay(1); // yield() to avoid WDT
  848. uint32_t in_remain = rowSize;
  849. uint32_t in_idx = 0;
  850. uint32_t in_bytes = 0;
  851. uint8_t in_byte = 0; // for depth <= 8
  852. uint8_t in_bits = 0; // for depth <= 8
  853. uint16_t color = GxEPD_WHITE;
  854. for (uint16_t col = 0; col < w; col++) // for each pixel
  855. {
  856. yield();
  857. if (!connection_ok || !(client.connected() || client.available())) break;
  858. // Time to read more pixel data?
  859. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  860. {
  861. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  862. uint32_t got = read8n(client, input_buffer, get);
  863. while ((got < get) && connection_ok)
  864. {
  865. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  866. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  867. got += gotmore;
  868. connection_ok = gotmore > 0;
  869. }
  870. in_bytes = got;
  871. in_remain -= got;
  872. bytes_read += got;
  873. }
  874. if (!connection_ok)
  875. {
  876. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  877. break;
  878. }
  879. switch (depth)
  880. {
  881. case 24:
  882. blue = input_buffer[in_idx++];
  883. green = input_buffer[in_idx++];
  884. red = input_buffer[in_idx++];
  885. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  886. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  887. color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  888. break;
  889. case 16:
  890. {
  891. uint8_t lsb = input_buffer[in_idx++];
  892. uint8_t msb = input_buffer[in_idx++];
  893. if (format == 0) // 555
  894. {
  895. blue = (lsb & 0x1F) << 3;
  896. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  897. red = (msb & 0x7C) << 1;
  898. color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  899. }
  900. else // 565
  901. {
  902. blue = (lsb & 0x1F) << 3;
  903. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  904. red = (msb & 0xF8);
  905. color = (msb << 8) | lsb;
  906. }
  907. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  908. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  909. }
  910. break;
  911. case 1:
  912. case 4:
  913. case 8:
  914. {
  915. if (0 == in_bits)
  916. {
  917. in_byte = input_buffer[in_idx++];
  918. in_bits = 8;
  919. }
  920. uint16_t pn = (in_byte >> bitshift) & bitmask;
  921. whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
  922. colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
  923. in_byte <<= depth;
  924. in_bits -= depth;
  925. color = rgb_palette_buffer[pn];
  926. }
  927. break;
  928. }
  929. if (with_color && has_multicolors)
  930. {
  931. // keep color
  932. }
  933. else if (whitish)
  934. {
  935. color = GxEPD_WHITE;
  936. }
  937. else if (colored && with_color)
  938. {
  939. color = GxEPD_COLORED;
  940. }
  941. else
  942. {
  943. color = GxEPD_BLACK;
  944. }
  945. uint16_t yrow = y + (flip ? h - row - 1 : row);
  946. display.drawPixel(x + col, yrow, color);
  947. } // end pixel
  948. } // end line
  949. }
  950. Serial.print("bytes read "); Serial.println(bytes_read);
  951. }
  952. }
  953. Serial.print("loaded in "); Serial.print(millis() - startTime); Serial.println(" ms");
  954. client.stop();
  955. if (!valid)
  956. {
  957. Serial.println("bitmap format not handled.");
  958. }
  959. }
  960. void showBitmapFrom_HTTP_Buffered(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
  961. {
  962. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  963. display.setFullWindow();
  964. display.firstPage();
  965. do
  966. {
  967. drawBitmapFrom_HTTP_ToBuffer(host, path, filename, x, y, with_color);
  968. }
  969. while (display.nextPage());
  970. }
  971. void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
  972. {
  973. // Use WiFiClientSecure class to create TLS connection
  974. #if USE_BearSSL
  975. BearSSL::WiFiClientSecure client;
  976. #else
  977. WiFiClientSecure client;
  978. #endif
  979. bool connection_ok = false;
  980. bool valid = false; // valid format to be handled
  981. bool flip = true; // bitmap is stored bottom-to-top
  982. uint32_t startTime = millis();
  983. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) return;
  984. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  985. Serial.print("connecting to "); Serial.println(host);
  986. #if defined (ESP8266)
  987. client.setBufferSizes(4096, 4096); // doesn't help
  988. if (fingerprint) client.setFingerprint(fingerprint);
  989. #elif defined (ESP32)
  990. if (certificate) client.setCACert(certificate);
  991. #endif
  992. if (!client.connect(host, httpsPort))
  993. {
  994. Serial.println("connection failed");
  995. return;
  996. }
  997. Serial.print("requesting URL: ");
  998. Serial.println(String("https://") + host + path + filename);
  999. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  1000. "Host: " + host + "\r\n" +
  1001. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  1002. "Connection: close\r\n\r\n");
  1003. Serial.println("request sent");
  1004. while (client.connected())
  1005. {
  1006. String line = client.readStringUntil('\n');
  1007. if (!connection_ok)
  1008. {
  1009. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  1010. if (connection_ok) Serial.println(line);
  1011. //if (!connection_ok) Serial.println(line);
  1012. }
  1013. if (!connection_ok) Serial.println(line);
  1014. //Serial.println(line);
  1015. if (line == "\r")
  1016. {
  1017. Serial.println("headers received");
  1018. break;
  1019. }
  1020. }
  1021. if (!connection_ok) return;
  1022. // Parse BMP header
  1023. if (read16(client) == 0x4D42) // BMP signature
  1024. {
  1025. uint32_t fileSize = read32(client);
  1026. uint32_t creatorBytes = read32(client);
  1027. uint32_t imageOffset = read32(client); // Start of image data
  1028. uint32_t headerSize = read32(client);
  1029. uint32_t width = read32(client);
  1030. uint32_t height = read32(client);
  1031. uint16_t planes = read16(client);
  1032. uint16_t depth = read16(client); // bits per pixel
  1033. uint32_t format = read32(client);
  1034. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  1035. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  1036. {
  1037. Serial.print("File size: "); Serial.println(fileSize);
  1038. Serial.print("Image Offset: "); Serial.println(imageOffset);
  1039. Serial.print("Header size: "); Serial.println(headerSize);
  1040. Serial.print("Bit Depth: "); Serial.println(depth);
  1041. Serial.print("Image size: ");
  1042. Serial.print(width);
  1043. Serial.print('x');
  1044. Serial.println(height);
  1045. // BMP rows are padded (if needed) to 4-byte boundary
  1046. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  1047. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  1048. if (height < 0)
  1049. {
  1050. height = -height;
  1051. flip = false;
  1052. }
  1053. uint16_t w = width;
  1054. uint16_t h = height;
  1055. if ((x + w - 1) >= display.epd2.WIDTH) w = display.epd2.WIDTH - x;
  1056. if ((y + h - 1) >= display.epd2.HEIGHT) h = display.epd2.HEIGHT - y;
  1057. if (w <= max_row_width) // handle with direct drawing
  1058. {
  1059. valid = true;
  1060. uint8_t bitmask = 0xFF;
  1061. uint8_t bitshift = 8 - depth;
  1062. uint16_t red, green, blue;
  1063. bool whitish, colored;
  1064. if (depth == 1) with_color = false;
  1065. if (depth <= 8)
  1066. {
  1067. if (depth < 8) bitmask >>= depth;
  1068. //bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
  1069. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  1070. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  1071. {
  1072. blue = client.read();
  1073. green = client.read();
  1074. red = client.read();
  1075. client.read();
  1076. bytes_read += 4;
  1077. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1078. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1079. if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
  1080. mono_palette_buffer[pn / 8] |= whitish << pn % 8;
  1081. if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
  1082. color_palette_buffer[pn / 8] |= colored << pn % 8;
  1083. }
  1084. }
  1085. display.clearScreen();
  1086. uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
  1087. //Serial.print("skip "); Serial.println(rowPosition - bytes_read);
  1088. bytes_read += skip(client, rowPosition - bytes_read);
  1089. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  1090. {
  1091. if (!connection_ok || !(client.connected() || client.available())) break;
  1092. delay(1); // yield() to avoid WDT
  1093. uint32_t in_remain = rowSize;
  1094. uint32_t in_idx = 0;
  1095. uint32_t in_bytes = 0;
  1096. uint8_t in_byte = 0; // for depth <= 8
  1097. uint8_t in_bits = 0; // for depth <= 8
  1098. uint8_t out_byte = 0xFF; // white (for w%8!=0 border)
  1099. uint8_t out_color_byte = 0xFF; // white (for w%8!=0 border)
  1100. uint32_t out_idx = 0;
  1101. for (uint16_t col = 0; col < w; col++) // for each pixel
  1102. {
  1103. yield();
  1104. if (!connection_ok || !(client.connected() || client.available())) break;
  1105. // Time to read more pixel data?
  1106. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  1107. {
  1108. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  1109. uint32_t got = read8n(client, input_buffer, get);
  1110. while ((got < get) && connection_ok)
  1111. {
  1112. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  1113. //if ((get - got) > client.available()) delay(200); // does improve? yes, if >= 200
  1114. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  1115. got += gotmore;
  1116. connection_ok = gotmore > 0;
  1117. }
  1118. in_bytes = got;
  1119. in_remain -= got;
  1120. bytes_read += got;
  1121. }
  1122. if (!connection_ok)
  1123. {
  1124. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  1125. break;
  1126. }
  1127. switch (depth)
  1128. {
  1129. case 24:
  1130. blue = input_buffer[in_idx++];
  1131. green = input_buffer[in_idx++];
  1132. red = input_buffer[in_idx++];
  1133. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1134. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1135. break;
  1136. case 16:
  1137. {
  1138. uint8_t lsb = input_buffer[in_idx++];
  1139. uint8_t msb = input_buffer[in_idx++];
  1140. if (format == 0) // 555
  1141. {
  1142. blue = (lsb & 0x1F) << 3;
  1143. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  1144. red = (msb & 0x7C) << 1;
  1145. }
  1146. else // 565
  1147. {
  1148. blue = (lsb & 0x1F) << 3;
  1149. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  1150. red = (msb & 0xF8);
  1151. }
  1152. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1153. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1154. }
  1155. break;
  1156. case 1:
  1157. case 4:
  1158. case 8:
  1159. {
  1160. if (0 == in_bits)
  1161. {
  1162. in_byte = input_buffer[in_idx++];
  1163. in_bits = 8;
  1164. }
  1165. uint16_t pn = (in_byte >> bitshift) & bitmask;
  1166. whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
  1167. colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
  1168. in_byte <<= depth;
  1169. in_bits -= depth;
  1170. }
  1171. break;
  1172. }
  1173. if (whitish)
  1174. {
  1175. // keep white
  1176. }
  1177. else if (colored && with_color)
  1178. {
  1179. out_color_byte &= ~(0x80 >> col % 8); // colored
  1180. }
  1181. else
  1182. {
  1183. out_byte &= ~(0x80 >> col % 8); // black
  1184. }
  1185. if ((7 == col % 8) || (col == w - 1)) // write that last byte! (for w%8!=0 border)
  1186. {
  1187. output_row_color_buffer[out_idx] = out_color_byte;
  1188. output_row_mono_buffer[out_idx++] = out_byte;
  1189. out_byte = 0xFF; // white (for w%8!=0 border)
  1190. out_color_byte = 0xFF; // white (for w%8!=0 border)
  1191. }
  1192. } // end pixel
  1193. int16_t yrow = y + (flip ? h - row - 1 : row);
  1194. display.writeImage(output_row_mono_buffer, output_row_color_buffer, x, yrow, w, 1);
  1195. } // end line
  1196. Serial.print("downloaded in "); Serial.print(millis() - startTime); Serial.println(" ms");
  1197. Serial.print("bytes read "); Serial.println(bytes_read);
  1198. display.refresh();
  1199. }
  1200. }
  1201. }
  1202. client.stop();
  1203. if (!valid)
  1204. {
  1205. Serial.println("bitmap format not handled.");
  1206. }
  1207. }
  1208. void drawBitmapFrom_HTTPS_ToBuffer(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
  1209. {
  1210. // Use WiFiClientSecure class to create TLS connection
  1211. #if USE_BearSSL
  1212. BearSSL::WiFiClientSecure client;
  1213. #else
  1214. WiFiClientSecure client;
  1215. #endif
  1216. bool connection_ok = false;
  1217. bool valid = false; // valid format to be handled
  1218. bool flip = true; // bitmap is stored bottom-to-top
  1219. bool has_multicolors = display.epd2.panel == GxEPD2::ACeP565;
  1220. uint32_t startTime = millis();
  1221. if ((x >= display.width()) || (y >= display.height())) return;
  1222. display.fillScreen(GxEPD_WHITE);
  1223. Serial.print("connecting to "); Serial.println(host);
  1224. #if defined (ESP8266)
  1225. client.setBufferSizes(4096, 4096); // doesn't help
  1226. if (fingerprint) client.setFingerprint(fingerprint);
  1227. #elif defined (ESP32)
  1228. if (certificate) client.setCACert(certificate);
  1229. #endif
  1230. if (!client.connect(host, httpsPort))
  1231. {
  1232. Serial.println("connection failed");
  1233. return;
  1234. }
  1235. Serial.print("requesting URL: ");
  1236. Serial.println(String("https://") + host + path + filename);
  1237. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  1238. "Host: " + host + "\r\n" +
  1239. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  1240. "Connection: close\r\n\r\n");
  1241. Serial.println("request sent");
  1242. while (client.connected())
  1243. {
  1244. String line = client.readStringUntil('\n');
  1245. if (!connection_ok)
  1246. {
  1247. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  1248. if (connection_ok) Serial.println(line);
  1249. //if (!connection_ok) Serial.println(line);
  1250. }
  1251. if (!connection_ok) Serial.println(line);
  1252. //Serial.println(line);
  1253. if (line == "\r")
  1254. {
  1255. Serial.println("headers received");
  1256. break;
  1257. }
  1258. }
  1259. if (!connection_ok) return;
  1260. // Parse BMP header
  1261. if (read16(client) == 0x4D42) // BMP signature
  1262. {
  1263. uint32_t fileSize = read32(client);
  1264. uint32_t creatorBytes = read32(client);
  1265. uint32_t imageOffset = read32(client); // Start of image data
  1266. uint32_t headerSize = read32(client);
  1267. uint32_t width = read32(client);
  1268. uint32_t height = read32(client);
  1269. uint16_t planes = read16(client);
  1270. uint16_t depth = read16(client); // bits per pixel
  1271. uint32_t format = read32(client);
  1272. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  1273. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  1274. {
  1275. Serial.print("File size: "); Serial.println(fileSize);
  1276. Serial.print("Image Offset: "); Serial.println(imageOffset);
  1277. Serial.print("Header size: "); Serial.println(headerSize);
  1278. Serial.print("Bit Depth: "); Serial.println(depth);
  1279. Serial.print("Image size: ");
  1280. Serial.print(width);
  1281. Serial.print('x');
  1282. Serial.println(height);
  1283. // BMP rows are padded (if needed) to 4-byte boundary
  1284. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  1285. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  1286. if (height < 0)
  1287. {
  1288. height = -height;
  1289. flip = false;
  1290. }
  1291. uint16_t w = width;
  1292. uint16_t h = height;
  1293. if ((x + w - 1) >= display.width()) w = display.width() - x;
  1294. if ((y + h - 1) >= display.height()) h = display.height() - y;
  1295. //if (w <= max_row_width) // handle with direct drawing
  1296. {
  1297. valid = true;
  1298. uint8_t bitmask = 0xFF;
  1299. uint8_t bitshift = 8 - depth;
  1300. uint16_t red, green, blue;
  1301. bool whitish, colored;
  1302. if (depth == 1) with_color = false;
  1303. if (depth <= 8)
  1304. {
  1305. if (depth < 8) bitmask >>= depth;
  1306. //bytes_read += skip(client, 54 - bytes_read); //palette is always @ 54
  1307. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  1308. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  1309. {
  1310. blue = client.read();
  1311. green = client.read();
  1312. red = client.read();
  1313. client.read();
  1314. bytes_read += 4;
  1315. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1316. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1317. if (0 == pn % 8) mono_palette_buffer[pn / 8] = 0;
  1318. mono_palette_buffer[pn / 8] |= whitish << pn % 8;
  1319. if (0 == pn % 8) color_palette_buffer[pn / 8] = 0;
  1320. color_palette_buffer[pn / 8] |= colored << pn % 8;
  1321. //Serial.print("0x00"); Serial.print(red, HEX); Serial.print(green, HEX); Serial.print(blue, HEX);
  1322. //Serial.print(" : "); Serial.print(whitish); Serial.print(", "); Serial.println(colored);
  1323. rgb_palette_buffer[pn] = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  1324. }
  1325. }
  1326. uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
  1327. //Serial.print("skip "); Serial.println(rowPosition - bytes_read);
  1328. bytes_read += skip(client, rowPosition - bytes_read);
  1329. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  1330. {
  1331. if (!connection_ok || !(client.connected() || client.available())) break;
  1332. delay(1); // yield() to avoid WDT
  1333. uint32_t in_remain = rowSize;
  1334. uint32_t in_idx = 0;
  1335. uint32_t in_bytes = 0;
  1336. uint8_t in_byte = 0; // for depth <= 8
  1337. uint8_t in_bits = 0; // for depth <= 8
  1338. uint16_t color = GxEPD_WHITE;
  1339. for (uint16_t col = 0; col < w; col++) // for each pixel
  1340. {
  1341. yield();
  1342. if (!connection_ok || !(client.connected() || client.available())) break;
  1343. // Time to read more pixel data?
  1344. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  1345. {
  1346. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  1347. uint32_t got = read8n(client, input_buffer, get);
  1348. while ((got < get) && connection_ok)
  1349. {
  1350. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  1351. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  1352. got += gotmore;
  1353. connection_ok = gotmore > 0;
  1354. }
  1355. in_bytes = got;
  1356. in_remain -= got;
  1357. bytes_read += got;
  1358. }
  1359. if (!connection_ok)
  1360. {
  1361. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  1362. break;
  1363. }
  1364. switch (depth)
  1365. {
  1366. case 24:
  1367. blue = input_buffer[in_idx++];
  1368. green = input_buffer[in_idx++];
  1369. red = input_buffer[in_idx++];
  1370. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1371. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1372. color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  1373. break;
  1374. case 16:
  1375. {
  1376. uint8_t lsb = input_buffer[in_idx++];
  1377. uint8_t msb = input_buffer[in_idx++];
  1378. if (format == 0) // 555
  1379. {
  1380. blue = (lsb & 0x1F) << 3;
  1381. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  1382. red = (msb & 0x7C) << 1;
  1383. color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
  1384. }
  1385. else // 565
  1386. {
  1387. blue = (lsb & 0x1F) << 3;
  1388. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  1389. red = (msb & 0xF8);
  1390. color = (msb << 8) | lsb;
  1391. }
  1392. whitish = with_color ? ((red > 0x80) && (green > 0x80) && (blue > 0x80)) : ((red + green + blue) > 3 * 0x80); // whitish
  1393. colored = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish or yellowish?
  1394. }
  1395. break;
  1396. case 1:
  1397. case 4:
  1398. case 8:
  1399. {
  1400. if (0 == in_bits)
  1401. {
  1402. in_byte = input_buffer[in_idx++];
  1403. in_bits = 8;
  1404. }
  1405. uint16_t pn = (in_byte >> bitshift) & bitmask;
  1406. whitish = mono_palette_buffer[pn / 8] & (0x1 << pn % 8);
  1407. colored = color_palette_buffer[pn / 8] & (0x1 << pn % 8);
  1408. in_byte <<= depth;
  1409. in_bits -= depth;
  1410. color = rgb_palette_buffer[pn];
  1411. }
  1412. break;
  1413. }
  1414. if (with_color && has_multicolors)
  1415. {
  1416. // keep color
  1417. }
  1418. else if (whitish)
  1419. {
  1420. color = GxEPD_WHITE;
  1421. }
  1422. else if (colored && with_color)
  1423. {
  1424. color = GxEPD_COLORED;
  1425. }
  1426. else
  1427. {
  1428. color = GxEPD_BLACK;
  1429. }
  1430. uint16_t yrow = y + (flip ? h - row - 1 : row);
  1431. display.drawPixel(x + col, yrow, color);
  1432. } // end pixel
  1433. } // end line
  1434. }
  1435. Serial.print("bytes read "); Serial.println(bytes_read);
  1436. }
  1437. }
  1438. Serial.print("loaded in "); Serial.print(millis() - startTime); Serial.println(" ms");
  1439. client.stop();
  1440. if (!valid)
  1441. {
  1442. Serial.println("bitmap format not handled.");
  1443. }
  1444. }
  1445. void showBitmapFrom_HTTPS_Buffered(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
  1446. {
  1447. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  1448. display.setFullWindow();
  1449. display.firstPage();
  1450. do
  1451. {
  1452. drawBitmapFrom_HTTPS_ToBuffer(host, path, filename, fingerprint, x, y, with_color, certificate);
  1453. }
  1454. while (display.nextPage());
  1455. }
  1456. uint16_t read16(WiFiClient& client)
  1457. {
  1458. // BMP data is stored little-endian, same as Arduino.
  1459. uint16_t result;
  1460. ((uint8_t *)&result)[0] = client.read(); // LSB
  1461. ((uint8_t *)&result)[1] = client.read(); // MSB
  1462. return result;
  1463. }
  1464. uint32_t read32(WiFiClient& client)
  1465. {
  1466. // BMP data is stored little-endian, same as Arduino.
  1467. uint32_t result;
  1468. ((uint8_t *)&result)[0] = client.read(); // LSB
  1469. ((uint8_t *)&result)[1] = client.read();
  1470. ((uint8_t *)&result)[2] = client.read();
  1471. ((uint8_t *)&result)[3] = client.read(); // MSB
  1472. return result;
  1473. }
  1474. #if USE_BearSSL
  1475. uint32_t skip(BearSSL::WiFiClientSecure& client, int32_t bytes)
  1476. {
  1477. int32_t remain = bytes;
  1478. uint32_t start = millis();
  1479. while ((client.connected() || client.available()) && (remain > 0))
  1480. {
  1481. if (client.available())
  1482. {
  1483. int16_t v = client.read();
  1484. remain--;
  1485. }
  1486. else delay(1);
  1487. if (millis() - start > 2000) break; // don't hang forever
  1488. }
  1489. return bytes - remain;
  1490. }
  1491. uint32_t read8n(BearSSL::WiFiClientSecure& client, uint8_t* buffer, int32_t bytes)
  1492. {
  1493. int32_t remain = bytes;
  1494. uint32_t start = millis();
  1495. while ((client.connected() || client.available()) && (remain > 0))
  1496. {
  1497. if (client.available())
  1498. {
  1499. int16_t v = client.read();
  1500. *buffer++ = uint8_t(v);
  1501. remain--;
  1502. }
  1503. else delay(1);
  1504. if (millis() - start > 2000) break; // don't hang forever
  1505. }
  1506. return bytes - remain;
  1507. }
  1508. #endif
  1509. uint32_t skip(WiFiClient& client, int32_t bytes)
  1510. {
  1511. int32_t remain = bytes;
  1512. uint32_t start = millis();
  1513. while ((client.connected() || client.available()) && (remain > 0))
  1514. {
  1515. if (client.available())
  1516. {
  1517. int16_t v = client.read();
  1518. remain--;
  1519. }
  1520. else delay(1);
  1521. if (millis() - start > 2000) break; // don't hang forever
  1522. }
  1523. return bytes - remain;
  1524. }
  1525. uint32_t read8n(WiFiClient& client, uint8_t* buffer, int32_t bytes)
  1526. {
  1527. int32_t remain = bytes;
  1528. uint32_t start = millis();
  1529. while ((client.connected() || client.available()) && (remain > 0))
  1530. {
  1531. if (client.available())
  1532. {
  1533. int16_t v = client.read();
  1534. *buffer++ = uint8_t(v);
  1535. remain--;
  1536. }
  1537. else delay(1);
  1538. if (millis() - start > 2000) break; // don't hang forever
  1539. }
  1540. return bytes - remain;
  1541. }