Selaa lähdekoodia

Version 1.1.2

added support for GDEW029T5
ZinggJM 7 vuotta sitten
vanhempi
sitoutus
dbc8ffb6ce
47 muutettua tiedostoa jossa 1273 lisäystä ja 590 poistoa
  1. 5 0
      ConnectingHardware.md
  2. BIN
      MyEPDs_UpdateInfos.pdf
  3. 7 1
      README.md
  4. 180 39
      examples/GxEPD2_Example/GxEPD2_Example.ino
  5. 7 4
      examples/GxEPD2_Example/GxEPD2_boards_added.h
  6. 1 1
      library.properties
  7. 1 0
      src/GxEPD2.h
  8. 30 16
      src/GxEPD2_3C.h
  9. 32 16
      src/GxEPD2_BW.h
  10. 1 0
      src/GxEPD2_EPD.cpp
  11. 2 0
      src/GxEPD2_EPD.h
  12. 7 0
      src/GxEPD2_GFX.h
  13. 24 5
      src/epd/GxEPD2_154.cpp
  14. 5 4
      src/epd/GxEPD2_154.h
  15. 23 4
      src/epd/GxEPD2_213.cpp
  16. 5 4
      src/epd/GxEPD2_213.h
  17. 23 3
      src/epd/GxEPD2_213_flex.cpp
  18. 5 4
      src/epd/GxEPD2_213_flex.h
  19. 22 0
      src/epd/GxEPD2_270.cpp
  20. 4 2
      src/epd/GxEPD2_270.h
  21. 23 4
      src/epd/GxEPD2_290.cpp
  22. 5 4
      src/epd/GxEPD2_290.h
  23. 335 0
      src/epd/GxEPD2_290_T5.cpp
  24. 67 0
      src/epd/GxEPD2_290_T5.h
  25. 23 3
      src/epd/GxEPD2_420.cpp
  26. 5 4
      src/epd/GxEPD2_420.h
  27. 22 8
      src/epd/GxEPD2_583.cpp
  28. 5 4
      src/epd/GxEPD2_583.h
  29. 22 8
      src/epd/GxEPD2_750.cpp
  30. 5 4
      src/epd/GxEPD2_750.h
  31. 112 61
      src/epd/WaveTables.h
  32. 23 11
      src/epd3c/GxEPD2_154c.cpp
  33. 5 4
      src/epd3c/GxEPD2_154c.h
  34. 22 11
      src/epd3c/GxEPD2_213c.cpp
  35. 5 4
      src/epd3c/GxEPD2_213c.h
  36. 22 11
      src/epd3c/GxEPD2_270c.cpp
  37. 5 4
      src/epd3c/GxEPD2_270c.h
  38. 22 11
      src/epd3c/GxEPD2_290c.cpp
  39. 5 4
      src/epd3c/GxEPD2_290c.h
  40. 24 5
      src/epd3c/GxEPD2_420c.cpp
  41. 5 4
      src/epd3c/GxEPD2_420c.h
  42. 23 11
      src/epd3c/GxEPD2_583c.cpp
  43. 5 4
      src/epd3c/GxEPD2_583c.h
  44. 23 11
      src/epd3c/GxEPD2_750c.cpp
  45. 5 4
      src/epd3c/GxEPD2_750c.h
  46. 0 288
      src/epd3c/WaveTables.h
  47. 71 0
      src/epd3c/WaveTables3c.h

+ 5 - 0
ConnectingHardware.md

@@ -10,6 +10,7 @@
 - these displays are for 3.3V supply and 3.3V data lines
 - never connect data lines directly to 5V Arduino data pins, use e.g. 4k7/10k resistor divider
 - series resistor only is not enough for reliable operation (back-feed effect through protection diodes)
+- 4k7/10k resistor divider may not work with flat cable extensions or Waveshare 4.2 board, use level converter then
 - do not forget to connect GND
 
 ## mapping suggestions
@@ -39,6 +40,10 @@
 #### mapping suggestion for Arduino MEGA
 - BUSY -> 7, RST -> 9, DC -> 8, CS-> 53, CLK -> 52, DIN -> 51
 
+#### mapping suggestion for Arduino DUE
+- BUSY -> 7, RST -> 9, DC -> 8, CS-> 77, CLK -> 76, DIN -> 75
+- SPI pins are on 6 pin 2x3 SPI header
+
 ## connection scheme for (discontinued) DESTM32-S2 connection board for e-paper panels:
 
 ```

BIN
MyEPDs_UpdateInfos.pdf


+ 7 - 1
README.md

@@ -10,6 +10,7 @@
 - these displays are for 3.3V supply and 3.3V data lines
 - never connect data lines directly to 5V Arduino data pins, use e.g. 4k7/10k resistor divider
 - series resistor only is not enough for reliable operation (back-feed effect through protection diodes)
+- 4k7/10k resistor divider may not work with flat cable extensions or Waveshare 4.2 board, use level converter then
 - do not forget to connect GND
 
 ### Paged Drawing, Picture Loop
@@ -37,7 +38,12 @@
 - Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
 - Good Dispay ePaper for Arduino : https://forum.arduino.cc/index.php?topic=436411.0
 
-### Version 1.1.1
+### Version 1.1.2
+- added support for GDEW029T5
+- fixed (added) clipping for partial window
+- fixed (added) powerOff() after full update (partial update keeps power on)
+- added hibernate() for minimum power use by displays that support it
+#### Version 1.1.1
 - 2.7" b/w GDEW027W3 with fast partial update support, based on new demo code wavetable
 - mapping suggestion added for Arduino MEGA
 - NOTE: use voltage divider resistors for 5V Arduinos, series resistor is not reliable enough

+ 180 - 39
examples/GxEPD2_Example/GxEPD2_Example.ino

@@ -22,6 +22,8 @@
 // mapping of Waveshare e-Paper ESP8266 Driver Board
 // BUSY -> GPIO16, RST -> GPIO5, DC -> GPIO4, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
 
+// NOTE for ESP8266: using SS (GPIO15) for CS may cause boot mode problems, use different pin in case
+
 // mapping suggestion for ESP32, e.g. LOLIN32, see .../variants/.../pins_arduino.h for your board
 // NOTE: there are variants with different pins for SPI ! CHECK SPI PINS OF YOUR BOARD
 // BUSY -> 4, RST -> 16, DC -> 17, CS -> SS(5), CLK -> SCK(18), DIN -> MOSI(23), GND -> GND, 3.3V -> 3.3V
@@ -47,8 +49,9 @@
 // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
 //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
-//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
+//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
+//GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 // can use only half buffer size
@@ -62,15 +65,16 @@
 // can use only half buffer size
 //GxEPD2_3C<GxEPD2_420c, GxEPD2_420c::HEIGHT / 2> display(GxEPD2_420c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 // can use only quarter buffer size
-//GxEPD2_3C<GxEPD2_583c, GxEPD2_583c::HEIGHT / 4> display(GxEPD2_583c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
+//GxEPD2_3C < GxEPD2_583c, GxEPD2_583c::HEIGHT / 4 > display(GxEPD2_583c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 //GxEPD2_3C<GxEPD2_750c, GxEPD2_750c::HEIGHT / 4> display(GxEPD2_750c(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4));
 
 // ***** for mapping of Waveshare e-Paper ESP8266 Driver Board *****
 // select one , can use full buffer size (full HEIGHT)
 //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
 //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
-//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
+//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
+//GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
 //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=15*/ SS, /*DC=4*/ 4, /*RST=5*/ 5, /*BUSY=16*/ 16));
 // can use only half buffer size
@@ -92,8 +96,9 @@
 // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
 //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
 //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
-//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
+//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
+//GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
 //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
 //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));
@@ -112,8 +117,9 @@
 // select one and adapt to your mapping
 //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
 //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
-//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
+//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
+//GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
 //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
 //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=4*/ SS, /*DC=*/ 3, /*RST=*/ 2, /*BUSY=*/ 1));
@@ -135,8 +141,9 @@
 // select one and adapt to your mapping
 //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
-//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
+//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
+//GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
@@ -218,6 +225,7 @@ void setup()
   //showBox(16, 16, 48, 32, false);
   //showBox(16, 56, 48, 32, true);
   display.powerOff();
+  deepSleepTest();
   Serial.println("setup done");
 }
 
@@ -225,22 +233,74 @@ void loop()
 {
 }
 
+const char HelloWorld[] = "Hello World!";
+const char HelloArduino[] = "Hello Arduino!";
+const char HelloEpaper[] = "Hello E-Paper!";
+
 void helloWorld()
 {
   //Serial.println("helloWorld");
   display.setRotation(1);
   display.setFont(&FreeMonoBold9pt7b);
   display.setTextColor(GxEPD_BLACK);
-  uint16_t x = (display.width() - 160) / 2;
-  uint16_t y = display.height() / 2;
+  int16_t tbx, tby; uint16_t tbw, tbh;
+  display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t x = (display.width() - tbw) / 2;
+  uint16_t y = (display.height() + tbh) / 2; // y is base line!
   display.setFullWindow();
   display.firstPage();
   do
   {
     display.fillScreen(GxEPD_WHITE);
     display.setCursor(x, y);
-    display.println("Hello World!");
+    display.print(HelloWorld);
+  }
+  while (display.nextPage());
+  //Serial.println("helloWorld done");
+}
+
+void helloWorldForDummies()
+{
+  //Serial.println("helloWorld");
+  const char text[] = "Hello World!";
+  // most e-papers have width < height (portrait) as native orientation, especially the small ones
+  // in GxEPD2 rotation 0 is used for native orientation (most TFT libraries use 0 fix for portrait orientation)
+  // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
+  display.setRotation(1);
+  // select a suitable font in Adafruit_GFX
+  display.setFont(&FreeMonoBold9pt7b);
+  // on e-papers black on white is more pleasant to read
+  display.setTextColor(GxEPD_BLACK);
+  // Adafruit_GFX has a handy method getTextBounds() to determine the boundary box for a text for the actual font
+  int16_t tbx, tby; uint16_t tbw, tbh; // boundary box window
+  display.getTextBounds(text, 0, 0, &tbx, &tby, &tbw, &tbh); // it works for 0, 0, fortunately (negative tby!)
+  // center the boundary box of the text
+  uint16_t x = (display.width() - tbw) / 2;
+  uint16_t y = (display.height() + tbh) / 2; // y is base line!
+  // full window mode is the initial mode, set it anyway
+  display.setFullWindow();
+  // here we use paged drawing, even if the processor has enough RAM for full buffer
+  // so this can be used with any supported processor board.
+  // the cost in code overhead and execution time penalty is marginal
+  // tell the graphics class to use paged drawing mode
+  display.firstPage();
+  do
+  {
+    // this part of code is executed multiple times, as many as needed,
+    // in case of full buffer it is executed once
+    // IMPORTANT: each iteration needs to draw the same, to avoid strange effects
+    // use a copy of values that might change, don't read e.g. from analog or pins in the loop!
+    display.fillScreen(GxEPD_WHITE); // set the background to white (fill the buffer with value for white)
+    display.setCursor(x, y); // set the postition to start printing text
+    display.print(text); // print some text
+    // end of part executed multiple times
   }
+  // tell the graphics class to transfer the buffer content (page) to the controller buffer
+  // the graphics class will command the controller to refresh to the screen when the last page has been transferred
+  // returns true if more pages need be drawn and transferred
+  // returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
+  // returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
+  // (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
   while (display.nextPage());
   //Serial.println("helloWorld done");
 }
@@ -248,36 +308,52 @@ void helloWorld()
 void helloFullScreenPartialMode()
 {
   //Serial.println("helloFullScreenPartialMode");
+  const char fullscreen[] = "full screen update";
+  const char fpm[] = "fast partial mode";
+  const char spm[] = "slow partial mode";
+  const char npm[] = "no partial mode";
   display.setPartialWindow(0, 0, display.width(), display.height());
   display.setRotation(1);
   display.setFont(&FreeMonoBold9pt7b);
   display.setTextColor(GxEPD_BLACK);
+  const char* updatemode;
+  if (display.epd2.hasFastPartialUpdate)
+  {
+    updatemode = fpm;
+  }
+  else if (display.epd2.hasPartialUpdate)
+  {
+    updatemode = spm;
+  }
+  else
+  {
+    updatemode = npm;
+  }
+  // do this outside of the loop
+  int16_t tbx, tby; uint16_t tbw, tbh;
+  // center update text
+  display.getTextBounds(fullscreen, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t utx = (display.width() - tbw) / 2;
+  // center update mode
+  display.getTextBounds(updatemode, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t umx = (display.width() - tbw) / 2;
+  // center HelloWorld
+  display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t hwx = (display.width() - tbw) / 2;
+  uint16_t y;
   display.firstPage();
   do
   {
-    uint16_t x = (display.width() - 160) / 2;
-    uint16_t y = display.height() / 2;
     display.fillScreen(GxEPD_WHITE);
-    display.setCursor(x, y);
-    display.println("Hello World!");
-    y = display.height() / 4;
-    display.setCursor(x, y);
-    display.println("full screen");
-    y = display.height() * 3 / 4;
-    if (display.width() <= 200) x = 0;
-    display.setCursor(x, y);
-    if (display.epd2.hasFastPartialUpdate)
-    {
-      display.println("fast partial mode");
-    }
-    else if (display.epd2.hasPartialUpdate)
-    {
-      display.println("slow partial mode");
-    }
-    else
-    {
-      display.println("no partial mode");
-    }
+    y = (display.height() + tbh) / 2; // y is base line!
+    display.setCursor(hwx, y);
+    display.print(HelloWorld);
+    y = display.height() / 4 + tbh / 2; // y is base line!
+    display.setCursor(utx, y);
+    display.print(fullscreen);
+    y = display.height() * 3 / 4 + tbh / 2; // y is base line!
+    display.setCursor(umx, y);
+    display.print(updatemode);
   }
   while (display.nextPage());
   //Serial.println("helloFullScreenPartialMode done");
@@ -289,15 +365,23 @@ void helloArduino()
   display.setRotation(1);
   display.setFont(&FreeMonoBold9pt7b);
   display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
-  uint16_t x = (display.width() - 160) / 2;
-  uint16_t y = display.height() / 4;
-  display.setPartialWindow(0, y - 14, display.width(), 20);
+  int16_t tbx, tby; uint16_t tbw, tbh;
+  // align with centered HelloWorld
+  display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t x = (display.width() - tbw) / 2;
+  // height might be different
+  display.getTextBounds(HelloArduino, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t y = display.height() / 4 + tbh / 2; // y is base line!
+  // make the window big enough to cover (overwrite) descenders of previous text
+  uint16_t wh = FreeMonoBold9pt7b.yAdvance;
+  display.setPartialWindow(0, y - tbh, display.width(), wh);
   display.firstPage();
   do
   {
     display.fillScreen(GxEPD_WHITE);
+    //display.drawRect(x, y - tbh, tbw, tbh, GxEPD_BLACK);
     display.setCursor(x, y);
-    display.println("Hello Arduino!");
+    display.print(HelloArduino);
   }
   while (display.nextPage());
   delay(1000);
@@ -310,20 +394,77 @@ void helloEpaper()
   display.setRotation(1);
   display.setFont(&FreeMonoBold9pt7b);
   display.setTextColor(display.epd2.hasColor ? GxEPD_RED : GxEPD_BLACK);
-  uint16_t x = (display.width() - 160) / 2;
-  uint16_t y = display.height() * 3 / 4;
-  display.setPartialWindow(0, y - 14, display.width(), 20);
+  int16_t tbx, tby; uint16_t tbw, tbh;
+  // align with centered HelloWorld
+  display.getTextBounds(HelloWorld, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t x = (display.width() - tbw) / 2;
+  // height might be different
+  display.getTextBounds(HelloEpaper, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t y = display.height() * 3 / 4 + tbh / 2; // y is base line!
+  // make the window big enough to cover (overwrite) descenders of previous text
+  uint16_t wh = FreeMonoBold9pt7b.yAdvance;
+  display.setPartialWindow(0, y - tbh, display.width(), wh);
   display.firstPage();
   do
   {
     display.fillScreen(GxEPD_WHITE);
     display.setCursor(x, y);
-    display.println("Hello E-Paper!");
+    display.println(HelloEpaper);
   }
   while (display.nextPage());
   //Serial.println("helloEpaper done");
 }
 
+void deepSleepTest()
+{
+  //Serial.println("deepSleepTest");
+  const char hibernating[] = "hibernating ...";
+  const char wokeup[] = "woke up from deep sleep";
+  const char again[] = "hibernating again ...";
+  display.setRotation(1);
+  display.setFont(&FreeMonoBold9pt7b);
+  display.setTextColor(GxEPD_BLACK);
+  int16_t tbx, tby; uint16_t tbw, tbh;
+  // center text
+  display.getTextBounds(hibernating, 0, 0, &tbx, &tby, &tbw, &tbh);
+  uint16_t x = (display.width() - tbw) / 2;
+  uint16_t y = (display.height() + tbh) / 2; // y is base line!
+  display.setFullWindow();
+  display.firstPage();
+  do
+  {
+    display.fillScreen(GxEPD_WHITE);
+    display.setCursor(x, y);
+    display.print(hibernating);
+  }
+  while (display.nextPage());
+  display.hibernate();
+  delay(5000);
+  display.getTextBounds(wokeup, 0, 0, &tbx, &tby, &tbw, &tbh);
+  x = (display.width() - tbw) / 2;
+  display.firstPage();
+  do
+  {
+    display.fillScreen(GxEPD_WHITE);
+    display.setCursor(x, y);
+    display.print(wokeup);
+  }
+  while (display.nextPage());
+  delay(5000);
+  display.getTextBounds(again, 0, 0, &tbx, &tby, &tbw, &tbh);
+  x = (display.width() - tbw) / 2;
+  display.firstPage();
+  do
+  {
+    display.fillScreen(GxEPD_WHITE);
+    display.setCursor(x, y);
+    display.println(again);
+  }
+  while (display.nextPage());
+  display.hibernate();
+  //Serial.println("deepSleepTest done");
+}
+
 void showBox(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool partial)
 {
   //Serial.println("showBox");

+ 7 - 4
examples/GxEPD2_Example/GxEPD2_boards_added.h

@@ -1,7 +1,7 @@
 // Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// Display Library based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Display Library based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -24,8 +24,9 @@
 // select one and adapt to your mapping
 //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
-//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
+//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
+//GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
 //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=77*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*BUSY=*/ 7));
@@ -53,8 +54,9 @@
 // select one and adapt to your mapping
 //GxEPD2_BW<GxEPD2_154, MAX_HEIGHT(GxEPD2_154)> display(GxEPD2_154(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
 //GxEPD2_BW<GxEPD2_213, MAX_HEIGHT(GxEPD2_213)> display(GxEPD2_213(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
-//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
+//GxEPD2_BW<GxEPD2_213_flex, MAX_HEIGHT(GxEPD2_213_flex)> display(GxEPD2_213_flex(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, MAX_HEIGHT(GxEPD2_290)> display(GxEPD2_290(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
+//GxEPD2_BW<GxEPD2_290_T5, MAX_HEIGHT(GxEPD2_290_T5)> display(GxEPD2_290_T5(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, MAX_HEIGHT(GxEPD2_270)> display(GxEPD2_270(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
 //GxEPD2_BW<GxEPD2_420, MAX_HEIGHT(GxEPD2_420)> display(GxEPD2_420(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
 //GxEPD2_BW<GxEPD2_583, MAX_HEIGHT(GxEPD2_583)> display(GxEPD2_583(/*CS=4*/ 4, /*DC=*/ 7, /*RST=*/ 6, /*BUSY=*/ 5));
@@ -74,8 +76,9 @@
 // select one and adapt to your mapping, can use full buffer size (full HEIGHT)
 //GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
 //GxEPD2_BW<GxEPD2_213, GxEPD2_213::HEIGHT> display(GxEPD2_213(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
-//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
+//GxEPD2_BW<GxEPD2_213_flex, GxEPD2_213_flex::HEIGHT> display(GxEPD2_213_flex(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15)); // GDEW0213I5F
 //GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(GxEPD2_290(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
+//GxEPD2_BW<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(GxEPD2_290_T5(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15)); // GDEW029T5
 //GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
 //GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));
 //GxEPD2_BW<GxEPD2_750, GxEPD2_750::HEIGHT> display(GxEPD2_750(/*CS=5*/ SS, /*DC=*/ 0, /*RST=*/ 2, /*BUSY=*/ 15));

+ 1 - 1
library.properties

@@ -1,5 +1,5 @@
 name=GxEPD2
-version=1.1.1
+version=1.1.2
 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

@@ -33,6 +33,7 @@ class GxEPD2
       GDE0213B1,  Waveshare_2_13_bw = GDE0213B1,
       GDEW0213I5F, Waveshare_2_13_flex = GDEW0213I5F,
       GDEH029A1,  Waveshare_2_9_bw = GDEH029A1,
+      GDEW029T5,  Waveshare_2_9_bw_T5 = GDEW029T5,
       GDEW027W3,  Waveshare_2_7_bw = GDEW027W3,
       GDEW042T2,  Waveshare_4_2_bw = GDEW042T2,
       GDEW0583T7, Waveshare_5_83_bw = GDEW0583T7,

+ 30 - 16
src/GxEPD2_3C.h

@@ -24,7 +24,7 @@
 
 #ifndef ENABLE_GxEPD2_GFX
 // default is off
-#define ENABLE_GxEPD2_GFX 0 
+#define ENABLE_GxEPD2_GFX 0
 #endif
 
 #if ENABLE_GxEPD2_GFX
@@ -65,7 +65,7 @@ class GxEPD2_3C : public Adafruit_GFX
 
     bool mirror(bool m)
     {
-      swap (_mirror, m);
+      _swap_ (_mirror, m);
       return m;
     }
 
@@ -77,7 +77,7 @@ class GxEPD2_3C : public Adafruit_GFX
       switch (getRotation())
       {
         case 1:
-          swap(x, y);
+          _swap_(x, y);
           x = WIDTH - x - 1;
           break;
         case 2:
@@ -85,20 +85,22 @@ class GxEPD2_3C : public Adafruit_GFX
           y = HEIGHT - y - 1;
           break;
         case 3:
-          swap(x, y);
+          _swap_(x, y);
           y = HEIGHT - y - 1;
           break;
       }
       // transpose partial window to 0,0
       x -= _pw_x;
       y -= _pw_y;
+      // clip to (partial) window
+      if ((x < 0) || (x >= _pw_w) || (y < 0) || (y >= _pw_h)) return;
       // adjust for current page
       y -= _current_page * _page_height;
       // check if in current page
       if ((y < 0) || (y >= _page_height)) return;
       uint16_t i = x / 8 + y * (_pw_w / 8);
       _black_buffer[i] = (_black_buffer[i] | (1 << (7 - x % 8))); // white
-      _color_buffer[i] = _color_buffer[i] = (_color_buffer[i] | (1 << (7 - x % 8)));
+      _color_buffer[i] = (_color_buffer[i] | (1 << (7 - x % 8)));
       if (color == GxEPD_WHITE) return;
       else if (color == GxEPD_BLACK) _black_buffer[i] = (_black_buffer[i] & (0xFF ^ (1 << (7 - x % 8))));
       else if (color == GxEPD_RED) _color_buffer[i] = (_color_buffer[i] & (0xFF ^ (1 << (7 - x % 8))));
@@ -142,6 +144,11 @@ class GxEPD2_3C : public Adafruit_GFX
       _pw_h = HEIGHT;
     }
 
+    // setPartialWindow, use parameters according to actual rotation.
+    // x and w should be multiple of 8, for rotation 0 or 2,
+    // y and h should be multiple of 8, for rotation 1 or 3,
+    // else window is increased as needed,
+    // this is an addressing limitation of the e-paper controllers
     void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
     {
       if (!epd2.hasPartialUpdate) return;
@@ -205,7 +212,7 @@ class GxEPD2_3C : public Adafruit_GFX
         fillScreen(GxEPD_WHITE);
         return true;
       }
-      else
+      else // full update
       {
         epd2.writeImage(_black_buffer, _color_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
         _current_page++;
@@ -216,13 +223,13 @@ class GxEPD2_3C : public Adafruit_GFX
           {
             if (!_second_phase)
             {
-              epd2.refresh(false);
+              epd2.refresh(false); // full update after first phase
               _second_phase = true;
               fillScreen(GxEPD_WHITE);
               return true;
             }
-            else epd2.refresh(true);
-          } else epd2.refresh(false);
+            else epd2.refresh(true); // partial update after second phase
+          } else epd2.refresh(false); // full update after only phase
           epd2.powerOff();
           return false;
         }
@@ -251,7 +258,7 @@ class GxEPD2_3C : public Adafruit_GFX
         }
         epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
       }
-      else
+      else // full update
       {
         epd2.setPaged(); // for GxEPD2_154c paged workaround
         for (_current_page = 0; _current_page < _pages; _current_page++)
@@ -271,7 +278,8 @@ class GxEPD2_3C : public Adafruit_GFX
             epd2.writeImage(_black_buffer, _color_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
           }
         }
-        epd2.refresh();
+        epd2.refresh(false); // full update
+        epd2.powerOff();
       }
       _current_page = 0;
     }
@@ -347,13 +355,19 @@ class GxEPD2_3C : public Adafruit_GFX
     {
       epd2.refresh(x, y, w, h);
     }
+    // turns off generation of panel driving voltages, avoids screen fading over time
     void powerOff()
     {
       epd2.powerOff();
     }
+    // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
+    void hibernate()
+    {
+      epd2.hibernate();
+    }
   private:
     template <typename T> static inline void
-    swap(T & a, T & b)
+    _swap_(T & a, T & b)
     {
       T t = a;
       a = b;
@@ -372,8 +386,8 @@ class GxEPD2_3C : public Adafruit_GFX
       switch (getRotation())
       {
         case 1:
-          swap(x, y);
-          swap(w, h);
+          _swap_(x, y);
+          _swap_(w, h);
           x = WIDTH - x - w;
           break;
         case 2:
@@ -381,8 +395,8 @@ class GxEPD2_3C : public Adafruit_GFX
           y = HEIGHT - y - h;
           break;
         case 3:
-          swap(x, y);
-          swap(w, h);
+          _swap_(x, y);
+          _swap_(w, h);
           y = HEIGHT - y - h;
           break;
       }

+ 32 - 16
src/GxEPD2_BW.h

@@ -18,6 +18,7 @@
 #include "epd/GxEPD2_213.h"
 #include "epd/GxEPD2_213_flex.h"
 #include "epd/GxEPD2_290.h"
+#include "epd/GxEPD2_290_T5.h"
 #include "epd/GxEPD2_270.h"
 #include "epd/GxEPD2_420.h"
 #include "epd/GxEPD2_583.h"
@@ -67,7 +68,7 @@ class GxEPD2_BW : public Adafruit_GFX
 
     bool mirror(bool m)
     {
-      swap (_mirror, m);
+      _swap_ (_mirror, m);
       return m;
     }
 
@@ -79,7 +80,7 @@ class GxEPD2_BW : public Adafruit_GFX
       switch (getRotation())
       {
         case 1:
-          swap(x, y);
+          _swap_(x, y);
           x = WIDTH - x - 1;
           break;
         case 2:
@@ -87,13 +88,15 @@ class GxEPD2_BW : public Adafruit_GFX
           y = HEIGHT - y - 1;
           break;
         case 3:
-          swap(x, y);
+          _swap_(x, y);
           y = HEIGHT - y - 1;
           break;
       }
       // transpose partial window to 0,0
       x -= _pw_x;
       y -= _pw_y;
+      // clip to (partial) window
+      if ((x < 0) || (x >= _pw_w) || (y < 0) || (y >= _pw_h)) return;
       // adjust for current page
       y -= _current_page * _page_height;
       if (_reverse) y = _page_height - y - 1;
@@ -139,6 +142,11 @@ class GxEPD2_BW : public Adafruit_GFX
       _pw_h = HEIGHT;
     }
 
+    // setPartialWindow, use parameters according to actual rotation.
+    // x and w should be multiple of 8, for rotation 0 or 2,
+    // y and h should be multiple of 8, for rotation 1 or 3,
+    // else window is increased as needed,
+    // this is an addressing limitation of the e-paper controllers
     void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
     {
       _rotate(x, y, w, h);
@@ -175,7 +183,7 @@ class GxEPD2_BW : public Adafruit_GFX
             epd2.refresh(_pw_x, _pw_y, _pw_w, _pw_h);
           }
         }
-        else
+        else // full update
         {
           epd2.writeImage(_buffer, 0, 0, WIDTH, HEIGHT);
           epd2.refresh(false);
@@ -183,6 +191,7 @@ class GxEPD2_BW : public Adafruit_GFX
           {
             epd2.writeImageAgain(_buffer, 0, 0, WIDTH, HEIGHT);
             epd2.refresh(true);
+            epd2.powerOff();
           }
         }
         return false;
@@ -228,7 +237,7 @@ class GxEPD2_BW : public Adafruit_GFX
         fillScreen(GxEPD_WHITE);
         return true;
       }
-      else
+      else // full update
       {
         if (!_second_phase) epd2.writeImage(_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
         else epd2.writeImageAgain(_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
@@ -240,13 +249,13 @@ class GxEPD2_BW : public Adafruit_GFX
           {
             if (!_second_phase)
             {
-              epd2.refresh(false);
+              epd2.refresh(false); // full update after first phase
               _second_phase = true;
               fillScreen(GxEPD_WHITE);
               return true;
             }
-            else epd2.refresh(true);
-          } else epd2.refresh(false);
+            else epd2.refresh(true); // partial update after second phase
+          } else epd2.refresh(false); // full update after only phase
           epd2.powerOff();
           return false;
         }
@@ -282,7 +291,7 @@ class GxEPD2_BW : public Adafruit_GFX
           // else make both controller buffers have equal content
         }
       }
-      else
+      else // full update
       {
         for (_current_page = 0; _current_page < _pages; _current_page++)
         {
@@ -291,7 +300,7 @@ class GxEPD2_BW : public Adafruit_GFX
           drawCallback(pv);
           epd2.writeImage(_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
         }
-        epd2.refresh(false);
+        epd2.refresh(false); // full update after first phase
         if (epd2.hasFastPartialUpdate)
         {
           // make both controller buffers have equal content
@@ -302,8 +311,9 @@ class GxEPD2_BW : public Adafruit_GFX
             drawCallback(pv);
             epd2.writeImageAgain(_buffer, 0, page_ys, WIDTH, gx_uint16_min(_page_height, HEIGHT - page_ys));
           }
-          epd2.refresh(true);
+          epd2.refresh(true); // partial update after second phase
         }
+        epd2.powerOff();
       }
       _current_page = 0;
     }
@@ -379,13 +389,19 @@ class GxEPD2_BW : public Adafruit_GFX
     {
       epd2.refresh(x, y, w, h);
     }
+    // turns off generation of panel driving voltages, avoids screen fading over time
     void powerOff()
     {
       epd2.powerOff();
     }
+    // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
+    void hibernate()
+    {
+      epd2.hibernate();
+    }
   private:
     template <typename T> static inline void
-    swap(T & a, T & b)
+    _swap_(T & a, T & b)
     {
       T t = a;
       a = b;
@@ -404,8 +420,8 @@ class GxEPD2_BW : public Adafruit_GFX
       switch (getRotation())
       {
         case 1:
-          swap(x, y);
-          swap(w, h);
+          _swap_(x, y);
+          _swap_(w, h);
           x = WIDTH - x - w;
           break;
         case 2:
@@ -413,8 +429,8 @@ class GxEPD2_BW : public Adafruit_GFX
           y = HEIGHT - y - h;
           break;
         case 3:
-          swap(x, y);
-          swap(w, h);
+          _swap_(x, y);
+          _swap_(w, h);
           y = HEIGHT - y - h;
           break;
       }

+ 1 - 0
src/GxEPD2_EPD.cpp

@@ -74,6 +74,7 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
 {
   if (_busy >= 0)
   {
+    delay(1); // add some margin to become active
     unsigned long start = micros();
     while (1)
     {

+ 2 - 0
src/GxEPD2_EPD.h

@@ -48,6 +48,8 @@ class GxEPD2_EPD
     virtual 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) = 0;
     virtual void refresh(bool partial_update_mode = false) = 0; // screen refresh from controller memory to full screen
     virtual void refresh(int16_t x, int16_t y, int16_t w, int16_t h) = 0; // screen refresh from controller memory, partial screen
+    virtual void powerOff() = 0; // turns off generation of panel driving voltages, avoids screen fading over time
+    virtual void hibernate() = 0; // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
     virtual void setPaged() {}; // for GxEPD2_154c paged workaround
     static inline uint16_t gx_uint16_min(uint16_t a, uint16_t b)
     {

+ 7 - 0
src/GxEPD2_GFX.h

@@ -25,6 +25,11 @@ class GxEPD2_GFX : public Adafruit_GFX
     virtual void fillScreen(uint16_t color) = 0; // 0x0 black, >0x0 white, to buffer
     virtual void display(bool partial_update_mode = false) = 0;
     virtual void setFullWindow() = 0;
+    // setPartialWindow, use parameters according to actual rotation.
+    // x and w should be multiple of 8, for rotation 0 or 2,
+    // y and h should be multiple of 8, for rotation 1 or 3,
+    // else window is increased as needed, 
+    // this is an addressing limitation of the e-paper controllers
     virtual void setPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 0;
     virtual void firstPage() = 0;
     virtual bool nextPage() = 0;
@@ -41,6 +46,8 @@ class GxEPD2_GFX : public Adafruit_GFX
     virtual 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) = 0;
     virtual void refresh(bool partial_update_mode = false) = 0; // screen refresh from controller memory to full screen
     virtual void refresh(int16_t x, int16_t y, int16_t w, int16_t h) = 0; // screen refresh from controller memory, partial screen
+    virtual void powerOff() = 0; // turns off generation of panel driving voltages, avoids screen fading over time
+    virtual void hibernate() = 0; // turns powerOff() and sets controller to deep sleep for minimum power use, ONLY if wakeable by RST (rst >= 0)
   public:
     GxEPD2_EPD& epd2;
 };

+ 24 - 5
src/epd/GxEPD2_154.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller : IL3829 : http://www.e-paper-display.com/download_detail/downloadsId=534.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_154::GxEPD2_154(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_154::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_154::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_154::clearScreen(uint8_t value)
@@ -183,11 +186,22 @@ void GxEPD2_154::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
   _Update_Part();
 }
 
-void GxEPD2_154::powerOff(void)
+void GxEPD2_154::powerOff()
 {
   _PowerOff();
 }
 
+void GxEPD2_154::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x10); // deep sleep mode
+    _writeData(0x1);     // enter deep sleep
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_154::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
   _writeCommand(0x11); // set ram entry mode
@@ -231,6 +245,14 @@ void GxEPD2_154::_PowerOff()
 
 void GxEPD2_154::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x01); // Panel configuration, Gate selection
   _writeData((HEIGHT - 1) % 256);
   _writeData((HEIGHT - 1) / 256);
@@ -281,6 +303,3 @@ void GxEPD2_154::_Update_Part()
   _waitWhileBusy("_Update_Part", partial_refresh_time);
   _writeCommand(0xff);
 }
-
-
-

+ 5 - 4
src/epd/GxEPD2_154.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller : IL3829 : http://www.e-paper-display.com/download_detail/downloadsId=534.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_154 : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -59,8 +61,7 @@ class GxEPD2_154 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 23 - 4
src/epd/GxEPD2_213.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL3895 : http://www.e-paper-display.com/download_detail/downloadsId=538.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_213::GxEPD2_213(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_213::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213::clearScreen(uint8_t value)
@@ -188,6 +191,17 @@ void GxEPD2_213::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_213::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x10); // deep sleep mode
+    _writeData(0x1);     // enter deep sleep
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_213::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
   _writeCommand(0x11); // set ram entry mode
@@ -231,6 +245,14 @@ void GxEPD2_213::_PowerOff()
 
 void GxEPD2_213::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x01); // Panel configuration, Gate selection
   _writeData((HEIGHT - 1) % 256);
   _writeData((HEIGHT - 1) / 256);
@@ -281,6 +303,3 @@ void GxEPD2_213::_Update_Part()
   _waitWhileBusy("_Update_Part", partial_refresh_time);
   _writeCommand(0xff);
 }
-
-
-

+ 5 - 4
src/epd/GxEPD2_213.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL3895 : http://www.e-paper-display.com/download_detail/downloadsId=538.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_213 : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -62,8 +64,7 @@ class GxEPD2_213 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 23 - 3
src/epd/GxEPD2_213_flex.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_213_flex::GxEPD2_213_flex(int8_t cs, int8_t dc, int8_t rst, int8_t busy)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213_flex::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_213_flex::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213_flex::clearScreen(uint8_t value)
@@ -197,6 +200,17 @@ void GxEPD2_213_flex::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_213_flex::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_213_flex::_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)
@@ -235,6 +249,14 @@ void GxEPD2_213_flex::_PowerOff()
 
 void GxEPD2_213_flex::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x01); //POWER SETTING
   _writeData (0x03);
   _writeData (0x00);
@@ -309,5 +331,3 @@ void GxEPD2_213_flex::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-

+ 5 - 4
src/epd/GxEPD2_213_flex.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_213_flex : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -59,8 +61,7 @@ class GxEPD2_213_flex : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 22 - 0
src/epd/GxEPD2_270.cpp

@@ -2,6 +2,7 @@
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
 // based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL91874 : http://www.e-paper-display.com/download_detail/downloadsId=539.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_270::GxEPD2_270(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_270::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_270::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_270::clearScreen(uint8_t value)
@@ -199,6 +202,17 @@ void GxEPD2_270::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_270::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_270::_setPartialRamArea(uint8_t command, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
   w = (w + 7 + (x % 8)) & 0xfff8; // byte boundary exclusive (round up)
@@ -248,6 +262,14 @@ void GxEPD2_270::_PowerOff()
 
 void GxEPD2_270::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x01); //POWER SETTING
   _writeData (0x03);
   _writeData (0x00);

+ 4 - 2
src/epd/GxEPD2_270.h

@@ -2,6 +2,7 @@
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
 // based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL91874 : http://www.e-paper-display.com/download_detail/downloadsId=539.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_270 : public GxEPD2_EPD
     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();
+    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 _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 _writeScreenBuffer(uint8_t value);
@@ -64,7 +66,7 @@ class GxEPD2_270 : public GxEPD2_EPD
     void _Update_Part();
     void _writeDataPGM(const uint8_t* data, uint16_t n);
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif

+ 23 - 4
src/epd/GxEPD2_290.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL3820 : http://www.e-paper-display.com/download_detail/downloadsId=540.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_290::GxEPD2_290(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_290::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_290::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_290::clearScreen(uint8_t value)
@@ -188,6 +191,17 @@ void GxEPD2_290::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_290::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x10); // deep sleep mode
+    _writeData(0x1);     // enter deep sleep
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_290::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
   _writeCommand(0x11); // set ram entry mode
@@ -231,6 +245,14 @@ void GxEPD2_290::_PowerOff()
 
 void GxEPD2_290::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x01); // Panel configuration, Gate selection
   _writeData((HEIGHT - 1) % 256);
   _writeData((HEIGHT - 1) / 256);
@@ -281,6 +303,3 @@ void GxEPD2_290::_Update_Part()
   _waitWhileBusy("_Update_Part", partial_refresh_time);
   _writeCommand(0xff);
 }
-
-
-

+ 5 - 4
src/epd/GxEPD2_290.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL3820 : http://www.e-paper-display.com/download_detail/downloadsId=540.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_290 : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -59,8 +61,7 @@ class GxEPD2_290 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 335 - 0
src/epd/GxEPD2_290_T5.cpp

@@ -0,0 +1,335 @@
+// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
+// Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
+//
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
+//
+// Author: Jean-Marc Zingg
+//
+// Version: see library.properties
+//
+// Library: https://github.com/ZinggJM/GxEPD2
+
+#include "GxEPD2_290_T5.h"
+#include "WaveTables.h"
+
+GxEPD2_290_T5::GxEPD2_290_T5(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
+  GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
+{
+  _initial = true;
+  _power_is_on = false;
+  _using_partial_mode = false;
+  _hibernating = false;
+}
+
+void GxEPD2_290_T5::init(uint32_t serial_diag_bitrate)
+{
+  GxEPD2_EPD::init(serial_diag_bitrate);
+  _initial = true;
+  _power_is_on = false;
+  _using_partial_mode = false;
+  _hibernating = false;
+}
+
+void GxEPD2_290_T5::clearScreen(uint8_t value)
+{
+  if (_initial)
+  {
+    _Init_Full();
+    _writeCommand(0x10); // preset previous
+    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+    {
+      _writeData(0xFF); // 0xFF is white
+    }
+    _writeCommand(0x13); // set current
+    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+    {
+      _writeData(value);
+    }
+    _Update_Full();
+    _initial = false;
+  }
+  if (!_using_partial_mode) _Init_Part();
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
+  _writeCommand(0x13);
+  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+  {
+    _writeData(value);
+  }
+  _Update_Part();
+  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
+  _writeCommand(0x13);
+  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+  {
+    _writeData(value);
+  }
+  _Update_Part();
+  _writeCommand(0x92); // partial out
+  _initial = false;
+}
+
+void GxEPD2_290_T5::writeScreenBuffer(uint8_t value)
+{
+  if (_initial) clearScreen(value);
+  else _writeScreenBuffer(value);
+}
+
+void GxEPD2_290_T5::_writeScreenBuffer(uint8_t value)
+{
+  if (!_using_partial_mode) _Init_Part();
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
+  _writeCommand(0x13);
+  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+  {
+    _writeData(value);
+  }
+  _writeCommand(0x92); // partial out
+}
+
+void GxEPD2_290_T5::writeImage(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
+  int16_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 (!_using_partial_mode) _Init_Part();
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(x1, y1, w1, h1);
+  _writeCommand(0x13);
+  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!
+      int16_t idx = mirror_y ? j + dx / 8 + ((h - 1 - (i + dy))) * wb : j + dx / 8 + (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;
+      _writeData(data);
+    }
+  }
+  _writeCommand(0x92); // partial out
+  delay(1); // yield() to avoid WDT on ESP8266 and ESP32
+}
+
+void GxEPD2_290_T5::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_290_T5::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_290_T5::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);
+}
+
+void GxEPD2_290_T5::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)
+{
+  writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
+  refresh(x, y, w, h);
+}
+
+void GxEPD2_290_T5::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)
+{
+  writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
+  refresh(x, y, w, h);
+}
+
+void GxEPD2_290_T5::refresh(bool partial_update_mode)
+{
+  if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
+  else
+  {
+    if (_using_partial_mode) _Init_Full();
+    _Update_Full();
+  }
+}
+
+void GxEPD2_290_T5::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
+{
+  x -= x % 8; // byte boundary
+  w -= x % 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
+  w1 -= x1 - x;
+  h1 -= y1 - y;
+  if (!_using_partial_mode) _Init_Part();
+  _writeCommand(0x91); // partial in
+  _setPartialRamArea(x1, y1, w1, h1);
+  _Update_Part();
+  _writeCommand(0x92); // partial out
+}
+
+void GxEPD2_290_T5::powerOff(void)
+{
+  _PowerOff();
+}
+
+void GxEPD2_290_T5::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
+void GxEPD2_290_T5::_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 / 256);
+  _writeData(x % 256);
+  //_writeData(xe / 256);
+  _writeData(xe % 256);
+  _writeData(y / 256);
+  _writeData(y % 256);
+  _writeData(ye / 256);
+  _writeData(ye % 256);
+  _writeData(0x01); // don't see any difference
+  //_writeData(0x00); // don't see any difference
+}
+
+void GxEPD2_290_T5::_PowerOn()
+{
+  if (!_power_is_on)
+  {
+    _writeCommand(0x04);
+    _waitWhileBusy("_PowerOn", power_on_time);
+  }
+  _power_is_on = true;
+}
+
+void GxEPD2_290_T5::_PowerOff()
+{
+  _writeCommand(0x02); // power off
+  _waitWhileBusy("_PowerOff", power_off_time);
+  _power_is_on = false;
+  _using_partial_mode = false;
+}
+
+void GxEPD2_290_T5::_InitDisplay()
+{
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
+  _writeCommand(0x01); //POWER SETTING
+  _writeData (0x03);
+  _writeData (0x00);
+  _writeData (0x2b);
+  _writeData (0x2b);
+  _writeData (0x03);
+  _writeCommand(0x06); //boost soft start
+  _writeData (0x17);   //A
+  _writeData (0x17);   //B
+  _writeData (0x17);   //C
+  _writeCommand(0x00); //panel setting
+  //_writeData(0xbf);    //LUT from register, 128x296
+  //_writeData(0x1f);    //LUT from OTP, 128x296
+  _writeData(hasFastPartialUpdate ? 0xbf : 0x1f); // for test with OTP LUT
+  _writeData(0x0d);    //VCOM to 0V fast
+  _writeCommand(0x30); //PLL setting
+  _writeData (0x3a);   // 3a 100HZ   29 150Hz 39 200HZ 31 171HZ
+  _writeCommand(0x61); //resolution setting
+  _writeData (WIDTH);
+  _writeData (HEIGHT >> 8);
+  _writeData (HEIGHT & 0xFF);
+}
+
+void GxEPD2_290_T5::_Init_Full()
+{
+  _InitDisplay();
+  _writeCommand(0x82); //vcom_DC setting
+  _writeData (0x08);
+  _writeCommand(0X50); //VCOM AND DATA INTERVAL SETTING
+  _writeData(0x97);    //WBmode:VBDF 17|D7 VBDW 97 VBDB 57   WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
+  _writeCommand(0x20);
+  _writeDataPGM(GxGDEW029T5_lut_20_vcomDC, sizeof(GxGDEW029T5_lut_20_vcomDC));
+  _writeCommand(0x21);
+  _writeDataPGM(GxGDEW029T5_lut_21_ww, sizeof(GxGDEW029T5_lut_21_ww));
+  _writeCommand(0x22);
+  _writeDataPGM(GxGDEW029T5_lut_22_bw, sizeof(GxGDEW029T5_lut_22_bw));
+  _writeCommand(0x23);
+  _writeDataPGM(GxGDEW029T5_lut_23_wb, sizeof(GxGDEW029T5_lut_23_wb));
+  _writeCommand(0x24);
+  _writeDataPGM(GxGDEW029T5_lut_24_bb, sizeof(GxGDEW029T5_lut_24_bb));
+  _PowerOn();
+  _using_partial_mode = false;
+}
+
+void GxEPD2_290_T5::_Init_Part()
+{
+  _InitDisplay();
+  _writeCommand(0x82); //vcom_DC setting
+  _writeData (0x08);
+  _writeCommand(0X50);
+  _writeData(0x17);    //WBmode:VBDF 17|D7 VBDW 97 VBDB 57   WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
+  _writeCommand(0x20);
+  _writeDataPGM(GxGDEW029T5_lut_20_vcomDC_partial, sizeof(GxGDEW029T5_lut_20_vcomDC_partial));
+  _writeCommand(0x21);
+  _writeDataPGM(GxGDEW029T5_lut_21_ww_partial, sizeof(GxGDEW029T5_lut_21_ww_partial));
+  _writeCommand(0x22);
+  _writeDataPGM(GxGDEW029T5_lut_22_bw_partial, sizeof(GxGDEW029T5_lut_22_bw_partial));
+  _writeCommand(0x23);
+  _writeDataPGM(GxGDEW029T5_lut_23_wb_partial, sizeof(GxGDEW029T5_lut_23_wb_partial));
+  _writeCommand(0x24);
+  _writeDataPGM(GxGDEW029T5_lut_24_bb_partial, sizeof(GxGDEW029T5_lut_24_bb_partial));
+  _PowerOn();
+  _using_partial_mode = true;
+}
+
+void GxEPD2_290_T5::_Update_Full()
+{
+  _writeCommand(0x12); //display refresh
+  _waitWhileBusy("_Update_Full", full_refresh_time);
+}
+
+void GxEPD2_290_T5::_Update_Part()
+{
+  _writeCommand(0x12); //display refresh
+  _waitWhileBusy("_Update_Part", partial_refresh_time);
+}

+ 67 - 0
src/epd/GxEPD2_290_T5.h

@@ -0,0 +1,67 @@
+// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
+// Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
+//
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
+//
+// Author: Jean-Marc Zingg
+//
+// Version: see library.properties
+//
+// Library: https://github.com/ZinggJM/GxEPD2
+
+#ifndef _GxEPD2_290_T5_H_
+#define _GxEPD2_290_T5_H_
+
+#include "../GxEPD2_EPD.h"
+
+class GxEPD2_290_T5 : public GxEPD2_EPD
+{
+  public:
+    // attributes
+    static const uint16_t WIDTH = 128;
+    static const uint16_t HEIGHT = 296;
+    static const GxEPD2::Panel panel = GxEPD2::GDEW029T5;
+    static const bool hasColor = false;
+    static const bool hasPartialUpdate = true;
+    static const bool hasFastPartialUpdate = true; // set this false for test with OTP LUT (GDEW029I6F)
+    static const uint16_t power_on_time = 400; // ms, e.g. 36553us
+    static const uint16_t power_off_time = 250; // ms, e.g. 20759us
+    static const uint16_t full_refresh_time = 2100; // ms, e.g. 2056899us
+    static const uint16_t partial_refresh_time = 400; // ms, e.g. 353649us
+    // constructor
+    GxEPD2_290_T5(int8_t cs, int8_t dc, int8_t rst, int8_t busy);
+    // methods (virtual)
+    void init(uint32_t serial_diag_bitrate = 0); // = 0 : disabled
+    //  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)
+    // 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 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);
+    // 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 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);
+    // 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 value);
+    void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
+    void _PowerOn();
+    void _PowerOff();
+    void _InitDisplay();
+    void _Init_Full();
+    void _Init_Part();
+    void _Update_Full();
+    void _Update_Part();
+  protected:
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
+};
+
+#endif

+ 23 - 3
src/epd/GxEPD2_420.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0398 : http://www.e-paper-display.com/download_detail/downloadsId=537.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_420::GxEPD2_420(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_420::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_420::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_420::clearScreen(uint8_t value)
@@ -192,6 +195,17 @@ void GxEPD2_420::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_420::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_420::_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)
@@ -230,6 +244,14 @@ void GxEPD2_420::_PowerOff()
 
 void GxEPD2_420::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x06); // boost
   _writeData(0x17);
   _writeData(0x17);
@@ -284,5 +306,3 @@ void GxEPD2_420::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-

+ 5 - 4
src/epd/GxEPD2_420.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0398 : http://www.e-paper-display.com/download_detail/downloadsId=537.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_420 : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -59,8 +61,7 @@ class GxEPD2_420 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 22 - 8
src/epd/GxEPD2_583.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_583::GxEPD2_583(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_583::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_583::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_583::clearScreen(uint8_t value)
@@ -235,6 +238,18 @@ void GxEPD2_583::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_583::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    // check if it supports this command!
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_583::_send8pixel(uint8_t data)
 {
   for (uint8_t j = 0; j < 8; j++)
@@ -287,12 +302,13 @@ void GxEPD2_583::_PowerOff()
 
 void GxEPD2_583::_InitDisplay()
 {
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x01);
   _writeData (0x37); // POWER SETTING
@@ -350,5 +366,3 @@ void GxEPD2_583::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-

+ 5 - 4
src/epd/GxEPD2_583.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_583 : public GxEPD2_EPD
     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();
+    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 value);
     void _send8pixel(uint8_t data);
@@ -60,8 +62,7 @@ class GxEPD2_583 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 22 - 8
src/epd/GxEPD2_750.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.good-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -18,6 +19,7 @@ GxEPD2_750::GxEPD2_750(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_750::init(uint32_t serial_diag_bitrate)
@@ -26,6 +28,7 @@ void GxEPD2_750::init(uint32_t serial_diag_bitrate)
   _initial = true;
   _power_is_on = false;
   _using_partial_mode = false;
+  _hibernating = false;
 }
 
 void GxEPD2_750::clearScreen(uint8_t value)
@@ -235,6 +238,18 @@ void GxEPD2_750::powerOff(void)
   _PowerOff();
 }
 
+void GxEPD2_750::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    // check if it supports this command!
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_750::_send8pixel(uint8_t data)
 {
   for (uint8_t j = 0; j < 8; j++)
@@ -287,12 +302,13 @@ void GxEPD2_750::_PowerOff()
 
 void GxEPD2_750::_InitDisplay()
 {
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   /**********************************release flash sleep**********************************/
   _writeCommand(0X65);     //FLASH CONTROL
@@ -357,5 +373,3 @@ void GxEPD2_750::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-

+ 5 - 4
src/epd/GxEPD2_750.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.good-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -47,7 +48,8 @@ class GxEPD2_750 : public GxEPD2_EPD
     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();
+    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 value);
     void _send8pixel(uint8_t data);
@@ -60,8 +62,7 @@ class GxEPD2_750 : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on, _using_partial_mode;
+    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif
-

+ 112 - 61
src/epd/WaveTables.h

@@ -49,6 +49,8 @@ const uint8_t GxGDEH029A1_LUTDefault_part[] PROGMEM =
   0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
+// GDEW0213I5F
+
 //full screen update LUT
 const unsigned char GxGDEW0213I5F_lut_20_vcomDC[] PROGMEM = 
 {
@@ -155,6 +157,116 @@ const unsigned char GxGDEW0213I5F_lut_24_bb_partial[] PROGMEM =
   0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
 };
 
+// GDEW029T5 originally same as GDEW0213I5F, changed for test
+
+//full screen update LUT
+const unsigned char GxGDEW029T5_lut_20_vcomDC[] PROGMEM = 
+{
+  0x00  , 0x08 , 0x00 , 0x00 , 0x00 , 0x02,
+  0x60  , 0x28 , 0x28 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x14 , 0x00 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x12 , 0x12 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
+  , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_21_ww[] PROGMEM = 
+{
+  0x40  , 0x08 , 0x00 , 0x00 , 0x00 , 0x02,
+  0x90  , 0x28 , 0x28 , 0x00 , 0x00 , 0x01,
+  0x40  , 0x14 , 0x00 , 0x00 , 0x00 , 0x01,
+  0xA0  , 0x12 , 0x12 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_22_bw[] PROGMEM = 
+{
+  0x40  , 0x17 , 0x00 , 0x00 , 0x00 , 0x02 ,
+  0x90  , 0x0F , 0x0F , 0x00 , 0x00 , 0x03 ,
+  0x40  , 0x0A , 0x01 , 0x00 , 0x00 , 0x01 ,
+  0xA0  , 0x0E , 0x0E , 0x00 , 0x00 , 0x02 ,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
+};
+const unsigned char GxGDEW029T5_lut_23_wb[] PROGMEM = 
+{
+  0x80  , 0x08 , 0x00 , 0x00 , 0x00 , 0x02,
+  0x90  , 0x28 , 0x28 , 0x00 , 0x00 , 0x01,
+  0x80  , 0x14 , 0x00 , 0x00 , 0x00 , 0x01,
+  0x50  , 0x12 , 0x12 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_24_bb[] PROGMEM = 
+{
+  0x80  , 0x08 , 0x00 , 0x00 , 0x00 , 0x02,
+  0x90  , 0x28 , 0x28 , 0x00 , 0x00 , 0x01,
+  0x80  , 0x14 , 0x00 , 0x00 , 0x00 , 0x01,
+  0x50  , 0x12 , 0x12 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+
+//partial screen update LUT
+//#define Tx19 0x19 // original value is 25 (phase length)
+#define Tx19 0x20   // new value for test is 32 (phase length)
+const unsigned char GxGDEW029T5_lut_20_vcomDC_partial[] PROGMEM = 
+{
+  0x00  , Tx19 , 0x01 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
+  , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_21_ww_partial[] PROGMEM = 
+{
+  0x00  , Tx19 , 0x01 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_22_bw_partial[] PROGMEM = 
+{
+  0x80  , Tx19 , 0x01 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_23_wb_partial[] PROGMEM = 
+{
+  0x40  , Tx19 , 0x01 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+const unsigned char GxGDEW029T5_lut_24_bb_partial[] PROGMEM = 
+{
+  0x00  , Tx19 , 0x01 , 0x00 , 0x00 , 0x01,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+  0x00  , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
+};
+
 //full screen update LUT
 const uint8_t GxGDEW027W3_lut_20_vcomDC[] PROGMEM =
 {
@@ -269,67 +381,6 @@ const uint8_t GxGDEW027W3_lut_24_bb_partial[] PROGMEM =
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-const uint8_t GxGDEW0154Z04_lut_20_vcom0[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x06 , 0x04 , 0x0A , 0x0A , 0x0F , 0x03 , 0x03 , 0x0C , 0x06 , 0x0A , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_21_w[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x46 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x86 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_22_b[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x4A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_23_g1[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_24_g2[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_25_vcom1[] PROGMEM = {  0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_26_red0[] PROGMEM = { 0x83  , 0x5D , 0x01 , 0x81 , 0x48 , 0x23 , 0x77 , 0x77 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_27_red1[] PROGMEM = { 0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-
-const uint8_t GxGDEW027C44_lut_20_vcomDC[] PROGMEM =
-{
-  0x00  , 0x00,
-  0x00  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R21H
-const uint8_t GxGDEW027C44_lut_21[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R22H  r
-const uint8_t GxGDEW027C44_lut_22_red[] PROGMEM = {
-  0xA0  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x90  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0xB0  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0xB0  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0xC0  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R23H  w
-const uint8_t GxGDEW027C44_lut_23_white[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R24H  b
-const uint8_t GxGDEW027C44_lut_24_black[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x20  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x10  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-
 const unsigned char GxGDEW042T2_lut_20_vcom0_full[] PROGMEM =
 {
 0x40, 0x17, 0x00, 0x00, 0x00, 0x02,        

+ 23 - 11
src/epd3c/GxEPD2_154c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0376F : http://www.e-paper-display.com/download_detail/downloadsId=541.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,7 +11,7 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_154c.h"
-#include "WaveTables.h"
+#include "WaveTables3c.h"
 
 const uint8_t GxEPD2_154c::bw2grey[] =
 {
@@ -27,6 +28,7 @@ GxEPD2_154c::GxEPD2_154c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   _power_is_on = false;
   _paged = false;
   _second_phase = false;
+  _hibernating = false;
 }
 
 void GxEPD2_154c::init(uint32_t serial_diag_bitrate)
@@ -36,6 +38,7 @@ void GxEPD2_154c::init(uint32_t serial_diag_bitrate)
   _power_is_on = false;
   _paged = false;
   _second_phase = false;
+  _hibernating = false;
 }
 
 void GxEPD2_154c::clearScreen(uint8_t value)
@@ -237,6 +240,18 @@ void GxEPD2_154c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_154c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    // check if it supports this command!
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_154c::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
 }
@@ -278,13 +293,13 @@ void GxEPD2_154c::setPaged()
 
 void GxEPD2_154c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x01);
   _writeData(0x07);
@@ -349,6 +364,3 @@ void GxEPD2_154c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_154c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0376F : http://www.e-paper-display.com/download_detail/downloadsId=541.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_154c : public GxEPD2_EPD
     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();
+    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)
     void setPaged(); // for GxEPD2_154c paged workaround
   private:
     void _writeScreenBuffer(uint8_t value);
@@ -62,10 +64,9 @@ class GxEPD2_154c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
     bool _paged, _second_phase;
     static const uint8_t bw2grey[];
 };
 
 #endif
-

+ 22 - 11
src/epd3c/GxEPD2_213c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_213c.h"
-#include "WaveTables.h"
+//#include "WaveTables3c.h"
 
 GxEPD2_213c::GxEPD2_213c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 20000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_213c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_213c::clearScreen(uint8_t value)
@@ -207,6 +210,17 @@ void GxEPD2_213c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_213c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_213c::_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)
@@ -244,13 +258,13 @@ void GxEPD2_213c::_PowerOff()
 
 void GxEPD2_213c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x06);
   _writeData (0x17);
@@ -291,6 +305,3 @@ void GxEPD2_213c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_213c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_213c : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -61,8 +63,7 @@ class GxEPD2_213c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 22 - 11
src/epd3c/GxEPD2_270c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL91874 : http://www.e-paper-display.com/download_detail/downloadsId=539.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_270c.h"
-#include "WaveTables.h"
+#include "WaveTables3c.h"
 
 GxEPD2_270c::GxEPD2_270c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 20000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_270c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_270c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_270c::clearScreen(uint8_t value)
@@ -207,6 +210,17 @@ void GxEPD2_270c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_270c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_270c::_writeData_nCS(const uint8_t* data, uint16_t n)
 {
   SPI.beginTransaction(_spi_settings);
@@ -252,13 +266,13 @@ void GxEPD2_270c::_PowerOff()
 
 void GxEPD2_270c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x01);
   _writeData (0x03);
@@ -347,6 +361,3 @@ void GxEPD2_270c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_270c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL91874 : http://www.e-paper-display.com/download_detail/downloadsId=539.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_270c : public GxEPD2_EPD
     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();
+    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 _writeData_nCS(const uint8_t* data, uint16_t n);
     void _writeScreenBuffer(uint8_t value);
@@ -62,8 +64,7 @@ class GxEPD2_270c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 22 - 11
src/epd3c/GxEPD2_290c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_290c.h"
-#include "WaveTables.h"
+//#include "WaveTables3c.h"
 
 GxEPD2_290c::GxEPD2_290c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 20000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_290c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_290c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_290c::clearScreen(uint8_t value)
@@ -207,6 +210,17 @@ void GxEPD2_290c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_290c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_290c::_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)
@@ -244,13 +258,13 @@ void GxEPD2_290c::_PowerOff()
 
 void GxEPD2_290c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x06);
   _writeData (0x17);
@@ -291,6 +305,3 @@ void GxEPD2_290c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_290c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0373 : http://www.e-paper-display.com/download_detail/downloadsId=535.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_290c : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -61,8 +63,7 @@ class GxEPD2_290c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 24 - 5
src/epd3c/GxEPD2_420c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0398 : http://www.e-paper-display.com/download_detail/downloadsId=537.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_420c.h"
-#include "WaveTables.h"
+//#include "WaveTables3c.h"
 
 GxEPD2_420c::GxEPD2_420c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 20000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_420c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_420c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_420c::clearScreen(uint8_t value)
@@ -207,6 +210,17 @@ void GxEPD2_420c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_420c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_420c::_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)
@@ -245,6 +259,14 @@ void GxEPD2_420c::_PowerOff()
 
 void GxEPD2_420c::_InitDisplay()
 {
+  if (_hibernating && (_rst >= 0))
+  {
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
+  }
   _writeCommand(0x06); //boost
   _writeData(0x17);
   _writeData(0x17);
@@ -276,6 +298,3 @@ void GxEPD2_420c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_420c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0398 : http://www.e-paper-display.com/download_detail/downloadsId=537.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_420c : public GxEPD2_EPD
     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();
+    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 value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
@@ -61,8 +63,7 @@ class GxEPD2_420c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 23 - 11
src/epd3c/GxEPD2_583c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_583c.h"
-#include "WaveTables.h"
+//#include "WaveTables3c.h"
 
 GxEPD2_583c::GxEPD2_583c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 40000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_583c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_583c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_583c::clearScreen(uint8_t value)
@@ -251,6 +254,18 @@ void GxEPD2_583c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_583c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    // check if it supports this command!
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_583c::_send8pixel(uint8_t black_data, uint8_t color_data)
 {
   for (uint8_t j = 0; j < 8; j++)
@@ -310,13 +325,13 @@ void GxEPD2_583c::_PowerOff()
 
 void GxEPD2_583c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   _writeCommand(0x01);
   _writeData (0x37); //POWER SETTING
@@ -371,6 +386,3 @@ void GxEPD2_583c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_583c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_583c : public GxEPD2_EPD
     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();
+    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 value);
     void _send8pixel(uint8_t black_data, uint8_t red_data);
@@ -62,8 +64,7 @@ class GxEPD2_583c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 23 - 11
src/epd3c/GxEPD2_750c.cpp

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -10,13 +11,14 @@
 // Library: https://github.com/ZinggJM/GxEPD2
 
 #include "GxEPD2_750c.h"
-#include "WaveTables.h"
+//#include "WaveTables3c.h"
 
 GxEPD2_750c::GxEPD2_750c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
   GxEPD2_EPD(cs, dc, rst, busy, LOW, 40000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
 {
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_750c::init(uint32_t serial_diag_bitrate)
@@ -24,6 +26,7 @@ void GxEPD2_750c::init(uint32_t serial_diag_bitrate)
   GxEPD2_EPD::init(serial_diag_bitrate);
   _initial = true;
   _power_is_on = false;
+  _hibernating = false;
 }
 
 void GxEPD2_750c::clearScreen(uint8_t value)
@@ -248,6 +251,18 @@ void GxEPD2_750c::powerOff()
   _PowerOff();
 }
 
+void GxEPD2_750c::hibernate()
+{
+  _PowerOff();
+  if (_rst >= 0)
+  {
+    // check if it supports this command!
+    _writeCommand(0x07); // deep sleep
+    _writeData(0xA5);    // check code
+    _hibernating = true;
+  }
+}
+
 void GxEPD2_750c::_send8pixel(uint8_t black_data, uint8_t color_data)
 {
   for (uint8_t j = 0; j < 8; j++)
@@ -307,13 +322,13 @@ void GxEPD2_750c::_PowerOff()
 
 void GxEPD2_750c::_InitDisplay()
 {
-  // reset required for wakeup
-  if (!_power_is_on && (_rst >= 0))
+  if (_hibernating && (_rst >= 0))
   {
-    digitalWrite(_rst, 0);
-    delay(10);
-    digitalWrite(_rst, 1);
-    delay(10);
+    digitalWrite(_rst, LOW);
+    delay(20);
+    digitalWrite(_rst, HIGH);
+    delay(200);
+    _hibernating = false;
   }
   /**********************************release flash sleep**********************************/
   _writeCommand(0X65);     //FLASH CONTROL
@@ -376,6 +391,3 @@ void GxEPD2_750c::_Update_Part()
   _writeCommand(0x12); //display refresh
   _waitWhileBusy("_Update_Part", partial_refresh_time);
 }
-
-
-

+ 5 - 4
src/epd3c/GxEPD2_750c.h

@@ -1,7 +1,8 @@
 // Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
 // Requires HW SPI and Adafruit_GFX. Caution: these e-papers require 3.3V supply AND data lines!
 //
-// based on Demo Example from Good Display: http://www.good-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+// Controller: IL0371 : http://www.e-paper-display.com/download_detail/downloadsId=536.html
 //
 // Author: Jean-Marc Zingg
 //
@@ -49,7 +50,8 @@ class GxEPD2_750c : public GxEPD2_EPD
     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();
+    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 value);
     void _send8pixel(uint8_t black_data, uint8_t red_data);
@@ -62,8 +64,7 @@ class GxEPD2_750c : public GxEPD2_EPD
     void _Update_Full();
     void _Update_Part();
   protected:
-    bool _initial, _power_is_on;
+    bool _initial, _power_is_on, _hibernating;
 };
 
 #endif
-

+ 0 - 288
src/epd3c/WaveTables.h

@@ -1,288 +0,0 @@
-#ifndef _WaveTables_H_
-#define _WaveTables_H_
-
-#if defined(ESP8266) || defined(ESP32)
-#include <pgmspace.h>
-#else
-#include <avr/pgmspace.h>
-#endif
-
-const uint8_t GDEP015OC1_LUTDefault_full[] PROGMEM =
-{
-  0x32,  // command
-  0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GDEP015OC1_LUTDefault_part[] PROGMEM =
-{
-  0x32,  // command
-  0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GxGDE0213B1_LUTDefault_full[] PROGMEM =
-{
-  0x32,  // command
-  0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x01, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GxGDE0213B1_LUTDefault_part[] PROGMEM =
-{
-  0x32,  // command
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GxGDEH029A1_LUTDefault_full[] PROGMEM =
-{
-  0x32,  // command
-  0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GxGDEH029A1_LUTDefault_part[] PROGMEM =
-{
-  0x32,  // command
-  0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const uint8_t GxGDEW027W3_lut_20_vcomDC[] PROGMEM =
-{
-0x00  ,0x00 ,
-0x00  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,    
-0x00  ,0x32 ,0x32 ,0x00 ,0x00 ,0x02,    
-0x00  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,    
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,    
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,    
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,    
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-};
-//R21H
-const uint8_t GxGDEW027W3_lut_21_ww[] PROGMEM =
-{
-0x50  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x60  ,0x32 ,0x32 ,0x00 ,0x00 ,0x02,
-0xA0  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-};
-//R22H  r
-const uint8_t GxGDEW027W3_lut_22_bw[] PROGMEM =
-{
-0x50  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x60  ,0x32 ,0x32 ,0x00 ,0x00 ,0x02,
-0xA0  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-};
-//R23H  w
-const uint8_t GxGDEW027W3_lut_23_wb[] PROGMEM =
-{
-0xA0  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x60  ,0x32 ,0x32 ,0x00 ,0x00 ,0x02,
-0x50  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-};
-//R24H  b
-const uint8_t GxGDEW027W3_lut_24_bb[] PROGMEM =
-{
-0xA0  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x60  ,0x32 ,0x32 ,0x00 ,0x00 ,0x02,
-0x50  ,0x0F ,0x0F ,0x00 ,0x00 ,0x05,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-0x00  ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,
-};
-
-const uint8_t GxGDEW0154Z04_lut_20_vcom0[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x06 , 0x04 , 0x0A , 0x0A , 0x0F , 0x03 , 0x03 , 0x0C , 0x06 , 0x0A , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_21_w[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x46 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x86 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_22_b[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x4A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_23_g1[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_24_g2[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
-const uint8_t GxGDEW0154Z04_lut_25_vcom1[] PROGMEM = {  0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_26_red0[] PROGMEM = { 0x83  , 0x5D , 0x01 , 0x81 , 0x48 , 0x23 , 0x77 , 0x77 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-const uint8_t GxGDEW0154Z04_lut_27_red1[] PROGMEM = { 0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
-
-const uint8_t GxGDEW027C44_lut_20_vcomDC[] PROGMEM =
-{
-  0x00  , 0x00,
-  0x00  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R21H
-const uint8_t GxGDEW027C44_lut_21[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R22H  r
-const uint8_t GxGDEW027C44_lut_22_red[] PROGMEM = {
-  0xA0  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x90  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0xB0  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0xB0  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0xC0  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R23H  w
-const uint8_t GxGDEW027C44_lut_23_white[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-//R24H  b
-const uint8_t GxGDEW027C44_lut_24_black[] PROGMEM = {
-  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
-  0x20  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
-  0x10  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
-  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
-  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
-  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
-};
-
-const unsigned char GxGDEW042T2_lut_20_vcom0_full[] PROGMEM =
-{
-0x40, 0x17, 0x00, 0x00, 0x00, 0x02,        
-0x00, 0x17, 0x17, 0x00, 0x00, 0x02,        
-0x00, 0x0A, 0x01, 0x00, 0x00, 0x01,        
-0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02,        
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_21_ww_full[] PROGMEM =
-{
-0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
-0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
-0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
-0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_22_bw_full[] PROGMEM =
-{
-0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
-0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
-0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
-0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     
-};
-
-const unsigned char GxGDEW042T2_lut_23_wb_full[] PROGMEM =
-{
-0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
-0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
-0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
-0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,         
-};
-
-const unsigned char GxGDEW042T2_lut_24_bb_full[] PROGMEM =
-{
-0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
-0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
-0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
-0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        
-};
-
-#define TP0A  2 // sustain phase for bb and ww, change phase for bw and wb
-#define TP0B 45 // change phase for bw and wb
-
-const unsigned char GxGDEW042T2_lut_20_vcom0_partial[] PROGMEM =
-{
-  0x00,
-  TP0A, TP0B, 0x01, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_21_ww_partial[] PROGMEM =
-{
-  0x80, // 10 00 00 00
-  TP0A, TP0B, 0x01, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_22_bw_partial[] PROGMEM =
-{
-  0xA0, // 10 10 00 00
-  TP0A, TP0B, 0x01, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_23_wb_partial[] PROGMEM =
-{
-  0x50, // 01 01 00 00
-  TP0A, TP0B, 0x01, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const unsigned char GxGDEW042T2_lut_24_bb_partial[] PROGMEM =
-{
-  0x40, // 01 00 00 00
-  TP0A, TP0B, 0x01, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-#endif
-

+ 71 - 0
src/epd3c/WaveTables3c.h

@@ -0,0 +1,71 @@
+#ifndef _WaveTables3c_H_
+#define _WaveTables3c_H_
+
+#if defined(ESP8266) || defined(ESP32)
+#include <pgmspace.h>
+#else
+#include <avr/pgmspace.h>
+#endif
+
+const uint8_t GxGDEW0154Z04_lut_20_vcom0[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x06 , 0x04 , 0x0A , 0x0A , 0x0F , 0x03 , 0x03 , 0x0C , 0x06 , 0x0A , 0x00 };
+const uint8_t GxGDEW0154Z04_lut_21_w[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x0A , 0x46 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x86 , 0x0A , 0x04 };
+const uint8_t GxGDEW0154Z04_lut_22_b[] PROGMEM = {  0x0E  , 0x14 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x4A , 0x04 };
+const uint8_t GxGDEW0154Z04_lut_23_g1[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
+const uint8_t GxGDEW0154Z04_lut_24_g2[] PROGMEM = { 0x8E  , 0x94 , 0x01 , 0x8A , 0x06 , 0x04 , 0x8A , 0x4A , 0x0F , 0x83 , 0x43 , 0x0C , 0x06 , 0x0A , 0x04 };
+const uint8_t GxGDEW0154Z04_lut_25_vcom1[] PROGMEM = {  0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
+const uint8_t GxGDEW0154Z04_lut_26_red0[] PROGMEM = { 0x83  , 0x5D , 0x01 , 0x81 , 0x48 , 0x23 , 0x77 , 0x77 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
+const uint8_t GxGDEW0154Z04_lut_27_red1[] PROGMEM = { 0x03  , 0x1D , 0x01 , 0x01 , 0x08 , 0x23 , 0x37 , 0x37 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
+
+const uint8_t GxGDEW027C44_lut_20_vcomDC[] PROGMEM =
+{
+  0x00  , 0x00,
+  0x00  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
+  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x00  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
+  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
+  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
+  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
+};
+//R21H
+const uint8_t GxGDEW027C44_lut_21[] PROGMEM = {
+  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
+  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
+  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
+  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
+  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
+};
+//R22H  r
+const uint8_t GxGDEW027C44_lut_22_red[] PROGMEM = {
+  0xA0  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
+  0x00  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
+  0x90  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0xB0  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
+  0xB0  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
+  0xC0  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
+};
+//R23H  w
+const uint8_t GxGDEW027C44_lut_23_white[] PROGMEM = {
+  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
+  0x40  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
+  0x80  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
+  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
+  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
+};
+//R24H  b
+const uint8_t GxGDEW027C44_lut_24_black[] PROGMEM = {
+  0x90  , 0x1A  , 0x1A  , 0x00  , 0x00  , 0x01,
+  0x20  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x84  , 0x0E  , 0x01  , 0x0E  , 0x01  , 0x10,
+  0x10  , 0x0A  , 0x0A  , 0x00  , 0x00  , 0x08,
+  0x00  , 0x04  , 0x10  , 0x00  , 0x00  , 0x05,
+  0x00  , 0x03  , 0x0E  , 0x00  , 0x00  , 0x0A,
+  0x00  , 0x23  , 0x00  , 0x00  , 0x00  , 0x01
+};
+
+#endif