Merge pull request #1269 from pkendall64/crsf-max-output
[ExpressLRS.git] / src / lib / SCREEN / TFT / tftscreen.cpp
blob4a85d61318c700bf548b924c0040444c868a4054
1 #ifdef HAS_TFT_SCREEN
3 #include "tftscreen.h"
4 #include "options.h"
5 #include "POWERMGNT.h"
7 #include <TFT_eSPI.h>
9 TFT_eSPI tft = TFT_eSPI();
11 bool is_confirmed = false;
13 const uint16_t *main_menu_icons[] = {
14 elrs_rate,
15 elrs_power,
16 elrs_ratio,
17 elrs_motion,
18 elrs_fan,
19 elrs_bind,
20 elrs_updatefw
23 #define COLOR_ELRS_BANNER_BACKGROUND 0x9E2D
25 #define SCREEN_X TFT_HEIGHT
26 #define SCREEN_Y TFT_WIDTH
28 //see #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
29 #define SCREEN_SMALL_FONT_SIZE 8
30 #define SCREEN_SMALL_FONT 1
32 //see #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
33 #define SCREEN_NORMAL_FONT_SIZE 16
34 #define SCREEN_NORMAL_FONT 2
36 //see #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
37 #define SCREEN_LARGE_FONT_SIZE 26
38 #define SCREEN_LARGE_FONT 4
40 //ICON SIZE Definition
41 #define SCREEN_LARGE_ICON_SIZE 60
42 #define SCREEN_NORAML_ICON_SIZE 20
43 #define SCREEN_NARROW_ICON_WEIGHT 14
45 //GAP Definition
46 #define SCREEN_CONTENT_GAP 10
47 #define SCREEN_FONT_GAP 5
49 //INIT LOGO PAGE Definition
50 #define INIT_PAGE_LOGO_X SCREEN_X
51 #define INIT_PAGE_LOGO_Y 53
52 #define INIT_PAGE_FONT_PADDING 3
53 #define INIT_PAGE_FONT_START_X SCREEN_FONT_GAP
54 #define INIT_PAGE_FONT_START_Y INIT_PAGE_LOGO_Y + (SCREEN_Y - INIT_PAGE_LOGO_Y - SCREEN_NORMAL_FONT_SIZE)/2
56 //IDLE PAGE Definition
57 #define IDLE_PAGE_START_X SCREEN_CONTENT_GAP
58 #define IDLE_PAGE_START_Y 0
60 #define IDLE_PAGE_STAT_START_X SCREEN_X/2 + SCREEN_CONTENT_GAP
61 #define IDLE_PAGE_STAT_Y_GAP (SCREEN_Y - SCREEN_NORMAL_FONT_SIZE * 3)/4
63 #define IDLE_PAGE_RATE_START_Y IDLE_PAGE_STAT_Y_GAP
64 #define IDLE_PAGE_POWER_START_Y IDLE_PAGE_RATE_START_Y + SCREEN_NORMAL_FONT_SIZE + IDLE_PAGE_STAT_Y_GAP
65 #define IDLE_PAGE_RATIO_START_Y IDLE_PAGE_POWER_START_Y + SCREEN_NORMAL_FONT_SIZE + IDLE_PAGE_STAT_Y_GAP
67 //MAIN PAGE Definition
68 #define MAIN_PAGE_ICON_START_X SCREEN_CONTENT_GAP
69 #define MAIN_PAGE_ICON_START_Y (SCREEN_Y - SCREEN_LARGE_ICON_SIZE)/2
71 #define MAIN_PAGE_WORD_START_X MAIN_PAGE_ICON_START_X + SCREEN_LARGE_ICON_SIZE + SCREEN_CONTENT_GAP
72 #define MAIN_PAGE_WORD_START_Y (SCREEN_Y - SCREEN_NORMAL_FONT_SIZE)/2
73 #define MAIN_PAGE_WORD_START_Y1 (SCREEN_Y - SCREEN_NORMAL_FONT_SIZE*2 - SCREEN_FONT_GAP)/2
74 #define MAIN_PAGE_WORD_START_Y2 MAIN_PAGE_WORD_START_Y1 + SCREEN_NORMAL_FONT_SIZE + SCREEN_FONT_GAP
76 //Sub Function Definiton
77 #define SUB_PAGE_VALUE_START_X SCREEN_CONTENT_GAP
78 #define SUB_PAGE_VALUE_START_Y (SCREEN_Y - SCREEN_LARGE_FONT_SIZE - SCREEN_NORMAL_FONT_SIZE - SCREEN_CONTENT_GAP)/2
80 #define SUB_PAGE_TIPS_START_X SCREEN_CONTENT_GAP
81 #define SUB_PAGE_TIPS_START_Y SCREEN_Y - SCREEN_NORMAL_FONT_SIZE - SCREEN_CONTENT_GAP
83 //Sub WIFI Mode & Bind Confirm Definiton
84 #define SUB_PAGE_ICON_START_X 0
85 #define SUB_PAGE_ICON_START_Y (SCREEN_Y - SCREEN_LARGE_ICON_SIZE)/2
87 #define SUB_PAGE_WORD_START_X SUB_PAGE_ICON_START_X + SCREEN_LARGE_ICON_SIZE
88 #define SUB_PAGE_WORD_START_Y1 (SCREEN_Y - SCREEN_NORMAL_FONT_SIZE*3 - SCREEN_FONT_GAP*2)/2
89 #define SUB_PAGE_WORD_START_Y2 SUB_PAGE_WORD_START_Y1 + SCREEN_NORMAL_FONT_SIZE + SCREEN_FONT_GAP
90 #define SUB_PAGE_WORD_START_Y3 SUB_PAGE_WORD_START_Y2 + SCREEN_NORMAL_FONT_SIZE + SCREEN_FONT_GAP
92 //Sub Binding Definiton
93 #define SUB_PAGE_BINDING_WORD_START_X 0
94 #define SUB_PAGE_BINDING_WORD_START_Y (SCREEN_Y - SCREEN_LARGE_FONT_SIZE)/2
96 void TFTScreen::init(bool reboot)
98 tft.init();
99 tft.setRotation(1);
100 tft.setSwapBytes(true);
102 if (!reboot) {
103 doScreenBackLight(HIGH);
104 tft.fillScreen(TFT_WHITE);
106 tft.pushImage(0, 0, INIT_PAGE_LOGO_X, INIT_PAGE_LOGO_Y, vendor_logo);
108 tft.fillRect(SCREEN_FONT_GAP, INIT_PAGE_FONT_START_Y - INIT_PAGE_FONT_PADDING,
109 SCREEN_X - SCREEN_FONT_GAP*2, SCREEN_NORMAL_FONT_SIZE + INIT_PAGE_FONT_PADDING*2, TFT_BLACK);
111 char buffer[50];
112 sprintf(buffer, "%s ELRS-", HARDWARE_VERSION);
113 strncat(buffer, version, 6);
114 displayFontCenter(INIT_PAGE_FONT_START_X, SCREEN_X - INIT_PAGE_FONT_START_X, INIT_PAGE_FONT_START_Y,
115 SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
116 String(buffer), TFT_WHITE, TFT_BLACK);
119 doScreenBackLight(LOW);
121 current_rate_index = 0;
122 current_power_index = 0;
123 current_ratio_index = 0;
124 current_powersaving_index = 0;
125 current_smartfan_index = 0;
127 if (!reboot) {
128 current_screen_status = SCREEN_STATUS_INIT;
129 current_page_index = PAGE_MAIN_MENU_INDEX;
130 main_menu_page_index = MAIN_MENU_RATE_INDEX;
132 else {
133 current_screen_status = SCREEN_STATUS_WORK;
134 current_page_index = PAGE_MAIN_MENU_INDEX;
135 main_menu_page_index = MAIN_MENU_UPDATEFW_INDEX;
136 updateMainMenuPage();
139 system_temperature = 25;
142 void TFTScreen::idleScreen()
144 tft.fillRect(0, 0, SCREEN_X/2, SCREEN_Y, COLOR_ELRS_BANNER_BACKGROUND);
145 tft.fillRect(SCREEN_X/2, 0, SCREEN_X/2, SCREEN_Y, TFT_WHITE);
147 tft.pushImage(IDLE_PAGE_START_X, IDLE_PAGE_START_Y, SCREEN_LARGE_ICON_SIZE, SCREEN_LARGE_ICON_SIZE, elrs_banner);
149 char buffer[20];
150 strncpy(buffer, version, 6);
151 sprintf(buffer+6, " %02d", system_temperature);
152 displayFontCenterWithCelsius(0, SCREEN_X/2, SCREEN_LARGE_ICON_SIZE + (SCREEN_Y - SCREEN_LARGE_ICON_SIZE - SCREEN_SMALL_FONT_SIZE)/2,
153 SCREEN_SMALL_FONT_SIZE, SCREEN_SMALL_FONT,
154 String(buffer), TFT_WHITE, COLOR_ELRS_BANNER_BACKGROUND);
156 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_RATE_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
157 rate_string[current_rate_index], TFT_BLACK, TFT_WHITE);
159 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_POWER_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
160 power_string[current_power_index], TFT_BLACK, TFT_WHITE);
162 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_RATIO_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
163 ratio_string[current_ratio_index], TFT_BLACK, TFT_WHITE);
165 current_screen_status = SCREEN_STATUS_IDLE;
168 void TFTScreen::updateMainMenuPage()
170 tft.fillScreen(TFT_WHITE);
172 tft.pushImage(MAIN_PAGE_ICON_START_X, MAIN_PAGE_ICON_START_Y, SCREEN_LARGE_ICON_SIZE, SCREEN_LARGE_ICON_SIZE, main_menu_icons[main_menu_page_index-1]);
175 displayFontCenter(MAIN_PAGE_WORD_START_X, SCREEN_X, MAIN_PAGE_WORD_START_Y1, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
176 main_menu_line_1[main_menu_page_index - 1], TFT_BLACK, TFT_WHITE);
178 displayFontCenter(MAIN_PAGE_WORD_START_X, SCREEN_X, MAIN_PAGE_WORD_START_Y2, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
179 main_menu_line_2[main_menu_page_index - 1], TFT_BLACK, TFT_WHITE);
182 void TFTScreen::updateSubFunctionPage()
184 tft.fillScreen(TFT_WHITE);
186 doValueSelection(USER_ACTION_NONE);
188 displayFontCenter(SUB_PAGE_TIPS_START_X, SCREEN_X, SUB_PAGE_TIPS_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
189 "PRESS TO CONFIRM", TFT_BLACK, TFT_WHITE);
192 void TFTScreen::updateSubWIFIModePage()
194 tft.fillScreen(TFT_WHITE);
196 tft.pushImage(SUB_PAGE_ICON_START_X, SUB_PAGE_ICON_START_Y, SCREEN_LARGE_ICON_SIZE, SCREEN_LARGE_ICON_SIZE, elrs_wifimode);
197 #if defined(HOME_WIFI_SSID) && defined(HOME_WIFI_PASSWORD)
198 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y1, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
199 "open http://", TFT_BLACK, TFT_WHITE);
201 String host_msg = String(wifi_hostname) + ".local";
202 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y2, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
203 host_msg, TFT_BLACK, TFT_WHITE);
205 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y3, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
206 "by browser", TFT_BLACK, TFT_WHITE);
207 #else
208 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y1, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
209 wifi_ap_ssid, TFT_BLACK, TFT_WHITE);
211 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y2, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
212 wifi_ap_password, TFT_BLACK, TFT_WHITE);
214 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y3, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
215 wifi_ap_address, TFT_BLACK, TFT_WHITE);
216 #endif
217 updatecallback(USER_UPDATE_TYPE_WIFI);
220 void TFTScreen::updateSubBindConfirmPage()
222 tft.fillScreen(TFT_WHITE);
224 tft.pushImage(SUB_PAGE_ICON_START_X, SUB_PAGE_ICON_START_Y, SCREEN_LARGE_ICON_SIZE, SCREEN_LARGE_ICON_SIZE, elrs_bind);
226 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y1, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
227 "PRESS TO", TFT_BLACK, TFT_WHITE);
229 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y2, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
230 "SEND BIND", TFT_BLACK, TFT_WHITE);
232 displayFontCenter(SUB_PAGE_WORD_START_X, SCREEN_X, SUB_PAGE_WORD_START_Y3, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
233 "REQUEST", TFT_BLACK, TFT_WHITE);
236 void TFTScreen::updateSubBindingPage()
238 tft.fillScreen(TFT_WHITE);
240 displayFontCenter(SUB_PAGE_BINDING_WORD_START_X, SCREEN_X, SUB_PAGE_BINDING_WORD_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
241 "BINDING", TFT_BLACK, TFT_WHITE);
243 updatecallback(USER_UPDATE_TYPE_BINDING);
245 current_screen_status = SCREEN_STATUS_BINDING;
248 void TFTScreen::doRateValueSelect(int action)
250 nextIndex(current_rate_index, action, RATE_MAX_NUMBER);
251 displayFontCenter(SUB_PAGE_VALUE_START_X, SCREEN_X, SUB_PAGE_VALUE_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
252 rate_string[current_rate_index], TFT_BLACK, TFT_WHITE);
255 void TFTScreen::doPowerValueSelect(int action)
257 nextIndex(current_power_index, action, MinPower, MaxPower+1);
258 displayFontCenter(SUB_PAGE_VALUE_START_X, SCREEN_X, SUB_PAGE_VALUE_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
259 power_string[current_power_index], TFT_BLACK, TFT_WHITE);
262 void TFTScreen::doRatioValueSelect(int action)
264 nextIndex(current_ratio_index, action, RATIO_MAX_NUMBER);
265 displayFontCenter(SUB_PAGE_VALUE_START_X, SCREEN_X, SUB_PAGE_VALUE_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
266 ratio_string[current_ratio_index], TFT_BLACK, TFT_WHITE);
270 void TFTScreen::doPowerSavingValueSelect(int action)
272 nextIndex(current_powersaving_index, action, POWERSAVING_MAX_NUMBER);
273 displayFontCenter(SUB_PAGE_VALUE_START_X, SCREEN_X, SUB_PAGE_VALUE_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
274 powersaving_string[current_powersaving_index], TFT_BLACK, TFT_WHITE);
277 void TFTScreen::doSmartFanValueSelect(int action)
279 nextIndex(current_smartfan_index, action, SMARTFAN_MAX_NUMBER);
280 displayFontCenter(SUB_PAGE_VALUE_START_X, SCREEN_X, SUB_PAGE_VALUE_START_Y, SCREEN_LARGE_FONT_SIZE, SCREEN_LARGE_FONT,
281 smartfan_string[current_smartfan_index], TFT_BLACK, TFT_WHITE);
284 void TFTScreen::doParamUpdate(uint8_t rate_index, uint8_t power_index, uint8_t ratio_index, uint8_t motion_index, uint8_t fan_index)
286 if(current_screen_status == SCREEN_STATUS_IDLE)
288 if(rate_index != current_rate_index)
290 current_rate_index = rate_index;
291 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_RATE_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
292 rate_string[current_rate_index], TFT_BLACK, TFT_WHITE);
295 if(power_index != current_power_index)
297 current_power_index = power_index;
298 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_POWER_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
299 power_string[current_power_index], TFT_BLACK, TFT_WHITE);
302 if(ratio_index != current_ratio_index)
304 current_ratio_index = ratio_index;
305 displayFontCenter(IDLE_PAGE_STAT_START_X, SCREEN_X, IDLE_PAGE_RATIO_START_Y, SCREEN_NORMAL_FONT_SIZE, SCREEN_NORMAL_FONT,
306 ratio_string[current_ratio_index], TFT_BLACK, TFT_WHITE);
309 else
311 current_rate_index = rate_index;
312 current_power_index = power_index;
313 current_ratio_index = ratio_index;
316 current_powersaving_index = motion_index;
317 current_smartfan_index = fan_index;
320 void TFTScreen::doTemperatureUpdate(uint8_t temperature)
322 if(current_screen_status == SCREEN_STATUS_IDLE && system_temperature != temperature)
324 char buffer[20];
325 strncpy(buffer, version, 6);
326 sprintf(buffer+6, " %02d", temperature);
327 displayFontCenterWithCelsius(0, SCREEN_X/2, SCREEN_LARGE_ICON_SIZE + (SCREEN_Y - SCREEN_LARGE_ICON_SIZE - SCREEN_SMALL_FONT_SIZE)/2,
328 SCREEN_SMALL_FONT_SIZE, SCREEN_SMALL_FONT,
329 String(buffer), TFT_WHITE, COLOR_ELRS_BANNER_BACKGROUND);
331 system_temperature = temperature;
334 void TFTScreen::displayFontCenterWithCelsius(uint32_t font_start_x, uint32_t font_end_x, uint32_t font_start_y,
335 int font_size, int font_type, String font_string,
336 uint16_t fgColor, uint16_t bgColor)
338 tft.fillRect(font_start_x, font_start_y, font_end_x - font_start_x, font_size, bgColor);
340 int start_pos = font_start_x + (font_end_x - font_start_x - tft.textWidth(font_string, font_type) - font_size)/2;
342 tft.setCursor(start_pos, font_start_y, font_type);
343 tft.setTextColor(fgColor, bgColor);
344 tft.print(font_string);
346 int celsius_start_pos = start_pos + tft.textWidth(font_string, font_type);
347 if(font_size == SCREEN_SMALL_FONT_SIZE)
349 tft.pushImage(celsius_start_pos, font_start_y, font_size/2, font_size, Celsius4x8);
352 int char_c_pos = celsius_start_pos + font_size/2;
353 tft.setCursor(char_c_pos, font_start_y, font_type);
354 tft.print("C");
357 void TFTScreen::displayFontCenter(uint32_t font_start_x, uint32_t font_end_x, uint32_t font_start_y,
358 int font_size, int font_type, String font_string,
359 uint16_t fgColor, uint16_t bgColor)
361 tft.fillRect(font_start_x, font_start_y, font_end_x - font_start_x, font_size, bgColor);
363 int start_pos = font_start_x + (font_end_x - font_start_x - tft.textWidth(font_string, font_type))/2;
364 tft.setCursor(start_pos, font_start_y, font_type);
366 tft.setTextColor(fgColor, bgColor);
367 tft.print(font_string);
371 void TFTScreen::doScreenBackLight(int state)
373 #ifdef TFT_BL
374 digitalWrite(TFT_BL, state);
375 #endif
377 #endif