-
Hi! I am using the Waveshare 7.5'' b/w/r display (GDEW075Z08) with a Firebeetle 2 ESP32-C6 for a battery-powered project. I have noticed that the partial refresh, which takes less than 2 seconds in the Waveshare library, takes as long as the full refresh in your library. I assume that some models have support for a faster partial refresh, like in the FastBlackWhiteOnColor example. So, would it be possible to adapt the library so that the GDEW075Z08 can also do a quick b/w partial refresh? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Yes, it is possible. This display has true partial window refresh. I will consider to add it when I have time for it. |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for your time writing up this awesome library in your free time @ZinggJM ! I am also eagerly waiting with my hands crossed when this feature will be available in the mainstream. I did take a look at the Just a few things to make the implementation as easy as possible, as your time is precious:
Missing implementations, which can probably be copy-pasted from class GxEPD2_750c_Z08 : public GxEPD2_EPD
{
public:
void writeImageNew(const uint8_t* black, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
void writeImagePrevious(const uint8_t* black, int16_t x, int16_t y, int16_t w, int16_t h, bool invert = false, bool mirror_y = false, bool pgm = false);
void writeImagePartNew(const uint8_t* black, 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 writeImagePartPrevious(const uint8_t* black, 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 refresh_bw(int16_t x, int16_t y, int16_t w, int16_t h);
private:
void _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);
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, bool mirror_y, bool pgm);
} My take on the implementation of said functions in he void GxEPD2_750c_Z08::_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
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;
_Init_Part();
_writeCommand(0x91); // partial in
_setPartialRamArea(x1, y1, w1, h1);
_writeCommand(command);
for (int16_t i = 0; i < h1; i++)
{
for (int16_t j = 0; j < w1 / 8; j++)
{
uint8_t data = 0xFF;
if (bitmap)
{
// 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_750c_Z08::_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;
if ((y_part < 0) || (y_part >= h_bitmap)) return;
int16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
x_part -= x_part % 8; // byte boundary
w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
x -= x % 8; // byte boundary
w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
int16_t x1 = x < 0 ? 0 : x; // limit
int16_t y1 = y < 0 ? 0 : y; // limit
int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
int16_t dx = x1 - x;
int16_t dy = y1 - y;
w1 -= dx;
h1 -= dy;
if ((w1 <= 0) || (h1 <= 0)) return;
if (!_using_partial_mode) _Init_Part();
_writeCommand(0x91); // partial in
_setPartialRamArea(x1, y1, w1, h1);
_writeCommand(command);
for (int16_t i = 0; i < h1; i++)
{
for (int16_t j = 0; j < w1 / 8; j++)
{
uint8_t data;
// use wb_bitmap, h_bitmap of bitmap for index!
int16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + ((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + (y_part + i + dy) * wb_bitmap;
if (pgm)
{
#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
data = pgm_read_byte(&bitmap[idx]);
#else
data = bitmap[idx];
#endif
}
else
{
data = bitmap[idx];
}
if (invert) data = ~data;
_writeData(data);
}
}
_writeCommand(0x92); // partial out
delay(1); // yield() to avoid WDT on ESP8266 and ESP32
}
void GxEPD2_750c_Z08::writeImageNew(const uint8_t* black, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
{
_writeImage(0x13, black, x, y, w, h, invert, mirror_y, pgm);
}
void GxEPD2_750c_Z08::writeImagePrevious(const uint8_t* black, int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
{
_writeImage(0x10, black, x, y, w, h, invert, mirror_y, pgm);
}
void GxEPD2_750c_Z08::writeImagePartNew(const uint8_t* black, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
{
_writeImagePart(0x13, black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
}
void GxEPD2_750c_Z08::writeImagePartPrevious(const uint8_t* black, int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
{
_writeImagePart(0x10, black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
}
void GxEPD2_750c_Z08::refresh_bw(int16_t x, int16_t y, int16_t w, int16_t h)
{
x -= x % 8;
w += (8 - (w % 8)) % 8;
int16_t x1 = x < 0 ? 0 : x;
int16_t y1 = y < 0 ? 0 : y;
int16_t w1 = (x + w < int16_t(WIDTH)) ? w : int16_t(WIDTH) - x;
int16_t h1 = (y + h < int16_t(HEIGHT)) ? h : int16_t(HEIGHT) - y;
if ((w1 <= 0) || (h1 <= 0)) return;
_Init_Part();
_writeCommand(0x91); // partial in
_setPartialRamArea(x1, y1, w1, h1);
_Update_Part();
_writeCommand(0x92); // partial out
} A working example to test this out would be awesome 🙏 |
Beta Was this translation helpful? Give feedback.
Yes, it is possible. This display has true partial window refresh. I will consider to add it when I have time for it.