Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / common / m5stack-tft / repo / main / tft_demo.c
1 /* TFT demo
2
3    This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5    Unless required by applicable law or agreed to in writing, this
6    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7    CONDITIONS OF ANY KIND, either express or implied.
8 */
9
10 #include <time.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "freertos/FreeRTOS.h"
15 #include "freertos/task.h"
16
17 #include "tftspi.h"
18 #include "tft.h"
19 #include "spiffs_vfs.h"
20
21 #ifdef CONFIG_EXAMPLE_USE_WIFI
22
23 #include "esp_wifi.h"
24 #include "freertos/event_groups.h"
25 #include "esp_sntp.h"
26 #include "esp_log.h"
27 #include "nvs_flash.h"
28
29 #endif
30
31
32 // ==========================================================
33 // Define which spi bus to use TFT_VSPI_HOST or TFT_HSPI_HOST
34 #define SPI_BUS TFT_HSPI_HOST
35 // ==========================================================
36
37
38 static int _demo_pass = 0;
39 static uint8_t doprint = 1;
40 static uint8_t run_gs_demo = 0; // Run gray scale demo if set to 1
41 static struct tm* tm_info;
42 static char tmp_buff[64];
43 static time_t time_now, time_last = 0;
44 static const char *file_fonts[3] = {"/spiffs/fonts/DotMatrix_M.fon", "/spiffs/fonts/Ubuntu.fon", "/spiffs/fonts/Grotesk24x48.fon"};
45
46 #define GDEMO_TIME 1000
47 #define GDEMO_INFO_TIME 5000
48
49 //==================================================================================
50 #ifdef CONFIG_EXAMPLE_USE_WIFI
51
52 static const char tag[] = "[TFT Demo]";
53
54 /* FreeRTOS event group to signal when we are connected & ready to make a request */
55 static EventGroupHandle_t wifi_event_group;
56
57 /* The event group allows multiple bits for each event,
58    but we only care about one event - are we connected
59    to the AP with an IP? */
60 const int CONNECTED_BIT = 0x00000001;
61
62 //------------------------------------------------------------
63 static esp_err_t event_handler(void *ctx, system_event_t *event)
64 {
65     switch(event->event_id) {
66     case SYSTEM_EVENT_STA_START:
67         esp_wifi_connect();
68         break;
69     case SYSTEM_EVENT_STA_GOT_IP:
70         xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
71         break;
72     case SYSTEM_EVENT_STA_DISCONNECTED:
73         /* This is a workaround as ESP32 WiFi libs don't currently
74            auto-reassociate. */
75         esp_wifi_connect();
76         xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
77         break;
78     default:
79         break;
80     }
81     return ESP_OK;
82 }
83
84 //-------------------------------
85 static void initialise_wifi(void)
86 {
87     tcpip_adapter_init();
88     wifi_event_group = xEventGroupCreate();
89     ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
90     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
91     ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
92     ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
93     wifi_config_t wifi_config = {
94         .sta = {
95             .ssid = CONFIG_WIFI_SSID,
96             .password = CONFIG_WIFI_PASSWORD,
97         },
98     };
99     ESP_LOGI(tag, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
100     ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
101     ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
102     ESP_ERROR_CHECK( esp_wifi_start() );
103 }
104
105 //-------------------------------
106 static void initialize_sntp(void)
107 {
108     ESP_LOGI(tag, "Initializing SNTP");
109     sntp_setoperatingmode(SNTP_OPMODE_POLL);
110     sntp_setservername(0, "pool.ntp.org");
111     sntp_init();
112 }
113
114 //--------------------------
115 static int obtain_time(void)
116 {
117         int res = 1;
118     initialise_wifi();
119     xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
120
121     initialize_sntp();
122
123     // wait for time to be set
124     int retry = 0;
125     const int retry_count = 20;
126
127     time(&time_now);
128         tm_info = localtime(&time_now);
129
130     while(tm_info->tm_year < (2016 - 1900) && ++retry < retry_count) {
131         //ESP_LOGI(tag, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
132                 sprintf(tmp_buff, "Wait %0d/%d", retry, retry_count);
133         TFT_print(tmp_buff, CENTER, LASTY);
134                 vTaskDelay(500 / portTICK_RATE_MS);
135         time(&time_now);
136         tm_info = localtime(&time_now);
137     }
138     if (tm_info->tm_year < (2016 - 1900)) {
139         ESP_LOGI(tag, "System time NOT set.");
140         res = 0;
141     }
142     else {
143         ESP_LOGI(tag, "System time is set.");
144     }
145
146     ESP_ERROR_CHECK( esp_wifi_stop() );
147     return res;
148 }
149
150 #endif  //CONFIG_EXAMPLE_USE_WIFI
151 //==================================================================================
152
153
154 //----------------------
155 static void _checkTime()
156 {
157         time(&time_now);
158         if (time_now > time_last) {
159                 color_t last_fg, last_bg;
160                 time_last = time_now;
161                 tm_info = localtime(&time_now);
162                 sprintf(tmp_buff, "%02d:%02d:%02d", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
163
164                 TFT_saveClipWin();
165                 TFT_resetclipwin();
166
167                 Font curr_font = tft_cfont;
168                 last_bg = tft_bg;
169                 last_fg = tft_fg;
170                 tft_fg = TFT_YELLOW;
171                 tft_bg = (color_t){ 64, 64, 64 };
172                 TFT_setFont(DEFAULT_FONT, NULL);
173
174                 TFT_fillRect(1, tft_height-TFT_getfontheight()-8, tft_width-3, TFT_getfontheight()+6, tft_bg);
175                 TFT_print(tmp_buff, CENTER, tft_height-TFT_getfontheight()-5);
176
177                 tft_cfont = curr_font;
178                 tft_fg = last_fg;
179                 tft_bg = last_bg;
180
181                 TFT_restoreClipWin();
182         }
183 }
184
185 /*
186 //----------------------
187 static int _checkTouch()
188 {
189         int tx, ty;
190         if (TFT_read_touch(&tx, &ty, 0)) {
191                 while (TFT_read_touch(&tx, &ty, 1)) {
192                         vTaskDelay(20 / portTICK_RATE_MS);
193                 }
194                 return 1;
195         }
196         return 0;
197 }
198 */
199
200 //---------------------
201 static int Wait(int ms)
202 {
203         uint8_t tm = 1;
204         if (ms < 0) {
205                 tm = 0;
206                 ms *= -1;
207         }
208         if (ms <= 50) {
209                 vTaskDelay(ms / portTICK_RATE_MS);
210                 //if (_checkTouch()) return 0;
211         }
212         else {
213                 for (int n=0; n<ms; n += 50) {
214                         vTaskDelay(50 / portTICK_RATE_MS);
215                         if (tm) _checkTime();
216                         //if (_checkTouch()) return 0;
217                 }
218         }
219         return 1;
220 }
221
222 //-------------------------------------------------------------------
223 static unsigned int rand_interval(unsigned int min, unsigned int max)
224 {
225     int r;
226     const unsigned int range = 1 + max - min;
227     const unsigned int buckets = RAND_MAX / range;
228     const unsigned int limit = buckets * range;
229
230     /* Create equal size buckets all in a row, then fire randomly towards
231      * the buckets until you land in one of them. All buckets are equally
232      * likely. If you land off the end of the line of buckets, try again. */
233     do
234     {
235         r = rand();
236     } while (r >= limit);
237
238     return min + (r / buckets);
239 }
240
241 // Generate random color
242 //-----------------------------
243 static color_t random_color() {
244
245         color_t color;
246         color.r  = (uint8_t)rand_interval(8,252);
247         color.g  = (uint8_t)rand_interval(8,252);
248         color.b  = (uint8_t)rand_interval(8,252);
249         return color;
250 }
251
252 //---------------------
253 static void _dispTime()
254 {
255         Font curr_font = tft_cfont;
256     if (tft_width < 240) TFT_setFont(DEF_SMALL_FONT, NULL);
257         else TFT_setFont(DEFAULT_FONT, NULL);
258
259     time(&time_now);
260         time_last = time_now;
261         tm_info = localtime(&time_now);
262         sprintf(tmp_buff, "%02d:%02d:%02d", tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
263         TFT_print(tmp_buff, CENTER, tft_height-TFT_getfontheight()-5);
264
265     tft_cfont = curr_font;
266 }
267
268 //---------------------------------
269 static void disp_header(char *info)
270 {
271         TFT_fillScreen(TFT_BLACK);
272         TFT_resetclipwin();
273
274         tft_fg = TFT_YELLOW;
275         tft_bg = (color_t){ 64, 64, 64 };
276
277     if (tft_width < 240) TFT_setFont(DEF_SMALL_FONT, NULL);
278         else TFT_setFont(DEFAULT_FONT, NULL);
279         TFT_fillRect(0, 0, tft_width-1, TFT_getfontheight()+8, tft_bg);
280         TFT_drawRect(0, 0, tft_width-1, TFT_getfontheight()+8, TFT_CYAN);
281
282         TFT_fillRect(0, tft_height-TFT_getfontheight()-9, tft_width-1, TFT_getfontheight()+8, tft_bg);
283         TFT_drawRect(0, tft_height-TFT_getfontheight()-9, tft_width-1, TFT_getfontheight()+8, TFT_CYAN);
284
285         TFT_print(info, CENTER, 4);
286         _dispTime();
287
288         tft_bg = TFT_BLACK;
289         TFT_setclipwin(0,TFT_getfontheight()+9, tft_width-1, tft_height-TFT_getfontheight()-10);
290 }
291
292 //---------------------------------------------
293 static void update_header(char *hdr, char *ftr)
294 {
295         color_t last_fg, last_bg;
296
297         TFT_saveClipWin();
298         TFT_resetclipwin();
299
300         Font curr_font = tft_cfont;
301         last_bg = tft_bg;
302         last_fg = tft_fg;
303         tft_fg = TFT_YELLOW;
304         tft_bg = (color_t){ 64, 64, 64 };
305     if (tft_width < 240) TFT_setFont(DEF_SMALL_FONT, NULL);
306         else TFT_setFont(DEFAULT_FONT, NULL);
307
308         if (hdr) {
309                 TFT_fillRect(1, 1, tft_width-3, TFT_getfontheight()+6, tft_bg);
310                 TFT_print(hdr, CENTER, 4);
311         }
312
313         if (ftr) {
314                 TFT_fillRect(1, tft_height-TFT_getfontheight()-8, tft_width-3, TFT_getfontheight()+6, tft_bg);
315                 if (strlen(ftr) == 0) _dispTime();
316                 else TFT_print(ftr, CENTER, tft_height-TFT_getfontheight()-5);
317         }
318
319         tft_cfont = curr_font;
320         tft_fg = last_fg;
321         tft_bg = last_bg;
322
323         TFT_restoreClipWin();
324 }
325
326 //------------------------
327 static void test_times() {
328
329         if (doprint) {
330             uint32_t tstart, t1, t2;
331                 disp_header("TIMINGS");
332                 // ** Show Fill screen and send_line timings
333                 tstart = clock();
334                 TFT_fillWindow(TFT_BLACK);
335                 t1 = clock() - tstart;
336                 printf("     Clear screen time: %u ms\r\n", t1);
337                 TFT_setFont(SMALL_FONT, NULL);
338                 sprintf(tmp_buff, "Clear screen: %u ms", t1);
339                 TFT_print(tmp_buff, 0, 140);
340
341                 color_t *color_line = heap_caps_malloc((tft_width*3), MALLOC_CAP_DMA);
342                 color_t *gsline = NULL;
343                 if (tft_gray_scale) gsline = malloc(tft_width*3);
344                 if (color_line) {
345                         float hue_inc = (float)((10.0 / (float)(tft_height-1) * 360.0));
346                         for (int x=0; x<tft_width; x++) {
347                                 color_line[x] = HSBtoRGB(hue_inc, 1.0, (float)x / (float)tft_width);
348                                 if (gsline) gsline[x] = color_line[x];
349                         }
350                         disp_select();
351                         tstart = clock();
352                         for (int n=0; n<1000; n++) {
353                                 if (gsline) memcpy(color_line, gsline, tft_width*3);
354                                 send_data(0 + TFT_STATIC_X_OFFSET, 40+(n&63) + TFT_STATIC_Y_OFFSET, tft_dispWin.x2-tft_dispWin.x1 + TFT_STATIC_X_OFFSET , 40+(n&63) + TFT_STATIC_Y_OFFSET, (uint32_t)(tft_dispWin.x2-tft_dispWin.x1+1), color_line);
355                                 wait_trans_finish(1);
356                         }
357                         t2 = clock() - tstart;
358                         disp_deselect();
359
360                         printf("Send color buffer time: %u us (%d pixels)\r\n", t2, tft_dispWin.x2-tft_dispWin.x1+1);
361                         free(color_line);
362
363                         sprintf(tmp_buff, "   Send line: %u us", t2);
364                         TFT_print(tmp_buff, 0, 144+TFT_getfontheight());
365                 }
366                 Wait(GDEMO_INFO_TIME);
367     }
368 }
369
370 // Image demo
371 //-------------------------
372 static void disp_images() {
373     uint32_t tstart;
374
375         disp_header("JPEG IMAGES");
376
377         if (spiffs_is_mounted) {
378                 // ** Show scaled (1/8, 1/4, 1/2 size) JPG images
379                 TFT_jpg_image(CENTER, CENTER, 3, SPIFFS_BASE_PATH"/images/test1.jpg", NULL, 0);
380                 Wait(500);
381
382                 TFT_jpg_image(CENTER, CENTER, 2, SPIFFS_BASE_PATH"/images/test2.jpg", NULL, 0);
383                 Wait(500);
384
385                 TFT_jpg_image(CENTER, CENTER, 1, SPIFFS_BASE_PATH"/images/test4.jpg", NULL, 0);
386                 Wait(500);
387
388                 // ** Show full size JPG image
389                 tstart = clock();
390                 TFT_jpg_image(CENTER, CENTER, 0, SPIFFS_BASE_PATH"/images/test3.jpg", NULL, 0);
391                 tstart = clock() - tstart;
392                 if (doprint) printf("       JPG Decode time: %u ms\r\n", tstart);
393                 sprintf(tmp_buff, "Decode time: %u ms", tstart);
394                 update_header(NULL, tmp_buff);
395                 Wait(-GDEMO_INFO_TIME);
396
397                 // ** Show BMP image
398                 update_header("BMP IMAGE", "");
399                 for (int scale=5; scale >= 0; scale--) {
400                         tstart = clock();
401                         TFT_bmp_image(CENTER, CENTER, scale, SPIFFS_BASE_PATH"/images/tiger.bmp", NULL, 0);
402                         tstart = clock() - tstart;
403                         if (doprint) printf("    BMP time, scale: %d: %u ms\r\n", scale, tstart);
404                         sprintf(tmp_buff, "Decode time: %u ms", tstart);
405                         update_header(NULL, tmp_buff);
406                         Wait(-500);
407                 }
408                 Wait(-GDEMO_INFO_TIME);
409         }
410         else if (doprint) printf("  No file system found.\r\n");
411 }
412
413 //---------------------
414 static void font_demo()
415 {
416         int x, y, n;
417         uint32_t end_time;
418
419         disp_header("FONT DEMO");
420
421         end_time = clock() + GDEMO_TIME;
422         n = 0;
423         while ((clock() < end_time) && (Wait(0))) {
424                 y = 4;
425                 for (int f=DEFAULT_FONT; f<FONT_7SEG; f++) {
426                         tft_fg = random_color();
427                         TFT_setFont(f, NULL);
428                         TFT_print("Welcome to ESP32", 4, y);
429                         y += TFT_getfontheight() + 4;
430                         n++;
431                 }
432         }
433         sprintf(tmp_buff, "%d STRINGS", n);
434         update_header(NULL, tmp_buff);
435         Wait(-GDEMO_INFO_TIME);
436
437         if (spiffs_is_mounted) {
438                 disp_header("FONT FROM FILE DEMO");
439
440                 tft_text_wrap = 1;
441                 for (int f=0; f<3; f++) {
442                         TFT_fillWindow(TFT_BLACK);
443                         update_header(NULL, "");
444
445                         TFT_setFont(USER_FONT, file_fonts[f]);
446                         if (f == 0) tft_font_line_space = 4;
447                         end_time = clock() + GDEMO_TIME;
448                         n = 0;
449                         while ((clock() < end_time) && (Wait(0))) {
450                                 tft_fg = random_color();
451                                 TFT_print("Welcome to ESP32\nThis is user font.", 0, 8);
452                                 n++;
453                         }
454                         if ((tft_width < 240) || (tft_height < 240)) TFT_setFont(DEF_SMALL_FONT, NULL);
455             else TFT_setFont(DEFAULT_FONT, NULL);
456                         tft_fg = TFT_YELLOW;
457                         TFT_print((char *)file_fonts[f], 0, (tft_dispWin.y2-tft_dispWin.y1)-TFT_getfontheight()-4);
458
459             tft_font_line_space = 0;
460                         sprintf(tmp_buff, "%d STRINGS", n);
461                         update_header(NULL, tmp_buff);
462                         Wait(-GDEMO_INFO_TIME);
463                 }
464                 tft_text_wrap = 0;
465         }
466
467         disp_header("ROTATED FONT DEMO");
468
469         end_time = clock() + GDEMO_TIME;
470         n = 0;
471         while ((clock() < end_time) && (Wait(0))) {
472                 for (int f=DEFAULT_FONT; f<FONT_7SEG; f++) {
473                         tft_fg = random_color();
474                         TFT_setFont(f, NULL);
475                         x = rand_interval(8, tft_dispWin.x2-8);
476                         y = rand_interval(0, (tft_dispWin.y2-tft_dispWin.y1)-TFT_getfontheight()-2);
477                         tft_font_rotate = rand_interval(0, 359);
478
479                         TFT_print("Welcome to ESP32", x, y);
480                         n++;
481                 }
482         }
483         tft_font_rotate = 0;
484         sprintf(tmp_buff, "%d STRINGS", n);
485         update_header(NULL, tmp_buff);
486         Wait(-GDEMO_INFO_TIME);
487
488         disp_header("7-SEG FONT DEMO");
489
490         int ms = 0;
491         int last_sec = 0;
492         uint32_t ctime = clock();
493         end_time = clock() + GDEMO_TIME*2;
494         n = 0;
495         while ((clock() < end_time) && (Wait(0))) {
496                 y = 12;
497                 ms = clock() - ctime;
498                 time(&time_now);
499                 tm_info = localtime(&time_now);
500                 if (tm_info->tm_sec != last_sec) {
501                         last_sec = tm_info->tm_sec;
502                         ms = 0;
503                         ctime = clock();
504                 }
505
506                 tft_fg = TFT_ORANGE;
507                 sprintf(tmp_buff, "%02d:%02d:%03d", tm_info->tm_min, tm_info->tm_sec, ms);
508                 TFT_setFont(FONT_7SEG, NULL);
509         if ((tft_width < 240) || (tft_height < 240)) set_7seg_font_atrib(8, 1, 1, TFT_DARKGREY);
510                 else set_7seg_font_atrib(12, 2, 1, TFT_DARKGREY);
511                 //TFT_clearStringRect(12, y, tmp_buff);
512                 TFT_print(tmp_buff, CENTER, y);
513                 n++;
514
515                 tft_fg = TFT_GREEN;
516                 y += TFT_getfontheight() + 12;
517                 if ((tft_width < 240) || (tft_height < 240)) set_7seg_font_atrib(9, 1, 1, TFT_DARKGREY);
518         else set_7seg_font_atrib(14, 3, 1, TFT_DARKGREY);
519                 sprintf(tmp_buff, "%02d:%02d", tm_info->tm_sec, ms / 10);
520                 //TFT_clearStringRect(12, y, tmp_buff);
521                 TFT_print(tmp_buff, CENTER, y);
522                 n++;
523
524                 tft_fg = random_color();
525                 y += TFT_getfontheight() + 8;
526                 set_7seg_font_atrib(6, 1, 1, TFT_DARKGREY);
527                 getFontCharacters((uint8_t *)tmp_buff);
528                 //TFT_clearStringRect(12, y, tmp_buff);
529                 TFT_print(tmp_buff, CENTER, y);
530                 n++;
531         }
532         sprintf(tmp_buff, "%d STRINGS", n);
533         update_header(NULL, tmp_buff);
534         Wait(-GDEMO_INFO_TIME);
535
536         disp_header("WINDOW DEMO");
537
538         TFT_saveClipWin();
539         TFT_resetclipwin();
540         TFT_drawRect(38, 48, (tft_width*3/4) - 36, (tft_height*3/4) - 46, TFT_WHITE);
541         TFT_setclipwin(40, 50, tft_width*3/4, tft_height*3/4);
542
543         if ((tft_width < 240) || (tft_height < 240)) TFT_setFont(DEF_SMALL_FONT, NULL);
544     else TFT_setFont(UBUNTU16_FONT, NULL);
545         tft_text_wrap = 1;
546         end_time = clock() + GDEMO_TIME;
547         n = 0;
548         while ((clock() < end_time) && (Wait(0))) {
549                 tft_fg = random_color();
550                 TFT_print("This text is printed inside the window.\nLong line can be wrapped to the next line.\nWelcome to ESP32", 0, 0);
551                 n++;
552         }
553         tft_text_wrap = 0;
554         sprintf(tmp_buff, "%d STRINGS", n);
555         update_header(NULL, tmp_buff);
556         Wait(-GDEMO_INFO_TIME);
557
558         TFT_restoreClipWin();
559 }
560
561 //---------------------
562 static void rect_demo()
563 {
564         int x, y, w, h, n;
565
566         disp_header("RECTANGLE DEMO");
567
568         uint32_t end_time = clock() + GDEMO_TIME;
569         n = 0;
570         while ((clock() < end_time) && (Wait(0))) {
571                 x = rand_interval(4, tft_dispWin.x2-4);
572                 y = rand_interval(4, tft_dispWin.y2-2);
573                 w = rand_interval(2, tft_dispWin.x2-x);
574                 h = rand_interval(2, tft_dispWin.y2-y);
575                 TFT_drawRect(x,y,w,h,random_color());
576                 n++;
577         }
578         sprintf(tmp_buff, "%d RECTANGLES", n);
579         update_header(NULL, tmp_buff);
580         Wait(-GDEMO_INFO_TIME);
581
582         update_header("FILLED RECTANGLE", "");
583         TFT_fillWindow(TFT_BLACK);
584         end_time = clock() + GDEMO_TIME;
585         n = 0;
586         while ((clock() < end_time) && (Wait(0))) {
587                 x = rand_interval(4, tft_dispWin.x2-4);
588                 y = rand_interval(4, tft_dispWin.y2-2);
589                 w = rand_interval(2, tft_dispWin.x2-x);
590                 h = rand_interval(2, tft_dispWin.y2-y);
591                 TFT_fillRect(x,y,w,h,random_color());
592                 TFT_drawRect(x,y,w,h,random_color());
593                 n++;
594         }
595         sprintf(tmp_buff, "%d RECTANGLES", n);
596         update_header(NULL, tmp_buff);
597         Wait(-GDEMO_INFO_TIME);
598 }
599
600 //----------------------
601 static void pixel_demo()
602 {
603         int x, y, n;
604
605         disp_header("DRAW PIXEL DEMO");
606
607         uint32_t end_time = clock() + GDEMO_TIME;
608         n = 0;
609         while ((clock() < end_time) && (Wait(0))) {
610                 x = rand_interval(0, tft_dispWin.x2);
611                 y = rand_interval(0, tft_dispWin.y2);
612                 TFT_drawPixel(x,y,random_color(),1);
613                 n++;
614         }
615         sprintf(tmp_buff, "%d PIXELS", n);
616         update_header(NULL, tmp_buff);
617         Wait(-GDEMO_INFO_TIME);
618 }
619
620 //---------------------
621 static void line_demo()
622 {
623         int x1, y1, x2, y2, n;
624
625         disp_header("LINE DEMO");
626
627         uint32_t end_time = clock() + GDEMO_TIME;
628         n = 0;
629         while ((clock() < end_time) && (Wait(0))) {
630                 x1 = rand_interval(0, tft_dispWin.x2);
631                 y1 = rand_interval(0, tft_dispWin.y2);
632                 x2 = rand_interval(0, tft_dispWin.x2);
633                 y2 = rand_interval(0, tft_dispWin.y2);
634                 TFT_drawLine(x1,y1,x2,y2,random_color());
635                 n++;
636         }
637         sprintf(tmp_buff, "%d LINES", n);
638         update_header(NULL, tmp_buff);
639         Wait(-GDEMO_INFO_TIME);
640 }
641
642 //----------------------
643 static void aline_demo()
644 {
645         int x, y, len, angle, n;
646
647         disp_header("LINE BY ANGLE DEMO");
648
649         x = (tft_dispWin.x2 - tft_dispWin.x1) / 2;
650         y = (tft_dispWin.y2 - tft_dispWin.y1) / 2;
651         if (x < y) len = x - 8;
652         else len = y -8;
653
654         uint32_t end_time = clock() + GDEMO_TIME;
655         n = 0;
656         while ((clock() < end_time) && (Wait(0))) {
657                 for (angle=0; angle < 360; angle++) {
658                         TFT_drawLineByAngle(x,y, 0, len, angle, random_color());
659                         n++;
660                 }
661         }
662
663         TFT_fillWindow(TFT_BLACK);
664         end_time = clock() + GDEMO_TIME;
665         while ((clock() < end_time) && (Wait(0))) {
666                 for (angle=0; angle < 360; angle++) {
667                         TFT_drawLineByAngle(x, y, len/4, len/4,angle, random_color());
668                         n++;
669                 }
670                 for (angle=0; angle < 360; angle++) {
671                         TFT_drawLineByAngle(x, y, len*3/4, len/4,angle, random_color());
672                         n++;
673                 }
674         }
675         sprintf(tmp_buff, "%d LINES", n);
676         update_header(NULL, tmp_buff);
677         Wait(-GDEMO_INFO_TIME);
678 }
679
680 //--------------------
681 static void arc_demo()
682 {
683         uint16_t x, y, r, th, n, i;
684         float start, end;
685         color_t color, fillcolor;
686
687         disp_header("ARC DEMO");
688
689         x = (tft_dispWin.x2 - tft_dispWin.x1) / 2;
690         y = (tft_dispWin.y2 - tft_dispWin.y1) / 2;
691
692         th = 6;
693         uint32_t end_time = clock() + GDEMO_TIME;
694         i = 0;
695         while ((clock() < end_time) && (Wait(0))) {
696                 if (x < y) r = x - 4;
697                 else r = y - 4;
698                 start = 0;
699                 end = 20;
700                 n = 1;
701                 while (r > 10) {
702                         color = random_color();
703                         TFT_drawArc(x, y, r, th, start, end, color, color);
704                         r -= (th+2);
705                         n++;
706                         start += 30;
707                         end = start + (n*20);
708                         i++;
709                 }
710         }
711         sprintf(tmp_buff, "%d ARCS", i);
712         update_header(NULL, tmp_buff);
713         Wait(-GDEMO_INFO_TIME);
714
715         update_header("OUTLINED ARC", "");
716         TFT_fillWindow(TFT_BLACK);
717         th = 8;
718         end_time = clock() + GDEMO_TIME;
719         i = 0;
720         while ((clock() < end_time) && (Wait(0))) {
721                 if (x < y) r = x - 4;
722                 else r = y - 4;
723                 start = 0;
724                 end = 350;
725                 n = 1;
726                 while (r > 10) {
727                         color = random_color();
728                         fillcolor = random_color();
729                         TFT_drawArc(x, y, r, th, start, end, color, fillcolor);
730                         r -= (th+2);
731                         n++;
732                         start += 20;
733                         end -= n*10;
734                         i++;
735                 }
736         }
737         sprintf(tmp_buff, "%d ARCS", i);
738         update_header(NULL, tmp_buff);
739         Wait(-GDEMO_INFO_TIME);
740 }
741
742 //-----------------------
743 static void circle_demo()
744 {
745         int x, y, r, n;
746
747         disp_header("CIRCLE DEMO");
748
749         uint32_t end_time = clock() + GDEMO_TIME;
750         n = 0;
751         while ((clock() < end_time) && (Wait(0))) {
752                 x = rand_interval(8, tft_dispWin.x2-8);
753                 y = rand_interval(8, tft_dispWin.y2-8);
754                 if (x < y) r = rand_interval(2, x/2);
755                 else r = rand_interval(2, y/2);
756                 TFT_drawCircle(x,y,r,random_color());
757                 n++;
758         }
759         sprintf(tmp_buff, "%d CIRCLES", n);
760         update_header(NULL, tmp_buff);
761         Wait(-GDEMO_INFO_TIME);
762
763         update_header("FILLED CIRCLE", "");
764         TFT_fillWindow(TFT_BLACK);
765         end_time = clock() + GDEMO_TIME;
766         n = 0;
767         while ((clock() < end_time) && (Wait(0))) {
768                 x = rand_interval(8, tft_dispWin.x2-8);
769                 y = rand_interval(8, tft_dispWin.y2-8);
770                 if (x < y) r = rand_interval(2, x/2);
771                 else r = rand_interval(2, y/2);
772                 TFT_fillCircle(x,y,r,random_color());
773                 TFT_drawCircle(x,y,r,random_color());
774                 n++;
775         }
776         sprintf(tmp_buff, "%d CIRCLES", n);
777         update_header(NULL, tmp_buff);
778         Wait(-GDEMO_INFO_TIME);
779 }
780
781 //------------------------
782 static void ellipse_demo()
783 {
784         int x, y, rx, ry, n;
785
786         disp_header("ELLIPSE DEMO");
787
788         uint32_t end_time = clock() + GDEMO_TIME;
789         n = 0;
790         while ((clock() < end_time) && (Wait(0))) {
791                 x = rand_interval(8, tft_dispWin.x2-8);
792                 y = rand_interval(8, tft_dispWin.y2-8);
793                 if (x < y) rx = rand_interval(2, x/4);
794                 else rx = rand_interval(2, y/4);
795                 if (x < y) ry = rand_interval(2, x/4);
796                 else ry = rand_interval(2, y/4);
797                 TFT_drawEllipse(x,y,rx,ry,random_color(),15);
798                 n++;
799         }
800         sprintf(tmp_buff, "%d ELLIPSES", n);
801         update_header(NULL, tmp_buff);
802         Wait(-GDEMO_INFO_TIME);
803
804         update_header("FILLED ELLIPSE", "");
805         TFT_fillWindow(TFT_BLACK);
806         end_time = clock() + GDEMO_TIME;
807         n = 0;
808         while ((clock() < end_time) && (Wait(0))) {
809                 x = rand_interval(8, tft_dispWin.x2-8);
810                 y = rand_interval(8, tft_dispWin.y2-8);
811                 if (x < y) rx = rand_interval(2, x/4);
812                 else rx = rand_interval(2, y/4);
813                 if (x < y) ry = rand_interval(2, x/4);
814                 else ry = rand_interval(2, y/4);
815                 TFT_fillEllipse(x,y,rx,ry,random_color(),15);
816                 TFT_drawEllipse(x,y,rx,ry,random_color(),15);
817                 n++;
818         }
819         sprintf(tmp_buff, "%d ELLIPSES", n);
820         update_header(NULL, tmp_buff);
821         Wait(-GDEMO_INFO_TIME);
822
823         update_header("ELLIPSE SEGMENTS", "");
824         TFT_fillWindow(TFT_BLACK);
825         end_time = clock() + GDEMO_TIME;
826         n = 0;
827         int k = 1;
828         while ((clock() < end_time) && (Wait(0))) {
829                 x = rand_interval(8, tft_dispWin.x2-8);
830                 y = rand_interval(8, tft_dispWin.y2-8);
831                 if (x < y) rx = rand_interval(2, x/4);
832                 else rx = rand_interval(2, y/4);
833                 if (x < y) ry = rand_interval(2, x/4);
834                 else ry = rand_interval(2, y/4);
835                 TFT_fillEllipse(x,y,rx,ry,random_color(), (1<<k));
836                 TFT_drawEllipse(x,y,rx,ry,random_color(), (1<<k));
837                 k = (k+1) & 3;
838                 n++;
839         }
840         sprintf(tmp_buff, "%d SEGMENTS", n);
841         update_header(NULL, tmp_buff);
842         Wait(-GDEMO_INFO_TIME);
843 }
844
845 //-------------------------
846 static void triangle_demo()
847 {
848         int x1, y1, x2, y2, x3, y3, n;
849
850         disp_header("TRIANGLE DEMO");
851
852         uint32_t end_time = clock() + GDEMO_TIME;
853         n = 0;
854         while ((clock() < end_time) && (Wait(0))) {
855                 x1 = rand_interval(4, tft_dispWin.x2-4);
856                 y1 = rand_interval(4, tft_dispWin.y2-2);
857                 x2 = rand_interval(4, tft_dispWin.x2-4);
858                 y2 = rand_interval(4, tft_dispWin.y2-2);
859                 x3 = rand_interval(4, tft_dispWin.x2-4);
860                 y3 = rand_interval(4, tft_dispWin.y2-2);
861                 TFT_drawTriangle(x1,y1,x2,y2,x3,y3,random_color());
862                 n++;
863         }
864         sprintf(tmp_buff, "%d TRIANGLES", n);
865         update_header(NULL, tmp_buff);
866         Wait(-GDEMO_INFO_TIME);
867
868         update_header("FILLED TRIANGLE", "");
869         TFT_fillWindow(TFT_BLACK);
870         end_time = clock() + GDEMO_TIME;
871         n = 0;
872         while ((clock() < end_time) && (Wait(0))) {
873                 x1 = rand_interval(4, tft_dispWin.x2-4);
874                 y1 = rand_interval(4, tft_dispWin.y2-2);
875                 x2 = rand_interval(4, tft_dispWin.x2-4);
876                 y2 = rand_interval(4, tft_dispWin.y2-2);
877                 x3 = rand_interval(4, tft_dispWin.x2-4);
878                 y3 = rand_interval(4, tft_dispWin.y2-2);
879                 TFT_fillTriangle(x1,y1,x2,y2,x3,y3,random_color());
880                 TFT_drawTriangle(x1,y1,x2,y2,x3,y3,random_color());
881                 n++;
882         }
883         sprintf(tmp_buff, "%d TRIANGLES", n);
884         update_header(NULL, tmp_buff);
885         Wait(-GDEMO_INFO_TIME);
886 }
887
888 //---------------------
889 static void poly_demo()
890 {
891         uint16_t x, y, rot, oldrot;
892         int i, n, r;
893         uint8_t sides[6] = {3, 4, 5, 6, 8, 10};
894         color_t color[6] = {TFT_WHITE, TFT_CYAN, TFT_RED,       TFT_BLUE,     TFT_YELLOW,     TFT_ORANGE};
895         color_t fill[6]  = {TFT_BLUE,  TFT_NAVY,   TFT_DARKGREEN, TFT_DARKGREY, TFT_LIGHTGREY, TFT_OLIVE};
896
897         disp_header("POLYGON DEMO");
898
899         x = (tft_dispWin.x2 - tft_dispWin.x1) / 2;
900         y = (tft_dispWin.y2 - tft_dispWin.y1) / 2;
901
902         rot = 0;
903         oldrot = 0;
904         uint32_t end_time = clock() + GDEMO_TIME;
905         n = 0;
906         while ((clock() < end_time) && (Wait(0))) {
907                 if (x < y) r = x - 4;
908                 else r = y - 4;
909                 for (i=5; i>=0; i--) {
910                         TFT_drawPolygon(x, y, sides[i], r, TFT_BLACK, TFT_BLACK, oldrot, 1);
911                         TFT_drawPolygon(x, y, sides[i], r, color[i], color[i], rot, 1);
912                         r -= 16;
913             if (r <= 0) { break; };
914                         n += 2;
915                 }
916                 Wait(100);
917                 oldrot = rot;
918                 rot = (rot + 15) % 360;
919         }
920         sprintf(tmp_buff, "%d POLYGONS", n);
921         update_header(NULL, tmp_buff);
922         Wait(-GDEMO_INFO_TIME);
923
924         update_header("FILLED POLYGON", "");
925         rot = 0;
926         end_time = clock() + GDEMO_TIME;
927         n = 0;
928         while ((clock() < end_time) && (Wait(0))) {
929                 if (x < y) r = x - 4;
930                 else r = y - 4;
931                 TFT_fillWindow(TFT_BLACK);
932                 for (i=5; i>=0; i--) {
933                         TFT_drawPolygon(x, y, sides[i], r, color[i], fill[i], rot, 2);
934                         r -= 16;
935             if (r <= 0) { break; }
936                         n += 2;
937                 }
938                 Wait(500);
939                 rot = (rot + 15) % 360;
940         }
941         sprintf(tmp_buff, "%d POLYGONS", n);
942         update_header(NULL, tmp_buff);
943         Wait(-GDEMO_INFO_TIME);
944 }
945
946 //----------------------
947 static void touch_demo()
948 {
949 #if USE_TOUCH
950         int tx, ty, ltx, lty, doexit = 0;
951
952         disp_header("TOUCH DEMO");
953         TFT_setFont(DEFAULT_FONT, NULL);
954         tft_fg = TFT_YELLOW;
955         TFT_print("Touch to draw", CENTER, 40);
956         TFT_print("Touch footer to clear", CENTER, 60);
957
958         ltx = -9999;
959         lty = -999;
960         while (1) {
961                 if (TFT_read_touch(&tx, &ty, 0)) {
962                         // Touched
963                         if (((tx >= tft_dispWin.x1) && (tx <= tft_dispWin.x2)) &&
964                                 ((ty >= tft_dispWin.y1) && (ty <= tft_dispWin.y2))) {
965                                 if ((doexit > 2) || ((abs(tx-ltx) < 5) && (abs(ty-lty) < 5))) {
966                                         if (((abs(tx-ltx) > 0) || (abs(ty-lty) > 0))) {
967                                                 TFT_fillCircle(tx-tft_dispWin.x1, ty-tft_dispWin.y1, 4,random_color());
968                                                 sprintf(tmp_buff, "%d,%d", tx, ty);
969                                                 update_header(NULL, tmp_buff);
970                                         }
971                                         ltx = tx;
972                                         lty = ty;
973                                 }
974                                 doexit = 0;
975                         }
976                         else if (ty > (tft_dispWin.y2+5)) TFT_fillWindow(TFT_BLACK);
977                         else {
978                                 doexit++;
979                                 if (doexit == 2) update_header(NULL, "---");
980                                 if (doexit > 50) return;
981                                 vTaskDelay(100 / portTICK_RATE_MS);
982                         }
983                 }
984                 else {
985                         doexit++;
986                         if (doexit == 2) update_header(NULL, "---");
987                         if (doexit > 50) return;
988                         vTaskDelay(100 / portTICK_RATE_MS);
989                 }
990         }
991 #endif
992 }
993
994
995 //===============
996 void tft_demo() {
997
998         tft_font_rotate = 0;
999         tft_text_wrap = 0;
1000         tft_font_transparent = 0;
1001         tft_font_forceFixed = 0;
1002         TFT_resetclipwin();
1003
1004         tft_image_debug = 0;
1005
1006     char dtype[16];
1007     
1008     switch (tft_disp_type) {
1009         case DISP_TYPE_ILI9341:
1010             sprintf(dtype, "ILI9341");
1011             break;
1012         case DISP_TYPE_ILI9488:
1013             sprintf(dtype, "ILI9488");
1014             break;
1015         case DISP_TYPE_ST7789V:
1016             sprintf(dtype, "ST7789V");
1017             break;
1018         case DISP_TYPE_ST7735:
1019             sprintf(dtype, "ST7735");
1020             break;
1021         case DISP_TYPE_ST7735R:
1022             sprintf(dtype, "ST7735R");
1023             break;
1024         case DISP_TYPE_ST7735B:
1025             sprintf(dtype, "ST7735B");
1026             break;
1027         default:
1028             sprintf(dtype, "Unknown");
1029     }
1030     
1031     uint8_t disp_rot = PORTRAIT;
1032         _demo_pass = 0;
1033         tft_gray_scale = 0;
1034         doprint = 1;
1035
1036         TFT_setRotation(disp_rot);
1037         disp_header("ESP32 TFT DEMO");
1038         TFT_setFont(COMIC24_FONT, NULL);
1039         int tempy = TFT_getfontheight() + 4;
1040         tft_fg = TFT_ORANGE;
1041         TFT_print("ESP32", CENTER, (tft_dispWin.y2-tft_dispWin.y1)/2 - tempy);
1042         TFT_setFont(UBUNTU16_FONT, NULL);
1043         tft_fg = TFT_CYAN;
1044         TFT_print("TFT Demo", CENTER, LASTY+tempy);
1045         tempy = TFT_getfontheight() + 4;
1046         TFT_setFont(DEFAULT_FONT, NULL);
1047         tft_fg = TFT_GREEN;
1048         sprintf(tmp_buff, "Read speed: %5.2f MHz", (float)tft_max_rdclock/1000000.0);
1049         TFT_print(tmp_buff, CENTER, LASTY+tempy);
1050
1051         Wait(4000);
1052
1053         while (1) {
1054                 if (run_gs_demo) {
1055                         if (_demo_pass == 8) doprint = 0;
1056                         // Change gray scale mode on every 2nd pass
1057                         tft_gray_scale = _demo_pass & 1;
1058                         // change display rotation
1059                         if ((_demo_pass % 2) == 0) {
1060                                 tft_bg = TFT_BLACK;
1061                                 TFT_setRotation(disp_rot);
1062                                 disp_rot++;
1063                                 disp_rot &= 3;
1064                         }
1065                 }
1066                 else {
1067                         if (_demo_pass == 4) doprint = 0;
1068                         // change display rotation
1069                         tft_bg = TFT_BLACK;
1070                         TFT_setRotation(disp_rot);
1071                         disp_rot++;
1072                         disp_rot &= 3;
1073                 }
1074
1075                 if (doprint) {
1076                         if (disp_rot == 1) sprintf(tmp_buff, "PORTRAIT");
1077                         if (disp_rot == 2) sprintf(tmp_buff, "LANDSCAPE");
1078                         if (disp_rot == 3) sprintf(tmp_buff, "PORTRAIT FLIP");
1079                         if (disp_rot == 0) sprintf(tmp_buff, "LANDSCAPE FLIP");
1080                         printf("\r\n==========================================\r\nDisplay: %s: %s %d,%d %s\r\n\r\n",
1081                                         dtype, tmp_buff, tft_width, tft_height, ((tft_gray_scale) ? "Gray" : "Color"));
1082                 }
1083
1084                 disp_header("Welcome to ESP32");
1085
1086                 test_times();
1087                 font_demo();
1088                 line_demo();
1089                 aline_demo();
1090                 rect_demo();
1091                 circle_demo();
1092                 ellipse_demo();
1093                 arc_demo();
1094                 triangle_demo();
1095                 poly_demo();
1096                 pixel_demo();
1097                 disp_images();
1098                 touch_demo();
1099
1100                 _demo_pass++;
1101         }
1102 }
1103
1104 /*
1105 // ================== TEST SD CARD ==========================================
1106
1107 #include "esp_vfs_fat.h"
1108 #include "driver/sdmmc_host.h"
1109 #include "driver/sdspi_host.h"
1110 #include "sdmmc_cmd.h"
1111
1112 // This example can use SDMMC and SPI peripherals to communicate with SD card.
1113 // SPI mode IS USED
1114
1115 // When testing SD and SPI modes, keep in mind that once the card has been
1116 // initialized in SPI mode, it can not be reinitialized in SD mode without
1117 // toggling power to the card.
1118
1119 // Pin mapping when using SPI mode.
1120 // With this mapping, SD card can be used both in SPI and 1-line SD mode.
1121 // Note that a pull-up on CS line is required in SD mode.
1122 #define sdPIN_NUM_MISO 19
1123 #define sdPIN_NUM_MOSI 18
1124 #define sdPIN_NUM_CLK  5
1125 #define sdPIN_NUM_CS   14
1126
1127 static const char *TAG = "SDCard test";
1128
1129 void test_sd_card(void)
1130 {
1131     printf("\n=======================================================\n");
1132     printf("===== Test using SD Card in SPI mode              =====\n");
1133     printf("===== SD Card uses the same gpio's as TFT display =====\n");
1134     printf("=======================================================\n\n");
1135     ESP_LOGI(TAG, "Initializing SD card");
1136     ESP_LOGI(TAG, "Using SPI peripheral");
1137
1138     sdmmc_host_t host = SDSPI_HOST_DEFAULT();
1139     sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
1140     slot_config.gpio_miso = sdPIN_NUM_MISO;
1141     slot_config.gpio_mosi = sdPIN_NUM_MOSI;
1142     slot_config.gpio_sck  = sdPIN_NUM_CLK;
1143     slot_config.gpio_cs   = sdPIN_NUM_CS;
1144     // This initializes the slot without card detect (CD) and write protect (WP) signals.
1145     // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
1146
1147     // Options for mounting the filesystem.
1148     // If format_if_mount_failed is set to true, SD card will be partitioned and
1149     // formatted in case when mounting fails.
1150     esp_vfs_fat_sdmmc_mount_config_t mount_config = {
1151         .format_if_mount_failed = false,
1152         .max_files = 5
1153     };
1154
1155     // Use settings defined above to initialize SD card and mount FAT filesystem.
1156     // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function.
1157     // Please check its source code and implement error recovery when developing
1158     // production applications.
1159     sdmmc_card_t* card;
1160     esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
1161
1162     if (ret != ESP_OK) {
1163         if (ret == ESP_FAIL) {
1164             ESP_LOGE(TAG, "Failed to mount filesystem. "
1165                 "If you want the card to be formatted, set format_if_mount_failed = true.");
1166         } else {
1167             ESP_LOGE(TAG, "Failed to initialize the card (%d). "
1168                 "Make sure SD card lines have pull-up resistors in place.", ret);
1169         }
1170         return;
1171     }
1172
1173     // Card has been initialized, print its properties
1174     sdmmc_card_print_info(stdout, card);
1175
1176     // Use POSIX and C standard library functions to work with files.
1177     // First create a file.
1178     ESP_LOGI(TAG, "Opening file");
1179     FILE* f = fopen("/sdcard/hello.txt", "w");
1180     if (f == NULL) {
1181         ESP_LOGE(TAG, "Failed to open file for writing");
1182         return;
1183     }
1184     fprintf(f, "Hello %s!\n", card->cid.name);
1185     fclose(f);
1186     ESP_LOGI(TAG, "File written");
1187
1188     // Check if destination file exists before renaming
1189     struct stat st;
1190     if (stat("/sdcard/foo.txt", &st) == 0) {
1191         // Delete it if it exists
1192         unlink("/sdcard/foo.txt");
1193     }
1194
1195     // Rename original file
1196     ESP_LOGI(TAG, "Renaming file");
1197     if (rename("/sdcard/hello.txt", "/sdcard/foo.txt") != 0) {
1198         ESP_LOGE(TAG, "Rename failed");
1199         return;
1200     }
1201
1202     // Open renamed file for reading
1203     ESP_LOGI(TAG, "Reading file");
1204     f = fopen("/sdcard/foo.txt", "r");
1205     if (f == NULL) {
1206         ESP_LOGE(TAG, "Failed to open file for reading");
1207         return;
1208     }
1209     char line[64];
1210     fgets(line, sizeof(line), f);
1211     fclose(f);
1212     // strip newline
1213     char* pos = strchr(line, '\n');
1214     if (pos) {
1215         *pos = '\0';
1216     }
1217     ESP_LOGI(TAG, "Read from file: '%s'", line);
1218
1219     // All done, unmount partition and disable SDMMC or SPI peripheral
1220     esp_vfs_fat_sdmmc_unmount();
1221     ESP_LOGI(TAG, "Card unmounted");
1222
1223     printf("===== SD Card test end ================================\n\n");
1224 }
1225
1226 // ================== TEST SD CARD ==========================================
1227 */
1228
1229
1230 //=============
1231 void app_main()
1232 {
1233     //test_sd_card();
1234     // ========  PREPARE DISPLAY INITIALIZATION  =========
1235
1236     esp_err_t ret;
1237
1238     // === SET GLOBAL VARIABLES ==========================
1239
1240         // ===================================================
1241         // ==== Set maximum spi clock for display read    ====
1242         //      operations, function 'find_rd_speed()'    ====
1243         //      can be used after display initialization  ====
1244         tft_max_rdclock = 8000000;
1245         // ===================================================
1246
1247     // ====================================================================
1248     // === Pins MUST be initialized before SPI interface initialization ===
1249     // ====================================================================
1250     TFT_PinsInit();
1251
1252     // ====  CONFIGURE SPI DEVICES(s)  ====================================================================================
1253
1254     spi_lobo_device_handle_t spi;
1255         
1256     spi_lobo_bus_config_t buscfg={
1257         .miso_io_num=PIN_NUM_MISO,                              // set SPI MISO pin
1258         .mosi_io_num=PIN_NUM_MOSI,                              // set SPI MOSI pin
1259         .sclk_io_num=PIN_NUM_CLK,                               // set SPI CLK pin
1260         .quadwp_io_num=-1,
1261         .quadhd_io_num=-1,
1262                 .max_transfer_sz = 6*1024,
1263     };
1264     spi_lobo_device_interface_config_t devcfg={
1265         .clock_speed_hz=8000000,                // Initial clock out at 8 MHz
1266         .mode=0,                                // SPI mode 0
1267         .spics_io_num=-1,                       // we will use external CS pin
1268                 .spics_ext_io_num=PIN_NUM_CS,           // external CS pin
1269                 .flags=LB_SPI_DEVICE_HALFDUPLEX,        // ALWAYS SET  to HALF DUPLEX MODE!! for display spi
1270     };
1271
1272 #if USE_TOUCH == TOUCH_TYPE_XPT2046
1273     spi_lobo_device_handle_t tsspi = NULL;
1274
1275     spi_lobo_device_interface_config_t tsdevcfg={
1276         .clock_speed_hz=2500000,                //Clock out at 2.5 MHz
1277         .mode=0,                                //SPI mode 0
1278         .spics_io_num=PIN_NUM_TCS,              //Touch CS pin
1279                 .spics_ext_io_num=-1,                   //Not using the external CS
1280                 //.command_bits=8,                        //1 byte command
1281     };
1282 #elif USE_TOUCH == TOUCH_TYPE_STMPE610
1283     spi_lobo_device_handle_t tsspi = NULL;
1284
1285     spi_lobo_device_interface_config_t tsdevcfg={
1286         .clock_speed_hz=1000000,                //Clock out at 1 MHz
1287         .mode=STMPE610_SPI_MODE,                //SPI mode 0
1288         .spics_io_num=PIN_NUM_TCS,              //Touch CS pin
1289                 .spics_ext_io_num=-1,                   //Not using the external CS
1290         .flags = 0,
1291     };
1292 #endif
1293
1294     // ====================================================================================================================
1295
1296
1297     vTaskDelay(500 / portTICK_RATE_MS);
1298         printf("\r\n==============================\r\n");
1299     printf("TFT display DEMO, LoBo 11/2017\r\n");
1300         printf("==============================\r\n");
1301     printf("Pins used: miso=%d, mosi=%d, sck=%d, cs=%d\r\n", PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_CS);
1302 #if USE_TOUCH > TOUCH_TYPE_NONE
1303     printf(" Touch CS: %d\r\n", PIN_NUM_TCS);
1304 #endif
1305         printf("==============================\r\n\r\n");
1306
1307         // ==================================================================
1308         // ==== Initialize the SPI bus and attach the LCD to the SPI bus ====
1309
1310         ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &devcfg, &spi);
1311     assert(ret==ESP_OK);
1312         printf("SPI: display device added to spi bus (%d)\r\n", SPI_BUS);
1313         tft_disp_spi = spi;
1314
1315         // ==== Test select/deselect ====
1316         ret = spi_lobo_device_select(spi, 1);
1317     assert(ret==ESP_OK);
1318         ret = spi_lobo_device_deselect(spi);
1319     assert(ret==ESP_OK);
1320
1321         printf("SPI: attached display device, speed=%u\r\n", spi_lobo_get_speed(spi));
1322         printf("SPI: bus uses native pins: %s\r\n", spi_lobo_uses_native_pins(spi) ? "true" : "false");
1323
1324 #if USE_TOUCH > TOUCH_TYPE_NONE
1325         // =====================================================
1326     // ==== Attach the touch screen to the same SPI bus ====
1327
1328         ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &tsdevcfg, &tsspi);
1329     assert(ret==ESP_OK);
1330         printf("SPI: touch screen device added to spi bus (%d)\r\n", SPI_BUS);
1331         tft_ts_spi = tsspi;
1332
1333         // ==== Test select/deselect ====
1334         ret = spi_lobo_device_select(tsspi, 1);
1335     assert(ret==ESP_OK);
1336         ret = spi_lobo_device_deselect(tsspi);
1337     assert(ret==ESP_OK);
1338
1339         printf("SPI: attached TS device, speed=%u\r\n", spi_lobo_get_speed(tsspi));
1340 #endif
1341
1342         // ================================
1343         // ==== Initialize the Display ====
1344
1345         printf("SPI: display init...\r\n");
1346         TFT_display_init();
1347 #ifdef TFT_START_COLORS_INVERTED
1348         TFT_invertDisplay(1);
1349 #endif
1350     printf("OK\r\n");
1351     #if USE_TOUCH == TOUCH_TYPE_STMPE610
1352         stmpe610_Init();
1353         vTaskDelay(10 / portTICK_RATE_MS);
1354     uint32_t tver = stmpe610_getID();
1355     printf("STMPE touch initialized, ver: %04x - %02x\r\n", tver >> 8, tver & 0xFF);
1356     #endif
1357         
1358         // ---- Detect maximum read speed ----
1359         tft_max_rdclock = find_rd_speed();
1360         printf("SPI: Max rd speed = %u\r\n", tft_max_rdclock);
1361
1362     // ==== Set SPI clock used for display operations ====
1363         spi_lobo_set_speed(spi, DEFAULT_SPI_CLOCK);
1364         printf("SPI: Changed speed to %u\r\n", spi_lobo_get_speed(spi));
1365
1366     printf("\r\n---------------------\r\n");
1367         printf("Graphics demo started\r\n");
1368         printf("---------------------\r\n");
1369
1370         tft_font_rotate = 0;
1371         tft_text_wrap = 0;
1372         tft_font_transparent = 0;
1373         tft_font_forceFixed = 0;
1374         tft_gray_scale = 0;
1375     TFT_setGammaCurve(DEFAULT_GAMMA_CURVE);
1376         TFT_setRotation(PORTRAIT);
1377         TFT_setFont(DEFAULT_FONT, NULL);
1378         TFT_resetclipwin();
1379
1380 #ifdef CONFIG_EXAMPLE_USE_WIFI
1381
1382     ESP_ERROR_CHECK( nvs_flash_init() );
1383
1384     // ===== Set time zone ======
1385         setenv("TZ", "CET-1CEST", 0);
1386         tzset();
1387         // ==========================
1388
1389         disp_header("GET NTP TIME");
1390
1391     time(&time_now);
1392         tm_info = localtime(&time_now);
1393
1394         // Is time set? If not, tm_year will be (1970 - 1900).
1395     if (tm_info->tm_year < (2016 - 1900)) {
1396         ESP_LOGI(tag, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
1397         tft_fg = TFT_CYAN;
1398         TFT_print("Time is not set yet", CENTER, CENTER);
1399         TFT_print("Connecting to WiFi", CENTER, LASTY+TFT_getfontheight()+2);
1400         TFT_print("Getting time over NTP", CENTER, LASTY+TFT_getfontheight()+2);
1401         tft_fg = TFT_YELLOW;
1402         TFT_print("Wait", CENTER, LASTY+TFT_getfontheight()+2);
1403         if (obtain_time()) {
1404                 tft_fg = TFT_GREEN;
1405                 TFT_print("System time is set.", CENTER, LASTY);
1406         }
1407         else {
1408                 tft_fg = TFT_RED;
1409                 TFT_print("ERROR.", CENTER, LASTY);
1410         }
1411         time(&time_now);
1412         update_header(NULL, "");
1413         Wait(-2000);
1414     }
1415 #endif
1416
1417         disp_header("File system INIT");
1418     tft_fg = TFT_CYAN;
1419         TFT_print("Initializing SPIFFS...", CENTER, CENTER);
1420     // ==== Initialize the file system ====
1421     printf("\r\n\n");
1422         vfs_spiffs_register();
1423     if (!spiffs_is_mounted) {
1424         tft_fg = TFT_RED;
1425         TFT_print("SPIFFS not mounted !", CENTER, LASTY+TFT_getfontheight()+2);
1426     }
1427     else {
1428         tft_fg = TFT_GREEN;
1429         TFT_print("SPIFFS Mounted.", CENTER, LASTY+TFT_getfontheight()+2);
1430     }
1431
1432         Wait(-2000);
1433
1434         //=========
1435     // Run demo
1436     //=========
1437         tft_demo();
1438 }