GxEPD2_213_flex.cpp 15 KB

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