Paperd.Ink Library 0.0.5
Library for interacting with Paperd.Ink devices.
Loading...
Searching...
No Matches
GxEPD2_750.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: these e-papers require 3.3V supply AND data lines!
3//
4// based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
5// Controller: IL0371 : http://www.good-display.com/download_detail/downloadsId=536.html
6//
7// Author: Jean-Marc Zingg
8//
9// Version: see library.properties
10//
11// Library: https://github.com/ZinggJM/GxEPD2
12
13#include "GxEPD2_750.h"
14
15GxEPD2_750::GxEPD2_750(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
16 GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
17{
18}
19
20void GxEPD2_750::clearScreen(uint8_t value)
21{
22 writeScreenBuffer(value);
23 refresh(true);
24}
25
27{
28 _initial_write = false; // initial full screen buffer clean done
29 if (!_using_partial_mode) _Init_Part();
30 if (value == 0xFF) value = 0x33; // white value for this controller
31 _writeCommand(0x10);
33 for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 2; i++)
34 {
35 _transfer(value);
36 }
38}
39
40void 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)
41{
42 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
43 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
44 uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
45 x -= x % 8; // byte boundary
46 w = wb * 8; // byte boundary
47 int16_t x1 = x < 0 ? 0 : x; // limit
48 int16_t y1 = y < 0 ? 0 : y; // limit
49 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
50 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
51 int16_t dx = x1 - x;
52 int16_t dy = y1 - y;
53 w1 -= dx;
54 h1 -= dy;
55 if ((w1 <= 0) || (h1 <= 0)) return;
56 if (!_using_partial_mode) _Init_Part();
57 _writeCommand(0x91); // partial in
58 _setPartialRamArea(x1, y1, w1, h1);
59 _writeCommand(0x10);
61 for (int16_t i = 0; i < h1; i++)
62 {
63 for (int16_t j = 0; j < w1 / 8; j++)
64 {
65 uint8_t data;
66 // use wb, h of bitmap for index!
67 uint16_t idx = mirror_y ? j + dx / 8 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 8 + uint16_t(i + dy) * wb;
68 if (pgm)
69 {
70#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
71 data = pgm_read_byte(&bitmap[idx]);
72#else
73 data = bitmap[idx];
74#endif
75 }
76 else
77 {
78 data = bitmap[idx];
79 }
80 if (invert) data = ~data;
81 _send8pixel(~data);
82 }
83 }
85 _writeCommand(0x92); // partial out
86 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
87}
88
89void GxEPD2_750::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
90 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
91{
92 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
93 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
94 if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
95 if ((x_part < 0) || (x_part >= w_bitmap)) return;
96 if ((y_part < 0) || (y_part >= h_bitmap)) return;
97 uint16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
98 x_part -= x_part % 8; // byte boundary
99 w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
100 h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
101 x -= x % 8; // byte boundary
102 w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
103 int16_t x1 = x < 0 ? 0 : x; // limit
104 int16_t y1 = y < 0 ? 0 : y; // limit
105 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
106 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
107 int16_t dx = x1 - x;
108 int16_t dy = y1 - y;
109 w1 -= dx;
110 h1 -= dy;
111 if ((w1 <= 0) || (h1 <= 0)) return;
112 if (!_using_partial_mode) _Init_Part();
113 _writeCommand(0x91); // partial in
114 _setPartialRamArea(x1, y1, w1, h1);
115 _writeCommand(0x10);
117 for (int16_t i = 0; i < h1; i++)
118 {
119 for (int16_t j = 0; j < w1 / 8; j++)
120 {
121 uint8_t data;
122 // use wb_bitmap, h_bitmap of bitmap for index!
123 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;
124 if (pgm)
125 {
126#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
127 data = pgm_read_byte(&bitmap[idx]);
128#else
129 data = bitmap[idx];
130#endif
131 }
132 else
133 {
134 data = bitmap[idx];
135 }
136 if (invert) data = ~data;
137 _send8pixel(~data);
138 }
139 }
140 _endTransfer();
141 _writeCommand(0x92); // partial out
142 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
143}
144
145void GxEPD2_750::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)
146{
147 if (black)
148 {
149 writeImage(black, x, y, w, h, invert, mirror_y, pgm);
150 }
151}
152
153void GxEPD2_750::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,
154 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
155{
156 if (black)
157 {
158 writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
159 }
160}
161
162void GxEPD2_750::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)
163{
164 if (data1)
165 {
166 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
167 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
168 uint16_t wb = (w + 1) / 2; // width bytes, bitmaps are padded
169 x -= x % 2; // byte boundary
170 w = wb * 2; // byte boundary
171 int16_t x1 = x < 0 ? 0 : x; // limit
172 int16_t y1 = y < 0 ? 0 : y; // limit
173 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
174 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
175 int16_t dx = x1 - x;
176 int16_t dy = y1 - y;
177 w1 -= dx;
178 h1 -= dy;
179 if ((w1 <= 0) || (h1 <= 0)) return;
180 if (!_using_partial_mode) _Init_Part();
181 _writeCommand(0x91); // partial in
182 _setPartialRamArea(x1, y1, w1, h1);
183 _writeCommand(0x10);
185 for (int16_t i = 0; i < h1; i++)
186 {
187 for (int16_t j = 0; j < w1 / 2; j++)
188 {
189 uint8_t data;
190 // use wb, h of bitmap for index!
191 uint16_t idx = mirror_y ? j + dx / 2 + uint16_t((h - 1 - (i + dy))) * wb : j + dx / 2 + uint16_t(i + dy) * wb;
192 if (pgm)
193 {
194#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
195 data = pgm_read_byte(&data1[idx]);
196#else
197 data = data1[idx];
198#endif
199 }
200 else
201 {
202 data = data1[idx];
203 }
204 if (invert) data = ~data;
205 _transfer(data);
206 }
207 }
208 _endTransfer();
209 _writeCommand(0x92); // partial out
210 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
211 }
212}
213
214void GxEPD2_750::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
215{
216 writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
217 refresh(x, y, w, h);
218}
219
220void GxEPD2_750::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
221 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
222{
223 writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
224 refresh(x, y, w, h);
225}
226
227void GxEPD2_750::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)
228{
229 writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
230 refresh(x, y, w, h);
231}
232
233void GxEPD2_750::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,
234 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
235{
236 writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
237 refresh(x, y, w, h);
238}
239
240void GxEPD2_750::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)
241{
242 writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
243 refresh(x, y, w, h);
244}
245
246void GxEPD2_750::refresh(bool partial_update_mode)
247{
248 if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
249 else
250 {
251 if (_using_partial_mode) _Init_Full();
252 _Update_Full();
253 }
254}
255
256void GxEPD2_750::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
257{
258 // intersection with screen
259 int16_t w1 = x < 0 ? w + x : w; // reduce
260 int16_t h1 = y < 0 ? h + y : h; // reduce
261 int16_t x1 = x < 0 ? 0 : x; // limit
262 int16_t y1 = y < 0 ? 0 : y; // limit
263 w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit
264 h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit
265 if ((w1 <= 0) || (h1 <= 0)) return;
266 // make x1, w1 multiple of 8
267 w1 += x1 % 8;
268 if (w1 % 8 > 0) w1 += 8 - w1 % 8;
269 x1 -= x1 % 8;
270 if (!_using_partial_mode) _Init_Part();
271 _writeCommand(0x91); // partial in
272 _setPartialRamArea(x1, y1, w1, h1);
273 _Update_Part();
274 _writeCommand(0x92); // partial out
275}
276
278{
279 _PowerOff();
280}
281
283{
284 _PowerOff();
285 if (_rst >= 0)
286 {
287 // check if it supports this command!
288 _writeCommand(0x07); // deep sleep
289 _writeData(0xA5); // check code
290 _hibernating = true;
291 }
292}
293
294void GxEPD2_750::_send8pixel(uint8_t data)
295{
296 for (uint8_t j = 0; j < 8; j++)
297 {
298 uint8_t t = data & 0x80 ? 0x00 : 0x03;
299 t <<= 4;
300 data <<= 1;
301 j++;
302 t |= data & 0x80 ? 0x00 : 0x03;
303 data <<= 1;
304 _transfer(t);
305 }
306}
307
308void GxEPD2_750::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
309{
310 uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte)
311 uint16_t ye = y + h - 1;
312 x &= 0xFFF8; // byte boundary
313 _writeCommand(0x90); // partial window
314 _writeData(x / 256);
315 _writeData(x % 256);
316 _writeData(xe / 256);
317 _writeData(xe % 256);
318 _writeData(y / 256);
319 _writeData(y % 256);
320 _writeData(ye / 256);
321 _writeData(ye % 256);
322 _writeData(0x01); // don't see any difference
323 //_writeData(0x00); // don't see any difference
324}
325
326void GxEPD2_750::_PowerOn()
327{
328 if (!_power_is_on)
329 {
330 _writeCommand(0x04);
331 _waitWhileBusy("_PowerOn", power_on_time);
332 }
333 _power_is_on = true;
334}
335
336void GxEPD2_750::_PowerOff()
337{
338 _writeCommand(0x02); // power off
339 _waitWhileBusy("_PowerOff", power_off_time);
340 _power_is_on = false;
341 _using_partial_mode = false;
342}
343
344void GxEPD2_750::_InitDisplay()
345{
346 if (_hibernating) _reset();
347 /**********************************release flash sleep**********************************/
348 _writeCommand(0X65); //FLASH CONTROL
349 _writeData(0x01);
350 _writeCommand(0xAB);
351 _writeCommand(0X65); //FLASH CONTROL
352 _writeData(0x00);
353 /**********************************release flash sleep**********************************/
354 _writeCommand(0x01);
355 _writeData (0x37); //POWER SETTING
356 _writeData (0x00);
357 _writeCommand(0X00); //PANNEL SETTING
358 _writeData(0xCF);
359 _writeData(0x08);
360 _writeCommand(0x06); //boost
361 _writeData (0xc7);
362 _writeData (0xcc);
363 _writeData (0x28);
364 _writeCommand(0x30); //PLL setting
365 _writeData (0x3c);
366 _writeCommand(0X41); //TEMPERATURE SETTING
367 _writeData(0x00);
368 _writeCommand(0X50); //VCOM AND DATA INTERVAL SETTING
369 _writeData(0x77);
370 _writeCommand(0X60); //TCON SETTING
371 _writeData(0x22);
372 _writeCommand(0x61); //tres 640*384
373 _writeData (0x02); //source 640
374 _writeData (0x80);
375 _writeData (0x01); //gate 384
376 _writeData (0x80);
377 _writeCommand(0X82); //VDCS SETTING
378 _writeData(0x1E); //decide by LUT file
379 _writeCommand(0xe5); //FLASH MODE
380 _writeData(0x03);
381 //_writeCommand(0x04); //POWER ON
382 //_waitWhileBusy();
383}
384
385void GxEPD2_750::_Init_Full()
386{
387 _InitDisplay();
388 _PowerOn();
389 _using_partial_mode = false;
390}
391
392void GxEPD2_750::_Init_Part()
393{
394 _InitDisplay();
395 _PowerOn();
396 _using_partial_mode = true;
397}
398
399void GxEPD2_750::_Update_Full()
400{
401 _writeCommand(0x12); //display refresh
402 _waitWhileBusy("_Update_Full", full_refresh_time);
403}
404
405void GxEPD2_750::_Update_Part()
406{
407 _writeCommand(0x12); //display refresh
408 _waitWhileBusy("_Update_Part", partial_refresh_time);
409}
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)
static const uint16_t full_refresh_time
Definition GxEPD2_750.h:30
void writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap, int16_t x, int16_t y, int16_t w, int16_t h, bool invert=false, bool mirror_y=false, bool pgm=false)
void refresh(bool partial_update_mode=false)
static const uint16_t power_on_time
Definition GxEPD2_750.h:28
static const uint16_t partial_refresh_time
Definition GxEPD2_750.h:31
void clearScreen(uint8_t value=0x33)
void hibernate()
static const uint16_t power_off_time
Definition GxEPD2_750.h:29
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 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 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)
GxEPD2_750(int16_t cs, int16_t dc, int16_t rst, int16_t busy)
void powerOff()
void writeScreenBuffer(uint8_t value=0x33)
static const uint16_t WIDTH
Definition GxEPD2_750.h:22
static const uint16_t HEIGHT
Definition GxEPD2_750.h:23
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 _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