Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

790 wiersze
23 KiB

  1. /*
  2. * Author: LoBo (loboris@gmail.com, loboris.github)
  3. *
  4. * Module supporting SPI ePaper displays
  5. *
  6. * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS
  7. * USING DIRECT or DMA SPI TRANSFER MODEs
  8. *
  9. */
  10. #include "spidriver/spi_master_lobo.h"
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <time.h>
  14. #include <string.h>
  15. #include "esp_system.h"
  16. #include "freertos/FreeRTOS.h"
  17. #include "freertos/task.h"
  18. #include "esp_heap_alloc_caps.h"
  19. #include "soc/spi_reg.h"
  20. #include "EPDspi.h"
  21. #define EPD_DEBUG 1
  22. #define EPD_BORDER_WHITE 0x61
  23. #define EPD_BORDER_BLACK 0x51
  24. #define EPD_BORDER EPD_BORDER_BLACK
  25. #define EPD2X9 1
  26. #define xDot 128
  27. #define yDot 296
  28. #define DELAYTIME 1500
  29. // ===== Global ======
  30. spi_lobo_device_handle_t disp_spi;
  31. uint8_t *gs_disp_buffer;
  32. uint8_t *disp_buffer;
  33. uint8_t *gs_drawBuff;
  34. uint8_t *drawBuff;
  35. int _width;
  36. int _height;
  37. uint16_t gs_used_shades;
  38. uint8_t _gs;
  39. uint8_t *LUT_part;
  40. uint8_t LUTDefault_fastest[31];
  41. uint8_t LUTDefault_part[31];
  42. uint8_t LUT_gs[31];
  43. uint8_t LUTDefault_full[31];
  44. uint8_t lvl_buf[16];
  45. uint8_t lvl_buf_jpg[16];
  46. // =====
  47. static uint8_t GDOControl[] = {0x01, (yDot-1)%256, (yDot-1)/256, 0x00};
  48. static uint8_t softstart[4] = {0x0c, 0xd7, 0xd6, 0x9d};
  49. static uint8_t VCOMVol[2] = {0x2c, 0xa8}; // VCOM 7c
  50. static uint8_t DummyLine[2] = {0x3a, 0x1a}; // 4 dummy line per gate
  51. static uint8_t Gatetime[2] = {0x3b, 0x08}; // 2us per line
  52. static uint8_t RamDataEntryMode[2] = {0x11, 0x01}; // Ram data entry mode
  53. static uint8_t Border[2] = {0x3c, EPD_BORDER}; // Border control ( 0x61: white border; 0x51: black border
  54. /*
  55. There are totally 20 phases for programmable Source waveform of different phase length.
  56. The phase period defined as TP [n] * T FRAME , where TP [n] range from 0 to 15.
  57. TP [n] = 0 indicates phase skipped
  58. Source Voltage Level: VS [n-XY] is constant in each phase
  59. VS [n-XY] indicates the voltage in phase n for transition from GS X to GS Y
  60.  00 – VSS
  61.  01 – VSH
  62.  10 – VSL
  63.  11 – NA
  64. VS [n-XY] and TP[n] are stored in waveform lookup table register [LUT].
  65. VS coding: VS[0-11] VS[0-10] VS[0-01] VS[0-00]
  66. */
  67. // --- VS ---- ---- TP ----
  68. //uint8_t LUTDefault_full[31] = {0x32, 0x02,0x02,0x01,0x11,0x12,0x12,0x22,0x22,0x66,0x69,0x69,0x59,0x58,0x99,0x99,0x88,0x00,0x00,0x00,0x00, 0xF8,0xB4,0x13,0x51,0x35,0x51,0x51,0x19,0x01,0x00};
  69. uint8_t LUTDefault_full[31] = {0x32, 0x11,0x11,0x10,0x02,0x02,0x22,0x22,0x22,0x22,0x22,0x51,0x51,0x55,0x88,0x08,0x08,0x88,0x88,0x00,0x00, 0x34,0x23,0x12,0x21,0x24,0x28,0x22,0x21,0xA1,0x01};
  70. uint8_t LUTDefault_part[31] = {0x32, 0x10,0x18,0x18,0x08,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x13,0x14,0x44,0x12,0x00,0x00,0x00,0x00,0x00,0x00};
  71. uint8_t LUT_gs[31] = {0x32, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  72. uint8_t LUTFastest[31] = {0x32, 0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  73. uint8_t lvl_buf[16] = {32,70,110,150,185,210,220,225,230,235,240,243,248,251,253,255};
  74. uint8_t lvl_buf_jpg[16] = {4,8,12,16,22,30,40,60,80,110,140,180,220,240,250,255};
  75. uint8_t *LUT_part = LUTDefault_part;
  76. spi_lobo_device_handle_t disp_spi = NULL;
  77. uint8_t *gs_disp_buffer = NULL;
  78. uint8_t *disp_buffer = NULL;
  79. uint8_t *drawBuff = NULL;
  80. uint8_t *gs_drawBuff = NULL;
  81. int _width = EPD_DISPLAY_WIDTH;
  82. int _height = EPD_DISPLAY_HEIGHT;
  83. uint8_t _gs = 0;
  84. uint16_t gs_used_shades = 0;
  85. //-----------------------------------------------------------
  86. static void IRAM_ATTR _dma_send(uint8_t *data, uint32_t size)
  87. {
  88. //Fill DMA descriptors
  89. spi_lobo_dmaworkaround_transfer_active(disp_spi->host->dma_chan); //mark channel as active
  90. spi_lobo_setup_dma_desc_links(disp_spi->host->dmadesc_tx, size, data, false);
  91. disp_spi->host->hw->user.usr_mosi_highpart=0;
  92. disp_spi->host->hw->dma_out_link.addr=(int)(&disp_spi->host->dmadesc_tx[0]) & 0xFFFFF;
  93. disp_spi->host->hw->dma_out_link.start=1;
  94. disp_spi->host->hw->user.usr_mosi_highpart=0;
  95. disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = (size * 8) - 1;
  96. // Start transfer
  97. disp_spi->host->hw->cmd.usr = 1;
  98. // Wait for SPI bus ready
  99. while (disp_spi->host->hw->cmd.usr);
  100. //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
  101. if (disp_spi->host->dma_chan) spi_lobo_dmaworkaround_idle(disp_spi->host->dma_chan);
  102. // Reset DMA
  103. disp_spi->host->hw->dma_conf.val |= SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST;
  104. disp_spi->host->hw->dma_out_link.start=0;
  105. disp_spi->host->hw->dma_in_link.start=0;
  106. disp_spi->host->hw->dma_conf.val &= ~(SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST);
  107. disp_spi->host->hw->dma_conf.out_data_burst_en=1;
  108. }
  109. //--------------------------------------------------------------------------
  110. static void IRAM_ATTR _direct_send(uint8_t *data, uint32_t len, uint8_t rep)
  111. {
  112. uint32_t cidx = 0; // buffer index
  113. uint32_t wd = 0;
  114. int idx = 0;
  115. int bits = 0;
  116. int wbits = 0;
  117. taskDISABLE_INTERRUPTS();
  118. while (len) {
  119. wd |= (uint32_t)data[idx] << wbits;
  120. wbits += 8;
  121. if (wbits == 32) {
  122. bits += wbits;
  123. wbits = 0;
  124. disp_spi->host->hw->data_buf[idx++] = wd;
  125. wd = 0;
  126. }
  127. len--; // Decrement data counter
  128. if (rep == 0) cidx++; // if not repeating data, increment buffer index
  129. }
  130. if (bits) {
  131. while (disp_spi->host->hw->cmd.usr); // Wait for SPI bus ready
  132. // Load send buffer
  133. disp_spi->host->hw->user.usr_mosi_highpart = 0;
  134. disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = bits-1;
  135. disp_spi->host->hw->user.usr_mosi = 1;
  136. disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0;
  137. disp_spi->host->hw->user.usr_miso = 0;
  138. disp_spi->host->hw->cmd.usr = 1; // Start transfer
  139. }
  140. // Wait for SPI bus ready
  141. while (disp_spi->host->hw->cmd.usr);
  142. taskENABLE_INTERRUPTS();
  143. }
  144. // ================================================================
  145. // === Main function to send data to display ======================
  146. // If rep==true: repeat sending data to display 'len' times
  147. // If rep==false: send 'len' data bytes from buffer to display
  148. // ** Device must already be selected and address window set **
  149. // ================================================================
  150. //---------------------------------------------------------------------------
  151. static void IRAM_ATTR SPI_send_data(uint8_t *data, uint32_t len, uint8_t rep)
  152. {
  153. if (len == 0) return;
  154. if ((len*8) <= 512) _direct_send(data, len, rep);
  155. else if (rep == 0) _dma_send(data, len);
  156. else {
  157. // ==== Repeat data, more than 512 bits total ====
  158. uint8_t *transbuf = pvPortMallocCaps(len, MALLOC_CAP_DMA);
  159. if (transbuf == NULL) return;
  160. memset(transbuf, data[0], len);
  161. _dma_send(transbuf, len);
  162. free(transbuf);
  163. }
  164. }
  165. // Send one byte to display
  166. //-------------------------------------
  167. void IRAM_ATTR SPI_Write(uint8_t value)
  168. {
  169. disp_spi->host->hw->data_buf[0] = (uint32_t)value;
  170. // Load send buffer
  171. disp_spi->host->hw->user.usr_mosi_highpart = 0;
  172. disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
  173. disp_spi->host->hw->user.usr_mosi = 1;
  174. disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0;
  175. disp_spi->host->hw->user.usr_miso = 0;
  176. // Start transfer
  177. disp_spi->host->hw->cmd.usr = 1;
  178. // Wait for SPI bus ready
  179. while (disp_spi->host->hw->cmd.usr);
  180. }
  181. // Check display busy line and wait while busy
  182. //-----------------------
  183. static uint8_t ReadBusy()
  184. {
  185. for (int i=0; i<400; i++){
  186. if (isEPD_BUSY == EPD_BUSY_LEVEL) return 1;
  187. vTaskDelay(10 / portTICK_RATE_MS);
  188. }
  189. return 0;
  190. }
  191. //-----------------------
  192. static uint8_t WaitBusy()
  193. {
  194. if (isEPD_BUSY != EPD_BUSY_LEVEL) return 1;
  195. vTaskDelay(10 / portTICK_RATE_MS);
  196. if (isEPD_BUSY != EPD_BUSY_LEVEL) return 1;
  197. return 0;
  198. }
  199. // Write one command without parameters
  200. //---------------------------------------
  201. static void EPD_WriteCMD(uint8_t command)
  202. {
  203. spi_lobo_device_select(disp_spi, 0);
  204. EPD_DC_0; // command write
  205. SPI_Write(command);
  206. }
  207. // Write command with one paramet
  208. //---------------------------------------
  209. static void EPD_WriteCMD_p1(uint8_t command,uint8_t para)
  210. {
  211. spi_lobo_device_select(disp_spi, 0);
  212. //ReadBusy();
  213. EPD_DC_0; // command write
  214. SPI_Write(command);
  215. EPD_DC_1; // data write
  216. SPI_Write(para);
  217. spi_lobo_device_deselect(disp_spi);
  218. }
  219. //----------------
  220. void EPD_PowerOn()
  221. {
  222. EPD_WriteCMD_p1(0x22,0xc0);
  223. EPD_WriteCMD(0x20);
  224. //EPD_WriteCMD(0xff);
  225. spi_lobo_device_deselect(disp_spi);
  226. #if EPD_DEBUG
  227. if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
  228. if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
  229. #else
  230. WaitBusy();
  231. ReadBusy();
  232. #endif
  233. }
  234. //-----------------
  235. void EPD_PowerOff()
  236. {
  237. EPD_WriteCMD_p1(0x22,0x03);
  238. EPD_WriteCMD(0x20);
  239. //EPD_WriteCMD(0xff);
  240. spi_lobo_device_deselect(disp_spi);
  241. #if EPD_DEBUG
  242. if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
  243. if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
  244. #else
  245. WaitBusy();
  246. ReadBusy();
  247. #endif
  248. #ifdef POWER_Pin
  249. gpio_set_level(DC_Pin, 0);
  250. gpio_set_level(MOSI_Pin, 0);
  251. gpio_set_level(SCK_Pin, 0);
  252. gpio_set_level(RST_Pin, 0);
  253. gpio_set_level(CS_Pin, 0);
  254. gpio_set_level(POWER_Pin, 0);
  255. #endif
  256. }
  257. // Send command with multiple parameters
  258. //----------------------------------------------------
  259. static void EPD_Write(uint8_t *value, uint8_t datalen)
  260. {
  261. uint8_t i = 0;
  262. uint8_t *ptemp;
  263. ptemp = value;
  264. spi_lobo_device_select(disp_spi, 0);
  265. //ReadBusy();
  266. EPD_DC_0; // When DC is 0, write command
  267. SPI_Write(*ptemp); //The first byte is written with the command value
  268. ptemp++;
  269. EPD_DC_1; // When DC is 1, write data
  270. for(i= 0;i<datalen-1;i++){ // sub the data
  271. SPI_Write(*ptemp);
  272. ptemp++;
  273. }
  274. spi_lobo_device_deselect(disp_spi);
  275. }
  276. // Send data buffer to display
  277. //----------------------------------------------------------------------------
  278. static void EPD_WriteDispRam(uint8_t XSize, uint16_t YSize, uint8_t *Dispbuff)
  279. {
  280. if (XSize%8 != 0) XSize = XSize+(8-XSize%8);
  281. XSize = XSize/8;
  282. spi_lobo_device_select(disp_spi, 0);
  283. //ReadBusy();
  284. EPD_DC_0; //command write
  285. SPI_Write(0x24);
  286. EPD_DC_1; //data write
  287. SPI_send_data(Dispbuff, XSize*YSize, 0);
  288. spi_lobo_device_deselect(disp_spi);
  289. }
  290. // Fill the display with value
  291. //-------------------------------------------------------------------------------
  292. static void EPD_WriteDispRamMono(uint8_t XSize, uint16_t YSize, uint8_t dispdata)
  293. {
  294. if (XSize%8 != 0) XSize = XSize+(8-XSize%8);
  295. XSize = XSize/8;
  296. spi_lobo_device_select(disp_spi, 0);
  297. //ReadBusy();
  298. EPD_DC_0; // command write
  299. SPI_Write(0x24);
  300. EPD_DC_1; // data write
  301. SPI_send_data(&dispdata, XSize*YSize, 1);
  302. spi_lobo_device_deselect(disp_spi);
  303. }
  304. /*
  305. === Set RAM X - Address Start / End Position (44h) ===
  306. Specify the start/end positions of the window address in the X direction by 8 times address unit.
  307. Data is written to the RAM within the area determined by the addresses specified by XSA [4:0] and XEA [4:0].
  308. These addresses must be set before the RAM write. It allows on XEA [4:0] ≤ XSA [4:0].
  309. The settings follow the condition on 00h ≤ XSA [4:0], XEA [4:0] ≤ 1Dh.
  310. The windows is followed by the control setting of Data Entry Setting (R11h)
  311. === Set RAM Y - Address Start / End Position (45h) ===
  312. Specify the start/end positions of the window address in the Y direction by an address unit.
  313. Data is written to the RAM within the area determined by the addresses specified by YSA [8:0] and YEA [8:0].
  314. These addresses must be set before the RAM write.
  315. It allows YEA [8:0] ≤ YSA [8:0].
  316. The settings follow the condition on 00h ≤ YSA [8:0], YEA [8:0] ≤ 13Fh.
  317. The windows is followed by the control setting of Data Entry Setting (R11h)
  318. */
  319. //--------------------------------------------------------------------------------------
  320. static void EPD_SetRamArea(uint8_t Xstart, uint8_t Xend, uint16_t Ystart, uint16_t Yend)
  321. {
  322. uint8_t RamAreaX[3]; // X start and end
  323. uint8_t RamAreaY[5]; // Y start and end
  324. RamAreaX[0] = 0x44; // command
  325. RamAreaX[1] = Xstart;
  326. RamAreaX[2] = Xend;
  327. RamAreaY[0] = 0x45; // command
  328. RamAreaY[1] = Ystart & 0xFF;
  329. RamAreaY[2] = Ystart >> 8;
  330. RamAreaY[3] = Yend & 0xFF;
  331. RamAreaY[4] = Yend >> 8;
  332. EPD_Write(RamAreaX, sizeof(RamAreaX));
  333. EPD_Write(RamAreaY, sizeof(RamAreaY));
  334. }
  335. //Set RAM X and Y address counter
  336. /*
  337. === Set RAM Address Counter (4Eh-4Fh) ===
  338. adrX[4:0]: Make initial settings for the RAM X address in the address counter (AC).
  339. adrY[8:0]: Make initial settings for the RAM Y address in the address counter (AC).
  340. After RAM data is written, the address counter is automatically updated according to the settings with AM, ID
  341. bits and setting for a new RAM address is not required in the address counter.
  342. Therefore, data is written consecutively without setting an address.
  343. The address counter is not automatically updated when data is read out from the RAM.
  344. RAM address setting cannot be made during the standby mode.
  345. The address setting should be made within the area designated with window addresses which is controlled
  346. by the Data Entry Setting (R11h) {AM, ID[1:0]} ; RAM Address XStart / XEnd Position (R44h) and RAM Address Ystart /Yend Position (R45h).
  347. Otherwise undesirable image will be displayed on the Panel.
  348. */
  349. //----------------------------------------------------------
  350. static void EPD_SetRamPointer(uint8_t addrX, uint16_t addrY)
  351. {
  352. uint8_t RamPointerX[2]; // default (0,0)
  353. uint8_t RamPointerY[3];
  354. //Set RAM X address counter
  355. RamPointerX[0] = 0x4e;
  356. RamPointerX[1] = addrX;
  357. //Set RAM Y address counter
  358. RamPointerY[0] = 0x4f;
  359. RamPointerY[1] = addrY & 0xFF;
  360. RamPointerY[2] = addrY >> 8;
  361. EPD_Write(RamPointerX, sizeof(RamPointerX));
  362. EPD_Write(RamPointerY, sizeof(RamPointerY));
  363. }
  364. //Set RAM X and Y address Start / End position
  365. //Set RAM X and Y address counter
  366. //----------------------------------------------------------------------------------------------
  367. static void part_display(uint8_t RAM_XST, uint8_t RAM_XEND ,uint16_t RAM_YST, uint16_t RAM_YEND)
  368. {
  369. EPD_SetRamArea(RAM_XST, RAM_XEND, RAM_YST, RAM_YEND);
  370. EPD_SetRamPointer (RAM_XST, RAM_YST);
  371. }
  372. //Initialize the display
  373. //--------------------
  374. static void EPD_Init()
  375. {
  376. #ifdef POWER_Pin
  377. gpio_set_level(POWER_Pin, 1);
  378. vTaskDelay(100 / portTICK_RATE_MS);
  379. #else
  380. vTaskDelay(10 / portTICK_RATE_MS);
  381. #endif
  382. // reset
  383. EPD_RST_0;
  384. vTaskDelay(10 / portTICK_RATE_MS);
  385. #if EPD_DEBUG
  386. uint32_t t1 = clock();
  387. #endif
  388. EPD_RST_1;
  389. for (int n=0; n<50; n++) {
  390. vTaskDelay(10 / portTICK_RATE_MS);
  391. if (isEPD_BUSY == EPD_BUSY_LEVEL) break;
  392. }
  393. SPI_Write(0x12); // software reset
  394. vTaskDelay(10 / portTICK_RATE_MS);
  395. ReadBusy();
  396. // set registers
  397. EPD_Write(GDOControl, sizeof(GDOControl)); // Panel configuration, Gate selection
  398. EPD_Write(softstart, sizeof(softstart)); // X decrease, Y decrease
  399. EPD_Write(VCOMVol, sizeof(VCOMVol)); // VCOM setting
  400. EPD_Write(DummyLine, sizeof(DummyLine)); // dummy line per gate
  401. EPD_Write(Gatetime, sizeof(Gatetime)); // Gate time setting
  402. EPD_Write(Border, sizeof(Border));
  403. EPD_Write(RamDataEntryMode, sizeof(RamDataEntryMode)); // X increase, Y decrease
  404. EPD_SetRamArea(0x00, (xDot-1)/8, yDot-1, 0);
  405. EPD_SetRamPointer(0x00, yDot-1);
  406. #if EPD_DEBUG
  407. t1 = clock() - t1;
  408. printf("[EPD] Init: %u ms\r\n", t1);
  409. #endif
  410. }
  411. //------------------------------
  412. static void EPD_UpdateFull(void)
  413. {
  414. /*
  415. + Enable Clock Signal,
  416. + Then Enable CP
  417. - Then Load Temperature value
  418. - Then Load LUT
  419. - Then INITIAL DISPLAY
  420. + Then PATTERN DISPLAY
  421. + Then Disable CP
  422. + Then Disable OSC
  423. */
  424. EPD_WriteCMD_p1(0x22,0xC7);
  425. EPD_WriteCMD(0x20);
  426. //EPD_WriteCMD(0xff);
  427. spi_lobo_device_deselect(disp_spi);
  428. #if EPD_DEBUG
  429. if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
  430. if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
  431. #else
  432. WaitBusy();
  433. ReadBusy();
  434. #endif
  435. }
  436. //-------------------------------
  437. static void EPD_Update_Part(void)
  438. {
  439. /*
  440. - Enable Clock Signal,
  441. - Then Enable CP
  442. - Then Load Temperature value
  443. - Then Load LUT
  444. - Then INITIAL DISPLAY
  445. + Then PATTERN DISPLAY
  446. - Then Disable CP
  447. - Then Disable OSC
  448. */
  449. EPD_WriteCMD_p1(0x22,0x04);
  450. EPD_WriteCMD(0x20);
  451. //EPD_WriteCMD(0xff);
  452. spi_lobo_device_deselect(disp_spi);
  453. #if EPD_DEBUG
  454. if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
  455. if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
  456. #else
  457. WaitBusy();
  458. ReadBusy();
  459. #endif
  460. }
  461. /*******************************************************************************
  462. Full screen initialization
  463. ********************************************************************************/
  464. static void EPD_init_Full(void)
  465. {
  466. EPD_Init(); // Reset and set register
  467. EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));
  468. EPD_PowerOn();
  469. }
  470. /*******************************************************************************
  471. Part screen initialization
  472. ********************************************************************************/
  473. static void EPD_init_Part(void)
  474. {
  475. EPD_Init(); // display
  476. EPD_Write((uint8_t *)LUT_part, 31);
  477. EPD_PowerOn();
  478. }
  479. void EPD_wake()
  480. {
  481. EPD_Init();
  482. EPD_PowerOn();
  483. }
  484. /********************************************************************************
  485. parameter:
  486. Label :
  487. =1 Displays the contents of the DisBuffer
  488. =0 Displays the contents of the first byte in DisBuffer,
  489. ********************************************************************************/
  490. static void EPD_Dis_Full(uint8_t *DisBuffer,uint8_t type)
  491. {
  492. EPD_SetRamPointer(0x00, yDot-1); // set ram pointer
  493. if (type == 0){
  494. // Fill screen with white
  495. EPD_WriteDispRamMono(xDot, yDot, 0xff);
  496. }
  497. else {
  498. // Fill screen from buffer
  499. EPD_WriteDispRam(xDot, yDot, (uint8_t *)DisBuffer);
  500. }
  501. EPD_UpdateFull();
  502. }
  503. /********************************************************************************
  504. WARNING: X is smaller screen dimension (0~127) !
  505. Y is larger screen dimension (0~295) !
  506. parameter:
  507. xStart : X direction Start coordinate
  508. xEnd : X direction end coordinate
  509. yStart : Y direction Start coordinate
  510. yEnd : Y direction end coordinate
  511. DisBuffer : Display content
  512. type :
  513. =1 Displays the contents of the DisBuffer
  514. =0 Displays the contents of the first byte in DisBuffer,
  515. ********************************************************************************/
  516. static void EPD_Dis_Part(uint8_t xStart, uint8_t xEnd, uint16_t yStart, uint16_t yEnd, uint8_t *DisBuffer, uint8_t type)
  517. {
  518. if (type == 0) {
  519. // Repeated color
  520. part_display(xStart/8, xEnd/8, yEnd, yStart);
  521. EPD_WriteDispRamMono(xEnd-xStart+1, yEnd-yStart+1, DisBuffer[0]);
  522. EPD_Update_Part();
  523. part_display(xStart/8, xEnd/8, yEnd, yStart);
  524. EPD_WriteDispRamMono(xEnd-xStart+1, yEnd-yStart+1, DisBuffer[0]);
  525. }
  526. else {
  527. // From buffer
  528. part_display(xStart/8, xEnd/8, yEnd, yStart);
  529. EPD_WriteDispRam(xEnd-xStart+1, yEnd-yStart+1,DisBuffer);
  530. EPD_Update_Part();
  531. part_display(xStart/8, xEnd/8, yEnd, yStart);
  532. EPD_WriteDispRam(xEnd-xStart+1, yEnd-yStart+1,DisBuffer);
  533. }
  534. }
  535. //======================================================================================================================================
  536. // Clear full screen
  537. //=========================
  538. void EPD_DisplayClearFull()
  539. {
  540. uint8_t m;
  541. EPD_init_Full();
  542. #if EPD_DEBUG
  543. uint32_t t1 = clock();
  544. #endif
  545. m = 0x00;
  546. EPD_Dis_Full(&m, 0); //all black
  547. #if EPD_DEBUG
  548. t1 = clock() - t1;
  549. printf("[EPD] Clear black: %u ms\r\n", t1);
  550. t1 = clock();
  551. #endif
  552. m = 0xff;
  553. EPD_Dis_Full(&m, 0); //all white
  554. #if EPD_DEBUG
  555. t1 = clock() - t1;
  556. printf("[EPD] Clear white: %u ms\r\n", t1);
  557. #endif
  558. }
  559. // Partial clear screen
  560. //=========================
  561. void EPD_DisplayClearPart()
  562. {
  563. uint8_t m = 0xFF;
  564. EPD_init_Part();
  565. #if EPD_DEBUG
  566. uint32_t t1 = clock();
  567. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all white
  568. m = 0x00;
  569. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all black
  570. m = 0xFF;
  571. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all white
  572. t1 = clock() - t1;
  573. printf("[EPD] Part Clear: %u ms\r\n", t1);
  574. #else
  575. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all white
  576. m = 0x00;
  577. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all black
  578. m = 0xFF;
  579. EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0); //all white
  580. #endif
  581. }
  582. //==================================
  583. void EPD_DisplaySetFull(uint8_t val)
  584. {
  585. EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));
  586. #if EPD_DEBUG
  587. uint32_t t1 = clock();
  588. EPD_Dis_Full(&val, 0);
  589. t1 = clock() - t1;
  590. printf("[EPD] Display Set Full: %u ms [%02x]\r\n", t1, val);
  591. #else
  592. EPD_Dis_Full(&val, 0);
  593. #endif
  594. }
  595. //======================================================================================
  596. void EPD_DisplaySetPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t val)
  597. {
  598. EPD_Write((uint8_t *)LUT_part, 31);
  599. #if EPD_DEBUG
  600. uint32_t t1 = clock();
  601. EPD_Dis_Part(yStart,yEnd,xStart,xEnd, &val,0);
  602. t1 = clock() - t1;
  603. printf("[EPD] Display Set Part: %u ms [%02x]\r\n", t1, val);
  604. #else
  605. EPD_Dis_Part(yStart,yEnd,xStart,xEnd, &val,0);
  606. #endif
  607. }
  608. //======================================
  609. void EPD_DisplayFull(uint8_t *DisBuffer)
  610. {
  611. EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));
  612. #if EPD_DEBUG
  613. uint32_t t1 = clock();
  614. EPD_Dis_Full((uint8_t *)DisBuffer,1);
  615. t1 = clock() - t1;
  616. printf("[EPD] Display Full: %u ms\r\n", t1);
  617. #else
  618. EPD_Dis_Full((uint8_t *)DisBuffer,1);
  619. #endif
  620. }
  621. //==========================================================================================
  622. void EPD_DisplayPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t *DisBuffer)
  623. {
  624. EPD_Write((uint8_t *)LUT_part, 31);
  625. #if EPD_DEBUG
  626. uint32_t t1 = clock();
  627. EPD_Dis_Part(yStart,yEnd,xStart,xEnd,(uint8_t *)DisBuffer,1);
  628. t1 = clock() - t1;
  629. printf("[EPD] Display Part: %u ms [%02x:%02x]\r\n", t1, LUT_gs[1], LUT_gs[21]);
  630. #else
  631. EPD_Dis_Part(yStart,yEnd,xStart,xEnd,(uint8_t *)DisBuffer,1);
  632. #endif
  633. }
  634. //============
  635. void EPD_Cls()
  636. {
  637. EPD_DisplaySetPart(0, EPD_DISPLAY_WIDTH-1, 0, EPD_DISPLAY_HEIGHT-1, 0xFF);
  638. memset(disp_buffer, 0xFF, _width * (_height/8));
  639. memset(gs_disp_buffer, 0, _width * _height);
  640. gs_used_shades = 0;
  641. }
  642. //-------------------------------------------------------------------------------
  643. void EPD_gsUpdate(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t gs)
  644. {
  645. uint8_t val, buf_val, new_val;
  646. int count=0, changed=0;
  647. int x;
  648. uint8_t y;
  649. for (x=xStart; x<=xEnd; x++) {
  650. for (y=yStart; y<=yEnd; y++) {
  651. val = gs_drawBuff[(y * (xEnd-xStart+1)) + x];
  652. if (val > 15) val >>= 4;
  653. if (val == gs) {
  654. buf_val = drawBuff[(x * ((yEnd-yStart+1)>>3)) + (y>>3)];
  655. new_val = buf_val;
  656. if (gs > 0) new_val &= (0x80 >> (y % 8)) ^ 0xFF;
  657. else new_val |= (0x80 >> (y % 8));
  658. if (new_val != buf_val) {
  659. drawBuff[(x * (_height>>3)) + (y>>3)] = new_val;
  660. changed++;
  661. }
  662. count++;
  663. }
  664. }
  665. }
  666. if (changed) {
  667. #if EPD_DEBUG
  668. printf("[EPD] GS Update %02x, count=%d changed=%d\r\n", gs, count, changed);
  669. #endif
  670. uint8_t *_lutPart = LUT_part;
  671. memset(LUT_gs+1, 0, 30);
  672. if (gs > 0) {
  673. if (gs > 0) {
  674. LUT_gs[1] = 0x18;
  675. LUT_gs[21] = gs;
  676. }
  677. }
  678. else {
  679. LUT_gs[1] = 0x28;
  680. LUT_gs[2] = 0x00;
  681. LUT_gs[21] = 15;
  682. }
  683. LUT_part = LUT_gs;
  684. EPD_DisplayPart(xStart, xEnd, yStart, yEnd, drawBuff);
  685. LUT_part = _lutPart;
  686. }
  687. }
  688. //-----------------------------------------------------------------------
  689. void EPD_Update(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd)
  690. {
  691. if (_gs == 0) EPD_DisplayPart(xStart, xEnd, yStart, yEnd, drawBuff);
  692. else {
  693. for (int n=0; n<16; n++) {
  694. if (gs_used_shades & (1<<n)) EPD_gsUpdate(xStart, xEnd, yStart, yEnd, n);
  695. }
  696. }
  697. }
  698. //-------------------
  699. void EPD_UpdateScreen()
  700. {
  701. EPD_Update(0, EPD_DISPLAY_WIDTH-1, 0, EPD_DISPLAY_HEIGHT-1);
  702. }
  703. //------------------------
  704. void EPD_wait(uint32_t ms)
  705. {
  706. if (ms < 100) ms = 100;
  707. uint32_t n = 0;
  708. while (n < ms) {
  709. vTaskDelay(100 / portTICK_RATE_MS);
  710. n += 100;
  711. }
  712. }