Merge pull request #1269 from pkendall64/crsf-max-output
[ExpressLRS.git] / src / lib / SCREEN / OLED / oledscreen.cpp
blob69d96d15960d911ef932445360643ff704697528
1 /*
2 * This file is part of the ExpressLRS distribution (https://github.com/ExpressLRS/ExpressLRS).
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #if defined(USE_OLED_SPI) || defined(USE_OLED_SPI_SMALL) || defined(USE_OLED_I2C) // This code will not be used if the hardware does not have a OLED display. Maybe a better way to blacklist it in platformio.ini?
18 // Default header files for Express LRS
19 #include "targets.h"
20 #include "options.h"
22 // OLED specific header files.
23 #include "oledscreen.h"
24 #include <U8g2lib.h> // Needed for the OLED drivers, this is a arduino package. It is maintained by platformIO
25 #include "XBMStrings.h" // Contains all the ELRS logos and animations for the UI
27 // Used for the the max power settings
28 #include "POWERMGNT.h"
30 #ifdef OLED_REVERSED
31 #define OLED_ROTATION U8G2_R2
32 #else
33 #define OLED_ROTATION U8G2_R0
34 #endif
36 #ifdef USE_OLED_SPI_SMALL
37 U8G2_SSD1306_128X32_UNIVISION_F_4W_SW_SPI u8g2(OLED_ROTATION, GPIO_PIN_OLED_SCK, GPIO_PIN_OLED_MOSI, GPIO_PIN_OLED_CS, GPIO_PIN_OLED_DC, GPIO_PIN_OLED_RST);
38 #endif
40 #ifdef USE_OLED_SPI
41 U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(OLED_ROTATION, GPIO_PIN_OLED_SCK, GPIO_PIN_OLED_MOSI, GPIO_PIN_OLED_CS, GPIO_PIN_OLED_DC, GPIO_PIN_OLED_RST);
42 #endif
44 #ifdef USE_OLED_I2C
45 U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(OLED_ROTATION, GPIO_PIN_OLED_RST, GPIO_PIN_OLED_SCK, GPIO_PIN_OLED_SDA);
46 #endif
48 #ifdef TARGET_TX_GHOST
49 /**
50 * helper function is used to draw xbmp on the OLED.
51 * x = x position of the image
52 * y = y position of the image
53 * size = demensions of the box size x size, this only works for square images 1:1
54 * image = XBM character string
56 #ifndef TARGET_TX_GHOST_LITE
57 static void helper(int x, int y, int size, const unsigned char * image){
58 u8g2.clearBuffer();
59 u8g2.drawXBMP(x, y, size, size, image);
60 u8g2.sendBuffer();
62 #endif
64 /**
65 * ghostChase will only be called for ghost TX hardware.
67 static void ghostChase(){
68 // Using i < 16 and (i*4) to get 64 total pixels. Change to i < 32 (i*2) to slow animation.
69 for(int i = 0; i < 20; i++){
70 u8g2.clearBuffer();
71 #ifndef TARGET_TX_GHOST_LITE
72 u8g2.drawXBMP((26 + i), 16, 32, 32, ghost);
73 u8g2.drawXBMP((-31 + (i*4)), 16, 32, 32, elrs32);
74 #else
75 u8g2.drawXBMP((26 + i), 0, 32, 32, ghost);
76 u8g2.drawXBMP((-31 + (i*4)), 0, 32, 32, elrs32);
77 #endif
78 u8g2.sendBuffer();
80 /**
81 * Animation for the ghost logo expanding in the center of the screen.
82 * helper function just draw's the XBM strings.
84 #ifndef TARGET_TX_GHOST_LITE
85 helper(38,12,40,elrs40);
86 helper(36,8,48,elrs48);
87 helper(34,4,56,elrs56);
88 helper(32,0,64,elrs64);
89 #endif
91 #endif
93 /**
94 * Displays the ExpressLRS logo
96 * @param values none
97 * @return void
99 static void displayLogo()
101 u8g2.begin();
102 u8g2.clearBuffer();
104 #ifdef TARGET_TX_GHOST
105 ghostChase();
106 #else
107 #ifdef USE_OLED_SPI_SMALL
108 u8g2.drawXBM(48, 0, 32, 32, elrs32);
109 #else
110 u8g2.drawXBM(32, 0, 64, 64, elrs64);
111 #endif
112 #endif
113 u8g2.sendBuffer();
117 static void displayFontCenter(const char * info)
119 u8g2.clearBuffer();
120 u8g2.setFont(u8g2_font_profont10_mr);
121 #ifdef USE_OLED_SPI_SMALL
122 u8g2.drawStr(32, 32, info);
123 #else
124 u8g2.drawStr(64, 64, info);
125 #endif
126 u8g2.sendBuffer();
129 void OLEDScreen::init(bool reboot)
131 u8g2.begin();
133 displayLogo();
136 current_screen_status = SCREEN_STATUS_INIT;
138 current_rate_index = 0;
139 current_power_index = 0;
140 current_ratio_index = 0;
142 current_page_index = PAGE_MAIN_MENU_INDEX;
144 main_menu_page_index = MAIN_MENU_RATE_INDEX;
146 u8g2.clearBuffer();
149 void helperDrawImage64(int menu)
151 // Adjust these to move them around on the screen
152 int x_pos = 65;
153 int y_pos = 5;
155 switch(menu){
156 case 0:
157 u8g2.drawXBM(x_pos, y_pos, 64, 44, rate_img64);
158 break;
159 case 1:
160 u8g2.drawXBM(x_pos, y_pos, 50, 50, power_img64);
161 break;
162 case 2:
163 u8g2.drawXBM(x_pos, y_pos, 64, 64, ratio_img64);
164 break;
165 case 3:
166 u8g2.drawXBM(x_pos, y_pos, 64, 64, powersaving_img64);
167 break;
168 case 4:
169 u8g2.drawXBM(x_pos, y_pos, 64, 64, fan_img64);
170 break;
171 case 5:
172 u8g2.drawXBM(x_pos, y_pos, 64, 64, bind_img64);
173 break;
174 case 6:
175 u8g2.drawXBM(x_pos, y_pos, 48, 44, wifi_img64);
176 break;
180 void helperDrawImage32(int menu)
182 // Adjust these to move them around on the screen
183 int x_pos = 65;
184 int y_pos = 5;
186 switch(menu){
187 case 0:
188 u8g2.drawXBM(x_pos, y_pos, 32, 22, rate_img32);
189 break;
190 case 1:
191 u8g2.drawXBM(x_pos, y_pos, 25, 25, power_img32);
192 break;
193 case 2:
194 u8g2.drawXBM(x_pos, y_pos, 32, 32, ratio_img32);
195 break;
196 case 3:
197 u8g2.drawXBM(x_pos, y_pos, 32, 32, powersaving_img32);
198 break;
199 case 4:
200 u8g2.drawXBM(x_pos, y_pos, 32, 32, fan_img32);
201 break;
202 case 5:
203 u8g2.drawXBM(x_pos, y_pos, 32, 32, bind_img32);
204 break;
205 case 6:
206 u8g2.drawXBM(x_pos, y_pos, 24, 22, wifi_img32);
207 break;
212 void OLEDScreen::displayMainScreen(){
213 u8g2.clearBuffer();
215 #ifdef USE_OLED_SPI_SMALL
216 u8g2.setFont(u8g2_font_t0_15_mr);
217 u8g2.drawStr(0,15, &(rate_string[current_rate_index])[0]);
218 u8g2.drawStr(70,15 ,&(ratio_string[current_ratio_index])[0]);
219 u8g2.drawStr(0,32, &(power_string[current_power_index])[0]);
220 u8g2.drawStr(70,32, "Test");
221 #else
222 u8g2.setFont(u8g2_font_t0_15_mr);
223 u8g2.drawStr(0,13, "ExpressLRS");
224 u8g2.drawStr(0,45, &(rate_string[current_rate_index])[0]);
225 u8g2.drawStr(70,45 , &(ratio_string[current_ratio_index])[0]);
226 u8g2.drawStr(0,60, &(power_string[current_power_index])[0]);
227 u8g2.setFont(u8g2_font_profont10_mr);
228 u8g2.drawStr(70,56, "TLM");
229 u8g2.drawStr(0,27, "Ver: ");
230 char buffer[7];
231 strncpy(buffer, version, 6);
232 buffer[6] = 0;
233 u8g2.drawStr(38,27, buffer);
234 #endif
235 u8g2.sendBuffer();
238 void OLEDScreen::idleScreen()
240 displayMainScreen();
242 current_screen_status = SCREEN_STATUS_IDLE;
245 void OLEDScreen::updateMainMenuPage()
247 u8g2.clearBuffer();
248 #ifdef USE_OLED_SPI_SMALL
249 u8g2.setFont(u8g2_font_t0_17_mr);
250 u8g2.drawStr(0,15, &(main_menu_line_1[main_menu_page_index - 1])[0]);
251 u8g2.drawStr(0,32, &(main_menu_line_2[main_menu_page_index - 1])[0]);
252 helperDrawImage32(main_menu_page_index - 1 );
253 #else
254 u8g2.setFont(u8g2_font_t0_17_mr);
255 u8g2.drawStr(0,20, &(main_menu_line_1[main_menu_page_index - 1])[0]);
256 u8g2.drawStr(0,50, &(main_menu_line_2[main_menu_page_index - 1])[0]);
257 helperDrawImage64(main_menu_page_index - 1);
258 #endif
259 u8g2.sendBuffer();
262 void OLEDScreen::updateSubFunctionPage()
264 doValueSelection(USER_ACTION_NONE);
267 void OLEDScreen::updateSubWIFIModePage()
269 u8g2.clearBuffer();
271 // TODO: Add a fancy wifi symbol like the cool TFT peeps
273 #if defined(HOME_WIFI_SSID) && defined(HOME_WIFI_PASSWORD)
274 #ifdef USE_OLED_SPI_SMALL
275 u8g2.setFont(u8g2_font_t0_17_mr);
276 u8g2.drawStr(0,15, "open http://");
277 u8g2.drawStr(70,15, (String(wifi_hostname)+".local").c_str());
278 u8g2.drawStr(0,32, "by browser");
279 #else
280 u8g2.setFont(u8g2_font_t0_17_mr);
281 u8g2.drawStr(0,13, "open http://");
282 u8g2.drawStr(0,33, (String(wifi_hostname)+".local").c_str());
283 u8g2.drawStr(0,63, "by browser");
284 #endif
285 #else
286 #ifdef USE_OLED_SPI_SMALL
287 u8g2.setFont(u8g2_font_t0_17_mr);
288 u8g2.drawStr(0,15, wifi_ap_ssid);
289 u8g2.drawStr(70,15, wifi_ap_password);
290 u8g2.drawStr(0,32, wifi_ap_address);
291 #else
292 u8g2.setFont(u8g2_font_t0_17_mr);
293 u8g2.drawStr(0,13, wifi_ap_ssid);
294 u8g2.drawStr(0,33, wifi_ap_password);
295 u8g2.drawStr(0,63, wifi_ap_address);
296 #endif
297 #endif
298 u8g2.sendBuffer();
299 updatecallback(USER_UPDATE_TYPE_WIFI);
302 void OLEDScreen::updateSubBindConfirmPage()
304 // TODO: Put bind image?
305 u8g2.clearBuffer();
307 #ifdef USE_OLED_SPI_SMALL
308 u8g2.setFont(u8g2_font_t0_17_mr);
309 u8g2.drawStr(0,15, "PRESS TO");
310 u8g2.drawStr(70,15 , "SEND BIND");
311 u8g2.drawStr(0,32, "REQUEST");
312 #else
313 u8g2.setFont(u8g2_font_t0_17_mr);
314 u8g2.drawStr(0,29, "PRESS TO SEND");
315 u8g2.drawStr(0,59, "BIND REQUEST");
316 #endif
317 u8g2.sendBuffer();
321 void OLEDScreen::updateSubBindingPage()
323 // TODO: Put bind image?
324 u8g2.clearBuffer();
326 #ifdef USE_OLED_SPI_SMALL
327 u8g2.setFont(u8g2_font_t0_17_mr);
328 u8g2.drawStr(0,15, "BINDING");
329 #else
330 u8g2.setFont(u8g2_font_t0_17_mr);
331 u8g2.drawStr(0,29, "BINDING");
332 #endif
333 u8g2.sendBuffer();
336 updatecallback(USER_UPDATE_TYPE_BINDING);
338 current_screen_status = SCREEN_STATUS_BINDING;
341 void OLEDScreen::doRateValueSelect(int action)
343 nextIndex(current_rate_index, action, RATE_MAX_NUMBER);
345 // TODO: Put bind image?
346 u8g2.clearBuffer();
347 #ifdef USE_OLED_SPI_SMALL
348 u8g2.setFont(u8g2_font_t0_16_mr);
349 u8g2.drawStr(0,15, &(rate_string[current_rate_index])[0]);
350 u8g2.setFont(u8g2_font_profont10_mr);
351 u8g2.drawStr(0,60, "PRESS TO CONFIRM");
352 helperDrawImage32(IMAGE_RATE);
353 #else
354 u8g2.setFont(u8g2_font_t0_16_mr);
355 u8g2.drawStr(0,20, &(rate_string[current_rate_index])[0]);
356 u8g2.setFont(u8g2_font_profont10_mr);
357 u8g2.drawStr(0,44, "PRESS TO");
358 u8g2.drawStr(0,56, "CONFIRM");
359 helperDrawImage64(IMAGE_RATE);
360 #endif
361 u8g2.sendBuffer();
364 void OLEDScreen::doPowerValueSelect(int action)
366 nextIndex(current_power_index, action, MinPower, MaxPower+1);
368 u8g2.clearBuffer();
369 #ifdef USE_OLED_SPI_SMALL
370 u8g2.setFont(u8g2_font_t0_16_mr);
371 u8g2.drawStr(0,15, &(power_string[current_power_index])[0]);
372 u8g2.setFont(u8g2_font_courR08_tr);
373 u8g2.drawStr(0,60, "PRESS TO CONFIRM");
374 helperDrawImage32(IMAGE_POWER);
375 #else
376 u8g2.setFont(u8g2_font_t0_16_mr);
377 u8g2.drawStr(0,20, &(power_string[current_power_index])[0]);
378 u8g2.setFont(u8g2_font_profont10_mr);
379 u8g2.drawStr(0,44, "PRESS TO");
380 u8g2.drawStr(0,56, "CONFIRM");
381 helperDrawImage64(IMAGE_POWER);
382 #endif
383 u8g2.sendBuffer();
386 void OLEDScreen::doRatioValueSelect(int action)
389 nextIndex(current_ratio_index, action, RATIO_MAX_NUMBER);
391 u8g2.clearBuffer();
392 #ifdef USE_OLED_SPI_SMALL
393 u8g2.setFont(u8g2_font_t0_16_mr);
394 u8g2.drawStr(0,15, &(ratio_string[current_ratio_index])[0]);
395 u8g2.setFont(u8g2_font_profont10_mr);
396 u8g2.drawStr(0,60, "PRESS TO CONFIRM");
397 helperDrawImage32(IMAGE_RATIO);
398 #else
399 u8g2.setFont(u8g2_font_t0_16_mr);
400 u8g2.drawStr(0,20, &(ratio_string[current_ratio_index])[0]);
401 u8g2.setFont(u8g2_font_profont10_mr);
402 u8g2.drawStr(0,44, "PRESS TO");
403 u8g2.drawStr(0,56, "CONFIRM");
404 helperDrawImage64(IMAGE_RATIO);
405 #endif
406 u8g2.sendBuffer();
409 void OLEDScreen::doPowerSavingValueSelect(int action)
411 nextIndex(current_smartfan_index, action, SMARTFAN_MAX_NUMBER);
412 // TODO display the value
415 void OLEDScreen::doSmartFanValueSelect(int action)
417 nextIndex(current_powersaving_index, action, POWERSAVING_MAX_NUMBER);
418 // TODO display the value
421 void OLEDScreen::doParamUpdate(uint8_t rate_index, uint8_t power_index, uint8_t ratio_index, uint8_t motion_index, uint8_t fan_index)
423 if(current_screen_status == SCREEN_STATUS_IDLE)
425 if(rate_index != current_rate_index)
427 current_rate_index = rate_index;
428 displayMainScreen();
431 if(power_index != current_power_index)
433 current_power_index = power_index;
434 displayMainScreen();
437 if(ratio_index != current_ratio_index)
439 current_ratio_index = ratio_index;
440 displayMainScreen();
443 else
445 current_rate_index = rate_index;
446 current_power_index = power_index;
447 current_ratio_index = ratio_index;
450 current_powersaving_index = motion_index;
451 current_smartfan_index = fan_index;
454 void OLEDScreen::doTemperatureUpdate(uint8_t temperature)
456 system_temperature = temperature;
457 if(current_screen_status == SCREEN_STATUS_IDLE)
459 char buffer[20];
460 strncpy(buffer, version, 6);
461 sprintf(buffer+6, " %02d", system_temperature);
462 // TODO
463 // displayFontCenterWithCelsius(0, SCREEN_X/2, SCREEN_LARGE_ICON_SIZE + (SCREEN_Y - SCREEN_LARGE_ICON_SIZE - SCREEN_SMALL_FONT_SIZE)/2,
464 // SCREEN_SMALL_FONT_SIZE, SCREEN_SMALL_FONT,
465 // String(buffer), TFT_WHITE, COLOR_ELRS_BANNER_BACKGROUND);
469 void OLEDScreen::doScreenBackLight(int state)
471 #ifdef GPIO_PIN_OLED_BL
472 digitalWrite(GPIO_PIN_OLED_BL, state);
473 #endif
476 #endif