GxEPD2_270.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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: IL91874 : http://www.e-paper-display.com/download_detail/downloadsId=539.html
  6. //
  7. // Author: Jean-Marc Zingg
  8. //
  9. // Version: see library.properties
  10. //
  11. // Library: https://github.com/ZinggJM/GxEPD2
  12. #include "GxEPD2_270.h"
  13. GxEPD2_270::GxEPD2_270(int16_t cs, int16_t dc, int16_t rst, int16_t busy) :
  14. GxEPD2_EPD(cs, dc, rst, busy, LOW, 10000000, WIDTH, HEIGHT, panel, hasColor, hasPartialUpdate, hasFastPartialUpdate)
  15. {
  16. }
  17. void GxEPD2_270::clearScreen(uint8_t value)
  18. {
  19. writeScreenBuffer(value);
  20. refresh(false);
  21. writeScreenBufferAgain(value);
  22. }
  23. void GxEPD2_270::writeScreenBuffer(uint8_t value)
  24. {
  25. _initial_write = false; // initial full screen buffer clean done
  26. if (!_using_partial_mode) _Init_Part();
  27. _writeCommand(0x13); // set current
  28. for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
  29. {
  30. _writeData(value);
  31. }
  32. if (_initial_refresh) writeScreenBufferAgain(value); // init "old data"
  33. }
  34. void GxEPD2_270::writeScreenBufferAgain(uint8_t value)
  35. {
  36. if (!_using_partial_mode) _Init_Part();
  37. _setPartialRamArea(0x14, 0, 0, WIDTH, HEIGHT);
  38. for (uint32_t i = 0; i < uint32_t(WIDTH) * uint32_t(HEIGHT) / 8; i++)
  39. {
  40. _writeData(value);
  41. }
  42. }
  43. void GxEPD2_270::writeImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  44. {
  45. _writeImage(0x15, bitmap, x, y, w, h, invert, mirror_y, pgm);
  46. }
  47. void GxEPD2_270::writeImageAgain(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  48. {
  49. _writeImage(0x14, bitmap, x, y, w, h, invert, mirror_y, pgm);
  50. }
  51. 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)
  52. {
  53. if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
  54. delay(1); // yield() to avoid WDT on ESP8266 and ESP32
  55. int16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
  56. x -= x % 8; // byte boundary
  57. w = wb * 8; // byte boundary
  58. int16_t x1 = x < 0 ? 0 : x; // limit
  59. int16_t y1 = y < 0 ? 0 : y; // limit
  60. int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
  61. int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
  62. int16_t dx = x1 - x;
  63. int16_t dy = y1 - y;
  64. w1 -= dx;
  65. h1 -= dy;
  66. if ((w1 <= 0) || (h1 <= 0)) return;
  67. if (!_using_partial_mode) _Init_Part();
  68. _setPartialRamArea(command, x1, y1, w1, h1);
  69. for (int16_t i = 0; i < h1; i++)
  70. {
  71. for (int16_t j = 0; j < w1 / 8; j++)
  72. {
  73. uint8_t data;
  74. // use wb, h of bitmap for index!
  75. int16_t idx = mirror_y ? j + dx / 8 + ((h - 1 - (i + dy))) * wb : j + dx / 8 + (i + dy) * wb;
  76. if (pgm)
  77. {
  78. #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
  79. data = pgm_read_byte(&bitmap[idx]);
  80. #else
  81. data = bitmap[idx];
  82. #endif
  83. }
  84. else
  85. {
  86. data = bitmap[idx];
  87. }
  88. if (invert) data = ~data;
  89. _writeData(data);
  90. }
  91. }
  92. delay(1); // yield() to avoid WDT on ESP8266 and ESP32
  93. }
  94. void GxEPD2_270::writeImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
  95. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  96. {
  97. _writeImagePart(0x15, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  98. }
  99. void GxEPD2_270::writeImagePartAgain(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
  100. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  101. {
  102. _writeImagePart(0x14, bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  103. }
  104. 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,
  105. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  106. {
  107. if (_initial_write) writeScreenBuffer(); // initial full screen buffer clean
  108. delay(1); // yield() to avoid WDT on ESP8266 and ESP32
  109. if ((w_bitmap < 0) || (h_bitmap < 0) || (w < 0) || (h < 0)) return;
  110. if ((x_part < 0) || (x_part >= w_bitmap)) return;
  111. if ((y_part < 0) || (y_part >= h_bitmap)) return;
  112. int16_t wb_bitmap = (w_bitmap + 7) / 8; // width bytes, bitmaps are padded
  113. x_part -= x_part % 8; // byte boundary
  114. w = w_bitmap - x_part < w ? w_bitmap - x_part : w; // limit
  115. h = h_bitmap - y_part < h ? h_bitmap - y_part : h; // limit
  116. x -= x % 8; // byte boundary
  117. w = 8 * ((w + 7) / 8); // byte boundary, bitmaps are padded
  118. int16_t x1 = x < 0 ? 0 : x; // limit
  119. int16_t y1 = y < 0 ? 0 : y; // limit
  120. int16_t w1 = x + w < int16_t(WIDTH) ? w : int16_t(WIDTH) - x; // limit
  121. int16_t h1 = y + h < int16_t(HEIGHT) ? h : int16_t(HEIGHT) - y; // limit
  122. int16_t dx = x1 - x;
  123. int16_t dy = y1 - y;
  124. w1 -= dx;
  125. h1 -= dy;
  126. if ((w1 <= 0) || (h1 <= 0)) return;
  127. if (!_using_partial_mode) _Init_Part();
  128. _setPartialRamArea(command, x1, y1, w1, h1);
  129. for (int16_t i = 0; i < h1; i++)
  130. {
  131. for (int16_t j = 0; j < w1 / 8; j++)
  132. {
  133. uint8_t data;
  134. // use wb_bitmap, h_bitmap of bitmap for index!
  135. 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;
  136. if (pgm)
  137. {
  138. #if defined(__AVR) || defined(ESP8266) || defined(ESP32)
  139. data = pgm_read_byte(&bitmap[idx]);
  140. #else
  141. data = bitmap[idx];
  142. #endif
  143. }
  144. else
  145. {
  146. data = bitmap[idx];
  147. }
  148. if (invert) data = ~data;
  149. _writeData(data);
  150. }
  151. }
  152. delay(1); // yield() to avoid WDT on ESP8266 and ESP32
  153. }
  154. void GxEPD2_270::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)
  155. {
  156. if (black)
  157. {
  158. writeImage(black, x, y, w, h, invert, mirror_y, pgm);
  159. }
  160. }
  161. void GxEPD2_270::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,
  162. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  163. {
  164. if (black)
  165. {
  166. writeImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  167. }
  168. }
  169. void GxEPD2_270::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)
  170. {
  171. if (data1)
  172. {
  173. writeImage(data1, x, y, w, h, invert, mirror_y, pgm);
  174. }
  175. }
  176. void GxEPD2_270::drawImage(const uint8_t bitmap[], int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  177. {
  178. writeImage(bitmap, x, y, w, h, invert, mirror_y, pgm);
  179. refresh(x, y, w, h);
  180. writeImageAgain(bitmap, x, y, w, h, invert, mirror_y, pgm);
  181. }
  182. void GxEPD2_270::drawImagePart(const uint8_t bitmap[], int16_t x_part, int16_t y_part, int16_t w_bitmap, int16_t h_bitmap,
  183. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  184. {
  185. writeImagePart(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  186. refresh(x, y, w, h);
  187. writeImagePartAgain(bitmap, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  188. }
  189. void GxEPD2_270::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)
  190. {
  191. if (black)
  192. {
  193. drawImage(black, x, y, w, h, invert, mirror_y, pgm);
  194. }
  195. }
  196. void GxEPD2_270::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,
  197. int16_t x, int16_t y, int16_t w, int16_t h, bool invert, bool mirror_y, bool pgm)
  198. {
  199. if (black)
  200. {
  201. drawImagePart(black, x_part, y_part, w_bitmap, h_bitmap, x, y, w, h, invert, mirror_y, pgm);
  202. }
  203. }
  204. void GxEPD2_270::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)
  205. {
  206. if (data1)
  207. {
  208. drawImage(data1, x, y, w, h, invert, mirror_y, pgm);
  209. }
  210. }
  211. void GxEPD2_270::refresh(bool partial_update_mode)
  212. {
  213. if (partial_update_mode) refresh(0, 0, WIDTH, HEIGHT);
  214. else
  215. {
  216. if (_using_partial_mode) _Init_Full();
  217. _Update_Full();
  218. _initial_refresh = false; // initial full update done
  219. }
  220. }
  221. void GxEPD2_270::refresh(int16_t x, int16_t y, int16_t w, int16_t h)
  222. {
  223. if (_initial_refresh) return refresh(false); // initial update needs be full update
  224. // intersection with screen
  225. int16_t w1 = x < 0 ? w + x : w; // reduce
  226. int16_t h1 = y < 0 ? h + y : h; // reduce
  227. int16_t x1 = x < 0 ? 0 : x; // limit
  228. int16_t y1 = y < 0 ? 0 : y; // limit
  229. w1 = x1 + w1 < int16_t(WIDTH) ? w1 : int16_t(WIDTH) - x1; // limit
  230. h1 = y1 + h1 < int16_t(HEIGHT) ? h1 : int16_t(HEIGHT) - y1; // limit
  231. if ((w1 <= 0) || (h1 <= 0)) return;
  232. // make x1, w1 multiple of 8
  233. w1 += x1 % 8;
  234. if (w1 % 8 > 0) w1 += 8 - w1 % 8;
  235. x1 -= x1 % 8;
  236. _refreshWindow(x1, y1, w1, h1);
  237. _waitWhileBusy("refresh", partial_refresh_time);
  238. }
  239. void GxEPD2_270::powerOff(void)
  240. {
  241. _PowerOff();
  242. }
  243. void GxEPD2_270::hibernate()
  244. {
  245. _PowerOff();
  246. if (_rst >= 0)
  247. {
  248. _writeCommand(0x07); // deep sleep
  249. _writeData(0xA5); // check code
  250. _hibernating = true;
  251. }
  252. }
  253. void GxEPD2_270::_setPartialRamArea(uint8_t command, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
  254. {
  255. w = (w + 7 + (x % 8)) & 0xfff8; // byte boundary exclusive (round up)
  256. _writeCommand(command);
  257. _writeData(x >> 8);
  258. _writeData(x & 0xf8);
  259. _writeData(y >> 8);
  260. _writeData(y & 0xff);
  261. _writeData(w >> 8);
  262. _writeData(w & 0xf8);
  263. _writeData(h >> 8);
  264. _writeData(h & 0xff);
  265. }
  266. void GxEPD2_270::_refreshWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
  267. {
  268. w = (w + 7 + (x % 8)) & 0xfff8; // byte boundary exclusive (round up)
  269. h = gx_uint16_min(h, 256); // strange controller error
  270. _writeCommand(0x16);
  271. _writeData(x >> 8);
  272. _writeData(x & 0xf8);
  273. _writeData(y >> 8);
  274. _writeData(y & 0xff);
  275. _writeData(w >> 8);
  276. _writeData(w & 0xf8);
  277. _writeData(h >> 8);
  278. _writeData(h & 0xff);
  279. }
  280. void GxEPD2_270::_PowerOn()
  281. {
  282. if (!_power_is_on)
  283. {
  284. _writeCommand(0x04);
  285. _waitWhileBusy("_PowerOn", power_on_time);
  286. }
  287. _power_is_on = true;
  288. }
  289. void GxEPD2_270::_PowerOff()
  290. {
  291. _writeCommand(0x02); // power off
  292. _waitWhileBusy("_PowerOff", power_off_time);
  293. _power_is_on = false;
  294. _using_partial_mode = false;
  295. }
  296. void GxEPD2_270::_InitDisplay()
  297. {
  298. if (_hibernating) _reset();
  299. _writeCommand(0x01); //POWER SETTING
  300. _writeData (0x03);
  301. _writeData (0x00);
  302. _writeData (0x2b);
  303. _writeData (0x2b);
  304. _writeCommand(0x06); //boost
  305. _writeData (0x07); //A
  306. _writeData (0x07); //B
  307. _writeData (0x17); //C
  308. _writeCommand(0x16);
  309. _writeData(0x00);
  310. //_writeCommand(0x04);
  311. //_waitWhileBusy("_wakeUp Power On");
  312. _writeCommand(0x00); //panel setting
  313. _writeData(0xbf); //KW-BF KWR-AF BWROTP 0f
  314. _writeCommand(0x30); //PLL setting
  315. _writeData (0x3a); //90 50HZ 3A 100HZ 29 150Hz 39 200HZ 31 171HZ
  316. _writeCommand(0x61); //resolution setting
  317. _writeData (0x00);
  318. _writeData (0xb0); //176
  319. _writeData (0x01);
  320. _writeData (0x08); //264
  321. _writeCommand(0x82); //vcom_DC setting
  322. _writeData (0x08); //0x28:-2.0V,0x12:-0.9V
  323. }
  324. //full screen update LUT
  325. const uint8_t GxEPD2_270::lut_20_vcomDC[] PROGMEM =
  326. {
  327. 0x00, 0x00,
  328. 0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
  329. 0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
  330. 0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
  331. 0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
  332. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  333. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  334. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  335. };
  336. const uint8_t GxEPD2_270::lut_21_ww[] PROGMEM =
  337. {
  338. 0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
  339. 0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  340. 0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
  341. 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
  342. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  343. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  344. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  345. };
  346. const uint8_t GxEPD2_270::lut_22_bw[] PROGMEM =
  347. {
  348. 0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
  349. 0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  350. 0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
  351. 0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
  352. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  353. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  354. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  355. };
  356. const uint8_t GxEPD2_270::lut_23_wb[] PROGMEM =
  357. {
  358. 0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  359. 0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  360. 0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  361. 0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  362. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  363. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  364. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  365. };
  366. const uint8_t GxEPD2_270::lut_24_bb[] PROGMEM =
  367. {
  368. 0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  369. 0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  370. 0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  371. 0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  372. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  373. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  374. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  375. };
  376. //partial screen update LUT
  377. const uint8_t GxEPD2_270::lut_20_vcomDC_partial[] PROGMEM =
  378. {
  379. 0x00, 0x00,
  380. 0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
  381. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  382. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  383. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  384. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  385. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  386. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  387. };
  388. const uint8_t GxEPD2_270::lut_21_ww_partial[] PROGMEM =
  389. {
  390. 0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
  391. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  392. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  393. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  394. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  395. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  396. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  397. };
  398. const uint8_t GxEPD2_270::lut_22_bw_partial[] PROGMEM =
  399. {
  400. 0x80, 0x19, 0x01, 0x00, 0x00, 0x01,
  401. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  402. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  403. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  404. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  405. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  406. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  407. };
  408. const uint8_t GxEPD2_270::lut_23_wb_partial[] PROGMEM =
  409. {
  410. 0x40, 0x19, 0x01, 0x00, 0x00, 0x01,
  411. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  412. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  413. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  414. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  415. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  416. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  417. };
  418. const uint8_t GxEPD2_270::lut_24_bb_partial[] PROGMEM =
  419. {
  420. 0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
  421. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  422. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  423. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  424. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  425. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  426. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  427. };
  428. void GxEPD2_270::_Init_Full()
  429. {
  430. _InitDisplay();
  431. _writeCommand(0x50); //VCOM AND DATA INTERVAL SETTING
  432. _writeData(0x97); //WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
  433. _writeCommand(0x20);
  434. _writeDataPGM_sCS(lut_20_vcomDC, sizeof(lut_20_vcomDC));
  435. _writeCommand(0x21);
  436. _writeDataPGM_sCS(lut_21_ww, sizeof(lut_21_ww));
  437. _writeCommand(0x22);
  438. _writeDataPGM_sCS(lut_22_bw, sizeof(lut_22_bw));
  439. _writeCommand(0x23);
  440. _writeDataPGM_sCS(lut_23_wb, sizeof(lut_23_wb));
  441. _writeCommand(0x24);
  442. _writeDataPGM_sCS(lut_24_bb, sizeof(lut_24_bb));
  443. _PowerOn();
  444. _using_partial_mode = false;
  445. }
  446. void GxEPD2_270::_Init_Part()
  447. {
  448. _InitDisplay();
  449. _writeCommand(0x50); //VCOM AND DATA INTERVAL SETTING
  450. _writeData(0x17); //WBmode:VBDF 17|D7 VBDW 97 VBDB 57 WBRmode:VBDF F7 VBDW 77 VBDB 37 VBDR B7
  451. _writeCommand(0x20);
  452. _writeDataPGM_sCS(lut_20_vcomDC_partial, sizeof(lut_20_vcomDC_partial));
  453. _writeCommand(0x21);
  454. _writeDataPGM_sCS(lut_21_ww_partial, sizeof(lut_21_ww_partial));
  455. _writeCommand(0x22);
  456. _writeDataPGM_sCS(lut_22_bw_partial, sizeof(lut_22_bw_partial));
  457. _writeCommand(0x23);
  458. _writeDataPGM_sCS(lut_23_wb_partial, sizeof(lut_23_wb_partial));
  459. _writeCommand(0x24);
  460. _writeDataPGM_sCS(lut_24_bb_partial, sizeof(lut_24_bb_partial));
  461. _PowerOn();
  462. _using_partial_mode = true;
  463. }
  464. void GxEPD2_270::_Update_Full()
  465. {
  466. _writeCommand(0x12); //display refresh
  467. _waitWhileBusy("_Update_Full", full_refresh_time);
  468. }
  469. void GxEPD2_270::_Update_Part()
  470. {
  471. _writeCommand(0x12); //display refresh
  472. _waitWhileBusy("_Update_Part", partial_refresh_time);
  473. }