5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 uint8_t currentSpeakerVolume
= 255;
24 uint8_t requiredSpeakerVolume
= 255;
25 uint8_t mainRequestFlags
= 0;
28 void onUSBConnectMenu(const char *result
)
30 if (result
== STR_USB_MASS_STORAGE
) {
31 setSelectedUsbMode(USB_MASS_STORAGE_MODE
);
33 else if (result
== STR_USB_JOYSTICK
) {
34 setSelectedUsbMode(USB_JOYSTICK_MODE
);
36 else if (result
== STR_USB_SERIAL
) {
37 setSelectedUsbMode(USB_SERIAL_MODE
);
42 void handleUsbConnection()
44 #if defined(STM32) && !defined(SIMU)
45 if (!usbStarted() && usbPlugged() && !(getSelectedUsbMode() == USB_UNSELECTED_MODE
)) {
47 if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE
) {
52 if (!usbStarted() && usbPlugged() && getSelectedUsbMode() == USB_UNSELECTED_MODE
) {
53 if((g_eeGeneral
.USBMode
== USB_UNSELECTED_MODE
) && (popupMenuNoItems
== 0)) {
54 POPUP_MENU_ADD_ITEM(STR_USB_JOYSTICK
);
55 POPUP_MENU_ADD_ITEM(STR_USB_MASS_STORAGE
);
57 POPUP_MENU_ADD_ITEM(STR_USB_SERIAL
);
59 POPUP_MENU_START(onUSBConnectMenu
);
61 if (g_eeGeneral
.USBMode
!= USB_UNSELECTED_MODE
) {
62 setSelectedUsbMode(g_eeGeneral
.USBMode
);
65 if (usbStarted() && !usbPlugged()) {
67 if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE
) {
71 setSelectedUsbMode(USB_UNSELECTED_MODE
);
74 #endif // defined(STM32) && !defined(SIMU)
77 void checkSpeakerVolume()
79 if (currentSpeakerVolume
!= requiredSpeakerVolume
) {
80 currentSpeakerVolume
= requiredSpeakerVolume
;
81 #if !defined(SOFTWARE_VOLUME)
82 setScaledVolume(currentSpeakerVolume
);
91 if (eepromIsWriting())
93 else if (TIME_TO_WRITE())
100 #if defined(RAMBACKUP)
101 if (TIME_TO_RAMBACKUP()) {
103 rambackupDirtyMsk
= 0;
106 if (TIME_TO_WRITE()) {
112 #define BAT_AVG_SAMPLES 8
114 void checkBatteryAlarms()
116 // TRACE("checkBatteryAlarms()");
117 if (IS_TXBATT_WARNING() && g_vbat100mV
>50) {
118 AUDIO_TX_BATTERY_LOW();
119 // TRACE("checkBatteryAlarms(): battery low");
121 #if defined(PCBSKY9X)
122 else if (g_eeGeneral
.temperatureWarn
&& getTemperature() >= g_eeGeneral
.temperatureWarn
) {
123 AUDIO_TX_TEMP_HIGH();
125 else if (g_eeGeneral
.mAhWarn
&& (g_eeGeneral
.mAhUsed
+ Current_used
* (488 + g_eeGeneral
.txCurrentCalibration
)/8192/36) / 500 >= g_eeGeneral
.mAhWarn
) { // TODO move calculation into board file
133 static uint32_t batSum
;
134 static uint8_t sampleCount
;
135 // filter battery voltage by averaging it
136 if (g_vbat100mV
== 0) {
137 g_vbat100mV
= (getBatteryVoltage() + 5) / 10;
142 batSum
+= getBatteryVoltage();
143 // TRACE("checkBattery(): sampled = %d", getBatteryVoltage());
144 if (++sampleCount
>= BAT_AVG_SAMPLES
) {
145 g_vbat100mV
= (batSum
+ BAT_AVG_SAMPLES
* 5 ) / (BAT_AVG_SAMPLES
* 10);
148 // TRACE("checkBattery(): g_vbat100mV = %d", g_vbat100mV);
153 void periodicTick_1s()
158 void periodicTick_10s()
160 checkBatteryAlarms();
162 checkLuaMemoryUsage();
168 static uint8_t count10s
;
169 static uint32_t lastTime
;
170 if ( (get_tmr10ms() - lastTime
) >= 100 ) {
173 if (++count10s
>= 10) {
180 #if defined(GUI) && defined(COLORLCD)
181 void guiMain(event_t evt
)
183 bool refreshNeeded
= false;
186 uint32_t t0
= get_tmr10ms();
187 static uint32_t lastLuaTime
= 0;
188 uint16_t interval
= (lastLuaTime
== 0 ? 0 : (t0
- lastLuaTime
));
190 if (interval
> maxLuaInterval
) {
191 maxLuaInterval
= interval
;
194 // run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running)
195 DEBUG_TIMER_START(debugTimerLuaBg
);
196 luaTask(0, RUN_MIX_SCRIPT
| RUN_FUNC_SCRIPT
| RUN_TELEM_BG_SCRIPT
, false);
197 DEBUG_TIMER_STOP(debugTimerLuaBg
);
198 // wait for LCD DMA to finish before continuing, because code from this point
199 // is allowed to change the contents of LCD buffer
201 // WARNING: make sure no code above this line does any change to the LCD display buffer!
203 DEBUG_TIMER_START(debugTimerLcdRefreshWait
);
205 DEBUG_TIMER_STOP(debugTimerLcdRefreshWait
);
207 // draw LCD from menus or from Lua script
208 // run Lua scripts that use LCD
210 DEBUG_TIMER_START(debugTimerLuaFg
);
211 refreshNeeded
= luaTask(evt
, RUN_STNDAL_SCRIPT
, true);
212 if (!refreshNeeded
) {
213 refreshNeeded
= luaTask(evt
, RUN_TELEM_FG_SCRIPT
, true);
215 DEBUG_TIMER_STOP(debugTimerLuaFg
);
217 t0
= get_tmr10ms() - t0
;
218 if (t0
> maxLuaDuration
) {
222 lcdRefreshWait(); // WARNING: make sure no code above this line does any change to the LCD display buffer!
225 if (!refreshNeeded
) {
226 DEBUG_TIMER_START(debugTimerMenus
);
228 // normal GUI from menus
229 const char * warn
= warningText
;
230 uint8_t menu
= popupMenuNoItems
;
232 static bool popupDisplayed
= false;
234 if (popupDisplayed
== false) {
235 menuHandlers
[menuLevel
](EVT_REFRESH
);
236 lcdDrawBlackOverlay();
237 TIME_MEASURE_START(storebackup
);
238 lcdStoreBackupBuffer();
239 TIME_MEASURE_STOP(storebackup
);
241 if (popupDisplayed
== false || evt
) {
242 popupDisplayed
= lcdRestoreBackupBuffer();
243 if (warn
) DISPLAY_WARNING(evt
);
245 const char * result
= runPopupMenu(evt
);
247 popupMenuHandler(result
);
248 if (menuEvent
== 0) {
254 refreshNeeded
= true;
258 if (popupDisplayed
) {
262 popupDisplayed
= false;
264 DEBUG_TIMER_START(debugTimerMenuHandlers
);
265 refreshNeeded
= menuHandlers
[menuLevel
](evt
);
266 DEBUG_TIMER_STOP(debugTimerMenuHandlers
);
269 if (menuEvent
== EVT_ENTRY
) {
270 menuVerticalPosition
= 0;
271 menuHorizontalPosition
= 0;
275 else if (menuEvent
== EVT_ENTRY_UP
) {
276 menuVerticalPosition
= menuVerticalPositions
[menuLevel
];
277 menuHorizontalPosition
= 0;
285 DEBUG_TIMER_STOP(debugTimerMenus
);
289 DEBUG_TIMER_START(debugTimerLcdRefresh
);
291 DEBUG_TIMER_STOP(debugTimerLcdRefresh
);
296 void handleGui(event_t event
) {
297 // if Lua standalone, run it and don't clear the screen (Lua will do it)
298 // else if Lua telemetry view, run it and don't clear the screen
299 // else clear scren and show normal menus
301 if (luaTask(event
, RUN_STNDAL_SCRIPT
, true)) {
302 // standalone script is active
304 else if (luaTask(event
, RUN_TELEM_FG_SCRIPT
, true)) {
305 // the telemetry screen is active
306 // prevent events from keys MENU, UP, DOWN, ENT(short) and EXIT(short) from reaching the normal menus,
307 // so Lua telemetry script can fully use them
309 uint8_t key
= EVT_KEY_MASK(event
);
310 // no need to filter out MENU and ENT(short), because they are not used by menuViewTelemetryFrsky()
311 if (key
== KEY_PLUS
|| key
== KEY_MINUS
|| (!IS_KEY_LONG(event
) && key
== KEY_EXIT
)) {
312 // TRACE("Telemetry script event 0x%02x killed", event);
316 menuHandlers
[menuLevel
](event
);
317 // todo drawStatusLine(); here???
323 menuHandlers
[menuLevel
](event
);
328 bool inPopupMenu
= false;
330 void guiMain(event_t evt
)
333 // TODO better lua stopwatch
334 uint32_t t0
= get_tmr10ms();
335 static uint32_t lastLuaTime
= 0;
336 uint16_t interval
= (lastLuaTime
== 0 ? 0 : (t0
- lastLuaTime
));
338 if (interval
> maxLuaInterval
) {
339 maxLuaInterval
= interval
;
342 // run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running)
343 luaTask(0, RUN_MIX_SCRIPT
| RUN_FUNC_SCRIPT
| RUN_TELEM_BG_SCRIPT
, false);
345 t0
= get_tmr10ms() - t0
;
346 if (t0
> maxLuaDuration
) {
349 #endif //#if defined(LUA)
351 // wait for LCD DMA to finish before continuing, because code from this point
352 // is allowed to change the contents of LCD buffer
354 // WARNING: make sure no code above this line does any change to the LCD display buffer!
359 // we have a popupMenuActive entry or exit event
360 menuVerticalPosition
= (menuEvent
== EVT_ENTRY_UP
) ? menuVerticalPositions
[menuLevel
] : 0;
361 menuHorizontalPosition
= 0;
367 // show warning on top of the normal menus
368 handleGui(0); // suppress events, they are handled by the warning
369 DISPLAY_WARNING(evt
);
371 else if (popupMenuNoItems
> 0) {
372 // popup menu is active display it on top of normal menus
373 handleGui(0); // suppress events, they are handled by the popup
375 TRACE("Popup Menu started");
378 const char * result
= runPopupMenu(evt
);
380 TRACE("popupMenuHandler(%s)", result
);
381 popupMenuHandler(result
);
387 TRACE("Popup Menu ended");
399 DEBUG_TIMER_START(debugTimerPerMain1
);
400 #if defined(PCBSKY9X) && !defined(REVA)
403 checkSpeakerVolume();
406 handleUsbConnection();
407 checkTrainerSettings();
409 DEBUG_TIMER_STOP(debugTimerPerMain1
);
411 if (mainRequestFlags
& (1 << REQUEST_FLIGHT_RESET
)) {
412 TRACE("Executing requested Flight Reset");
414 mainRequestFlags
&= ~(1 << REQUEST_FLIGHT_RESET
);
417 event_t evt
= getEvent(false);
418 if (evt
&& (g_eeGeneral
.backlightMode
& e_backlight_mode_keys
)) {
419 // on keypress turn the light on
422 doLoopCommonActions();
423 #if defined(NAVIGATION_STICKS)
424 uint8_t sticks_evt
= getSticksNavigationEvent();
430 #if defined(RAMBACKUP)
431 if (unexpectedShutdown
) {
432 drawFatalErrorScreen(STR_EMERGENCY_MODE
);
438 static bool sdcard_present_before
= SD_CARD_PRESENT();
439 bool sdcard_present_now
= SD_CARD_PRESENT();
440 if (sdcard_present_now
&& !sdcard_present_before
) {
443 sdcard_present_before
= sdcard_present_now
;
447 // In case the SD card is removed during the session
448 if (!SD_CARD_PRESENT() && !unexpectedShutdown
) {
449 drawFatalErrorScreen(STR_NO_SDCARD
);
455 if (usbPlugged() && getSelectedUsbMode() == USB_MASS_STORAGE_MODE
) {
456 // disable access to menus
465 DEBUG_TIMER_START(debugTimerGuiMain
);
467 DEBUG_TIMER_STOP(debugTimerGuiMain
);
470 #if defined(PCBTARANIS)
471 if (mainRequestFlags
& (1 << REQUEST_SCREENSHOT
)) {
473 mainRequestFlags
&= ~(1 << REQUEST_SCREENSHOT
);
477 #if defined(PCBX9E) && !defined(SIMU)
478 toplcdRefreshStart();
479 setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER
+g_model
.toplcdTimer
));
480 setTopSecondTimer(g_eeGeneral
.globalTimer
+ sessionTimer
);
481 setTopRssi(TELEMETRY_RSSI());
482 setTopBatteryValue(g_vbat100mV
);
483 setTopBatteryState(GET_TXBATT_BARS(), IS_TXBATT_WARNING());
487 #if defined(INTERNAL_GPS)