Răsfoiți Sursa

Version 1.1.8

- fix for incomplete download in GxEPD2_WiFi_Example
- added missing method displayWindow() to GxEPD2_GFX base class
- fix and clean up of initial refresh for panels with differential update
- add clean of controller buffer(s) on initial write to controller, for partial update.
ZinggJM 7 ani în urmă
părinte
comite
febed07c1b

+ 8 - 1
README.md

@@ -67,7 +67,14 @@
 #### other supported panels
 - ED060SCT        6" grey levels, on Waveshare e-Paper IT8951 Driver HAT
 
-### Version 1.1.7
+### Version 1.1.8
+- fix for incomplete download in GxEPD2_WiFi_Example
+- added missing method displayWindow() to GxEPD2_GFX base class
+- fix and clean up of initial refresh for panels with differential update
+- initial refresh needs to be full update, not "fast partial update", for these panels,
+- as the screen content may differ from the "previous buffer" content.
+- add clean of controller buffer(s) on initial write to controller, for partial update.
+#### Version 1.1.7
 - enhanced support for full buffered, non-paged use, for processors with enough RAM
 - use void display(bool partial_update_mode = false); corresponds to update() in  GxEPD
 - use added void displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);

+ 2 - 1
examples/GxEPD2_Example/GxEPD2_Example.ino

@@ -15,13 +15,14 @@
 
 // mapping suggestion from Waveshare SPI e-Paper to Wemos D1 mini
 // BUSY -> D2, RST -> D4, DC -> D3, CS -> D8, CLK -> D5, DIN -> D7, 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 from Waveshare SPI e-Paper to generic ESP8266
 // BUSY -> GPIO4, RST -> GPIO2, DC -> GPIO0, 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 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

+ 6 - 6
examples/GxEPD2_Spiffs_Loader/GxEPD2_Spiffs_Loader.ino

@@ -178,7 +178,7 @@ void downloadFile_HTTP(const char* host, const char* path, const char* filename,
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   bool ok = false;
-  while (client.connected())
+  while (client.connected() || client.available())
   {
     String line = client.readStringUntil('\n');
     if (!ok)
@@ -212,7 +212,7 @@ void downloadFile_HTTP(const char* host, const char* path, const char* filename,
     Serial.print(target); Serial.println(" open failed");
     return;
   }
-  while (client.connected())
+  while (client.connected() || client.available())
   {
     size_t available = client.available();
     size_t fetch = available <= sizeof(buffer) ? available : sizeof(buffer);
@@ -268,7 +268,7 @@ void downloadFile_HTTPS(const char* host, const char* path, const char* filename
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   bool ok = false;
-  while (client.connected())
+  while (client.connected() || client.available())
   {
     String line = client.readStringUntil('\n');
     if (!ok)
@@ -302,17 +302,17 @@ void downloadFile_HTTPS(const char* host, const char* path, const char* filename
     Serial.print(target); Serial.println(" open failed");
     return;
   }
-  while (client.connected())
+  while (client.connected() || client.available())
   {
     // this doesn't work as expected, but it helps for long downloads
     int32_t start = millis();
     for (int16_t t = 0, dly = 50; t < 20; t++, dly += 50)
     {
-      if (!client.connected()) break;
+      if (!(client.connected() || client.available())) break;
       if (client.available()) break; // read would not recover after having returned 0
       delay(dly);
     }
-    if (!client.connected()) break;
+    if (!(client.connected() || client.available())) break;
     int32_t elapsed = millis() - start;
     if (elapsed > 250)
     {

+ 16 - 16
examples/GxEPD2_WiFi_Example/GxEPD2_WiFi_Example.ino

@@ -354,7 +354,7 @@ void showBitmapFrom_HTTP(const char* host, const char* path, const char* filenam
   Serial.println(String("http://") + host + path + filename);
   client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
-               "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
+               "User-Agent: GxEPD2_WiFi_Example\r\n" +
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   while (client.connected())
@@ -443,7 +443,7 @@ void showBitmapFrom_HTTP(const char* host, const char* path, const char* filenam
         bytes_read += skip(client, rowPosition - bytes_read);
         for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
         {
-          if (!connection_ok || !client.connected()) break;
+          if (!connection_ok || !(client.connected() || client.available())) break;
           delay(1); // yield() to avoid WDT
           uint32_t in_remain = rowSize;
           uint32_t in_idx = 0;
@@ -456,7 +456,7 @@ void showBitmapFrom_HTTP(const char* host, const char* path, const char* filenam
           for (uint16_t col = 0; col < w; col++) // for each pixel
           {
             yield();
-            if (!connection_ok || !client.connected()) break;
+            if (!connection_ok || !(client.connected() || client.available())) break;
             // Time to read more pixel data?
             if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
             {
@@ -580,7 +580,7 @@ void drawBitmapFrom_HTTP_ToBuffer(const char* host, const char* path, const char
   Serial.println(String("http://") + host + path + filename);
   client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
-               "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
+               "User-Agent: GxEPD2_WiFi_Example\r\n" +
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   while (client.connected())
@@ -671,7 +671,7 @@ void drawBitmapFrom_HTTP_ToBuffer(const char* host, const char* path, const char
         bytes_read += skip(client, rowPosition - bytes_read);
         for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
         {
-          if (!connection_ok || !client.connected()) break;
+          if (!connection_ok || !(client.connected() || client.available())) break;
           delay(1); // yield() to avoid WDT
           uint32_t in_remain = rowSize;
           uint32_t in_idx = 0;
@@ -682,7 +682,7 @@ void drawBitmapFrom_HTTP_ToBuffer(const char* host, const char* path, const char
           for (uint16_t col = 0; col < w; col++) // for each pixel
           {
             yield();
-            if (!connection_ok || !client.connected()) break;
+            if (!connection_ok || !(client.connected() || client.available())) break;
             // Time to read more pixel data?
             if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
             {
@@ -830,7 +830,7 @@ void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filena
   Serial.println(String("https://") + host + path + filename);
   client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
-               "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
+               "User-Agent: GxEPD2_WiFi_Example\r\n" +
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   while (client.connected())
@@ -919,7 +919,7 @@ void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filena
         bytes_read += skip(client, rowPosition - bytes_read);
         for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
         {
-          if (!connection_ok || !client.connected()) break;
+          if (!connection_ok || !(client.connected() || client.available())) break;
           delay(1); // yield() to avoid WDT
           uint32_t in_remain = rowSize;
           uint32_t in_idx = 0;
@@ -932,7 +932,7 @@ void showBitmapFrom_HTTPS(const char* host, const char* path, const char* filena
           for (uint16_t col = 0; col < w; col++) // for each pixel
           {
             yield();
-            if (!connection_ok || !client.connected()) break;
+            if (!connection_ok || !(client.connected() || client.available())) break;
             // Time to read more pixel data?
             if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
             {
@@ -1077,7 +1077,7 @@ void drawBitmapFrom_HTTPS_ToBuffer(const char* host, const char* path, const cha
   Serial.println(String("https://") + host + path + filename);
   client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
-               "User-Agent: GxEPD2_Spiffs_Loader\r\n" +
+               "User-Agent: GxEPD2_WiFi_Example\r\n" +
                "Connection: close\r\n\r\n");
   Serial.println("request sent");
   while (client.connected())
@@ -1168,7 +1168,7 @@ void drawBitmapFrom_HTTPS_ToBuffer(const char* host, const char* path, const cha
         bytes_read += skip(client, rowPosition - bytes_read);
         for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
         {
-          if (!connection_ok || !client.connected()) break;
+          if (!connection_ok || !(client.connected() || client.available())) break;
           delay(1); // yield() to avoid WDT
           uint32_t in_remain = rowSize;
           uint32_t in_idx = 0;
@@ -1179,7 +1179,7 @@ void drawBitmapFrom_HTTPS_ToBuffer(const char* host, const char* path, const cha
           for (uint16_t col = 0; col < w; col++) // for each pixel
           {
             yield();
-            if (!connection_ok || !client.connected()) break;
+            if (!connection_ok || !(client.connected() || client.available())) break;
             // Time to read more pixel data?
             if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
             {
@@ -1312,7 +1312,7 @@ uint32_t skip(BearSSL::WiFiClientSecure& client, int32_t bytes)
 {
   int32_t remain = bytes;
   uint32_t start = millis();
-  while (client.connected() && (remain > 0))
+  while ((client.connected() || client.available()) && (remain > 0))
   {
     if (client.available())
     {
@@ -1329,7 +1329,7 @@ uint32_t read(BearSSL::WiFiClientSecure& client, uint8_t* buffer, int32_t bytes)
 {
   int32_t remain = bytes;
   uint32_t start = millis();
-  while (client.connected() && (remain > 0))
+  while ((client.connected() || client.available()) && (remain > 0))
   {
     if (client.available())
     {
@@ -1349,7 +1349,7 @@ uint32_t skip(WiFiClient& client, int32_t bytes)
 {
   int32_t remain = bytes;
   uint32_t start = millis();
-  while (client.connected() && (remain > 0))
+  while ((client.connected() || client.available()) && (remain > 0))
   {
     if (client.available())
     {
@@ -1366,7 +1366,7 @@ uint32_t read(WiFiClient& client, uint8_t* buffer, int32_t bytes)
 {
   int32_t remain = bytes;
   uint32_t start = millis();
-  while (client.connected() && (remain > 0))
+  while ((client.connected() || client.available()) && (remain > 0))
   {
     if (client.available())
     {

+ 1 - 1
extras/Particle/examples/GxEPD2_ParticleExample/project.properties

@@ -1,2 +1,2 @@
 name=GxEPD2_ParticleExample
-dependencies.GxEPD2=1.1.7
+dependencies.GxEPD2=1.1.8

+ 1 - 1
library.properties

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

+ 4 - 1
src/GxEPD2_EPD.cpp

@@ -23,6 +23,8 @@ GxEPD2_EPD::GxEPD2_EPD(int8_t cs, int8_t dc, int8_t rst, int8_t busy, int8_t bus
   _cs(cs), _dc(dc), _rst(rst), _busy(busy), _busy_level(busy_level), _busy_timeout(busy_timeout), _diag_enabled(false),
   _spi_settings(4000000, MSBFIRST, SPI_MODE0)
 {
+  _initial_write = true;
+  _initial_refresh = true;
   _power_is_on = false;
   _using_partial_mode = false;
   _hibernating = false;
@@ -35,7 +37,8 @@ void GxEPD2_EPD::init(uint32_t serial_diag_bitrate)
 
 void GxEPD2_EPD::init(uint32_t serial_diag_bitrate, bool initial, bool pulldown_rst_mode)
 {
-  _initial = initial;
+  _initial_write = initial;
+  _initial_refresh = initial;
   _pulldown_rst_mode = pulldown_rst_mode;
   _power_is_on = false;
   _using_partial_mode = false;

+ 2 - 1
src/GxEPD2_EPD.h

@@ -93,7 +93,8 @@ class GxEPD2_EPD
     uint32_t _busy_timeout;
     bool _diag_enabled, _pulldown_rst_mode;
     SPISettings _spi_settings;
-    bool _initial, _power_is_on, _using_partial_mode, _hibernating;
+    bool _initial_write, _initial_refresh; 
+    bool _power_is_on, _using_partial_mode, _hibernating;
 };
 
 #endif

+ 9 - 0
src/GxEPD2_GFX.h

@@ -13,6 +13,7 @@
 #define _GxEPD2_GFX_H_
 
 #include <Adafruit_GFX.h>
+#include <GxEPD2_EPD.h>
 
 class GxEPD2_GFX : public Adafruit_GFX
 {
@@ -29,7 +30,15 @@ class GxEPD2_GFX : public Adafruit_GFX
     // pulldown_rst_mode true for alternate RST handling to avoid feeding 5V through RST pin
     virtual void init(uint32_t serial_diag_bitrate, bool initial, bool pulldown_rst_mode = false) = 0;
     virtual void fillScreen(uint16_t color) = 0; // 0x0 black, >0x0 white, to buffer
+    // display buffer content to screen, useful for full screen buffer
     virtual void display(bool partial_update_mode = false) = 0;
+    // display part of buffer content to screen, useful for full screen buffer
+    // displayWindow, 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 displayWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) = 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,

+ 10 - 3
src/epd/GxEPD2_154.cpp

@@ -19,7 +19,8 @@ GxEPD2_154::GxEPD2_154(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_154::clearScreen(uint8_t value)
 {
-  if (_initial)
+  _initial_write = false; // initial full screen buffer clean done
+  if (_initial_refresh)
   {
     _Init_Full();
     _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -29,6 +30,7 @@ void GxEPD2_154::clearScreen(uint8_t value)
       _writeData(value);
     }
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
   else
   {
@@ -49,12 +51,13 @@ void GxEPD2_154::clearScreen(uint8_t value)
     _writeData(value);
   }
   _Update_Part();
-  _initial = false;
 }
 
 void GxEPD2_154::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
+  _initial_write = false; // initial full screen buffer clean done
+  // this controller has no command to write "old data"
+  if (_initial_refresh) clearScreen(value);
   else _writeScreenBuffer(value);
 }
 
@@ -71,6 +74,7 @@ void GxEPD2_154::_writeScreenBuffer(uint8_t value)
 
 void GxEPD2_154::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -116,6 +120,7 @@ void GxEPD2_154::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_154::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -233,11 +238,13 @@ void GxEPD2_154::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_154::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 10 - 3
src/epd/GxEPD2_213.cpp

@@ -19,7 +19,8 @@ GxEPD2_213::GxEPD2_213(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_213::clearScreen(uint8_t value)
 {
-  if (_initial)
+  _initial_write = false; // initial full screen buffer clean done
+  if (_initial_refresh)
   {
     _Init_Full();
     _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -29,6 +30,7 @@ void GxEPD2_213::clearScreen(uint8_t value)
       _writeData(value);
     }
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
   else
   {
@@ -49,12 +51,13 @@ void GxEPD2_213::clearScreen(uint8_t value)
     _writeData(value);
   }
   _Update_Part();
-  _initial = false;
 }
 
 void GxEPD2_213::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
+  _initial_write = false; // initial full screen buffer clean done
+  // this controller has no command to write "old data"
+  if (_initial_refresh) clearScreen(value);
   else _writeScreenBuffer(value);
 }
 
@@ -71,6 +74,7 @@ void GxEPD2_213::_writeScreenBuffer(uint8_t value)
 
 void GxEPD2_213::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -116,6 +120,7 @@ void GxEPD2_213::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_213::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -233,11 +238,13 @@ void GxEPD2_213::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_213::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 9 - 35
src/epd/GxEPD2_213_B72.cpp

@@ -19,45 +19,14 @@ GxEPD2_213_B72::GxEPD2_213_B72(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_213_B72::clearScreen(uint8_t value)
 {
-  if (_initial)
-  {
-    _Init_Full();
-    _writeCommand(0x26); // preset previous
-    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
-    {
-      _writeData(0xFF); // 0xFF is white
-    }
-    _writeCommand(0x24); // 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();
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x24); // set current
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
-  {
-    _writeData(value);
-  }
-  _Update_Part();
-  _writeCommand(0x26); // set previous same
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
-  {
-    _writeData(value);
-  }
+  writeScreenBuffer(value);
+  refresh(true);
+  writeScreenBufferAgain(value);
 }
 
 void GxEPD2_213_B72::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_213_B72::_writeScreenBuffer(uint8_t value)
-{
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
   _writeCommand(0x24);
@@ -65,6 +34,7 @@ void GxEPD2_213_B72::_writeScreenBuffer(uint8_t value)
   {
     _writeData(value);
   }
+  if (_initial_refresh) writeScreenBufferAgain(value); // init "old data"
 }
 
 void GxEPD2_213_B72::writeScreenBufferAgain(uint8_t value)
@@ -90,6 +60,7 @@ void GxEPD2_213_B72::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t
 
 void GxEPD2_213_B72::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -147,6 +118,7 @@ void GxEPD2_213_B72::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part,
 void GxEPD2_213_B72::_writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                      int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -267,11 +239,13 @@ void GxEPD2_213_B72::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_213_B72::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 0 - 1
src/epd/GxEPD2_213_B72.h

@@ -66,7 +66,6 @@ class GxEPD2_213_B72 : public GxEPD2_EPD
     void _writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
     void _writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                          int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
-    void _writeScreenBuffer(uint8_t value);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
     void _PowerOn();
     void _PowerOff();

+ 17 - 44
src/epd/GxEPD2_213_flex.cpp

@@ -19,63 +19,33 @@ GxEPD2_213_flex::GxEPD2_213_flex(int8_t cs, int8_t dc, int8_t rst, int8_t busy)
 
 void GxEPD2_213_flex::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;
+  writeScreenBuffer(value);
+  refresh(true);
+  writeScreenBuffer(value);
 }
 
 void GxEPD2_213_flex::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_213_flex::_writeScreenBuffer(uint8_t value)
-{
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x13);
+  _writeCommand(0x13); // set current
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
   {
     _writeData(value);
   }
-  _writeCommand(0x92); // partial out
+  if (_initial_refresh)
+  {
+    _writeCommand(0x10); // preset previous
+    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+    {
+      _writeData(0xFF); // 0xFF is white
+    }
+  }
 }
 
 void GxEPD2_213_flex::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -123,6 +93,7 @@ void GxEPD2_213_flex::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, i
 void GxEPD2_213_flex::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                      int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -242,11 +213,13 @@ void GxEPD2_213_flex::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_213_flex::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 0 - 1
src/epd/GxEPD2_213_flex.h

@@ -58,7 +58,6 @@ class GxEPD2_213_flex : public GxEPD2_EPD
     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();

+ 15 - 41
src/epd/GxEPD2_270.cpp

@@ -19,56 +19,26 @@ GxEPD2_270::GxEPD2_270(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_270::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();
-  _setPartialRamArea(0x15, 0, 0, WIDTH, HEIGHT);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
-  {
-    _writeData(value);
-  }
-  _refreshWindow(0, 0, WIDTH, HEIGHT);
-  _waitWhileBusy("clearScreen", partial_refresh_time);
-  _setPartialRamArea(0x14, 0, 0, WIDTH, HEIGHT);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
-  {
-    _writeData(value);
-  }
+  writeScreenBuffer(value);
+  refresh(true);
+  writeScreenBufferAgain(value);
 }
 
 void GxEPD2_270::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_270::_writeScreenBuffer(uint8_t value)
-{
-  _Init_Part();
-  _setPartialRamArea(0x15, 0, 0, WIDTH, HEIGHT);
+  _initial_write = false; // initial full screen buffer clean done
+  if (!_using_partial_mode) _Init_Part();
+  _writeCommand(0x13); // set current
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
   {
     _writeData(value);
   }
+  if (_initial_refresh) writeScreenBufferAgain(value); // init "old data"
 }
 
 void GxEPD2_270::writeScreenBufferAgain(uint8_t value)
 {
-  _Init_Part();
+  if (!_using_partial_mode) _Init_Part();
   _setPartialRamArea(0x14, 0, 0, WIDTH, HEIGHT);
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
   {
@@ -88,6 +58,7 @@ void GxEPD2_270::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, i
 
 void GxEPD2_270::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -130,20 +101,21 @@ void GxEPD2_270::_writeImage(uint8_t command, const uint8_t bitmap[], int16_t x,
 }
 
 void GxEPD2_270::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   _writeImagePart(0x15, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
 }
 
 void GxEPD2_270::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-    int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                     int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   _writeImagePart(0x14, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
 }
 
 void GxEPD2_270::_writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -263,11 +235,13 @@ void GxEPD2_270::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_270::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 0 - 1
src/epd/GxEPD2_270.h

@@ -66,7 +66,6 @@ class GxEPD2_270 : public GxEPD2_EPD
     void _writeImage(uint8_t command, const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
     void _writeImagePart(uint8_t command, const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                          int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
-    void _writeScreenBuffer(uint8_t value);
     void _setPartialRamArea(uint8_t command, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
     void _refreshWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
     void _PowerOn();

+ 10 - 3
src/epd/GxEPD2_290.cpp

@@ -19,7 +19,8 @@ GxEPD2_290::GxEPD2_290(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_290::clearScreen(uint8_t value)
 {
-  if (_initial)
+  _initial_write = true; // initial full screen buffer clean done
+  if (_initial_refresh)
   {
     _Init_Full();
     _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -29,6 +30,7 @@ void GxEPD2_290::clearScreen(uint8_t value)
       _writeData(value);
     }
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
   else
   {
@@ -49,12 +51,13 @@ void GxEPD2_290::clearScreen(uint8_t value)
     _writeData(value);
   }
   _Update_Part();
-  _initial = false;
 }
 
 void GxEPD2_290::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
+  _initial_write = false; // initial full screen buffer clean done
+  // this controller has no command to write "old data"
+  if (_initial_refresh) clearScreen(value);
   else _writeScreenBuffer(value);
 }
 
@@ -71,6 +74,7 @@ void GxEPD2_290::_writeScreenBuffer(uint8_t value)
 
 void GxEPD2_290::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -116,6 +120,7 @@ void GxEPD2_290::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_290::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -233,11 +238,13 @@ void GxEPD2_290::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_290::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 21 - 48
src/epd/GxEPD2_290_T5.cpp

@@ -19,63 +19,33 @@ GxEPD2_290_T5::GxEPD2_290_T5(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 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;
+  writeScreenBuffer(value);
+  refresh(true);
+  writeScreenBuffer(value);
 }
 
 void GxEPD2_290_T5::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_290_T5::_writeScreenBuffer(uint8_t value)
-{
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x13);
+  _writeCommand(0x13); // set current
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
   {
     _writeData(value);
   }
-  _writeCommand(0x92); // partial out
+  if (_initial_refresh)
+  {
+    _writeCommand(0x10); // preset previous
+    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
+    {
+      _writeData(0xFF); // 0xFF is white
+    }
+  }
 }
 
 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)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -121,8 +91,9 @@ void GxEPD2_290_T5::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int
 }
 
 void GxEPD2_290_T5::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                   int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -182,7 +153,7 @@ void GxEPD2_290_T5::writeImage(const uint8_t* black, const uint8_t* color, int16
 }
 
 void GxEPD2_290_T5::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                   int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   if (black)
   {
@@ -206,7 +177,7 @@ void GxEPD2_290_T5::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int1
 }
 
 void GxEPD2_290_T5::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                               int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
   refresh(x, y, w, h);
@@ -221,7 +192,7 @@ void GxEPD2_290_T5::drawImage(const uint8_t* black, const uint8_t* color, int16_
 }
 
 void GxEPD2_290_T5::drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                               int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
   refresh(x, y, w, h);
@@ -242,11 +213,13 @@ void GxEPD2_290_T5::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_290_T5::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 0 - 1
src/epd/GxEPD2_290_T5.h

@@ -58,7 +58,6 @@ class GxEPD2_290_T5 : public GxEPD2_EPD
     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();

+ 15 - 37
src/epd/GxEPD2_420.cpp

@@ -19,58 +19,33 @@ GxEPD2_420::GxEPD2_420(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_420::clearScreen(uint8_t value)
 {
-  if (_initial)
+  writeScreenBuffer(value);
+  refresh(true);
+  writeScreenBuffer(value);
+}
+
+void GxEPD2_420::writeScreenBuffer(uint8_t value)
+{
+  _initial_write = false; // initial full screen buffer clean done
+  if (!_using_partial_mode) _Init_Part();
+  if (_initial_refresh)
   {
-    _Init_Full();
-    _writeCommand(0x13);
+    _writeCommand(0x10); // init old data
     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_420::writeScreenBuffer(uint8_t value)
-{
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_420::_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_420::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -118,6 +93,7 @@ void GxEPD2_420::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_420::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -237,11 +213,13 @@ void GxEPD2_420::refresh(bool partial_update_mode)
   {
     if (_using_partial_mode) _Init_Full();
     _Update_Full();
+    _initial_refresh = false; // initial full update done
   }
 }
 
 void GxEPD2_420::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
 {
+  if (_initial_refresh) return refresh(false); // initial update needs be full update
   x -= x % 8; // byte boundary
   w -= x % 8; // byte boundary
   int16_t x1 = x < 0 ? 0 : x; // limit

+ 0 - 1
src/epd/GxEPD2_420.h

@@ -58,7 +58,6 @@ class GxEPD2_420 : public GxEPD2_EPD
     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();

+ 7 - 40
src/epd/GxEPD2_583.cpp

@@ -19,60 +19,25 @@ GxEPD2_583::GxEPD2_583(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_583::clearScreen(uint8_t value)
 {
-  if (value == 0xFF) value = 0x33; // white value for this controller
-  if (_initial)
-  {
-    _Init_Full();
-    _writeCommand(0x10);
-    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-    {
-      _writeData(value);
-    }
-    _Update_Full();
-    _initial = false;
-  }
-  if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x10);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-  {
-    _writeData(value);
-  }
-  _Update_Part();
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x10);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-  {
-    _writeData(value);
-  }
-  _Update_Part();
-  _writeCommand(0x92); // partial out
-  _initial = false;
+  writeScreenBuffer(value);
+  refresh(true);
 }
 
 void GxEPD2_583::writeScreenBuffer(uint8_t value)
 {
-  if (value == 0xFF) value = 0x33; // white value for this controller
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_583::_writeScreenBuffer(uint8_t value)
-{
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
+  if (value == 0xFF) value = 0x33; // white value for this controller
   _writeCommand(0x10);
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
   {
     _writeData(value);
   }
-  _writeCommand(0x92); // partial out
 }
 
 void GxEPD2_583::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
   x -= x % 8; // byte boundary
@@ -120,6 +85,7 @@ void GxEPD2_583::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_583::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -191,6 +157,7 @@ void GxEPD2_583::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t
 {
   if (data1)
   {
+    if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
     delay(1); // yield() to avoid WDT on ESP8266 and ESP32
     int16_t wb = (w + 1) / 2; // width bytes, bitmaps are padded
     x -= x % 2; // byte boundary

+ 0 - 1
src/epd/GxEPD2_583.h

@@ -58,7 +58,6 @@ class GxEPD2_583 : public GxEPD2_EPD
     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);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
     void _PowerOn();

+ 7 - 40
src/epd/GxEPD2_750.cpp

@@ -19,60 +19,25 @@ GxEPD2_750::GxEPD2_750(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_750::clearScreen(uint8_t value)
 {
-  if (value == 0xFF) value = 0x33; // white value for this controller
-  if (_initial)
-  {
-    _Init_Full();
-    _writeCommand(0x10);
-    for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-    {
-      _writeData(value);
-    }
-    _Update_Full();
-    _initial = false;
-  }
-  if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x10);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-  {
-    _writeData(value);
-  }
-  _Update_Part();
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
-  _writeCommand(0x10);
-  for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
-  {
-    _writeData(value);
-  }
-  _Update_Part();
-  _writeCommand(0x92); // partial out
-  _initial = false;
+  writeScreenBuffer(value);
+  refresh(true);
 }
 
 void GxEPD2_750::writeScreenBuffer(uint8_t value)
 {
-  if (value == 0xFF) value = 0x33; // white value for this controller
-  if (_initial) clearScreen(value);
-  else _writeScreenBuffer(value);
-}
-
-void GxEPD2_750::_writeScreenBuffer(uint8_t value)
-{
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
-  _writeCommand(0x91); // partial in
-  _setPartialRamArea(0, 0, WIDTH, HEIGHT);
+  if (value == 0xFF) value = 0x33; // white value for this controller
   _writeCommand(0x10);
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
   {
     _writeData(value);
   }
-  _writeCommand(0x92); // partial out
 }
 
 void GxEPD2_750::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
   x -= x % 8; // byte boundary
@@ -120,6 +85,7 @@ void GxEPD2_750::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 void GxEPD2_750::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -191,6 +157,7 @@ void GxEPD2_750::writeNative(const uint8_t* data1, const uint8_t* data2, int16_t
 {
   if (data1)
   {
+    if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
     delay(1); // yield() to avoid WDT on ESP8266 and ESP32
     int16_t wb = (w + 1) / 2; // width bytes, bitmaps are padded
     x -= x % 2; // byte boundary

+ 0 - 1
src/epd/GxEPD2_750.h

@@ -58,7 +58,6 @@ class GxEPD2_750 : public GxEPD2_EPD
     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);
     void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
     void _PowerOn();

+ 0 - 1
src/epd3c/GxEPD2_154c.cpp

@@ -61,7 +61,6 @@ void GxEPD2_154c::clearScreen(uint8_t black_value, uint8_t color_value)
     _writeData(color_value);
   }
   _Update_Full();
-  _initial = false;
 }
 
 void GxEPD2_154c::writeScreenBuffer(uint8_t value)

+ 4 - 4
src/epd3c/GxEPD2_213c.cpp

@@ -15,9 +15,6 @@
 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::clearScreen(uint8_t value)
@@ -27,6 +24,7 @@ void GxEPD2_213c::clearScreen(uint8_t value)
 
 void GxEPD2_213c::clearScreen(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -42,7 +40,6 @@ void GxEPD2_213c::clearScreen(uint8_t black_value, uint8_t color_value)
   }
   _Update_Part();
   _writeCommand(0x92); // partial out
-  _initial = false;
 }
 
 void GxEPD2_213c::writeScreenBuffer(uint8_t value)
@@ -52,6 +49,7 @@ void GxEPD2_213c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_213c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -75,6 +73,7 @@ void GxEPD2_213c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_213c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -158,6 +157,7 @@ void GxEPD2_213c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_213c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;

+ 4 - 0
src/epd3c/GxEPD2_270c.cpp

@@ -24,6 +24,7 @@ void GxEPD2_270c::clearScreen(uint8_t value)
 
 void GxEPD2_270c::clearScreen(uint8_t black_value, uint8_t red_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _setPartialRamArea_270c(0x14, 0, 0, WIDTH, HEIGHT);
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
@@ -45,6 +46,7 @@ void GxEPD2_270c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_270c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _setPartialRamArea_270c(0x14, 0, 0, WIDTH, HEIGHT);
   for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
@@ -65,6 +67,7 @@ void GxEPD2_270c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_270c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -145,6 +148,7 @@ void GxEPD2_270c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_270c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;

+ 4 - 1
src/epd3c/GxEPD2_290c.cpp

@@ -24,6 +24,7 @@ void GxEPD2_290c::clearScreen(uint8_t value)
 
 void GxEPD2_290c::clearScreen(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -39,7 +40,6 @@ void GxEPD2_290c::clearScreen(uint8_t black_value, uint8_t color_value)
   }
   _Update_Part();
   _writeCommand(0x92); // partial out
-  _initial = false;
 }
 
 void GxEPD2_290c::writeScreenBuffer(uint8_t value)
@@ -49,6 +49,7 @@ void GxEPD2_290c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_290c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -72,6 +73,7 @@ void GxEPD2_290c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_290c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -155,6 +157,7 @@ void GxEPD2_290c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_290c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;

+ 4 - 1
src/epd3c/GxEPD2_420c.cpp

@@ -24,6 +24,7 @@ void GxEPD2_420c::clearScreen(uint8_t value)
 
 void GxEPD2_420c::clearScreen(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -39,7 +40,6 @@ void GxEPD2_420c::clearScreen(uint8_t black_value, uint8_t color_value)
   }
   _Update_Part();
   _writeCommand(0x92); // partial out
-  _initial = false;
 }
 
 void GxEPD2_420c::writeScreenBuffer(uint8_t value)
@@ -49,6 +49,7 @@ void GxEPD2_420c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_420c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -72,6 +73,7 @@ void GxEPD2_420c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_420c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -155,6 +157,7 @@ void GxEPD2_420c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_420c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;

+ 7 - 0
src/epd3c/GxEPD2_583c.cpp

@@ -19,6 +19,7 @@ GxEPD2_583c::GxEPD2_583c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_583c::clearScreen(uint8_t value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   if (value == 0xFF) value = 0x33; // white value for this controller
   _Init_Part();
   _writeCommand(0x91); // partial in
@@ -34,6 +35,7 @@ void GxEPD2_583c::clearScreen(uint8_t value)
 
 void GxEPD2_583c::clearScreen(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -48,6 +50,7 @@ void GxEPD2_583c::clearScreen(uint8_t black_value, uint8_t color_value)
 
 void GxEPD2_583c::writeScreenBuffer(uint8_t value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   if (value == 0xFF) value = 0x33; // white value for this controller
   _Init_Part();
   _writeCommand(0x91); // partial in
@@ -62,6 +65,7 @@ void GxEPD2_583c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_583c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -80,6 +84,7 @@ void GxEPD2_583c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_583c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
   x -= x % 8; // byte boundary
@@ -158,6 +163,7 @@ void GxEPD2_583c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_583c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -235,6 +241,7 @@ void GxEPD2_583c::writeNative(const uint8_t* data1, const uint8_t* data2, int16_
 {
   if (data1)
   {
+    if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
     delay(1); // yield() to avoid WDT on ESP8266 and ESP32
     int16_t wb = (w + 1) / 2; // width bytes, bitmaps are padded
     x -= x % 2; // byte boundary

+ 7 - 0
src/epd3c/GxEPD2_750c.cpp

@@ -19,6 +19,7 @@ GxEPD2_750c::GxEPD2_750c(int8_t cs, int8_t dc, int8_t rst, int8_t busy) :
 
 void GxEPD2_750c::clearScreen(uint8_t value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   if (value == 0xFF) value = 0x33; // white value for this controller
   _Init_Part();
   _writeCommand(0x91); // partial in
@@ -34,6 +35,7 @@ void GxEPD2_750c::clearScreen(uint8_t value)
 
 void GxEPD2_750c::clearScreen(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -48,6 +50,7 @@ void GxEPD2_750c::clearScreen(uint8_t black_value, uint8_t color_value)
 
 void GxEPD2_750c::writeScreenBuffer(uint8_t value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   if (value == 0xFF) value = 0x33; // white value for this controller
   _Init_Part();
   _writeCommand(0x91); // partial in
@@ -62,6 +65,7 @@ void GxEPD2_750c::writeScreenBuffer(uint8_t value)
 
 void GxEPD2_750c::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   _Init_Part();
   _writeCommand(0x91); // partial in
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
@@ -80,6 +84,7 @@ void GxEPD2_750c::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 
 void GxEPD2_750c::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 (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
   x -= x % 8; // byte boundary
@@ -155,6 +160,7 @@ void GxEPD2_750c::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t
 void GxEPD2_750c::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
                                  int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -232,6 +238,7 @@ void GxEPD2_750c::writeNative(const uint8_t* data1, const uint8_t* data2, int16_
 {
   if (data1)
   {
+    if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
     delay(1); // yield() to avoid WDT on ESP8266 and ESP32
     int16_t wb = (w + 1) / 2; // width bytes, bitmaps are padded
     x -= x % 2; // byte boundary

+ 12 - 7
src/it8951/GxEPD2_it60.cpp

@@ -107,9 +107,10 @@ void GxEPD2_it60::init(uint32_t serial_diag_bitrate, bool initial, bool pulldown
 
 void GxEPD2_it60::clearScreen(uint8_t value)
 {
-  if (_initial) _Init_Full();
+  _initial_write = false; // initial full screen buffer clean done
+  if (_initial_refresh) _Init_Full();
   else _Init_Part();
-  _initial = false;
+  _initial_refresh = false;
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
   SPI.beginTransaction(_spi_settings);
   if (_cs >= 0) digitalWrite(_cs, LOW);
@@ -131,12 +132,13 @@ void GxEPD2_it60::clearScreen(uint8_t value)
 
 void GxEPD2_it60::writeScreenBuffer(uint8_t value)
 {
-  if (_initial) clearScreen(value);
+  if (_initial_refresh) clearScreen(value);
   else _writeScreenBuffer(value);
 }
 
 void GxEPD2_it60::_writeScreenBuffer(uint8_t value)
 {
+  _initial_write = false; // initial full screen buffer clean done
   if (!_using_partial_mode) _Init_Part();
   _setPartialRamArea(0, 0, WIDTH, HEIGHT);
   SPI.beginTransaction(_spi_settings);
@@ -158,6 +160,7 @@ void GxEPD2_it60::_writeScreenBuffer(uint8_t value)
 
 void GxEPD2_it60::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   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
@@ -211,8 +214,9 @@ void GxEPD2_it60::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16
 }
 
 void GxEPD2_it60::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
+  if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
   delay(1); // yield() to avoid WDT on ESP8266 and ESP32
   if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
   if ((x_part < 0) || (x_part >= w_bitmap)) return;
@@ -277,7 +281,7 @@ void GxEPD2_it60::writeImage(const uint8_t* black, const uint8_t* color, int16_t
 }
 
 void GxEPD2_it60::writeImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   if (black)
   {
@@ -289,6 +293,7 @@ void GxEPD2_it60::writeNative(const uint8_t* data1, const uint8_t* data2, int16_
 {
   if (data1)
   {
+    if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
     delay(1); // yield() to avoid WDT on ESP8266 and ESP32
     int16_t x1 = x < 0 ? 0 : x; // limit
     int16_t y1 = y < 0 ? 0 : y; // limit
@@ -346,7 +351,7 @@ void GxEPD2_it60::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_
 }
 
 void GxEPD2_it60::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                               int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
   _refresh(x, y, w, h, true);
@@ -359,7 +364,7 @@ void GxEPD2_it60::drawImage(const uint8_t* black, const uint8_t* color, int16_t
 }
 
 void GxEPD2_it60::drawImagePart(const uint8_t* black, const uint8_t* color, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
-                               int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
+                                int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
 {
   writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
   _refresh(x, y, w, h, true);