Paperd.Ink Library 0.0.5
Library for interacting with Paperd.Ink devices.
Loading...
Searching...
No Matches
GxEPD2_it78_1872x1404.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// GxEPD2_it78_1872x1404 class is based on Demo Example from Waveshare for Raspberry PI https://github.com/waveshare/IT8951/archive/master.zip
5// Controller: IT8951 : https://www.waveshare.com/w/upload/1/18/IT8951_D_V0.2.4.3_20170728.pdf
6//
7// The GxEPD2_it78_1872x1404 driver class supports the Waveshare e-Paper IT8951 Driver HAT connected with SPI for the ED078KC2 7.8" e-paper panel (parallel IF)
8// https://www.waveshare.com/product/displays/e-paper/7.8inch-e-paper-hat.htm
9// This Driver HAT requires 5V power supply but works with 3.3V data lines; requires both MOSI and MISO SPI lines.
10//
11// Author: Jean-Marc Zingg
12//
13// Version: see library.properties
14//
15// Library: https://github.com/ZinggJM/GxEPD2
16
18
19#define VCOM 1500 //e.g. -1.53 = 1530 = 0x5FA
20
21//Built in I80 Command Code
22#define IT8951_TCON_SYS_RUN 0x0001
23#define IT8951_TCON_STANDBY 0x0002
24#define IT8951_TCON_SLEEP 0x0003
25#define IT8951_TCON_REG_RD 0x0010
26#define IT8951_TCON_REG_WR 0x0011
27#define IT8951_TCON_LD_IMG 0x0020
28#define IT8951_TCON_LD_IMG_AREA 0x0021
29#define IT8951_TCON_LD_IMG_END 0x0022
30
31//I80 User defined command code
32#define USDEF_I80_CMD_DPY_AREA 0x0034
33#define USDEF_I80_CMD_GET_DEV_INFO 0x0302
34#define USDEF_I80_CMD_DPY_BUF_AREA 0x0037
35#define USDEF_I80_CMD_VCOM 0x0039
36
37//Rotate mode
38#define IT8951_ROTATE_0 0
39#define IT8951_ROTATE_90 1
40#define IT8951_ROTATE_180 2
41#define IT8951_ROTATE_270 3
42
43//Pixel mode , BPP - Bit per Pixel
44#define IT8951_2BPP 0
45#define IT8951_3BPP 1
46#define IT8951_4BPP 2
47#define IT8951_8BPP 3
48
49//Endian Type
50#define IT8951_LDIMG_L_ENDIAN 0
51#define IT8951_LDIMG_B_ENDIAN 1
52
53#define SYS_REG_BASE 0x0000
54#define I80CPCR (SYS_REG_BASE + 0x04)
55#define MCSR_BASE_ADDR 0x0200
56#define LISAR (MCSR_BASE_ADDR + 0x0008)
57
58GxEPD2_it78_1872x1404::GxEPD2_it78_1872x1404(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
59 GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate),
60 _spi_settings(24000000, MSBFIRST, SPI_MODE0),
61 _spi_settings_for_read(1000000, MSBFIRST, SPI_MODE0)
62{
63}
64
65void GxEPD2_it78_1872x1404::init(uint32_t serial_diag_bitrate)
66{
67 init(serial_diag_bitrate, true, 20, false);
68}
69
70void GxEPD2_it78_1872x1404::init(uint32_t serial_diag_bitrate, bool initial, uint16_t reset_duration, bool pulldown_rst_mode)
71{
72 GxEPD2_EPD::init(serial_diag_bitrate, initial, reset_duration, pulldown_rst_mode);
73
74 // we need a long reset pulse
75 if (_rst >= 0)
76 {
77 digitalWrite(_rst, LOW);
78 delay(200);
79 digitalWrite(_rst, HIGH);
80 delay(200);
81 _waitWhileBusy("init reset_to_ready", reset_to_ready_time);
82 }
83
84 _writeCommand16(USDEF_I80_CMD_GET_DEV_INFO);
85 _waitWhileBusy("GetIT8951SystemInfo", power_on_time);
86 _readData16((uint16_t*)&IT8951DevInfo, sizeof(IT8951DevInfo) / 2);
87 if (_diag_enabled)
88 {
89 //Show Device information of IT8951
90 printf("Panel(W,H) = (%d,%d)\r\n",
91 IT8951DevInfo.usPanelW, IT8951DevInfo.usPanelH );
92 printf("Image Buffer Address = %lX\r\n",
93 uint32_t(IT8951DevInfo.usImgBufAddrL) | (uint32_t(IT8951DevInfo.usImgBufAddrH) << 16));
94 //Show Firmware and LUT Version
95 printf("FW Version = %s\r\n", (uint8_t*)IT8951DevInfo.usFWVersion);
96 printf("LUT Version = %s\r\n", (uint8_t*)IT8951DevInfo.usLUTVersion);
97 }
98 //Set to Enable I80 Packed mode
99 _IT8951WriteReg(I80CPCR, 0x0001);
100 if (VCOM != _IT8951GetVCOM())
101 {
102 _IT8951SetVCOM(VCOM);
103 printf("VCOM = -%.02fV\n", (double)_IT8951GetVCOM() / 1000);
104 }
105 printf("VCOM = -%.02fV\n", (double)_IT8951GetVCOM() / 1000);
106}
107
109{
110 _initial_write = false; // initial full screen buffer clean done
111 if (_initial_refresh) _Init_Full();
112 else _Init_Part();
113 _initial_refresh = false;
114 _setPartialRamArea(0, 0, WIDTH, HEIGHT);
115 SPI.beginTransaction(_spi_settings);
116 if (_cs >= 0) digitalWrite(_cs, LOW);
117 _transfer16(0x0000); // preamble for write data
118 _waitWhileBusy2("clearScreen preamble", default_wait_time);
119 for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT); i++)
120 {
121 SPI.transfer(value);
122#if defined(ESP8266) || defined(ESP32)
123 if (0 == i % 10000) yield();
124#endif
125 }
126 if (_cs >= 0) digitalWrite(_cs, HIGH);
127 SPI.endTransaction();
128 _writeCommand16(IT8951_TCON_LD_IMG_END);
129 _waitWhileBusy2("clearScreen load end", default_wait_time);
130 _refresh(0, 0, WIDTH, HEIGHT, false);
131}
132
134{
135 if (_initial_refresh) clearScreen(value);
136 else _writeScreenBuffer(value);
137}
138
139void GxEPD2_it78_1872x1404::_writeScreenBuffer(uint8_t value)
140{
141 _initial_write = false; // initial full screen buffer clean done
142 if (!_using_partial_mode) _Init_Part();
143 _setPartialRamArea(0, 0, WIDTH, HEIGHT);
144 SPI.beginTransaction(_spi_settings);
145 if (_cs >= 0) digitalWrite(_cs, LOW);
146 _transfer16(0x0000); // preamble for write data
147 _waitWhileBusy2("clearScreen preamble", default_wait_time);
148 for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT); i++)
149 {
150 SPI.transfer(value);
151#if defined(ESP8266) || defined(ESP32)
152 if (0 == i % 10000) yield();
153#endif
154 }
155 if (_cs >= 0) digitalWrite(_cs, HIGH);
156 SPI.endTransaction();
157 _writeCommand16(IT8951_TCON_LD_IMG_END);
158 _waitWhileBusy2("_writeScreenBuffer load end", default_wait_time);
159}
160
161void GxEPD2_it78_1872x1404::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
162{
163 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
164 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
165 int16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
166 x -= x % 8; // byte boundary
167 w = wb * 8; // byte boundary
168 int16_t x1 = x < 0 ? 0 : x; // limit
169 int16_t y1 = y < 0 ? 0 : y; // limit
170 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
171 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
172 int16_t dx = x1 - x;
173 int16_t dy = y1 - y;
174 w1 -= dx;
175 h1 -= dy;
176 if ((w1 <= 0) || (h1 <= 0)) return;
177 if (!_using_partial_mode) _Init_Part();
178 _setPartialRamArea(x1, y1, w1, h1);
179 SPI.beginTransaction(_spi_settings);
180 if (_cs >= 0) digitalWrite(_cs, LOW);
181 _transfer16(0x0000); // preamble for write data
182 _waitWhileBusy2("writeImage preamble", default_wait_time);
183 for (int16_t i = 0; i < h1; i++)
184 {
185 for (int16_t j = 0; j < w1 / 8; j++)
186 {
187 uint8_t data;
188 // use wb, h of bitmap for index!
189 uint32_t idx = mirror_y ? uint32_t(j + dx / 8) + uint32_t((h - 1 - (i + dy))) * uint32_t(wb) : uint32_t(j + dx / 8) + uint32_t(i + dy) * uint32_t(wb);
190 if (pgm)
191 {
192#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
193 data = pgm_read_byte(&bitmap[idx]);
194#else
195 data = bitmap[idx];
196#endif
197 }
198 else
199 {
200 data = bitmap[idx];
201 }
202 if (invert) data = ~data;
203 _send8pixel(~data);
204 }
205#if defined(ESP8266) || defined(ESP32)
206 yield();
207#endif
208 }
209 if (_cs >= 0) digitalWrite(_cs, HIGH);
210 SPI.endTransaction();
211 _writeCommand16(IT8951_TCON_LD_IMG_END);
212 _waitWhileBusy2("writeImage load end", default_wait_time);
213 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
214}
215
216void GxEPD2_it78_1872x1404::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
217 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
218{
219 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
220 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
221 if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
222 if ((x_part < 0) || (x_part >= w_bitmap)) return;
223 if ((y_part < 0) || (y_part >= h_bitmap)) return;
224 int16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
225 x_part -= x_part % 8; // byte boundary
226 w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
227 h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
228 x -= x % 8; // byte boundary
229 w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
230 int16_t x1 = x < 0 ? 0 : x; // limit
231 int16_t y1 = y < 0 ? 0 : y; // limit
232 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
233 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
234 int16_t dx = x1 - x;
235 int16_t dy = y1 - y;
236 w1 -= dx;
237 h1 -= dy;
238 if ((w1 <= 0) || (h1 <= 0)) return;
239 if (!_using_partial_mode) _Init_Part();
240 _setPartialRamArea(x1, y1, w1, h1);
241 SPI.beginTransaction(_spi_settings);
242 if (_cs >= 0) digitalWrite(_cs, LOW);
243 _transfer16(0x0000); // preamble for write data
244 _waitWhileBusy2("writeImage preamble", default_wait_time);
245 for (int16_t i = 0; i < h1; i++)
246 {
247 for (int16_t j = 0; j < w1 / 8; j++)
248 {
249 uint8_t data;
250 // use wb_bitmap, h_bitmap of bitmap for index!
251 uint32_t idx = mirror_y ? x_part / 8 + (j + dx / 8) + uint32_t((h_bitmap - 1 - (y_part + i + dy))) * uint32_t(wb_bitmap) : x_part / 8 + j + dx / 8 + uint32_t(y_part + i + dy) * uint32_t(wb_bitmap);
252 if (pgm)
253 {
254#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
255 data = pgm_read_byte(&bitmap[idx]);
256#else
257 data = bitmap[idx];
258#endif
259 }
260 else
261 {
262 data = bitmap[idx];
263 }
264 if (invert) data = ~data;
265 _send8pixel(~data);
266 }
267 }
268 if (_cs >= 0) digitalWrite(_cs, HIGH);
269 SPI.endTransaction();
270 _writeCommand16(IT8951_TCON_LD_IMG_END);
271 _waitWhileBusy2("writeImage load end", default_wait_time);
272 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
273}
274
275void GxEPD2_it78_1872x1404::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)
276{
277 if (black)
278 {
279 writeImage(black, x, y, w, h, invert, mirror_y, pgm);
280 }
281}
282
283void GxEPD2_it78_1872x1404::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,
284 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
285{
286 if (black)
287 {
288 writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
289 }
290}
291
292void GxEPD2_it78_1872x1404::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)
293{
294 if (data1)
295 {
296 if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
297 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
298 int16_t x1 = x < 0 ? 0 : x; // limit
299 int16_t y1 = y < 0 ? 0 : y; // limit
300 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
301 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
302 int16_t dx = x1 - x;
303 int16_t dy = y1 - y;
304 w1 -= dx;
305 h1 -= dy;
306 if ((w1 <= 0) || (h1 <= 0)) return;
307 if (!_using_partial_mode) _Init_Part();
308 _setPartialRamArea(x1, y1, w1, h1);
309 SPI.beginTransaction(_spi_settings);
310 if (_cs >= 0) digitalWrite(_cs, LOW);
311 _transfer16(0x0000); // preamble for write data
312 _waitWhileBusy2("writeNative preamble", default_wait_time);
313 for (int16_t i = 0; i < h1; i++)
314 {
315 for (int16_t j = 0; j < w1; j++)
316 {
317 uint8_t data;
318 // use w, h of bitmap for index!
319 uint32_t idx = mirror_y ? uint32_t(j + dx) + uint32_t((h - 1 - (i + dy))) * uint32_t(w) : uint32_t(j + dx) + uint32_t(i + dy) * uint32_t(w);
320 if (pgm)
321 {
322#if defined(__AVR) || defined(ESP8266) || defined(ESP32)
323 data = pgm_read_byte(&data1[idx]);
324#else
325 data = data1[idx];
326#endif
327 }
328 else
329 {
330 data = data1[idx];
331 }
332 if (invert) data = ~data;
333 SPI.transfer(data);
334 }
335#if defined(ESP8266) || defined(ESP32)
336 yield();
337#endif
338 }
339 if (_cs >= 0) digitalWrite(_cs, HIGH);
340 SPI.endTransaction();
341 _writeCommand16(IT8951_TCON_LD_IMG_END);
342 _waitWhileBusy2("writeNative load end", default_wait_time);
343 delay(1); // yield() to avoid WDT on ESP8266 and ESP32
344 }
345}
346
347void GxEPD2_it78_1872x1404::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
348{
349 writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
350 _refresh(x, y, w, h, true);
351}
352
353void GxEPD2_it78_1872x1404::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
354 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
355{
356 writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
357 _refresh(x, y, w, h, true);
358}
359
360void GxEPD2_it78_1872x1404::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)
361{
362 writeImage(black, color, x, y, w, h, invert, mirror_y, pgm);
363 _refresh(x, y, w, h, true);
364}
365
366void GxEPD2_it78_1872x1404::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,
367 int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
368{
369 writeImagePart(black, color, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
370 _refresh(x, y, w, h, true);
371}
372
373void GxEPD2_it78_1872x1404::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)
374{
375 writeNative(data1, data2, x, y, w, h, invert, mirror_y, pgm);
376 _refresh(x, y, w, h, false);
377}
378
379void GxEPD2_it78_1872x1404::refresh(bool partial_update_mode)
380{
381 _refresh(0, 0, WIDTH, HEIGHT, partial_update_mode);
382}
383
384void GxEPD2_it78_1872x1404::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
385{
386 _refresh(x, y, w, h, true);
387}
388
389void GxEPD2_it78_1872x1404::_refresh(int16_t x, int16_t y, int16_t w, int16_t h, bool partial_update_mode)
390{
391 //x -= x % 8; // byte boundary
392 //w -= x % 8; // byte boundary
393 int16_t x1 = x < 0 ? 0 : x; // limit
394 int16_t y1 = y < 0 ? 0 : y; // limit
395 int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
396 int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
397 w1 -= x1 - x;
398 h1 -= y1 - y;
399 //Send I80 Display Command (User defined command of IT8951)
400 _writeCommand16(USDEF_I80_CMD_DPY_AREA); //0x0034
401 _waitWhileBusy2("refresh cmd", refresh_cmd_time);
402 //Write arguments
403 _writeData16(x1);
404 _waitWhileBusy2("refresh x", refresh_par_time);
405 _writeData16(y1);
406 _waitWhileBusy2("refresh y", refresh_par_time);
407 _writeData16(w1);
408 _waitWhileBusy2("refresh w", refresh_par_time);
409 _writeData16(h1);
410 _waitWhileBusy2("refresh h", refresh_par_time);
411 _writeData16(partial_update_mode ? 1 : 2); // mode
413}
414
416{
417 _PowerOff();
418}
419
421{
422 if (_power_is_on) _PowerOff();
423 if (_rst >= 0)
424 {
425 // this does not work, does not reduce power, uses more than in stand by mode
426 //delay(1000);
427 //_IT8951Sleep();
428 //delay(1000);
429 //_hibernating = true;
430 }
431}
432
433void GxEPD2_it78_1872x1404::_send8pixel(uint8_t data)
434{
435 for (uint8_t j = 0; j < 8; j++)
436 {
437 SPI.transfer(data & 0x80 ? 0x00 : 0xFF);
438 data <<= 1;
439 }
440}
441
442void GxEPD2_it78_1872x1404::_setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
443{
444 //_IT8951WriteReg(LISAR + 2 , IT8951DevInfo.usImgBufAddrH);
445 //_IT8951WriteReg(LISAR , IT8951DevInfo.usImgBufAddrL);
446 uint16_t usArg[5];
447 //usArg[0] = (IT8951_LDIMG_L_ENDIAN << 8 ) | (IT8951_8BPP << 4) | (IT8951_ROTATE_0);
448 usArg[0] = (IT8951_LDIMG_B_ENDIAN << 8 ) | (IT8951_8BPP << 4) | (IT8951_ROTATE_0);
449 usArg[1] = x;
450 usArg[2] = y;
451 usArg[3] = w;
452 usArg[4] = h;
453 _writeCommandData16(IT8951_TCON_LD_IMG_AREA , usArg , 5);
454}
455
456void GxEPD2_it78_1872x1404::_PowerOn()
457{
458 if (!_power_is_on)
459 {
460 _IT8951SystemRun();
461 _waitWhileBusy("_PowerOn", power_on_time);
462 }
463 _power_is_on = true;
464}
465
466void GxEPD2_it78_1872x1404::_PowerOff()
467{
468 _IT8951StandBy();
469 _waitWhileBusy("_PowerOff", power_off_time);
470 _power_is_on = false;
471 _using_partial_mode = false;
472}
473
474void GxEPD2_it78_1872x1404::_InitDisplay()
475{
476 // we need a long reset pulse
477 if (_hibernating && (_rst >= 0))
478 {
479 digitalWrite(_rst, LOW);
480 delay(200);
481 digitalWrite(_rst, HIGH);
482 delay(200);
483 }
484}
485
486void GxEPD2_it78_1872x1404::_Init_Full()
487{
488 _InitDisplay();
489 _PowerOn();
490 _using_partial_mode = false;
491}
492
493void GxEPD2_it78_1872x1404::_Init_Part()
494{
495 _InitDisplay();
496 _PowerOn();
497 _using_partial_mode = true;
498}
499
500void GxEPD2_it78_1872x1404::_waitWhileBusy2(const char* comment, uint16_t busy_time)
501{
502 if (_busy >= 0)
503 {
504 unsigned long start = micros();
505 while (1)
506 {
507 if (digitalRead(_busy) != _busy_level) break;
508 delay(1);
509 if (micros() - start > _busy_timeout)
510 {
511 Serial.println("Busy Timeout!");
512 break;
513 }
514 }
515 if (comment)
516 {
517#if !defined(DISABLE_DIAGNOSTIC_OUTPUT)
518 if (_diag_enabled)
519 {
520 unsigned long elapsed = micros() - start;
521 if (elapsed > diag_min_time * 1000)
522 {
523 Serial.print(comment);
524 Serial.print(" : ");
525 Serial.println(elapsed);
526 }
527 }
528#endif
529 }
530 (void) start;
531 }
532 else delay(busy_time);
533}
534
535uint16_t GxEPD2_it78_1872x1404::_transfer16(uint16_t value)
536{
537 uint16_t rv = SPI.transfer(value >> 8) << 8;
538 return (rv | SPI.transfer(value));
539}
540
541void GxEPD2_it78_1872x1404::_writeCommand16(uint16_t c)
542{
543 String s = String("_writeCommand16(0x") + String(c, HEX) + String(")");
544 _waitWhileBusy2(s.c_str(), default_wait_time);
545 SPI.beginTransaction(_spi_settings);
546 if (_cs >= 0) digitalWrite(_cs, LOW);
547 _transfer16(0x6000); // preamble for write command
548 _waitWhileBusy2("_writeCommand16 preamble", default_wait_time);
549 _transfer16(c);
550 if (_cs >= 0) digitalWrite(_cs, HIGH);
551 SPI.endTransaction();
552 //_waitWhileBusy(s.c_str(), default_wait_time);
553}
554
555void GxEPD2_it78_1872x1404::_writeData16(uint16_t d)
556{
557 _waitWhileBusy2("_writeData16", default_wait_time);
558 SPI.beginTransaction(_spi_settings);
559 if (_cs >= 0) digitalWrite(_cs, LOW);
560 _transfer16(0x0000); // preamble for write data
561 _waitWhileBusy2("_writeData16 preamble", default_wait_time);
562 _transfer16(d);
563 if (_cs >= 0) digitalWrite(_cs, HIGH);
564 SPI.endTransaction();
565}
566
567void GxEPD2_it78_1872x1404::_writeData16(const uint16_t* d, uint32_t n)
568{
569 _waitWhileBusy2("_writeData16", default_wait_time);
570 SPI.beginTransaction(_spi_settings);
571 if (_cs >= 0) digitalWrite(_cs, LOW);
572 _transfer16(0x0000); // preamble for write data
573 _waitWhileBusy2("_writeData16 preamble", default_wait_time);
574 for (uint32_t i = 0; i < n; i++)
575 {
576 _transfer16(*d++);
577 }
578 if (_cs >= 0) digitalWrite(_cs, HIGH);
579 SPI.endTransaction();
580}
581
582uint16_t GxEPD2_it78_1872x1404::_readData16()
583{
584 _waitWhileBusy2("_readData16", default_wait_time);
585 SPI.beginTransaction(_spi_settings);
586 if (_cs >= 0) digitalWrite(_cs, LOW);
587 _transfer16(0x1000); // preamble for read data
588 _waitWhileBusy2("_readData16 preamble", default_wait_time);
589 _transfer16(0); // dummy
590 _waitWhileBusy2("_readData16 dummy", default_wait_time);
591 uint16_t rv = _transfer16(0);
592 if (_cs >= 0) digitalWrite(_cs, HIGH);
593 SPI.endTransaction();
594 return rv;
595}
596
597void GxEPD2_it78_1872x1404::_readData16(uint16_t* d, uint32_t n)
598{
599 _waitWhileBusy2("_readData16", default_wait_time);
600 SPI.beginTransaction(_spi_settings);
601 if (_cs >= 0) digitalWrite(_cs, LOW);
602 _transfer16(0x1000); // preamble for read data
603 _waitWhileBusy2("_readData16 preamble", default_wait_time);
604 _transfer16(0); // dummy
605 _waitWhileBusy2("_readData16 dummy", default_wait_time);
606 for (uint32_t i = 0; i < n; i++)
607 {
608 *d++ = _transfer16(0);
609 //_waitWhileBusy("_readData16 data", default_wait_time);
610 }
611 if (_cs >= 0) digitalWrite(_cs, HIGH);
612 SPI.endTransaction();
613}
614
615void GxEPD2_it78_1872x1404::_writeCommandData16(uint16_t c, const uint16_t* d, uint16_t n)
616{
617 _writeCommand16(c);
618 for (uint16_t i = 0; i < n; i++)
619 {
620 _writeData16(d[i]);
621 }
622}
623
624void GxEPD2_it78_1872x1404::_IT8951SystemRun()
625{
626 _writeCommand16(IT8951_TCON_SYS_RUN);
627}
628
629void GxEPD2_it78_1872x1404::_IT8951StandBy()
630{
631 _writeCommand16(IT8951_TCON_STANDBY);
632}
633
634void GxEPD2_it78_1872x1404::_IT8951Sleep()
635{
636 _writeCommand16(IT8951_TCON_SLEEP);
637}
638
639uint16_t GxEPD2_it78_1872x1404::_IT8951ReadReg(uint16_t usRegAddr)
640{
641 uint16_t usData;
642
643 //Send Cmd and Register Address
644 _writeCommand16(IT8951_TCON_REG_RD);
645 _writeData16(usRegAddr);
646 //Read data from Host Data bus
647 usData = _readData16();
648 return usData;
649}
650
651void GxEPD2_it78_1872x1404::_IT8951WriteReg(uint16_t usRegAddr, uint16_t usValue)
652{
653 //Send Cmd , Register Address and Write Value
654 _writeCommand16(IT8951_TCON_REG_WR);
655 _writeData16(usRegAddr);
656 _writeData16(usValue);
657}
658
659uint16_t GxEPD2_it78_1872x1404::_IT8951GetVCOM(void)
660{
661 uint16_t vcom;
662
663 _writeCommand16(USDEF_I80_CMD_VCOM);
664 _waitWhileBusy2("_IT8951GetVCOM", default_wait_time);
665 _writeData16(0);
666 //Read data from Host Data bus
667 vcom = _readData16();
668 return vcom;
669}
670
671void GxEPD2_it78_1872x1404::_IT8951SetVCOM(uint16_t vcom)
672{
673 _writeCommand16(USDEF_I80_CMD_VCOM);
674 _waitWhileBusy2("_IT8951SetVCOM", default_wait_time);
675 _writeData16(1);
676 //Read data from Host Data bus
677 _writeData16(vcom);
678 _waitWhileBusy2("_IT8951SetVCOM", set_vcom_time);
679}
#define IT8951_TCON_SYS_RUN
#define IT8951_8BPP
#define IT8951_TCON_LD_IMG_AREA
#define IT8951_TCON_LD_IMG_END
#define I80CPCR
#define IT8951_TCON_REG_RD
#define IT8951_ROTATE_0
#define USDEF_I80_CMD_DPY_AREA
#define USDEF_I80_CMD_VCOM
#define IT8951_TCON_REG_WR
#define IT8951_LDIMG_B_ENDIAN
#define VCOM
#define IT8951_TCON_SLEEP
#define IT8951_TCON_STANDBY
#define USDEF_I80_CMD_GET_DEV_INFO
bool _diag_enabled
Definition GxEPD2_EPD.h:114
int16_t _busy_level
Definition GxEPD2_EPD.h:112
bool _using_partial_mode
Definition GxEPD2_EPD.h:118
virtual void init(uint32_t serial_diag_bitrate=0)
void _waitWhileBusy(const char *comment=0, uint16_t busy_time=5000)
bool _power_is_on
Definition GxEPD2_EPD.h:118
bool _initial_refresh
Definition GxEPD2_EPD.h:117
bool _initial_write
Definition GxEPD2_EPD.h:117
uint32_t _busy_timeout
Definition GxEPD2_EPD.h:113
int16_t _rst
Definition GxEPD2_EPD.h:112
int16_t _busy
Definition GxEPD2_EPD.h:112
bool _hibernating
Definition GxEPD2_EPD.h:118
int16_t _cs
Definition GxEPD2_EPD.h:112
static const uint16_t diag_min_time
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 clearScreen(uint8_t value=0x33)
static const uint16_t full_refresh_time
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)
static const uint16_t refresh_par_time
void refresh(bool partial_update_mode=false)
static const uint16_t reset_to_ready_time
static const uint16_t HEIGHT
static const uint16_t set_vcom_time
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 power_off_time
GxEPD2_it78_1872x1404(int16_t cs, int16_t dc, int16_t rst, int16_t busy)
static const uint16_t WIDTH
static const uint16_t power_on_time
void init(uint32_t serial_diag_bitrate=0)
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)
static const uint16_t default_wait_time
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 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 writeScreenBuffer(uint8_t value=0x33)
static const uint16_t refresh_cmd_time