Răsfoiți Sursa

Merge pull request #116 from ZinggJM/work_in_progress

Version 1.6.4
ZinggJM 1 an în urmă
părinte
comite
2f28fdd5c5
27 a modificat fișierele cu 527 adăugiri și 12 ștergeri
  1. 4 1
      README.md
  2. 6 0
      examples/GxEPD2_Example/GxEPD2_Example.ino
  3. 3 1
      examples/GxEPD2_Example/GxEPD2_display_selection_new_style.h
  4. 1 0
      examples/GxEPD2_Example/GxEPD2_selection_check.h
  5. 3 1
      examples/GxEPD2_GFX_Example/GxEPD2_display_selection_new_style.h
  6. 1 0
      examples/GxEPD2_GFX_Example/GxEPD2_selection_check.h
  7. 3 1
      examples/GxEPD2_HelloWorld/GxEPD2_display_selection_new_style.h
  8. 1 0
      examples/GxEPD2_HelloWorld/GxEPD2_selection_check.h
  9. 3 1
      examples/GxEPD2_NotPagedExample/GxEPD2_display_selection_new_style.h
  10. 1 0
      examples/GxEPD2_NotPagedExample/GxEPD2_selection_check.h
  11. 3 1
      examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_display_selection_new_style.h
  12. 1 0
      examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_selection_check.h
  13. 3 1
      examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_display_selection_new_style.h
  14. 1 0
      examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_selection_check.h
  15. 3 1
      examples/GxEPD2_SD_Example/GxEPD2_display_selection_new_style.h
  16. 1 0
      examples/GxEPD2_SD_Example/GxEPD2_selection_check.h
  17. 3 1
      examples/GxEPD2_SerialFlash_Example/GxEPD2_display_selection_new_style.h
  18. 1 0
      examples/GxEPD2_SerialFlash_Example/GxEPD2_selection_check.h
  19. 3 1
      examples/GxEPD2_Spiffs_Example/GxEPD2_display_selection_new_style.h
  20. 1 0
      examples/GxEPD2_Spiffs_Example/GxEPD2_selection_check.h
  21. 3 1
      examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_display_selection_new_style.h
  22. 1 0
      examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_selection_check.h
  23. 1 1
      library.properties
  24. 1 0
      src/GxEPD2.h
  25. 3 0
      src/GxEPD2_BW.h
  26. 389 0
      src/gdey/GxEPD2_370_GDEY037T03.cpp
  27. 83 0
      src/gdey/GxEPD2_370_GDEY037T03.h

+ 4 - 1
README.md

@@ -110,6 +110,7 @@
 - GDEY029F51H    2.9" 4-color 168x384, JD79667
 - Waveshare3inch4color 3.0" 4-color 168x400
 - GDEQ031T10     3.1" b/w 240x320, UC8253
+- GDEY037T03     3.7" b/w 240x416, UC8253
 - ED037TC1       3.7" b/w 280x480, SSD1677, Waveshare 3.7"
 - GDEW0371W7     3.7" b/w 240x416, UC8171 (IL0324)
 - GDEW042T2      4.2" b/w 400x300, UC8176 (IL0398)
@@ -164,7 +165,9 @@
 - Let me know about interesting panels that fall into this category.
 - I occasionally buy new panels, but adding support will take as much time as needed.
 
-### Version 1.6.3
+### Version 1.6.4
+- added support for GDEY037T03 3.7" b/w 240x416, UC8253
+#### Version 1.6.3
 - updated GxEPD2_4C.h with WIDTH_VISIBLE (for GDEY0213F51)
 - updated GxEPD2_154_Z90c.cpp powerOff() handling
 - updated powerOff() handling for other 3-color displays

+ 6 - 0
examples/GxEPD2_Example/GxEPD2_Example.ino

@@ -43,6 +43,7 @@
 #include <GxEPD2_4C.h>
 #include <GxEPD2_7C.h>
 #include <Fonts/FreeMonoBold9pt7b.h>
+#include <Fonts/FreeMonoBold12pt7b.h>
 
 // select the display constructor line in one of the following files (old style):
 #include "GxEPD2_display_selection.h"
@@ -184,6 +185,10 @@ void setup()
 #elif (defined(ARDUINO_ARCH_ESP32) && defined(ARDUINO_LOLIN_S2_MINI))
   // SPI.begin(sck, miso, mosi, ss); // preset for remapped pins
   SPI.begin(18, -1, 16, 33); // my LOLIN ESP32 S2 mini connection
+#endif
+#if defined(ESP32) && defined(ARDUINO_ESP32S3_DEV) && true // CrowPanel
+  pinMode(7, OUTPUT);
+  digitalWrite(7, HIGH); // enable power to the panel
 #endif
   //display.init(115200); // default 10ms reset pulse, e.g. for bare panels with DESPI-C02
   display.init(115200, true, 2, false); // USE THIS for Waveshare boards with "clever" reset circuit, 2ms reset pulse
@@ -210,6 +215,7 @@ void setup()
   //helloValue(123.9, 1);
   //delay(1000);
   showFont("FreeMonoBold9pt7b", &FreeMonoBold9pt7b);
+  //showFont("FreeMonoBold12pt7b", &FreeMonoBold12pt7b);
   delay(1000);
   if (display.epd2.WIDTH < 104)
   {

+ 3 - 1
examples/GxEPD2_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_GFX_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_GFX_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_HelloWorld/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_HelloWorld/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_NotPagedExample/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_NotPagedExample/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_SD_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_SD_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_SerialFlash_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_SerialFlash_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_Spiffs_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_Spiffs_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 3 - 1
examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_display_selection_new_style.h

@@ -58,8 +58,9 @@
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T94 // GDEY029T94 128x296, SSD1680, (FPC-A005 20.06.15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_290_GDEY029T71H // GDEY029T71H 168x384, SSD1685, (FPC-H004 22.03.24)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_310_GDEQ031T10 // GDEQ031T10 240x320, UC8253, (no inking, backside mark KEGMO 3100)
-//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
+//#define GxEPD2_DRIVER_CLASS GxEPD2_370_GDEY037T03 // GDEY037T03 240x416, UC8253, (FPC-F002, hidden on CrowPanel)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_370_TC1 // ED037TC1  280x480, SSD1677, (ICA-FU-20 ichia 2029), Waveshare 3.7"
+//#define GxEPD2_DRIVER_CLASS GxEPD2_371     // GDEW0371W7  240x416, UC8171 (IL0324), (missing)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420     // GDEW042T2   400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_M01 // GDEW042M01  400x300, UC8176 (IL0398), (WFT042CZ15)
 //#define GxEPD2_DRIVER_CLASS GxEPD2_420_GDEY042T81 // GDEY042T81 400x300, SSD1683 (no inking)
@@ -215,6 +216,7 @@ GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> displ
 #elif defined(ARDUINO_ESP32S3_DEV)
 // ESP32E6-E01 : only 50 pin FPC works on actual version (11.1.2025)
 GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS*/ 2, /*DC=*/ 3, /*RST=*/ 4, /*BUSY=*/ 5)); // Good Display ESP32E6-E01 board
+//GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 45, /*DC=*/ 46, /*RST=*/ 47, /*BUSY=*/ 48)); // CrowPanel wiring
 #else
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13)); // Good Display ESP32 Development Kit ESP32-L
 //GxEPD2_DISPLAY_CLASS<GxEPD2_DRIVER_CLASS, MAX_HEIGHT(GxEPD2_DRIVER_CLASS)> display(GxEPD2_DRIVER_CLASS(/*CS=*/ 27, /*DC=*/ 14, /*RST=*/ 12, /*BUSY=*/ 13, /*CS2=*/ 4)); // for GDEM1085T51 with ESP32-L

+ 1 - 0
examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_selection_check.h

@@ -51,6 +51,7 @@
 #define GxEPD2_310_GDEQ031T10_IS_BW true
 #define GxEPD2_371_IS_BW true
 #define GxEPD2_370_TC1_IS_BW true
+#define GxEPD2_370_GDEY037T03_IS_BW true
 #define GxEPD2_420_IS_BW true
 #define GxEPD2_420_M01_IS_BW true
 #define GxEPD2_420_GDEY042T81_IS_BW true

+ 1 - 1
library.properties

@@ -1,5 +1,5 @@
 name=GxEPD2
-version=1.6.3
+version=1.6.4
 author=Jean-Marc Zingg
 maintainer=Jean-Marc Zingg
 sentence=Arduino Display Library for SPI E-Paper displays from Dalian Good Display and Waveshare. 

+ 1 - 0
src/GxEPD2.h

@@ -69,6 +69,7 @@ class GxEPD2
       GDEY027T91,
       GDEQ031T10,
       ED037TC1,
+      GDEY037T03,
       GDEW0371W7, Waveshare_3_7_bw = GDEW0371W7,
       GDEW042T2,  Waveshare_4_2_bw = GDEW042T2,
       GDEW042M01,

+ 3 - 0
src/GxEPD2_BW.h

@@ -157,6 +157,9 @@
 #if __has_include("epd/GxEPD2_370_TC1.h")
 #include "epd/GxEPD2_370_TC1.h"
 #endif
+#if __has_include("gdey/GxEPD2_370_GDEY037T03.h")
+#include "gdey/GxEPD2_370_GDEY037T03.h"
+#endif
 #if __has_include("epd/GxEPD2_420.h")
 #include "epd/GxEPD2_420.h"
 #endif

+ 389 - 0
src/gdey/GxEPD2_370_GDEY037T03.cpp

@@ -0,0 +1,389 @@
+// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
+// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
+//
+// based on Demo Example from Good Display: https://www.good-display.com/product/426.html
+// Panel: GDEY037T03 : https://www.good-display.com/product/437.html
+// Controller: UC8253 : https://v4.cecdn.yun300.cn/100001_1909185148/UC8253.pdf
+//
+// Author: Jean-Marc Zingg
+//
+// Version: see library.properties
+//
+// Library: https://github.com/ZinggJM/GxEPD2
+
+#include "GxEPD2_370_GDEY037T03.h"
+
+GxEPD2_370_GDEY037T03::GxEPD2_370_GDEY037T03(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
+  GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
+{
+}
+
+void GxEPD2_370_GDEY037T03::clearScreen(uint8_t value)
+{
+  // full refresh needed for all cases (previous != screen)
+  _writeScreenBuffer(0x10, value); // set previous
+  _writeScreenBuffer(0x13, value); // set current
+  refresh(false); // full refresh
+  _initial_write = false;
+}
+
+void GxEPD2_370_GDEY037T03::writeScreenBuffer(uint8_t value)
+{
+  if (_initial_write) return clearScreen(value);
+  _writeScreenBuffer(0x13, value); // set current
+}
+
+void GxEPD2_370_GDEY037T03::writeScreenBufferAgain(uint8_t value)
+{
+  _writeScreenBuffer(0x10, value); // set previous
+  //_writeScreenBuffer(0x13, value); // set current, not needed
+}
+
+void GxEPD2_370_GDEY037T03::_writeScreenBuffer(uint8_t command, uint8_t value)
+{
+  if (!_init_display_done) _InitDisplay();
+  _writeCommand(command);
+  _startTransfer();
+  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+  {
+    _transfer(value);
+  }
+  _endTransfer();
+}
+
+void GxEPD2_370_GDEY037T03::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  _writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm);
+}
+
+void GxEPD2_370_GDEY037T03::writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  _writeImage(0x10, bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
+  _writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm); // set current
+}
+
+void GxEPD2_370_GDEY037T03::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  _writeImage(0x10, bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
+  //_writeImage(0x13, bitmap, x, y, w, h, invert, mirror_y, pgm); // set current, not needed
+}
+
+void GxEPD2_370_GDEY037T03::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  delay(1); // yield() to avoid WDT on ESP8266 and ESP32
+  uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
+  x -= x % 8; // byte boundary
+  w = wb * 8; // byte boundary
+  int16_t x1 = x < 0 ? 0 : x; // limit
+  int16_t y1 = y < 0 ? 0 : y; // limit
+  int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
+  int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
+  int16_t dx = x1 - x;
+  int16_t dy = y1 - y;
+  w1 -= dx;
+  h1 -= dy;
+  if ((w1 <= 0) || (h1 <= 0)) return;
+  if (!_init_display_done) _InitDisplay();
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(x1, y1, w1, h1);
+  _writeCommand(command);
+  _startTransfer();
+  for (int16_t i = 0; i < h1; i++)
+  {
+    for (int16_t j = 0; j < w1 / 8; j++)
+    {
+      uint8_t data;
+      // use wb, h of bitmap for index!
+      uint16_t idx = mirror_y ? j + dx / 8 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 8 + uint16_t(i + dy) * wb;
+      if (pgm)
+      {
+#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
+        data = pgm_read_byte(&bitmap[idx]);
+#else
+        data = bitmap[idx];
+#endif
+      }
+      else
+      {
+        data = bitmap[idx];
+      }
+      if (invert) data = ~data;
+      _transfer(data);
+    }
+  }
+  _endTransfer();
+  _writeCommand(0x92); // partial out
+  delay(1); // yield() to avoid WDT on ESP8266 and ESP32
+}
+
+void GxEPD2_370_GDEY037T03::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  _writeImagePart(0x13, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
+}
+
+void GxEPD2_370_GDEY037T03::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  _writeImagePart(0x10, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); // set previous
+  //_writeImagePart(0x13, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm); // set current, not needed
+}
+
+void GxEPD2_370_GDEY037T03::_writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  delay(1); // yield() to avoid WDT on ESP8266 and ESP32
+  if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
+  if ((x_part < 0) || (x_part >= w_bitmap)) return;
+  if ((y_part < 0) || (y_part >= h_bitmap)) return;
+  uint16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
+  x_part -= x_part % 8; // byte boundary
+  w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
+  h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
+  x -= x % 8; // byte boundary
+  w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
+  int16_t x1 = x < 0 ? 0 : x; // limit
+  int16_t y1 = y < 0 ? 0 : y; // limit
+  int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
+  int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
+  int16_t dx = x1 - x;
+  int16_t dy = y1 - y;
+  w1 -= dx;
+  h1 -= dy;
+  if ((w1 <= 0) || (h1 <= 0)) return;
+  if (!_init_display_done) _InitDisplay();
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(x1, y1, w1, h1);
+  _writeCommand(command);
+  _startTransfer();
+  for (int16_t i = 0; i < h1; i++)
+  {
+    for (int16_t j = 0; j < w1 / 8; j++)
+    {
+      uint8_t data;
+      // use wb_bitmap, h_bitmap of bitmap for index!
+      uint16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + uint16_t((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + uint16_t(y_part + i + dy) * wb_bitmap;
+      if (pgm)
+      {
+#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
+        data = pgm_read_byte(&bitmap[idx]);
+#else
+        data = bitmap[idx];
+#endif
+      }
+      else
+      {
+        data = bitmap[idx];
+      }
+      if (invert) data = ~data;
+      _transfer(data);
+    }
+  }
+  _endTransfer();
+  _writeCommand(0x92); // partial out
+  delay(1); // yield() to avoid WDT on ESP8266 and ESP32
+}
+
+void GxEPD2_370_GDEY037T03::writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (black)
+  {
+    writeImage(black, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (black)
+  {
+    writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (data1)
+  {
+    writeImage(data1, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
+  refresh(x, y, w, h);
+  writeImageAgain(bitmap, x, y, w, h, invert, mirror_y, pgm);
+}
+
+void GxEPD2_370_GDEY037T03::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
+  refresh(x, y, w, h);
+  writeImagePartAgain(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
+}
+
+void GxEPD2_370_GDEY037T03::drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (black)
+  {
+    drawImage(black, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (black)
+  {
+    drawImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+{
+  if (data1)
+  {
+    drawImage(data1, x, y, w, h, invert, mirror_y, pgm);
+  }
+}
+
+void GxEPD2_370_GDEY037T03::refresh(bool partial_update_mode)
+{
+  if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
+  else
+  {
+    _Update_Full();
+    _initial_refresh = false; // initial full update done
+  }
+}
+
+void GxEPD2_370_GDEY037T03::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
+{
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
+  // intersection with screen
+  int16_t w1 = x < 0 ? w + x : w; // reduce
+  int16_t h1 = y < 0 ? h + y : h; // reduce
+  int16_t x1 = x < 0 ? 0 : x; // limit
+  int16_t y1 = y < 0 ? 0 : y; // limit
+  w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit
+  h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit
+  if ((w1 <= 0) || (h1 <= 0)) return;
+  // make x1, w1 multiple of 8
+  w1 += x1 % 8;
+  if (w1 % 8 > 0) w1 += 8 - w1 % 8;
+  x1 -= x1 % 8;
+  if (usePartialUpdateWindow) _writeCommand(0x91); // partial in
+  _setPartialRamArea(x1, y1, w1, h1);
+  _Update_Part();
+  if (usePartialUpdateWindow) _writeCommand(0x92); // partial out
+}
+
+void GxEPD2_370_GDEY037T03::powerOff(void)
+{
+  _PowerOff();
+}
+
+void GxEPD2_370_GDEY037T03::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+    _init_display_done = false;
+  }
+}
+
+void GxEPD2_370_GDEY037T03::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
+{
+  uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte)
+  uint16_t ye = y + h - 1;
+  x &= 0xFFF8; // byte boundary
+  _writeCommand(0x90); // partial window
+  _writeData(x);
+  _writeData(xe);
+  _writeData(y / 256);
+  _writeData(y % 256);
+  _writeData(ye / 256);
+  _writeData(ye % 256);
+  _writeData(0x01);
+}
+
+void GxEPD2_370_GDEY037T03::_PowerOn()
+{
+  if (!_power_is_on)
+  {
+    _writeCommand(0x04);
+    _waitWhileBusy("_PowerOn", power_on_time);
+  }
+  _power_is_on = true;
+}
+
+void GxEPD2_370_GDEY037T03::_PowerOff()
+{
+  if (_power_is_on)
+  {
+    _writeCommand(0x02); // power off
+    _waitWhileBusy("_PowerOff", power_off_time);
+  }
+  _power_is_on = false;
+}
+
+void GxEPD2_370_GDEY037T03::_InitDisplay()
+{
+  if (_hibernating) _reset();
+  else
+  {
+    _writeCommand(0x00); // PANEL SETTING
+    _writeData(0x1e);    // soft reset
+    _writeData(0x0d);
+    delay(1);
+  }
+  _power_is_on = false;
+  _writeCommand(0x00); // PANEL SETTING
+  _writeData(0x1f);    // KW: 3f, KWR: 2F, BWROTP: 0f, BWOTP: 1f
+  _writeData(0x0d);
+  _init_display_done = true;
+}
+
+void GxEPD2_370_GDEY037T03::_Update_Full()
+{
+  if (useFastFullUpdate)
+  {
+    _writeCommand(0xE0); // Cascade Setting (CCSET)
+    _writeData(0x02);    // TSFIX
+    _writeCommand(0xE5); // Force Temperature (TSSET)
+    //_writeData(0x5F);    // 1486000us
+    _writeData(0x5A);    // 1005000us, less greyish
+  }
+  _writeCommand(0x50);
+  _writeData(0x97);
+  _PowerOn();
+  _writeCommand(0x12); //display refresh
+  _waitWhileBusy("_Update_Full", full_refresh_time);
+  _PowerOff();
+  if (useFastFullUpdate) _InitDisplay(); // undo TSFIX
+}
+
+void GxEPD2_370_GDEY037T03::_Update_Part()
+{
+  if (hasFastPartialUpdate)
+  {
+    _writeCommand(0xE0); // Cascade Setting (CCSET)
+    _writeData(0x02);    // TSFIX
+    _writeCommand(0xE5); // Force Temperature (TSSET)
+    _writeData(0x6E);
+  }
+  _writeCommand(0x50);
+  _writeData(0xD7);
+  _PowerOn();
+  _writeCommand(0x12); //display refresh
+  _waitWhileBusy("_Update_Part", partial_refresh_time);
+  _PowerOff();
+  if (hasFastPartialUpdate) _InitDisplay(); // undo TSFIX
+}

+ 83 - 0
src/gdey/GxEPD2_370_GDEY037T03.h

@@ -0,0 +1,83 @@
+// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
+// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
+//
+// based on Demo Example from Good Display: https://www.good-display.com/product/426.html
+// Panel: GDEY037T03 : https://www.good-display.com/product/437.html
+// Controller: UC8253 : https://v4.cecdn.yun300.cn/100001_1909185148/UC8253.pdf
+//
+// Author: Jean-Marc Zingg
+//
+// Version: see library.properties
+//
+// Library: https://github.com/ZinggJM/GxEPD2
+
+#ifndef _GxEPD2_370_GDEY037T03_H_
+#define _GxEPD2_370_GDEY037T03_H_
+
+#include "../GxEPD2_EPD.h"
+
+class GxEPD2_370_GDEY037T03 : public GxEPD2_EPD
+{
+  public:
+    // attributes
+    static const uint16_t WIDTH = 240;
+    static const uint16_t WIDTH_VISIBLE = WIDTH;
+    static const uint16_t HEIGHT = 416;
+    static const GxEPD2::Panel panel = GxEPD2::GDEY037T03;
+    static const bool hasColor = false;
+    static const bool hasPartialUpdate = true;
+    static const bool usePartialUpdateWindow = true; // set false for better image
+    static const bool hasFastPartialUpdate = true; // set this false to force full refresh always
+    static const bool useFastFullUpdate = true; // set false for extended (low) temperature range, 1005000us vs 2950000us
+    static const uint16_t power_on_time = 50; // ms, e.g. 46000us
+    static const uint16_t power_off_time = 50; // ms, e.g. 40000us
+    static const uint16_t full_refresh_time = 1500; // ms, e.g. 1005000us or 1486000us
+    static const uint16_t partial_refresh_time = 350; // ms, e.g. 343000us
+    // constructor
+    GxEPD2_370_GDEY037T03(int16_t cs, int16_t dc, int16_t rst, int16_t busy);
+    // methods (virtual)
+    //  Support for Bitmaps (Sprites) to Controller Buffer and to Screen
+    void clearScreen(uint8_t value = 0xFF); // init controller memory and screen (default white)
+    void writeScreenBuffer(uint8_t value = 0xFF); // init controller memory (default white)
+    void writeScreenBufferAgain(uint8_t value = 0xFF); // init previous buffer controller memory (default white)
+    // write to controller memory, without screen refresh; x and w should be multiple of 8
+    void writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void writeImageForFullRefresh(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                        int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void writeImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                        int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    // for differential update: set current and previous buffers equal (for fast partial update to work correctly)
+    void writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                             int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    // write sprite of native data to controller memory, without screen refresh; x and w should be multiple of 8
+    void writeNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    // write to controller memory, with screen refresh; x and w should be multiple of 8
+    void drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                       int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void drawImage(const uint8_t* black, const uint8_t* color, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                       int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    // write sprite of native data to controller memory, with screen refresh; x and w should be multiple of 8
+    void drawNative(const uint8_t* data1, const uint8_t* data2, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void refresh(bool partial_update_mode = false); // screen refresh from controller memory to full screen
+    void refresh(int16_t x, int16_t y, int16_t w, int16_t h); // screen refresh from controller memory, partial screen
+    void powerOff(); // turns off generation of panel driving voltages, avoids screen fading over time
+    void hibernate(); // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
+  private:
+    void _writeScreenBuffer(uint8_t command, uint8_t value);
+    void _writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void _writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
+                         int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
+    void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
+    void _PowerOn();
+    void _PowerOff();
+    void _InitDisplay();
+    void _Update_Full();
+    void _Update_Part();
+};
+
+#endif