epd1in54.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /**
  2. * @filename : epd1in54b.c
  3. * @brief : Implements for e-paper library
  4. * @author : Yehui from Waveshare
  5. *
  6. * Copyright (C) Waveshare September 12 2017
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documnetation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include <stdlib.h>
  27. #include "epd1in54.h"
  28. #include "epdif.h"
  29. #define LUAT_LOG_TAG "luat.epaper"
  30. #include "luat_log.h"
  31. //#define CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED 0
  32. #define CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT 0
  33. #define EPD_1IN54F_WIDTH 200
  34. #define EPD_1IN54F_HEIGHT 200
  35. #define EPD_1IN54F_ROW_LEN (EPD_1IN54F_HEIGHT / 8u)
  36. #define EPD_1IN54F_PARTIAL_CNT 5;
  37. static uint8_t partial_counter = 0;
  38. static const uint8_t lut_vcom_dc1[] = {
  39. 0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  42. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  43. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  44. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  45. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  46. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  47. };
  48. static const uint8_t lut_ww1[] = {
  49. 0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
  50. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  51. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55. };
  56. static const uint8_t lut_bw1[] = {
  57. 0x01, 0x84, 0x84, 0x83, 0x01, 0x01, 0x01,
  58. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  59. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  60. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  61. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  62. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  63. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  65. };
  66. static const uint8_t lut_wb1[] = {
  67. 0x01, 0x44, 0x44, 0x43, 0x01, 0x01, 0x01,
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  69. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  74. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  75. };
  76. static const uint8_t lut_bb1[] = {
  77. 0x01, 0x04, 0x04, 0x03, 0x01, 0x01, 0x01,
  78. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  79. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  80. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  81. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  82. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  83. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  85. };
  86. static void EPD_1IN54F_load_partial_lut(EPD* epd)
  87. {
  88. EPD_1IN54F_SendCommand(epd,0x20); // LUT VCOM register
  89. for (int i = 0; i < 56; i++)
  90. EPD_1IN54F_SendData(epd, lut_vcom_dc1[i]);
  91. // EPD_1IN54F_SendData((uint8_t *)lut_vcom_dc1, sizeof(lut_vcom_dc1));
  92. EPD_1IN54F_SendCommand(epd,0x21); // LUT White-to-White
  93. for (int i = 0; i < 56; i++)
  94. EPD_1IN54F_SendData(epd, lut_ww1[i]);
  95. // EPD_1IN54F_SendData((uint8_t *)lut_ww1, sizeof(lut_ww1));
  96. EPD_1IN54F_SendCommand(epd,0x22); // LUT Black-to-White
  97. //EPD_1IN54F_SendData((uint8_t *)lut_bw1, sizeof(lut_bw1));
  98. for (int i = 0; i < 56; i++)
  99. EPD_1IN54F_SendData(epd, lut_bw1[i]);
  100. EPD_1IN54F_SendCommand(epd,0x23); // LUT White-to-Black
  101. //EPD_1IN54F_SendData((uint8_t *)lut_wb1,sizeof(lut_wb1));
  102. for (int i = 0; i < 56; i++)
  103. EPD_1IN54F_SendData(epd, lut_wb1[i]);
  104. EPD_1IN54F_SendCommand(epd,0x24); // LUT Black-to-Black
  105. //EPD_1IN54F_SendData((uint8_t *)lut_bb1, sizeof(lut_bb1));
  106. for (int i = 0; i < 56; i++)
  107. EPD_1IN54F_SendData(epd, lut_bb1[i]);
  108. }
  109. static void EPD_1IN54F_partial_in(EPD* epd)
  110. {
  111. // ESP_LOGD(TAG, "Partial in!");
  112. // Panel setting: accept LUT from registers instead of OTP
  113. #if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
  114. uint8_t pst_use_reg_lut[] = { 0xf3, 0x0e };
  115. #elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
  116. uint8_t pst_use_reg_lut[] = { 0xff, 0x0e };
  117. #else
  118. #//error "Unsupported orientation - only portrait modes are supported for now"
  119. #endif
  120. EPD_1IN54F_SendCommand(epd,0x00);
  121. // EPD_1IN54F_SendData(pst_use_reg_lut, sizeof(pst_use_reg_lut));
  122. for (int i = 0; i < 2; i++)
  123. EPD_1IN54F_SendData(epd, pst_use_reg_lut[i]);
  124. // WORKAROUND: need to ignore OLD framebuffer or otherwise partial refresh won't work
  125. uint8_t vcom = 0xb7;
  126. EPD_1IN54F_SendCommand(epd,0x50);
  127. EPD_1IN54F_SendData(epd, vcom);
  128. // Dump LUT in
  129. EPD_1IN54F_load_partial_lut(epd);
  130. // Go partial!
  131. EPD_1IN54F_SendCommand(epd,0x91);
  132. }
  133. static void EPD_1IN54F_partial_out(EPD* epd)
  134. {
  135. // ESP_LOGD(TAG, "Partial out!");
  136. // Panel setting: use LUT from OTP
  137. #if defined (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT_INVERTED)
  138. uint8_t pst_use_otp_lut[] = { 0xd3, 0x0e };
  139. #elif defined(CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)
  140. uint8_t pst_use_otp_lut[] = { 0xdf, 0x0e };
  141. #else
  142. //#error "Unsupported orientation - only portrait modes are supported for now"
  143. #endif
  144. EPD_1IN54F_SendCommand(epd,0x00);
  145. //EPD_1IN54F_SendData(pst_use_otp_lut, sizeof(pst_use_otp_lut));
  146. for (int i = 0; i < 2; i++)
  147. EPD_1IN54F_SendData(epd, pst_use_otp_lut[i]);
  148. // WORKAROUND: re-enable OLD framebuffer to get a better full refresh
  149. uint8_t vcom = 0x97;
  150. EPD_1IN54F_SendCommand(epd,0x50);
  151. EPD_1IN54F_SendData(epd, vcom);
  152. // Out from partial!
  153. EPD_1IN54F_SendCommand(epd,0x92);
  154. }
  155. int EPD_1IN54F_Init(EPD* epd, const unsigned char* lut) {
  156. epd->reset_pin = EPD_RST_PIN;
  157. epd->dc_pin = EPD_DC_PIN;
  158. epd->cs_pin = EPD_CS_PIN;
  159. epd->busy_pin = EPD_BUSY_PIN;
  160. epd->width = EPD_1IN54F_WIDTH;
  161. epd->height = EPD_1IN54F_HEIGHT;
  162. /* this calls the peripheral hardware interface, see epdif */
  163. if (EpdInitCallback() != 0) {
  164. return -1;
  165. }
  166. /* EPD hardware init start */
  167. EPD_1IN54F_Reset(epd);
  168. /*
  169. EPD_1IN54F_SendCommand(epd, DRIVER_OUTPUT_CONTROL);
  170. EPD_1IN54F_SendData(epd, (EPD_1IN54F_HEIGHT - 1) & 0xFF);
  171. EPD_1IN54F_SendData(epd, ((EPD_1IN54F_HEIGHT - 1) >> 8) & 0xFF);
  172. EPD_1IN54F_SendData(epd, 0x00); // GD = 0; SM = 0; TB = 0;
  173. EPD_1IN54F_SendCommand(epd, BOOSTER_SOFT_START_CONTROL);
  174. EPD_1IN54F_SendData(epd, 0xD7);
  175. EPD_1IN54F_SendData(epd, 0xD6);
  176. EPD_1IN54F_SendData(epd, 0x9D);
  177. EPD_1IN54F_SendCommand(epd, WRITE_VCOM_REGISTER);
  178. EPD_1IN54F_SendData(epd, 0xA8); // VCOM 7C
  179. EPD_1IN54F_SendCommand(epd, SET_DUMMY_LINE_PERIOD);
  180. EPD_1IN54F_SendData(epd, 0x1A); // 4 dummy lines per gate
  181. EPD_1IN54F_SendCommand(epd, SET_GATE_TIME);
  182. EPD_1IN54F_SendData(epd, 0x08); // 2us per line
  183. EPD_1IN54F_SendCommand(epd, DATA_ENTRY_MODE_SETTING);
  184. EPD_1IN54F_SendData(epd, 0x03); // X increment; Y increment
  185. EPD_1IN54F_SetLut(epd, epd->lut);
  186. */
  187. ///*
  188. EPD_1IN54F_SendCommand(epd,0x00); // panel setting
  189. EPD_1IN54F_SendData (epd,0xdf);
  190. EPD_1IN54F_SendData (epd,0x0e);
  191. EPD_1IN54F_SendCommand(epd,0x01); // power setting
  192. EPD_1IN54F_SendData(epd,0x03);
  193. EPD_1IN54F_SendData(epd,0x06); // 16V
  194. EPD_1IN54F_SendData(epd,0x2A);//
  195. EPD_1IN54F_SendData(epd,0x2A);//
  196. EPD_1IN54F_SendCommand(epd,0x4D); // FITIinternal code
  197. EPD_1IN54F_SendData (epd,0x55);
  198. EPD_1IN54F_SendCommand(epd,0xaa);
  199. EPD_1IN54F_SendData (epd,0x0f);
  200. EPD_1IN54F_SendCommand(epd,0xE9);
  201. EPD_1IN54F_SendData (epd,0x02);
  202. EPD_1IN54F_SendCommand(epd,0xb6);
  203. EPD_1IN54F_SendData (epd,0x11);
  204. EPD_1IN54F_SendCommand(epd,0xF3);
  205. EPD_1IN54F_SendData (epd,0x0a);
  206. EPD_1IN54F_SendCommand(epd,0x06); // boost soft start
  207. EPD_1IN54F_SendData (epd,0xc7);
  208. EPD_1IN54F_SendData (epd,0x0c);
  209. EPD_1IN54F_SendData (epd,0x0c);
  210. EPD_1IN54F_SendCommand(epd,0x61); // resolution setting
  211. EPD_1IN54F_SendData (epd,0xc8); // 200
  212. EPD_1IN54F_SendData (epd,0x00);
  213. EPD_1IN54F_SendData (epd,0xc8); // 200
  214. EPD_1IN54F_SendCommand(epd,0x60); // Tcon setting
  215. EPD_1IN54F_SendData (epd,0x00);
  216. EPD_1IN54F_SendCommand(epd,0x82); // VCOM DC setting
  217. EPD_1IN54F_SendData (epd,0x12);
  218. EPD_1IN54F_SendCommand(epd,0x30); // PLL control
  219. EPD_1IN54F_SendData (epd,0x3C); // default 50Hz
  220. EPD_1IN54F_SendCommand(epd,0X50); // VCOM and data interval
  221. EPD_1IN54F_SendData(epd,0x97);//
  222. EPD_1IN54F_SendCommand(epd,0XE3); // power saving register
  223. EPD_1IN54F_SendData(epd,0x00); // default
  224. EPD_1IN54F_SendCommand(epd,0X04);
  225. //*/
  226. /* esp32 lib
  227. EPD_1IN54F_SendCommand(epd,0x00); // panel setting
  228. EPD_1IN54F_SendData (epd,0xdf);
  229. EPD_1IN54F_SendData (epd,0x0e);
  230. EPD_1IN54F_SendCommand(epd,0x4d); // panel setting
  231. EPD_1IN54F_SendData (epd,0x55);
  232. EPD_1IN54F_SendCommand(epd,0xaa); // panel setting
  233. EPD_1IN54F_SendData (epd,0x0f);
  234. EPD_1IN54F_SendCommand(epd,0xe9); // panel setting
  235. EPD_1IN54F_SendData (epd,0x02);
  236. EPD_1IN54F_SendCommand(epd,0xb6); // panel setting
  237. EPD_1IN54F_SendData (epd,0x11);
  238. EPD_1IN54F_SendCommand(epd,0xf3); // panel setting
  239. EPD_1IN54F_SendData (epd,0x0a);
  240. EPD_1IN54F_SendCommand(epd,0x61); // resolution setting
  241. EPD_1IN54F_SendData (epd,0xc8); // 200
  242. EPD_1IN54F_SendData (epd,0x00);
  243. EPD_1IN54F_SendData (epd,0xc8); // 200
  244. EPD_1IN54F_SendCommand(epd,0x60); // panel setting
  245. EPD_1IN54F_SendData (epd,0x00);
  246. EPD_1IN54F_SendCommand(epd,0x50); // panel setting
  247. EPD_1IN54F_SendData (epd,0x97);
  248. EPD_1IN54F_SendCommand(epd,0xe3); // panel setting
  249. EPD_1IN54F_SendData (epd,0x00);
  250. */
  251. EPD_1IN54F_DelayMs(epd, 100);
  252. EPD_1IN54F_WaitUntilIdle(epd);
  253. /* EPD hardware init end */
  254. return 0;
  255. }
  256. /**
  257. * @brief: this calls the corresponding function from epdif.h
  258. * usually there is no need to change this function
  259. */
  260. void EPD_1IN54F_DigitalWrite(EPD* epd, int pin, int value) {
  261. EpdDigitalWriteCallback(pin, value);
  262. }
  263. /**
  264. * @brief: this calls the corresponding function from epdif.h
  265. * usually there is no need to change this function
  266. */
  267. int EPD_1IN54F_DigitalRead(EPD* epd, int pin) {
  268. return EpdDigitalReadCallback(pin);
  269. }
  270. /**
  271. * @brief: this calls the corresponding function from epdif.h
  272. * usually there is no need to change this function
  273. */
  274. void EPD_1IN54F_DelayMs(EPD* epd, unsigned int delaytime) { // 1ms
  275. EpdDelayMsCallback(delaytime);
  276. }
  277. /**
  278. * @brief: basic function for sending commands
  279. */
  280. void EPD_1IN54F_SendCommand(EPD* epd, unsigned char command) {
  281. EPD_1IN54F_DigitalWrite(epd, epd->dc_pin, LOW);
  282. EpdSpiTransferCallback(command);
  283. }
  284. /**
  285. * @brief: basic function for sending data
  286. */
  287. void EPD_1IN54F_SendData(EPD* epd, unsigned char data) {
  288. EPD_1IN54F_DigitalWrite(epd, epd->dc_pin, HIGH);
  289. EpdSpiTransferCallback(data);
  290. }
  291. /**
  292. * @brief: Wait until the busy_pin goes LOW
  293. */
  294. void EPD_1IN54F_WaitUntilIdle(EPD* epd) {
  295. EPD_Busy_WaitUntil(0,0);
  296. // while(EPD_1IN54F_DigitalRead(epd, epd->busy_pin) == HIGH) { //0: busy, 1: idle
  297. // EPD_1IN54F_DelayMs(epd, 100);
  298. // }
  299. }
  300. /**
  301. * @brief: module reset.
  302. * often used to awaken the module in deep sleep,
  303. * see EPD::Sleep();
  304. */
  305. void EPD_1IN54F_Reset(EPD* epd) {
  306. EPD_1IN54F_DigitalWrite(epd, epd->reset_pin, LOW); //module reset
  307. EPD_1IN54F_DelayMs(epd, 200);
  308. EPD_1IN54F_DigitalWrite(epd, epd->reset_pin, HIGH);
  309. EPD_1IN54F_DelayMs(epd, 200);
  310. }
  311. /**
  312. * @brief: module Power on.
  313. */
  314. void EPD_1IN54F_power_on(EPD* epd) {
  315. EPD_1IN54F_SendCommand(epd, 0x50);
  316. EPD_1IN54F_SendData(epd,0x97);
  317. EPD_1IN54F_SendCommand(epd, 0x04);
  318. }
  319. /**
  320. * @brief: module Power off.
  321. */
  322. void EPD_1IN54F_power_off(EPD* epd) {
  323. EPD_1IN54F_SendCommand(epd, 0x50);
  324. EPD_1IN54F_SendData(epd,0xf7);
  325. EPD_1IN54F_SendCommand(epd, 0x02);
  326. }
  327. /**
  328. * @brief: put an image buffer to the frame memory.
  329. * this won't update the display.
  330. */
  331. void EPD_1IN54F_SetFrameMemory(
  332. EPD* epd,
  333. const unsigned char* image_buffer,
  334. int x,
  335. int y,
  336. int image_width,
  337. int image_height
  338. ) {
  339. int x_end;
  340. int y_end;
  341. if (
  342. image_buffer == NULL ||
  343. x < 0 || image_width < 0 ||
  344. y < 0 || image_height < 0
  345. ) {
  346. return;
  347. }
  348. /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  349. x &= 0xF8;
  350. image_width &= 0xF8;
  351. if (x + image_width >= epd->width) {
  352. x_end = epd->width - 1;
  353. } else {
  354. x_end = x + image_width - 1;
  355. }
  356. if (y + image_height >= epd->height) {
  357. y_end = epd->height - 1;
  358. } else {
  359. y_end = y + image_height - 1;
  360. }
  361. // 局刷还不行
  362. EPD_1IN54F_SetMemoryArea(epd, x, y, x_end, y_end);
  363. //EPD_1IN54F_SetMemoryPointer(epd, x, y);
  364. //EPD_1IN54F_SendCommand(epd, WRITE_RAM);
  365. EPD_1IN54F_SendCommand(epd, 0x10);
  366. /* send the image data */
  367. for (int j = 0; j < y_end - y + 1; j++) {
  368. for (int i = 0; i < (x_end - x + 1) / 8; i++) {
  369. EPD_1IN54F_SendData(epd, image_buffer[i + j * (image_width / 8)]);
  370. }
  371. }
  372. EPD_1IN54F_SendCommand(epd, 0x13);
  373. /* send the image data */
  374. for (int j = 0; j < y_end - y + 1; j++) {
  375. for (int i = 0; i < (x_end - x + 1) / 8; i++) {
  376. EPD_1IN54F_SendData(epd, image_buffer[i + j * (image_width / 8)]);
  377. }
  378. }
  379. }
  380. /**
  381. * @brief: clear the frame memory with the specified color.
  382. * this won't update the display.
  383. */
  384. void EPD_1IN54F_ClearFrameMemory(EPD* epd, unsigned char color) {
  385. EPD_1IN54F_SetMemoryArea(epd, 0, 0, epd->width - 1, epd->height - 1);
  386. EPD_1IN54F_SetMemoryPointer(epd, 0, 0);
  387. EPD_1IN54F_SendCommand(epd, WRITE_RAM);
  388. /* send the color data */
  389. for (int i = 0; i < epd->width / 8 * epd->height; i++) {
  390. EPD_1IN54F_SendData(epd, color);
  391. }
  392. }
  393. /**
  394. * @brief: update the display
  395. * there are 2 memory areas embedded in the e-paper display
  396. * but once this function is called,
  397. * the the next action of SetFrameMemory or ClearFrame will
  398. * set the other memory area.
  399. */
  400. void EPD_1IN54F_DisplayFrame(EPD* epd) {
  401. // EPD_1IN54F_SendCommand(epd, DISPLAY_UPDATE_CONTROL_2);
  402. // EPD_1IN54F_SendData(epd, 0xC4);
  403. // EPD_1IN54F_SendCommand(epd, MASTER_ACTIVATION);
  404. // EPD_1IN54F_SendCommand(epd, TERMINATE_FRAME_READ_WRITE);
  405. EPD_1IN54F_SendCommand(epd, 0x12);
  406. EPD_1IN54F_WaitUntilIdle(epd);
  407. }
  408. /**
  409. * @brief: After this command is transmitted, the chip would enter the
  410. * deep-sleep mode to save power.
  411. * The deep sleep mode would return to standby by hardware reset.
  412. * You can use EPD_1IN54F_Init() to awaken
  413. */
  414. void EPD_1IN54F_Sleep(EPD* epd) {
  415. EPD_1IN54F_SendCommand(epd, DEEP_SLEEP_MODE);
  416. EPD_1IN54F_WaitUntilIdle(epd);
  417. }
  418. /**
  419. * @brief: set the look-up tables
  420. */
  421. static void EPD_1IN54F_SetLut(EPD* epd, const unsigned char* lut) {
  422. epd->lut = lut;
  423. EPD_1IN54F_SendCommand(epd, WRITE_LUT_REGISTER);
  424. /* the length of look-up table is 30 bytes */
  425. for (int i = 0; i < 30; i++) {
  426. EPD_1IN54F_SendData(epd, epd->lut[i]);
  427. }
  428. }
  429. /**
  430. * @brief: private function to specify the memory area for data R/W
  431. */
  432. static void EPD_1IN54F_SetMemoryArea(EPD* epd, int x_start, int y_start, int x_end, int y_end) {
  433. // EPD_1IN54F_SendCommand(epd, SET_RAM_X_ADDRESS_START_END_POSITION);
  434. // /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  435. // EPD_1IN54F_SendData(epd, (x_start >> 3) & 0xFF);
  436. // EPD_1IN54F_SendData(epd, (x_end >> 3) & 0xFF);
  437. // EPD_1IN54F_SendCommand(epd, SET_RAM_Y_ADDRESS_START_END_POSITION);
  438. // EPD_1IN54F_SendData(epd, y_start & 0xFF);
  439. // EPD_1IN54F_SendData(epd, (y_start >> 8) & 0xFF);
  440. // EPD_1IN54F_SendData(epd, y_end & 0xFF);
  441. // EPD_1IN54F_SendData(epd, (y_end >> 8) & 0xFF);
  442. uint16_t xe = (x_start + x_end - 1) | 0x0007; // byte boundary inclusive (last byte)
  443. uint16_t ye = y_start + y_end - 1;
  444. x_start &= 0xFFF8; // byte boundary
  445. EPD_1IN54F_SendCommand(epd,0x90); // partial window
  446. //_writeData(x / 256);
  447. EPD_1IN54F_SendData(epd,x_start % 256);
  448. //_writeData(xe / 256);
  449. EPD_1IN54F_SendData(epd,xe % 256);
  450. EPD_1IN54F_SendData(epd,y_start / 256);
  451. EPD_1IN54F_SendData(epd,y_start % 256);
  452. EPD_1IN54F_SendData(epd,ye / 256);
  453. EPD_1IN54F_SendData(epd,ye % 256);
  454. EPD_1IN54F_SendData(epd,0x01); // don't see any difference
  455. //_writeData(0x00); // don't see any difference
  456. }
  457. /**
  458. * @brief: private function to specify the start point for data R/W
  459. */
  460. static void EPD_1IN54F_SetMemoryPointer(EPD* epd, int x, int y) {
  461. EPD_1IN54F_SendCommand(epd, SET_RAM_X_ADDRESS_COUNTER);
  462. /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  463. EPD_1IN54F_SendData(epd, (x >> 3) & 0xFF);
  464. EPD_1IN54F_SendCommand(epd, SET_RAM_Y_ADDRESS_COUNTER);
  465. EPD_1IN54F_SendData(epd, y & 0xFF);
  466. EPD_1IN54F_SendData(epd, (y >> 8) & 0xFF);
  467. EPD_1IN54F_WaitUntilIdle(epd);
  468. }
  469. static const unsigned char lut_full_update[] =
  470. {
  471. 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22,
  472. 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, 0x88,
  473. 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51,
  474. 0x35, 0x51, 0x51, 0x19, 0x01, 0x00
  475. };
  476. // static const unsigned char lut_partial_update[] =
  477. // {
  478. // 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00,
  479. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  480. // 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12,
  481. // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  482. // };
  483. static void EPD_1IN54F_update_partial(EPD* epd,uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t *data)
  484. {
  485. EPD_1IN54F_power_on(epd);
  486. EPD_1IN54F_partial_in(epd);
  487. // Set partial window
  488. uint8_t ptl_setting[8] = { x1, x2, 0, y1, 0, y2, 0x01 };
  489. //uint8_t ptl_setting[8] = { x1, x1+x2, 0, y1, 0, y1+y2, 0x01 };
  490. //EPD_1IN54F_SendCommand(epd,0X90); // power saving register
  491. EPD_1IN54F_SendCommand(epd,0x90);
  492. for (int i = 0; i < 7; i++)
  493. EPD_1IN54F_SendData(epd, ptl_setting[i]);
  494. //uint8_t *data_ptr = (uint8_t *)data;
  495. EPD_1IN54F_SendCommand(epd,0x13);
  496. for (size_t h_idx = 0; h_idx < y2; h_idx++) {
  497. //EPD_1IN54F_SendData(data_ptr, EPD_1IN54F_ROW_LEN);
  498. for (int i = 0; i < x2/8; i++)
  499. EPD_1IN54F_SendData(epd, data[i]);
  500. data += x2/8;
  501. // len -= EPD_1IN54F_ROW_LEN;
  502. }
  503. // ESP_LOGD(TAG, "Partial wait start");
  504. EPD_1IN54F_SendCommand(epd,0x12);
  505. EPD_1IN54F_WaitUntilIdle(epd);
  506. // ESP_LOGD(TAG, "Partial updated");
  507. EPD_1IN54F_partial_out(epd);
  508. EPD_1IN54F_power_off(epd);
  509. }
  510. void EPD_1IN54F_fb_full_update(EPD* epd,uint8_t *data, size_t len)
  511. {
  512. EPD_1IN54F_power_on(epd);
  513. // ESP_LOGD(TAG, "Performing full update, len: %u", len);
  514. uint8_t *data_ptr = data;
  515. // Fill OLD data (maybe not necessary)
  516. uint8_t old_data[EPD_1IN54F_ROW_LEN] = { 0 };
  517. EPD_1IN54F_SendCommand(epd,0x10);
  518. for (size_t idx = 0; idx < EPD_1IN54F_HEIGHT; idx++) {
  519. //jd79653a_spi_send_data(old_data, EPD_1IN54F_ROW_LEN);
  520. for (int i = 0; i < EPD_1IN54F_ROW_LEN; i++)
  521. EPD_1IN54F_SendData(epd, old_data[i]);
  522. }
  523. // Fill NEW data
  524. EPD_1IN54F_SendCommand(epd,0x13);
  525. for (size_t h_idx = 0; h_idx < EPD_1IN54F_HEIGHT; h_idx++) {
  526. //jd79653a_spi_send_data(data_ptr, EPD_1IN54F_ROW_LEN);
  527. for (int i = 0; i < EPD_1IN54F_ROW_LEN; i++)
  528. EPD_1IN54F_SendData(epd, data_ptr[i]);
  529. data_ptr += EPD_1IN54F_ROW_LEN;
  530. //len -= EPD_1IN54F_ROW_LEN;
  531. }
  532. //ESP_LOGD(TAG, "Rest len: %u", len);
  533. EPD_1IN54F_SendCommand(epd,0x12); // Issue refresh command
  534. EPD_1IN54F_DelayMs(epd, 100);
  535. EPD_1IN54F_WaitUntilIdle(epd);
  536. EPD_1IN54F_power_off(epd);
  537. }
  538. //void jd79653a_lv_fb_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
  539. void jd79653a_lv_fb_flush(
  540. EPD* epd,
  541. const unsigned char *color_map,
  542. int x,
  543. int y,
  544. int image_width,
  545. int image_height
  546. ){
  547. // size_t len = ((area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1)) / 8;
  548. // ESP_LOGD(TAG, "x1: 0x%x, x2: 0x%x, y1: 0x%x, y2: 0x%x", area->x1, area->x2, area->y1, area->y2);
  549. // ESP_LOGD(TAG, "Writing LVGL fb with len: %u, partial counter: %u", len, partial_counter);
  550. uint8_t *buf = (uint8_t *) color_map;
  551. if (partial_counter == 0) {
  552. // ESP_LOGD(TAG, "Refreshing in FULL");
  553. EPD_1IN54F_fb_full_update(epd, buf, ((EPD_1IN54F_HEIGHT * EPD_1IN54F_WIDTH) / 8));
  554. partial_counter = EPD_1IN54F_PARTIAL_CNT; // Reset partial counter here
  555. } else {
  556. EPD_1IN54F_update_partial(epd, x, y, x+image_width-1, y+image_height-1, buf);
  557. partial_counter -= 1; // ...or otherwise, decrease 1
  558. }
  559. // lv_disp_flush_ready(drv);
  560. }
  561. #define UBYTE uint8_t
  562. UBYTE EPD_1IN54FF_Init(void);
  563. void EPD_1IN54FF_Clear(void);
  564. void EPD_1IN54FF_Display(UBYTE *Image);
  565. void EPD_1IN54FF_Sleep(void);
  566. #define BUSY_Pin (18)
  567. #define RST_Pin (7)
  568. #define DC_Pin (9)
  569. #define SPI_CS_Pin (16)
  570. static EPD _epd;
  571. UBYTE EPD_1IN54FF_Init(void) {
  572. _epd.busy_pin = EPD_BUSY_PIN;
  573. _epd.reset_pin = EPD_RST_PIN;
  574. _epd.dc_pin = EPD_DC_PIN;
  575. _epd.cs_pin = EPD_CS_PIN;
  576. _epd.width = EPD_1IN54F_WIDTH;
  577. _epd.height = EPD_1IN54F_HEIGHT;
  578. LLOGD("EPD_1IN54F_Init");
  579. EPD_1IN54F_Init(&_epd, lut_full_update);
  580. return 0;
  581. }
  582. void EPD_1IN54FF_Clear(void) {
  583. ;
  584. }
  585. void EPD_1IN54FF_Display(UBYTE *Image) {
  586. EPD_1IN54F_SetFrameMemory(&_epd, Image, 0, 0, EPD_1IN54F_WIDTH, EPD_1IN54F_HEIGHT);
  587. EPD_1IN54F_DisplayFrame(&_epd);
  588. }
  589. void EPD_1IN54FF_Sleep(void) {
  590. EPD_1IN54F_Sleep(&_epd);
  591. }
  592. /* END OF FILE */