Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / common / m5stack-tft / repo / components / tft / tftspi.c
1 /*
2  *  Author: LoBo (loboris@gmail.com, loboris.github)
3  *
4  *  Module supporting SPI TFT displays based on ILI9341 & ILI9488 controllers
5  *
6  * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS
7  * USING DIRECT or DMA SPI TRANSFER MODEs
8  *
9 */
10
11 #include <string.h>
12 #include "tftspi.h"
13 #include "freertos/task.h"
14 #include "soc/spi_reg.h"
15 #include "driver/gpio.h"
16
17
18 // ====================================================
19 // ==== Global variables, default values ==============
20
21 // Converts colors to grayscale if set to 1
22 uint8_t tft_gray_scale = 0;
23 // Spi clock for reading data from display memory in Hz
24 uint32_t tft_max_rdclock = 8000000;
25
26 // Default display dimensions
27 int tft_width = DEFAULT_TFT_DISPLAY_WIDTH;
28 int tft_height = DEFAULT_TFT_DISPLAY_HEIGHT;
29
30 // Display type, DISP_TYPE_ILI9488 or DISP_TYPE_ILI9341
31 uint8_t tft_disp_type = DEFAULT_DISP_TYPE;
32
33 // Spi device handles for display and touch screen
34 spi_lobo_device_handle_t tft_disp_spi = NULL;
35 spi_lobo_device_handle_t tft_ts_spi = NULL;
36
37 // ====================================================
38
39
40 static color_t *trans_cline = NULL;
41 static uint8_t _dma_sending = 0;
42
43 // RGB to GRAYSCALE constants
44 // 0.2989  0.5870  0.1140
45 #define GS_FACT_R 0.2989
46 #define GS_FACT_G 0.4870
47 #define GS_FACT_B 0.2140
48
49
50
51 // ==== Functions =====================
52
53 //------------------------------------------------------
54 esp_err_t IRAM_ATTR wait_trans_finish(uint8_t free_line)
55 {
56         // Wait for SPI bus ready
57         while (tft_disp_spi->host->hw->cmd.usr);
58         if ((free_line) && (trans_cline)) {
59                 free(trans_cline);
60                 trans_cline = NULL;
61         }
62         if (_dma_sending) {
63             //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
64             if (tft_disp_spi->host->dma_chan) spi_lobo_dmaworkaround_idle(tft_disp_spi->host->dma_chan);
65
66             // Reset DMA
67                 tft_disp_spi->host->hw->dma_conf.val |= SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST;
68                 tft_disp_spi->host->hw->dma_out_link.start=0;
69                 tft_disp_spi->host->hw->dma_in_link.start=0;
70                 tft_disp_spi->host->hw->dma_conf.val &= ~(SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST);
71                 tft_disp_spi->host->hw->dma_conf.out_data_burst_en=1;
72                 _dma_sending = 0;
73         }
74     return ESP_OK;
75 }
76
77 //-------------------------------
78 esp_err_t IRAM_ATTR disp_select()
79 {
80         wait_trans_finish(1);
81         return spi_lobo_device_select(tft_disp_spi, 0);
82 }
83
84 //---------------------------------
85 esp_err_t IRAM_ATTR disp_deselect()
86 {
87         wait_trans_finish(1);
88         return spi_lobo_device_deselect(tft_disp_spi);
89 }
90
91 //---------------------------------------------------------------------------------------------------
92 static void IRAM_ATTR _spi_transfer_start(spi_lobo_device_handle_t spi_dev, int wrbits, int rdbits) {
93         // Load send buffer
94         spi_dev->host->hw->user.usr_mosi_highpart = 0;
95         spi_dev->host->hw->mosi_dlen.usr_mosi_dbitlen = wrbits-1;
96         spi_dev->host->hw->user.usr_mosi = 1;
97     if (rdbits) {
98         spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = rdbits;
99         spi_dev->host->hw->user.usr_miso = 1;
100     }
101     else {
102         spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = 0;
103         spi_dev->host->hw->user.usr_miso = 0;
104     }
105         // Start transfer
106         spi_dev->host->hw->cmd.usr = 1;
107     // Wait for SPI bus ready
108         while (spi_dev->host->hw->cmd.usr);
109 }
110
111 // Send 1 byte display command, display must be selected
112 //------------------------------------------------
113 void IRAM_ATTR disp_spi_transfer_cmd(int8_t cmd) {
114         // Wait for SPI bus ready
115         while (tft_disp_spi->host->hw->cmd.usr);
116
117         // Set DC to 0 (command mode);
118     gpio_set_level(PIN_NUM_DC, 0);
119
120     tft_disp_spi->host->hw->data_buf[0] = (uint32_t)cmd;
121     _spi_transfer_start(tft_disp_spi, 8, 0);
122 }
123
124 // Send command with data to display, display must be selected
125 //----------------------------------------------------------------------------------
126 void IRAM_ATTR disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t len) {
127         // Wait for SPI bus ready
128         while (tft_disp_spi->host->hw->cmd.usr);
129
130     // Set DC to 0 (command mode);
131     gpio_set_level(PIN_NUM_DC, 0);
132
133     tft_disp_spi->host->hw->data_buf[0] = (uint32_t)cmd;
134     _spi_transfer_start(tft_disp_spi, 8, 0);
135
136         if ((len == 0) || (data == NULL)) return;
137
138     // Set DC to 1 (data mode);
139         gpio_set_level(PIN_NUM_DC, 1);
140
141         uint8_t idx=0, bidx=0;
142         uint32_t bits=0;
143         uint32_t count=0;
144         uint32_t wd = 0;
145         while (count < len) {
146                 // get data byte from buffer
147                 wd |= (uint32_t)data[count] << bidx;
148         count++;
149         bits += 8;
150                 bidx += 8;
151         if (count == len) {
152                 tft_disp_spi->host->hw->data_buf[idx] = wd;
153                 break;
154         }
155                 if (bidx == 32) {
156                         tft_disp_spi->host->hw->data_buf[idx] = wd;
157                         idx++;
158                         bidx = 0;
159                         wd = 0;
160                 }
161         if (idx == 16) {
162                 // SPI buffer full, send data
163                         _spi_transfer_start(tft_disp_spi, bits, 0);
164
165                         bits = 0;
166                 idx = 0;
167                         bidx = 0;
168         }
169     }
170     if (bits > 0) _spi_transfer_start(tft_disp_spi, bits, 0);
171 }
172
173 // Set the address window for display write & read commands, display must be selected
174 //---------------------------------------------------------------------------------------------------
175 static void IRAM_ATTR disp_spi_transfer_addrwin(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2) {
176         uint32_t wd;
177
178     taskDISABLE_INTERRUPTS();
179         // Wait for SPI bus ready
180         while (tft_disp_spi->host->hw->cmd.usr);
181     gpio_set_level(PIN_NUM_DC, 0);
182
183         tft_disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_CASET;
184         tft_disp_spi->host->hw->user.usr_mosi_highpart = 0;
185         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
186         tft_disp_spi->host->hw->user.usr_mosi = 1;
187         tft_disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0;
188         tft_disp_spi->host->hw->user.usr_miso = 0;
189
190         tft_disp_spi->host->hw->cmd.usr = 1; // Start transfer
191
192         wd = (uint32_t)(x1>>8);
193         wd |= (uint32_t)(x1&0xff) << 8;
194         wd |= (uint32_t)(x2>>8) << 16;
195         wd |= (uint32_t)(x2&0xff) << 24;
196
197         while (tft_disp_spi->host->hw->cmd.usr); // wait transfer end
198         gpio_set_level(PIN_NUM_DC, 1);
199         tft_disp_spi->host->hw->data_buf[0] = wd;
200         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 31;
201         tft_disp_spi->host->hw->cmd.usr = 1; // Start transfer
202
203     while (tft_disp_spi->host->hw->cmd.usr);
204     gpio_set_level(PIN_NUM_DC, 0);
205     tft_disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_PASET;
206         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
207         tft_disp_spi->host->hw->cmd.usr = 1; // Start transfer
208
209         wd = (uint32_t)(y1>>8);
210         wd |= (uint32_t)(y1&0xff) << 8;
211         wd |= (uint32_t)(y2>>8) << 16;
212         wd |= (uint32_t)(y2&0xff) << 24;
213
214         while (tft_disp_spi->host->hw->cmd.usr);
215         gpio_set_level(PIN_NUM_DC, 1);
216
217         tft_disp_spi->host->hw->data_buf[0] = wd;
218         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 31;
219         tft_disp_spi->host->hw->cmd.usr = 1; // Start transfer
220         while (tft_disp_spi->host->hw->cmd.usr);
221     taskENABLE_INTERRUPTS();
222 }
223
224 // Convert color to gray scale
225 //----------------------------------------------
226 static color_t IRAM_ATTR color2gs(color_t color)
227 {
228         color_t _color;
229     float gs_clr = GS_FACT_R * color.r + GS_FACT_G * color.g + GS_FACT_B * color.b;
230     if (gs_clr > 255) gs_clr = 255;
231
232     _color.r = (uint8_t)gs_clr;
233     _color.g = (uint8_t)gs_clr;
234     _color.b = (uint8_t)gs_clr;
235
236     return _color;
237 }
238
239 // Set display pixel at given coordinates to given color
240 //------------------------------------------------------------------------
241 void IRAM_ATTR drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel)
242 {
243         if (!(tft_disp_spi->cfg.flags & LB_SPI_DEVICE_HALFDUPLEX)) return;
244
245         if (sel) {
246                 if (disp_select()) return;
247         }
248         else wait_trans_finish(1);
249
250         uint32_t wd = 0;
251     color_t _color = color;
252         if (tft_gray_scale) _color = color2gs(color);
253
254     taskDISABLE_INTERRUPTS();
255         disp_spi_transfer_addrwin(x, x+1, y, y+1);
256
257         // Send RAM WRITE command
258     gpio_set_level(PIN_NUM_DC, 0);
259     tft_disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_RAMWR;
260         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
261         tft_disp_spi->host->hw->cmd.usr = 1;            // Start transfer
262         while (tft_disp_spi->host->hw->cmd.usr);        // Wait for SPI bus ready
263
264         wd = (uint32_t)_color.r;
265         wd |= (uint32_t)_color.g << 8;
266         wd |= (uint32_t)_color.b << 16;
267
268     // Set DC to 1 (data mode);
269         gpio_set_level(PIN_NUM_DC, 1);
270
271         tft_disp_spi->host->hw->data_buf[0] = wd;
272         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 23;
273         tft_disp_spi->host->hw->cmd.usr = 1;            // Start transfer
274         while (tft_disp_spi->host->hw->cmd.usr);        // Wait for SPI bus ready
275
276     taskENABLE_INTERRUPTS();
277    if (sel) disp_deselect();
278 }
279
280 //-----------------------------------------------------------
281 static void IRAM_ATTR _dma_send(uint8_t *data, uint32_t size)
282 {
283     //Fill DMA descriptors
284     spi_lobo_dmaworkaround_transfer_active(tft_disp_spi->host->dma_chan); //mark channel as active
285     spi_lobo_setup_dma_desc_links(tft_disp_spi->host->dmadesc_tx, size, data, false);
286     tft_disp_spi->host->hw->user.usr_mosi_highpart=0;
287     tft_disp_spi->host->hw->dma_out_link.addr=(int)(&tft_disp_spi->host->dmadesc_tx[0]) & 0xFFFFF;
288     tft_disp_spi->host->hw->dma_out_link.start=1;
289     tft_disp_spi->host->hw->user.usr_mosi_highpart=0;
290
291         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = (size * 8) - 1;
292
293         _dma_sending = 1;
294         // Start transfer
295         tft_disp_spi->host->hw->cmd.usr = 1;
296 }
297
298 //---------------------------------------------------------------------------
299 static void IRAM_ATTR _direct_send(color_t *color, uint32_t len, uint8_t rep)
300 {
301         uint32_t cidx = 0;      // color buffer index
302         uint32_t wd = 0;
303         int idx = 0;
304         int bits = 0;
305         int wbits = 0;
306
307     taskDISABLE_INTERRUPTS();
308         color_t _color = color[0];
309         if ((rep) && (tft_gray_scale)) _color = color2gs(color[0]);
310
311         while (len) {
312                 // ** Get color data from color buffer **
313                 if (rep == 0) {
314                         if (tft_gray_scale) _color = color2gs(color[cidx]);
315                         else _color = color[cidx];
316                 }
317
318                 wd |= (uint32_t)_color.r << wbits;
319                 wbits += 8;
320                 if (wbits == 32) {
321                         bits += wbits;
322                         wbits = 0;
323                         tft_disp_spi->host->hw->data_buf[idx++] = wd;
324                         wd = 0;
325                 }
326                 wd |= (uint32_t)_color.g << wbits;
327                 wbits += 8;
328                 if (wbits == 32) {
329                         bits += wbits;
330                         wbits = 0;
331                         tft_disp_spi->host->hw->data_buf[idx++] = wd;
332                         wd = 0;
333                 }
334                 wd |= (uint32_t)_color.b << wbits;
335                 wbits += 8;
336                 if (wbits == 32) {
337                         bits += wbits;
338                         wbits = 0;
339                         tft_disp_spi->host->hw->data_buf[idx++] = wd;
340                         wd = 0;
341                 }
342         len--;                                  // Decrement colors counter
343         if (rep == 0) cidx++;   // if not repeating color, increment color buffer index
344     }
345         if (bits) {
346                 while (tft_disp_spi->host->hw->cmd.usr);                                                // Wait for SPI bus ready
347                 tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = bits-1;    // set number of bits to be sent
348         tft_disp_spi->host->hw->cmd.usr = 1;                                                    // Start transfer
349         }
350     taskENABLE_INTERRUPTS();
351 }
352
353 // ================================================================
354 // === Main function to send data to display ======================
355 // If  rep==true:  repeat sending color data to display 'len' times
356 // If rep==false:  send 'len' color data from color buffer to display
357 // ** Device must already be selected and address window set **
358 // ================================================================
359 //----------------------------------------------------------------------------------------------
360 static void IRAM_ATTR _TFT_pushColorRep(color_t *color, uint32_t len, uint8_t rep, uint8_t wait)
361 {
362         if (len == 0) return;
363         if (!(tft_disp_spi->cfg.flags & LB_SPI_DEVICE_HALFDUPLEX)) return;
364
365         // Send RAM WRITE command
366     gpio_set_level(PIN_NUM_DC, 0);
367     tft_disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_RAMWR;
368         tft_disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
369         tft_disp_spi->host->hw->cmd.usr = 1;            // Start transfer
370         while (tft_disp_spi->host->hw->cmd.usr);        // Wait for SPI bus ready
371
372         gpio_set_level(PIN_NUM_DC, 1);                                                          // Set DC to 1 (data mode);
373
374         if ((len*24) <= 512) {
375
376                 _direct_send(color, len, rep);
377
378         }
379         else if (rep == 0)  {
380                 // ==== use DMA transfer ====
381                 // ** Prepare data
382                 if (tft_gray_scale) {
383                         for (int n=0; n<len; n++) {
384                                 color[n] = color2gs(color[n]);
385                         }
386             }
387
388             _dma_send((uint8_t *)color, len*3);
389         }
390         else {
391                 // ==== Repeat color, more than 512 bits total ====
392
393                 color_t _color;
394                 uint32_t buf_colors;
395                 int buf_bytes, to_send;
396
397                 /*
398                 to_send = len;
399                 while (to_send > 0) {
400                         wait_trans_finish(0);
401                         _direct_send(color, ((to_send > 21) ? 21 : to_send), rep);
402                         to_send -= 21;
403                 }
404                 */
405
406                 buf_colors = ((len > (tft_width*2)) ? (tft_width*2) : len);
407                 buf_bytes = buf_colors * 3;
408
409                 // Prepare color buffer of maximum 2 color lines
410                 trans_cline = heap_caps_malloc(buf_bytes, MALLOC_CAP_DMA);
411                 if (trans_cline == NULL) return;
412
413                 // Prepare fill color
414                 if (tft_gray_scale) _color = color2gs(color[0]);
415                 else _color = color[0];
416
417                 // Fill color buffer with fill color
418                 for (uint32_t i=0; i<buf_colors; i++) {
419                         trans_cline[i] = _color;
420                 }
421
422                 // Send 'len' colors
423                 to_send = len;
424                 while (to_send > 0) {
425                         wait_trans_finish(0);
426                         _dma_send((uint8_t *)trans_cline, ((to_send > buf_colors) ? buf_bytes : (to_send*3)));
427                         to_send -= buf_colors;
428                 }
429         }
430
431         if (wait) wait_trans_finish(1);
432 }
433
434 // Write 'len' color data to TFT 'window' (x1,y2),(x2,y2)
435 //-------------------------------------------------------------------------------------------
436 void IRAM_ATTR TFT_pushColorRep(int x1, int y1, int x2, int y2, color_t color, uint32_t len)
437 {
438         if (disp_select() != ESP_OK) return;
439
440         // ** Send address window **
441         disp_spi_transfer_addrwin(x1, x2, y1, y2);
442
443         _TFT_pushColorRep(&color, len, 1, 1);
444
445         disp_deselect();
446 }
447
448 // Write 'len' color data to TFT 'window' (x1,y2),(x2,y2) from given buffer
449 // ** Device must already be selected **
450 //-----------------------------------------------------------------------------------
451 void IRAM_ATTR send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf)
452 {
453         // ** Send address window **
454         disp_spi_transfer_addrwin(x1, x2, y1, y2);
455         _TFT_pushColorRep(buf, len, 0, 0);
456 }
457
458 // Reads 'len' pixels/colors from the TFT's GRAM 'window'
459 // 'buf' is an array of bytes with 1st byte reserved for reading 1 dummy byte
460 // and the rest is actually an array of color_t values
461 //--------------------------------------------------------------------------------------------
462 int IRAM_ATTR read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, uint8_t set_sp)
463 {
464         spi_lobo_transaction_t t;
465         uint32_t current_clock = 0;
466
467     memset(&t, 0, sizeof(t));  //Zero out the transaction
468         memset(buf, 0, len*sizeof(color_t));
469
470         if (set_sp) {
471                 if (disp_deselect() != ESP_OK) return -1;
472                 // Change spi clock if needed
473                 current_clock = spi_lobo_get_speed(tft_disp_spi);
474                 if (tft_max_rdclock < current_clock) spi_lobo_set_speed(tft_disp_spi, tft_max_rdclock);
475         }
476
477         if (disp_select() != ESP_OK) return -2;
478
479         // ** Send address window **
480         disp_spi_transfer_addrwin(x1, x2, y1, y2);
481
482     // ** GET pixels/colors **
483         disp_spi_transfer_cmd(TFT_RAMRD);
484
485     t.length=0;                //Send nothing
486     t.tx_buffer=NULL;
487     t.rxlength=8*((len*3)+1);  //Receive size in bits
488     t.rx_buffer=buf;
489     //t.user = (void*)1;
490
491         esp_err_t res = spi_lobo_transfer_data(tft_disp_spi, &t); // Receive using direct mode
492
493         disp_deselect();
494
495         if (set_sp) {
496                 // Restore spi clock if needed
497                 if (tft_max_rdclock < current_clock) spi_lobo_set_speed(tft_disp_spi, current_clock);
498         }
499
500     return res;
501 }
502
503 // Reads one pixel/color from the TFT's GRAM at position (x,y)
504 //-----------------------------------------------
505 color_t IRAM_ATTR readPixel(int16_t x, int16_t y)
506 {
507     uint8_t color_buf[sizeof(color_t)+1] = {0};
508
509     read_data(x, y, x+1, y+1, 1, color_buf, 1);
510
511     color_t color;
512         color.r = color_buf[1];
513         color.g = color_buf[2];
514         color.b = color_buf[3];
515         return color;
516 }
517
518 // get 16-bit data from touch controller for specified type
519 // ** Touch device must already be selected **
520 //----------------------------------------
521 int IRAM_ATTR touch_get_data(uint8_t type)
522 {
523     /*
524     esp_err_t ret;
525     spi_lobo_transaction_t t;
526     memset(&t, 0, sizeof(t));            //Zero out the transaction
527     uint8_t rxdata[2] = {0};
528
529     // send command byte & receive 2 byte response
530     t.rxlength=8*2;
531     t.rx_buffer=&rxdata;
532     t.command = type;
533
534     ret = spi_lobo_transfer_data(tft_ts_spi, &t);    // Transmit using direct mode
535
536     if (ret != ESP_OK) return -1;
537     return (((int)(rxdata[0] << 8) | (int)(rxdata[1])) >> 4);
538     */
539     spi_lobo_device_select(tft_ts_spi, 0);
540
541     tft_ts_spi->host->hw->data_buf[0] = type;
542     _spi_transfer_start(tft_ts_spi, 24, 24);
543     uint16_t res = (uint16_t)(tft_ts_spi->host->hw->data_buf[0] >> 8);
544
545     spi_lobo_device_deselect(tft_ts_spi);
546
547     return res;
548 }
549
550 // ==== STMPE610 ===============================================================
551
552
553 // ----- STMPE610 --------------------------------------------------------------------------
554
555 // Send 1 byte display command, display must be selected
556 //---------------------------------------------------------
557 static void IRAM_ATTR stmpe610_write_reg(uint8_t reg, uint8_t val) {
558
559     spi_lobo_device_select(tft_ts_spi, 0);
560
561     tft_ts_spi->host->hw->data_buf[0] = (val << 8) | reg;
562     _spi_transfer_start(tft_ts_spi, 16, 0);
563
564     spi_lobo_device_deselect(tft_ts_spi);
565 }
566
567 //-----------------------------------------------
568 static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) {
569     spi_lobo_device_select(tft_ts_spi, 0);
570
571     tft_ts_spi->host->hw->data_buf[0] = (reg << 8) | (reg | 0x80);
572     _spi_transfer_start(tft_ts_spi, 16, 16);
573     uint8_t res = tft_ts_spi->host->hw->data_buf[0] >> 8;
574
575     spi_lobo_device_deselect(tft_ts_spi);
576     return res;
577 }
578
579 //-----------------------------------------
580 static uint16_t IRAM_ATTR stmpe610_read_word(uint8_t reg) {
581     spi_lobo_device_select(tft_ts_spi, 0);
582
583     tft_ts_spi->host->hw->data_buf[0] = ((((reg+1) << 8) | ((reg+1) | 0x80)) << 16) | (reg << 8) | (reg | 0x80);
584     _spi_transfer_start(tft_ts_spi, 32, 32);
585     uint16_t res = (uint16_t)(tft_ts_spi->host->hw->data_buf[0] & 0xFF00);
586     res |= (uint16_t)(tft_ts_spi->host->hw->data_buf[0] >> 24);
587
588     spi_lobo_device_deselect(tft_ts_spi);
589     return res;
590 }
591
592 //-----------------------
593 uint32_t stmpe610_getID()
594 {
595     uint16_t tid = stmpe610_read_word(0);
596     uint8_t tver = stmpe610_read_byte(2);
597     return (tid << 8) | tver;
598 }
599
600 //==================
601 void stmpe610_Init()
602 {
603     stmpe610_write_reg(STMPE610_REG_SYS_CTRL1, 0x02);        // Software chip reset
604     vTaskDelay(10 / portTICK_RATE_MS);
605
606     stmpe610_write_reg(STMPE610_REG_SYS_CTRL2, 0x04);        // Temperature sensor clock off, GPIO clock off, touch clock on, ADC clock on
607
608     stmpe610_write_reg(STMPE610_REG_INT_EN, 0x00);           // Don't Interrupt on INT pin
609
610     stmpe610_write_reg(STMPE610_REG_ADC_CTRL1, 0x48);        // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce
611     vTaskDelay(2 / portTICK_RATE_MS);
612     stmpe610_write_reg(STMPE610_REG_ADC_CTRL2, 0x01);        // ADC speed 3.25MHz
613     stmpe610_write_reg(STMPE610_REG_GPIO_AF, 0x00);          // GPIO alternate function - OFF
614     stmpe610_write_reg(STMPE610_REG_TSC_CFG, 0xE3);          // Averaging 8, touch detect delay 1ms, panel driver settling time 1ms
615     stmpe610_write_reg(STMPE610_REG_FIFO_TH, 0x01);          // FIFO threshold = 1
616     stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x01);         // FIFO reset enable
617     stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x00);         // FIFO reset disable
618     stmpe610_write_reg(STMPE610_REG_TSC_FRACT_XYZ, 0x07);    // Z axis data format
619     stmpe610_write_reg(STMPE610_REG_TSC_I_DRIVE, 0x01);      // max 50mA touchscreen line current
620     stmpe610_write_reg(STMPE610_REG_TSC_CTRL, 0x30);         // X&Y&Z, 16 reading window
621     stmpe610_write_reg(STMPE610_REG_TSC_CTRL, 0x31);         // X&Y&Z, 16 reading window, TSC enable
622     stmpe610_write_reg(STMPE610_REG_INT_STA, 0xFF);          // Clear all interrupts
623     stmpe610_write_reg(STMPE610_REG_INT_CTRL, 0x00);         // Level interrupt, disable interrupts
624 }
625
626 //===========================================================
627 int stmpe610_get_touch(uint16_t *x, uint16_t *y, uint16_t *z)
628 {
629         if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0;
630
631     // Get touch data
632     uint8_t fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE);
633     while (fifo_size < 2) {
634         if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0;
635         fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE);
636     }
637     while (fifo_size > 120) {
638         if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0;
639         *x = stmpe610_read_word(STMPE610_REG_TSC_DATA_X);
640         *y = stmpe610_read_word(STMPE610_REG_TSC_DATA_Y);
641         *z = stmpe610_read_byte(STMPE610_REG_TSC_DATA_Z);
642         fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE);
643     }
644     for (uint8_t i=0; i < (fifo_size-1); i++) {
645         *x = stmpe610_read_word(STMPE610_REG_TSC_DATA_X);
646         *y = stmpe610_read_word(STMPE610_REG_TSC_DATA_Y);
647         *z = stmpe610_read_byte(STMPE610_REG_TSC_DATA_Z);
648     }
649
650     *x = 4096 - *x;
651     /*
652     // Clear the rest of the fifo
653     {
654         stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x01);                // FIFO reset enable
655         stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x00);                // FIFO reset disable
656     }
657     */
658         return 1;
659 }
660
661 // ==== STMPE610 ===========================================================================
662
663
664 // Find maximum spi clock for successful read from display RAM
665 // ** Must be used AFTER the display is initialized **
666 //======================
667 uint32_t find_rd_speed()
668 {
669         esp_err_t ret;
670         color_t color;
671         uint32_t max_speed = 1000000;
672     uint32_t change_speed, cur_speed;
673     int line_check;
674     color_t *color_line = NULL;
675     uint8_t *line_rdbuf = NULL;
676     uint8_t gs = tft_gray_scale;
677
678     tft_gray_scale = 0;
679     cur_speed = spi_lobo_get_speed(tft_disp_spi);
680
681         color_line = malloc(tft_width*3);
682     if (color_line == NULL) goto exit;
683
684     line_rdbuf = malloc((tft_width*3)+1);
685         if (line_rdbuf == NULL) goto exit;
686
687         color_t *rdline = (color_t *)(line_rdbuf+1);
688
689         // Fill test line with colors
690         color = (color_t){0xEC,0xA8,0x74};
691         for (int x=0; x<tft_width; x++) {
692                 color_line[x] = color;
693         }
694
695         // Find maximum read spi clock
696         for (uint32_t speed=2000000; speed<=cur_speed; speed += 1000000) {
697                 change_speed = spi_lobo_set_speed(tft_disp_spi, speed);
698                 if (change_speed == 0) goto exit;
699
700                 memset(line_rdbuf, 0, tft_width*sizeof(color_t)+1);
701
702                 if (disp_select()) goto exit;
703                 // Write color line
704                 send_data(0, tft_height/2, tft_width-1, tft_height/2, tft_width, color_line);
705                 if (disp_deselect()) goto exit;
706
707                 // Read color line
708                 ret = read_data(0, tft_height/2, tft_width-1, tft_height/2, tft_width, line_rdbuf, 0);
709
710                 // Compare
711                 line_check = 0;
712                 if (ret == ESP_OK) {
713                         for (int y=0; y<tft_width; y++) {
714                                 if ((color_line[y].r & 0xFC) != (rdline[y].r & 0xFC)) line_check = 1;
715                                 else if ((color_line[y].g & 0xFC) != (rdline[y].g & 0xFC)) line_check = 1;
716                                 else if ((color_line[y].b & 0xFC) != (rdline[y].b & 0xFC)) line_check =  1;
717                                 if (line_check) break;
718                         }
719                 }
720                 else line_check = ret;
721
722                 if (line_check) break;
723                 max_speed = speed;
724         }
725
726 exit:
727     tft_gray_scale = gs;
728         if (line_rdbuf) free(line_rdbuf);
729         if (color_line) free(color_line);
730
731         // restore spi clk
732         change_speed = spi_lobo_set_speed(tft_disp_spi, cur_speed);
733
734         return max_speed;
735 }
736
737 //---------------------------------------------------------------------------
738 // Companion code to the initialization table.
739 // Reads and issues a series of LCD commands stored in byte array
740 //---------------------------------------------------------------------------
741 static void commandList(spi_lobo_device_handle_t spi, const uint8_t *addr) {
742   uint8_t  numCommands, numArgs, cmd;
743   uint16_t ms;
744
745   numCommands = *addr++;                                // Number of commands to follow
746   while(numCommands--) {                                // For each command...
747     cmd = *addr++;                                              // save command
748     numArgs  = *addr++;                                 // Number of args to follow
749     ms       = numArgs & TFT_CMD_DELAY; // If high bit set, delay follows args
750     numArgs &= ~TFT_CMD_DELAY;                  // Mask out delay bit
751
752         disp_spi_transfer_cmd_data(cmd, (uint8_t *)addr, numArgs);
753
754         addr += numArgs;
755
756     if(ms) {
757       ms = *addr++;              // Read post-command delay time (ms)
758       if(ms == 255) ms = 500;    // If 255, delay for 500 ms
759           vTaskDelay(ms / portTICK_RATE_MS);
760     }
761   }
762 }
763
764 //==================================
765 void _tft_setRotation(uint8_t rot) {
766         uint8_t rotation = rot & 3; // can't be higher than 3
767         uint8_t send = 1;
768         uint8_t madctl = 0;
769         uint16_t tmp;
770
771     if ((rotation & 1)) {
772         // in landscape modes must be width > height
773         if (tft_width < tft_height) {
774             tmp = tft_width;
775             tft_width  = tft_height;
776             tft_height = tmp;
777         }
778     }
779     else {
780         // in portrait modes must be width < height
781         if (tft_width > tft_height) {
782             tmp = tft_width;
783             tft_width  = tft_height;
784             tft_height = tmp;
785         }
786     }
787     #if TFT_INVERT_ROTATION
788     switch (rotation) {
789         case PORTRAIT:
790         madctl = (MADCTL_MV | TFT_RGB_BGR);
791         break;
792         case LANDSCAPE:
793         madctl = (MADCTL_MX | TFT_RGB_BGR);
794         break;
795         case PORTRAIT_FLIP:
796         madctl = (MADCTL_MV | TFT_RGB_BGR);
797         break;
798         case LANDSCAPE_FLIP:
799         madctl = (MADCTL_MY | TFT_RGB_BGR);
800         break;
801     }
802     #elif TFT_INVERT_ROTATION1
803     switch (rotation) {
804         case PORTRAIT:
805         madctl = (MADCTL_MY | MADCTL_MX | TFT_RGB_BGR);
806         break;
807         case LANDSCAPE:
808         madctl = (MADCTL_MY | MADCTL_MV | TFT_RGB_BGR);
809         break;
810         case PORTRAIT_FLIP:
811         madctl = (TFT_RGB_BGR);
812         break;
813         case LANDSCAPE_FLIP:
814         madctl = (MADCTL_MX | MADCTL_MV | TFT_RGB_BGR);
815         break;
816     }
817     #elif TFT_INVERT_ROTATION2
818     switch (rotation) {
819         case PORTRAIT:
820         madctl = (MADCTL_MX | MADCTL_MV | TFT_RGB_BGR);
821         break;
822         case LANDSCAPE:
823         madctl = (TFT_RGB_BGR);
824         break;
825         case PORTRAIT_FLIP:
826         madctl = (MADCTL_MY | MADCTL_MV | TFT_RGB_BGR);
827         break;
828         case LANDSCAPE_FLIP:
829         madctl = (MADCTL_MY | MADCTL_MX | TFT_RGB_BGR);
830         break;
831     }
832     #else
833     switch (rotation) {
834         case PORTRAIT:
835         madctl = (MADCTL_MX | TFT_RGB_BGR);
836         break;
837         case LANDSCAPE:
838         madctl = (MADCTL_MV | TFT_RGB_BGR);
839         break;
840         case PORTRAIT_FLIP:
841         madctl = (MADCTL_MY | TFT_RGB_BGR);
842         break;
843         case LANDSCAPE_FLIP:
844         madctl = (MADCTL_MX | MADCTL_MY | MADCTL_MV | TFT_RGB_BGR);
845         break;
846     }
847     #endif
848         if (send) {
849                 if (disp_select() == ESP_OK) {
850                         disp_spi_transfer_cmd_data(TFT_MADCTL, &madctl, 1);
851                         disp_deselect();
852                 }
853         }
854
855 }
856
857 //=================
858 void TFT_PinsInit()
859 {
860     // Route all used pins to GPIO control
861     gpio_pad_select_gpio(PIN_NUM_CS);
862     gpio_pad_select_gpio(PIN_NUM_MISO);
863     gpio_pad_select_gpio(PIN_NUM_MOSI);
864     gpio_pad_select_gpio(PIN_NUM_CLK);
865     gpio_pad_select_gpio(PIN_NUM_DC);
866
867     gpio_set_direction(PIN_NUM_MISO, GPIO_MODE_INPUT);
868     gpio_set_pull_mode(PIN_NUM_MISO, GPIO_PULLUP_ONLY);
869     gpio_set_direction(PIN_NUM_CS, GPIO_MODE_OUTPUT);
870     gpio_set_direction(PIN_NUM_MOSI, GPIO_MODE_OUTPUT);
871     gpio_set_direction(PIN_NUM_CLK, GPIO_MODE_OUTPUT);
872     gpio_set_direction(PIN_NUM_DC, GPIO_MODE_OUTPUT);
873     gpio_set_level(PIN_NUM_DC, 0);
874 #if USE_TOUCH
875     gpio_pad_select_gpio(PIN_NUM_TCS);
876     gpio_set_direction(PIN_NUM_TCS, GPIO_MODE_OUTPUT);
877 #endif
878 #if PIN_NUM_BCKL
879     gpio_pad_select_gpio(PIN_NUM_BCKL);
880     gpio_set_direction(PIN_NUM_BCKL, GPIO_MODE_OUTPUT);
881     gpio_set_level(PIN_NUM_BCKL, PIN_BCKL_OFF);
882 #endif
883
884 #if PIN_NUM_RST
885     gpio_pad_select_gpio(PIN_NUM_RST);
886     gpio_set_direction(PIN_NUM_RST, GPIO_MODE_OUTPUT);
887     gpio_set_level(PIN_NUM_RST, 0);
888 #endif
889 }
890
891 // Initialize the display
892 // ====================
893 void TFT_display_init()
894 {
895     esp_err_t ret;
896
897 #if PIN_NUM_RST
898     //Reset the display
899     gpio_set_level(PIN_NUM_RST, 0);
900     vTaskDelay(20 / portTICK_RATE_MS);
901     gpio_set_level(PIN_NUM_RST, 1);
902     vTaskDelay(150 / portTICK_RATE_MS);
903 #endif
904
905     ret = disp_select();
906     assert(ret==ESP_OK);
907     //Send all the initialization commands
908         if (tft_disp_type == DISP_TYPE_ILI9341) {
909                 commandList(tft_disp_spi, ILI9341_init);
910         }
911         else if (tft_disp_type == DISP_TYPE_ILI9488) {
912                 commandList(tft_disp_spi, ILI9488_init);
913         }
914         else if (tft_disp_type == DISP_TYPE_ST7789V) {
915                 commandList(tft_disp_spi, ST7789V_init);
916         }
917         else if (tft_disp_type == DISP_TYPE_ST7735) {
918                 commandList(tft_disp_spi, STP7735_init);
919         }
920         else if (tft_disp_type == DISP_TYPE_ST7735R) {
921                 commandList(tft_disp_spi, STP7735R_init);
922                 commandList(tft_disp_spi, Rcmd2green);
923                 commandList(tft_disp_spi, Rcmd3);
924         }
925         else if (tft_disp_type == DISP_TYPE_ST7735B) {
926                 commandList(tft_disp_spi, STP7735R_init);
927                 commandList(tft_disp_spi, Rcmd2red);
928                 commandList(tft_disp_spi, Rcmd3);
929             uint8_t dt = 0xC0;
930                 disp_spi_transfer_cmd_data(TFT_MADCTL, &dt, 1);
931         }
932         else assert(0);
933
934     ret = disp_deselect();
935         assert(ret==ESP_OK);
936
937         // Clear screen
938     _tft_setRotation(PORTRAIT);
939         TFT_pushColorRep(TFT_STATIC_WIDTH_OFFSET, TFT_STATIC_HEIGHT_OFFSET, tft_width + TFT_STATIC_WIDTH_OFFSET -1, tft_height + TFT_STATIC_HEIGHT_OFFSET -1, (color_t){0,0,0}, (uint32_t)(tft_height*tft_width));
940
941         ///Enable backlight
942 #if PIN_NUM_BCKL
943     gpio_set_level(PIN_NUM_BCKL, PIN_BCKL_ON);
944 #endif
945 }
946
947