Paperd.Ink Library 0.0.5
Library for interacting with Paperd.Ink devices.
Loading...
Searching...
No Matches
GxEPD2_750c_Z90.cpp
Go to the documentation of this file.
1// Display Library for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
2// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
3//
4// based on Demo Example from Good Display: http://www.e-paper-display.com/download_detail/downloadsId=808.html
5// Panel: GDEH075Z90 : http://www.e-paper-display.com/products_detail/productId=535.html
6// Controller: SSD1677 : http://www.e-paper-display.com/SSD1677Specification.pdf
7//
8// Author: Jean-Marc Zingg
9//
10// Version: see library.properties
11//
12// Library: https://github.com/ZinggJM/GxEPD2
13
14#include "GxEPD2_750c_Z90.h"
15
16GxEPD2_750c_Z90::GxEPD2_750c_Z90(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
17 GxEPD2_EPD(cs, dc, rst, busy, HIGH, 25000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
18{
19}
20
22{
23 clearScreen(value, 0xFF);
24}
25
26void GxEPD2_750c_Z90::clearScreen(uint8_t black_value, uint8_t color_value)
27{
28 writeScreenBuffer(black_value, color_value);
29 _Update_Full();
30}
31
33{
34 writeScreenBuffer(value, 0xFF);
35}
36
37void GxEPD2_750c_Z90::writeScreenBuffer(uint8_t black_value, uint8_t color_value)
38{
39 _initial_write = false; // initial full screen buffer clean done
40 _Init_Full();
41 _setPartialRamArea(0, 0, WIDTH, HEIGHT);
42 _writeCommand(0x24);
44 for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
45 {
46 _transfer(black_value);
47 }
49 _writeCommand(0x26);
51 for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
52 {
53 _transfer(~color_value);
54 }
56}
57
58void GxEPD2_750c_Z90::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
59{
60 writeImage(bitmap, NULL, x, y, w, h, invert, mirror_y, pgm);
61}
62
63void GxEPD2_750c_Z90::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)
64{
65 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
66 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
67 uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
68 x -= x % 8; // byte boundary
69 w = wb * 8; // byte boundary
70 int16_t x1 = x < 0 ? 0 : x; // limit
71 int16_t y1 = y < 0 ? 0 : y; // limit
72 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
73 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
74 int16_t dx = x1 - x;
75 int16_t dy = y1 - y;
76 w1 -= dx;
77 h1 -= dy;
78 if ((w1 <= 0) || (h1 <= 0)) return;
79 _Init_Part();
80 _setPartialRamArea(x1, y1, w1, h1);
81 _writeCommand(0x24);
83 for (int16_t i = 0; i < h1; i++)
84 {
85 for (int16_t j = 0; j < w1 / 8; j++)
86 {
87 uint8_t data = 0xFF;
88 if (black)
89 {
90 // use wb, h of bitmap for index!
91 uint16_t idx = mirror_y ? j + dx / 8 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 8 + uint16_t(i + dy) * wb;
92 if (pgm)
93 {
94#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
95 data = pgm_read_byte(&black[idx]);
96#else
97 data = black[idx];
98#endif
99 }
100 else
101 {
102 data = black[idx];
103 }
104 if (invert) data = ~data;
105 }
106 _transfer(data);
107 }
108 }
109 _endTransfer();
110 _writeCommand(0x26);
112 for (int16_t i = 0; i < h1; i++)
113 {
114 for (int16_t j = 0; j < w1 / 8; j++)
115 {
116 uint8_t data = 0xFF;
117 if (color)
118 {
119 // use wb, h of bitmap for index!
120 uint16_t idx = mirror_y ? j + dx / 8 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 8 + uint16_t(i + dy) * wb;
121 if (pgm)
122 {
123#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
124 data = pgm_read_byte(&color[idx]);
125#else
126 data = color[idx];
127#endif
128 }
129 else
130 {
131 data = color[idx];
132 }
133 if (invert) data = ~data;
134 }
135 _transfer(~data);
136 }
137 }
138 _endTransfer();
139 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
140}
141
142void GxEPD2_750c_Z90::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
143 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
144{
145 writeImagePart(bitmap, NULL, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
146}
147
148void GxEPD2_750c_Z90::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,
149 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
150{
151 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
152 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
153 if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
154 if ((x_part < 0) || (x_part >= w_bitmap)) return;
155 if ((y_part < 0) || (y_part >= h_bitmap)) return;
156 uint16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
157 x_part -= x_part % 8; // byte boundary
158 w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
159 h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
160 x -= x % 8; // byte boundary
161 w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
162 int16_t x1 = x < 0 ? 0 : x; // limit
163 int16_t y1 = y < 0 ? 0 : y; // limit
164 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
165 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
166 int16_t dx = x1 - x;
167 int16_t dy = y1 - y;
168 w1 -= dx;
169 h1 -= dy;
170 if ((w1 <= 0) || (h1 <= 0)) return;
171 if (!_using_partial_mode) _Init_Part();
172 _setPartialRamArea(x1, y1, w1, h1);
173 _writeCommand(0x24);
175 for (int16_t i = 0; i < h1; i++)
176 {
177 for (int16_t j = 0; j < w1 / 8; j++)
178 {
179 uint8_t data;
180 // use wb_bitmap, h_bitmap of bitmap for index!
181 uint16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + uint16_t((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + uint16_t(y_part + i + dy) * wb_bitmap;
182 if (pgm)
183 {
184#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
185 data = pgm_read_byte(&black[idx]);
186#else
187 data = black[idx];
188#endif
189 }
190 else
191 {
192 data = black[idx];
193 }
194 if (invert) data = ~data;
195 _transfer(data);
196 }
197 }
198 _endTransfer();
199 _writeCommand(0x26);
201 for (int16_t i = 0; i < h1; i++)
202 {
203 for (int16_t j = 0; j < w1 / 8; j++)
204 {
205 uint8_t data = 0xFF;
206 if (color)
207 {
208 // use wb_bitmap, h_bitmap of bitmap for index!
209 uint16_t idx = mirror_y ? x_part / 8 + j + dx / 8 + uint16_t((h_bitmap - 1 - (y_part + i + dy))) * wb_bitmap : x_part / 8 + j + dx / 8 + uint16_t(y_part + i + dy) * wb_bitmap;
210 if (pgm)
211 {
212#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
213 data = pgm_read_byte(&color[idx]);
214#else
215 data = color[idx];
216#endif
217 }
218 else
219 {
220 data = color[idx];
221 }
222 if (invert) data = ~data;
223 }
224 _transfer(~data);
225 }
226 }
227 _endTransfer();
228 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
229}
230
231void GxEPD2_750c_Z90::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)
232{
233 if (data1)
234 {
235 writeImage(data1, x, y, w, h, invert, mirror_y, pgm);
236 }
237}
238
239void GxEPD2_750c_Z90::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
240{
241 writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
242 refresh(x, y, w, h);
243}
244
245void GxEPD2_750c_Z90::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
246 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
247{
248 writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
249 refresh(x, y, w, h);
250}
251
252void GxEPD2_750c_Z90::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)
253{
254 writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
255 refresh(x, y, w, h);
256}
257
258void GxEPD2_750c_Z90::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,
259 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
260{
261 writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
262 refresh(x, y, w, h);
263}
264
265void GxEPD2_750c_Z90::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)
266{
267 writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
268 refresh(x, y, w, h);
269}
270
271void GxEPD2_750c_Z90::refresh(bool partial_update_mode)
272{
273 if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
274 else _Update_Full();
275}
276
277void GxEPD2_750c_Z90::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
278{
279 _Update_Part();
280}
281
283{
284 _PowerOff();
285}
286
288{
289 _PowerOff();
290 if (_rst >= 0)
291 {
292 _writeCommand(0x10); // deep sleep
293 _writeData(0x11); // deep sleep
294 _hibernating = true;
295 }
296}
297
298void GxEPD2_750c_Z90::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
299{
300 //Serial.print("_setPartialRamArea("); Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(w); Serial.print(", "); Serial.print(h); Serial.println(")");
301 _writeCommand(0x11); // Data entry mode
302 _writeData(entry_mode & 0x03);
303 switch (entry_mode & 0x03)
304 {
305 case 0x00: // x decrement, y decrement
306 _setRamArea(WIDTH - x - 1, WIDTH - w - x, HEIGHT - y - 1, HEIGHT - h - y);
307 _setRamPointer(WIDTH - x - 1, HEIGHT - y - 1);
308 break;
309 case 0x01: // x increment, y decrement
310 _setRamArea(x, x + w - 1, HEIGHT - y - 1, HEIGHT - h - y);
311 _setRamPointer(x, HEIGHT - y - 1);
312 break;
313 case 0x02: // x decrement, y incrment
314 _setRamArea(WIDTH - x - 1, WIDTH - w - x, y, y + h - 1);
315 _setRamPointer(WIDTH - x - 1, y);
316 break;
317 case 0x03: // x increment, y increment
318 _setRamArea(x, x + w - 1, y, y + h - 1);
319 _setRamPointer(x, y);
320 }
321}
322
323void GxEPD2_750c_Z90::_setRamArea(uint16_t xs, uint16_t xe, uint16_t ys, uint16_t ye)
324{
325 //Serial.print("_setRamArea("); Serial.print(xs); Serial.print(", "); Serial.print(ys); Serial.print(", "); Serial.print(xe); Serial.print(", "); Serial.print(ye); Serial.println(")");
326 _writeCommand(0x44); // Set RAM X address Start/End position
327 _writeData(xs % 256);
328 _writeData(xs / 256);
329 _writeData(xe % 256);
330 _writeData(xe / 256);
331 _writeCommand(0x45); // Set RAM Y address Start/End position
332 _writeData(ys % 256);
333 _writeData(ys / 256);
334 _writeData(ye % 256);
335 _writeData(ye / 256);
336}
337
338void GxEPD2_750c_Z90::_setRamPointer(uint16_t xs, uint16_t ys)
339{
340 //Serial.print("_setRamPointer("); Serial.print(xs); Serial.print(", "); Serial.print(ys); Serial.println(")");
341 _writeCommand(0x4E); // Set RAM X Address Counter
342 _writeData(xs % 256);
343 _writeData(xs / 256);
344 _writeCommand(0x4F); // Set RAM Y Address Counter
345 _writeData(ys % 256);
346 _writeData(ys / 256);
347}
348
349void GxEPD2_750c_Z90::_PowerOn()
350{
351 if (!_power_is_on)
352 {
353 _writeCommand(0x22);
354 _writeData(0xc0);
355 _writeCommand(0x20);
356 _waitWhileBusy("_PowerOn", power_on_time);
357 }
358 _power_is_on = true;
359}
360
361void GxEPD2_750c_Z90::_PowerOff()
362{
363 if (_power_is_on)
364 {
365 _writeCommand(0x22);
366 _writeData(0xc3);
367 _writeCommand(0x20);
368 _waitWhileBusy("_PowerOff", power_off_time);
369 }
370 _power_is_on = false;
371 _using_partial_mode = false;
372}
373
374void GxEPD2_750c_Z90::_InitDisplay()
375{
376 if (_hibernating) _reset();
377 _writeCommand(0x12); //SWRESET
379 _writeCommand(0x0C); // Soft start setting
380 _writeData(0xAE);
381 _writeData(0xC7);
382 _writeData(0xC3);
383 _writeData(0xC0);
384 _writeData(0x40);
385 _writeCommand(0x01); // Set MUX as 527
386 _writeData(0x0F);
387 _writeData(0x02);
388 _writeData(0x00);
389 _setPartialRamArea(0, 0, WIDTH, HEIGHT);
390 _writeCommand(0x3C); // VBD
391 _writeData(0x01); // LUT1, for white
392 _writeCommand(0x18); // Temperature Sensor Selection
393 _writeData(0x80); // internal temperature sensor
394 _writeCommand(0x22); // Display Update Sequence Options
395 _writeData(0xB1); // Load Temperature and waveform setting.
396 _writeCommand(0x20); // Master Activation
398}
399
400void GxEPD2_750c_Z90::_Init_Full()
401{
402 _InitDisplay();
403 _PowerOn();
404}
405
406void GxEPD2_750c_Z90::_Init_Part()
407{
408 _InitDisplay();
409 _PowerOn();
410}
411
412void GxEPD2_750c_Z90::_Update_Full()
413{
414 _writeCommand(0x22); // Display Update Sequence Options
415 _writeData(0xC7); //
416 _writeCommand(0x20); // Master Activation
417 _waitWhileBusy("_Update_Full", full_refresh_time);
418}
419
420void GxEPD2_750c_Z90::_Update_Part()
421{
422 _writeCommand(0x22); // Display Update Sequence Options
423 _writeData(0xC7); //
424 _writeCommand(0x20); // Master Activation
425 _waitWhileBusy("_Update_Part", partial_refresh_time);
426}
static const uint16_t power_off_time
static const uint16_t WIDTH
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 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)
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 writeScreenBuffer(uint8_t value=0xFF)
static const uint16_t full_refresh_time
static const uint8_t entry_mode
GxEPD2_750c_Z90(int16_t cs, int16_t dc, int16_t rst, int16_t busy)
static const uint16_t power_on_time
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 refresh(bool partial_update_mode=false)
void clearScreen(uint8_t value=0xFF)
static const uint16_t partial_refresh_time
void drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, int16_t x, int16_t y, int16_t w, int16_t h, bool invert=false, bool mirror_y=false, bool pgm=false)
void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, int16_t x, int16_t y, int16_t w, int16_t h, bool invert=false, bool mirror_y=false, bool pgm=false)
static const uint16_t HEIGHT
void _endTransfer()
void _writeCommand(uint8_t c)
void _writeData(uint8_t d)
bool _using_partial_mode
Definition GxEPD2_EPD.h:118
void _waitWhileBusy(const char *comment=0, uint16_t busy_time=5000)
bool _power_is_on
Definition GxEPD2_EPD.h:118
void _startTransfer()
void _transfer(uint8_t value)
void _reset()
bool _initial_write
Definition GxEPD2_EPD.h:117
int16_t _rst
Definition GxEPD2_EPD.h:112
bool _hibernating
Definition GxEPD2_EPD.h:118