40 #include "actuatorsettings.h"
41 #include "flightstatus.h"
42 #include "flightbatterystate.h"
43 #include "flightbatterysettings.h"
44 #include "homelocation.h"
45 #include "manualcontrolcommand.h"
46 #include "manualcontrolsettings.h"
47 #include "rgbledsettings.h"
48 #include "stabilizationsettings.h"
49 #include "stateestimation.h"
51 #include "vtxsettings.h"
60 static const uint16_t
BAND_5G8_A_FREQS[VTXSETTINGS_BAND_5G8_A_FREQUENCY_MAXOPTVAL + 1] = {
61 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH15865] = 5865,
62 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH25845] = 5845,
63 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH35825] = 5825,
64 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH45805] = 5805,
65 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH55785] = 5785,
66 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH65765] = 5765,
67 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH75745] = 5745,
68 [VTXSETTINGS_BAND_5G8_A_FREQUENCY_CH85725] = 5725
71 static const uint16_t
BAND_5G8_B_FREQS[VTXSETTINGS_BAND_5G8_B_FREQUENCY_MAXOPTVAL + 1] = {
72 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH15733] = 5733,
73 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH25752] = 5752,
74 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH35771] = 5771,
75 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH45790] = 5790,
76 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH55809] = 5809,
77 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH65828] = 5828,
78 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH75847] = 5847,
79 [VTXSETTINGS_BAND_5G8_B_FREQUENCY_CH85866] = 5866
82 static const uint16_t
BAND_5G8_E_FREQS[VTXSETTINGS_BAND_5G8_E_FREQUENCY_MAXOPTVAL + 1] = {
83 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH15705] = 5705,
84 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH25685] = 5685,
85 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH35665] = 5665,
86 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH45645] = 5645,
87 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH55885] = 5885,
88 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH65905] = 5905,
89 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH75925] = 5925,
90 [VTXSETTINGS_BAND_5G8_E_FREQUENCY_CH85945] = 5945
93 static const uint16_t
AIRWAVE_FREQS[VTXSETTINGS_AIRWAVE_FREQUENCY_MAXOPTVAL + 1] = {
94 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH15740] = 5740,
95 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH25760] = 5760,
96 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH35780] = 5780,
97 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH45800] = 5800,
98 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH55820] = 5820,
99 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH65840] = 5840,
100 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH75860] = 5860,
101 [VTXSETTINGS_AIRWAVE_FREQUENCY_CH85880] = 5880
104 static const uint16_t
RACEBAND_FREQS[VTXSETTINGS_RACEBAND_FREQUENCY_MAXOPTVAL + 1] = {
105 [VTXSETTINGS_RACEBAND_FREQUENCY_CH15658] = 5658,
106 [VTXSETTINGS_RACEBAND_FREQUENCY_CH25695] = 5695,
107 [VTXSETTINGS_RACEBAND_FREQUENCY_CH35732] = 5732,
108 [VTXSETTINGS_RACEBAND_FREQUENCY_CH45769] = 5769,
109 [VTXSETTINGS_RACEBAND_FREQUENCY_CH55806] = 5806,
110 [VTXSETTINGS_RACEBAND_FREQUENCY_CH65843] = 5843,
111 [VTXSETTINGS_RACEBAND_FREQUENCY_CH75880] = 5880,
112 [VTXSETTINGS_RACEBAND_FREQUENCY_CH85917] = 5917
115 static const uint16_t
VTX_POWER[VTXSETTINGS_POWER_GLOBAL_MAXOPTVAL + 1] = {
116 [VTXSETTINGS_POWER_25] = 25,
117 [VTXSETTINGS_POWER_200] = 200,
118 [VTXSETTINGS_POWER_500] = 500,
119 [VTXSETTINGS_POWER_800] = 800,
123 enum menu_fsm_event {
133 enum menu_fsm_state {
136 #if defined(USE_STM32F4xx_BRAINFPVRE1)
139 FSM_STATE_MAIN_RGBLEDS,
140 FSM_STATE_MAIN_FILTER,
141 FSM_STATE_MAIN_FMODE,
142 FSM_STATE_MAIN_HOMELOC,
143 FSM_STATE_MAIN_PIDRATE,
144 FSM_STATE_MAIN_PIDATT,
145 FSM_STATE_MAIN_STICKLIMITS,
147 FSM_STATE_MAIN_STATS,
148 FSM_STATE_MAIN_BATTERY,
150 #if defined(USE_STM32F4xx_BRAINFPVRE1)
151 FSM_STATE_RE1_IR_PROTOCOL,
152 FSM_STATE_RE1_IR_IDILAP,
153 FSM_STATE_RE1_IR_IDTRACKMATE,
154 FSM_STATE_RE1_SAVEEXIT,
158 FSM_STATE_RGB_DEFAULTCOLOR,
159 FSM_STATE_RGB_RANGECOLOR_BASE,
160 FSM_STATE_RGB_RANGECOLOR_END,
161 FSM_STATE_RGB_SAVEEXIT,
164 FSM_STATE_FILTER_ATT,
165 FSM_STATE_FILTER_NAV,
166 FSM_STATE_FILTER_SAVEEXIT,
167 FSM_STATE_FILTER_EXIT,
175 FSM_STATE_FMODE_SAVEEXIT,
176 FSM_STATE_FMODE_EXIT,
178 FSM_STATE_HOMELOC_SET,
179 FSM_STATE_HOMELOC_EXIT,
181 FSM_STATE_PIDRATE_ROLLP,
182 FSM_STATE_PIDRATE_ROLLI,
183 FSM_STATE_PIDRATE_ROLLD,
184 FSM_STATE_PIDRATE_ROLLILIMIT,
185 FSM_STATE_PIDRATE_PITCHP,
186 FSM_STATE_PIDRATE_PITCHI,
187 FSM_STATE_PIDRATE_PITCHD,
188 FSM_STATE_PIDRATE_PITCHILIMIT,
189 FSM_STATE_PIDRATE_YAWP,
190 FSM_STATE_PIDRATE_YAWI,
191 FSM_STATE_PIDRATE_YAWD,
192 FSM_STATE_PIDRATE_YAWILIMIT,
193 FSM_STATE_PIDRATE_SAVEEXIT,
194 FSM_STATE_PIDRATE_EXIT,
196 FSM_STATE_PIDATT_ROLLP,
197 FSM_STATE_PIDATT_ROLLI,
198 FSM_STATE_PIDATT_ROLLILIMIT,
199 FSM_STATE_PIDATT_PITCHP,
200 FSM_STATE_PIDATT_PITCHI,
201 FSM_STATE_PIDATT_PITCHILIMIT,
202 FSM_STATE_PIDATT_YAWP,
203 FSM_STATE_PIDATT_YAWI,
204 FSM_STATE_PIDATT_YAWILIMIT,
205 FSM_STATE_PIDATT_SAVEEXIT,
206 FSM_STATE_PIDATT_EXIT,
208 FSM_STATE_STICKLIMITS_ROLLA,
209 FSM_STATE_STICKLIMITS_PITCHA,
210 FSM_STATE_STICKLIMITS_YAWA,
211 FSM_STATE_STICKLIMITS_ROLLR,
212 FSM_STATE_STICKLIMITS_PITCHR,
213 FSM_STATE_STICKLIMITS_YAWR,
214 FSM_STATE_STICKLIMITS_ROLLEXR,
215 FSM_STATE_STICKLIMITS_PITCHEXR,
216 FSM_STATE_STICKLIMITS_YAWEXR,
217 FSM_STATE_STICKLIMITS_ROLLEXH,
218 FSM_STATE_STICKLIMITS_PITCHEXH,
219 FSM_STATE_STICKLIMITS_YAWEXH,
220 FSM_STATE_STICKLIMITS_MOTORPOWER,
221 FSM_STATE_STICKLIMITS_CAMERATILT,
222 FSM_STATE_STICKLIMITS_SAVEEXIT,
223 FSM_STATE_STICKLIMITS_EXIT,
229 FSM_STATE_VTX_SAVEEXIT,
232 FSM_STATE_STATS_EXIT,
234 FSM_STATE_BATTERY_CAPACITY,
235 FSM_STATE_BATTERY_CELLCOUNT,
236 FSM_STATE_BATTERY_WARNING,
237 FSM_STATE_BATTERY_ALARM,
238 FSM_STATE_BATTERY_WARN_TIME,
239 FSM_STATE_BATTERY_ALARM_TIME,
240 FSM_STATE_BATTERY_SAVEEXIT,
241 FSM_STATE_BATTERY_EXIT,
247 #if defined(USE_STM32F4xx_BRAINFPVRE1)
248 static void brainre1_menu(
void);
249 #define FSM_STATE_TOP FSM_STATE_MAIN_RE1
251 #define FSM_STATE_TOP FSM_STATE_MAIN_RGBLEDS
255 struct menu_fsm_transition {
263 static bool held_long;
266 static void main_menu(
void);
267 static void rgbled_menu(
void);
268 static void filter_menu(
void);
269 static void flightmode_menu(
void);
270 static void homeloc_menu(
void);
271 static void pidrate_menu(
void);
272 static void pidatt_menu(
void);
273 static void sticklimits_menu(
void);
274 static void vtx_menu();
275 static void stats_menu(
void);
276 static void battery_menu(
void);
282 #if defined(USE_STM32F4xx_BRAINFPVRE1)
283 [FSM_STATE_MAIN_RE1] = {
284 .menu_fn = main_menu,
286 [FSM_EVENT_UP] = FSM_STATE_MAIN_BATTERY,
287 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_RGBLEDS,
288 [FSM_EVENT_RIGHT] = FSM_STATE_RE1_IR_PROTOCOL,
292 [FSM_STATE_MAIN_RGBLEDS] = {
293 .menu_fn = main_menu,
295 #if defined(USE_STM32F4xx_BRAINFPVRE1)
296 [FSM_EVENT_UP] = FSM_STATE_MAIN_RE1,
298 [FSM_EVENT_UP] = FSM_STATE_MAIN_BATTERY,
300 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_FILTER,
301 [FSM_EVENT_RIGHT] = FSM_STATE_RGB_DEFAULTCOLOR,
304 [FSM_STATE_MAIN_FILTER] = {
305 .menu_fn = main_menu,
307 [FSM_EVENT_UP] = FSM_STATE_MAIN_RGBLEDS,
308 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_FMODE,
309 [FSM_EVENT_RIGHT] = FSM_STATE_FILTER_ATT,
312 [FSM_STATE_MAIN_FMODE] = {
313 .menu_fn = main_menu,
315 [FSM_EVENT_UP] = FSM_STATE_MAIN_FILTER,
316 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_HOMELOC,
317 [FSM_EVENT_RIGHT] = FSM_STATE_FMODE_1,
320 [FSM_STATE_MAIN_HOMELOC] = {
321 .menu_fn = main_menu,
323 [FSM_EVENT_UP] = FSM_STATE_MAIN_FMODE,
324 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_PIDRATE,
325 [FSM_EVENT_RIGHT] = FSM_STATE_HOMELOC_SET,
328 [FSM_STATE_MAIN_PIDRATE] = {
329 .menu_fn = main_menu,
331 [FSM_EVENT_UP] = FSM_STATE_MAIN_HOMELOC,
332 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_PIDATT,
333 [FSM_EVENT_RIGHT] = FSM_STATE_PIDRATE_ROLLP,
336 [FSM_STATE_MAIN_PIDATT] = {
337 .menu_fn = main_menu,
339 [FSM_EVENT_UP] = FSM_STATE_MAIN_PIDRATE,
340 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_STICKLIMITS,
341 [FSM_EVENT_RIGHT] = FSM_STATE_PIDATT_ROLLP,
344 [FSM_STATE_MAIN_STICKLIMITS] = {
345 .menu_fn = main_menu,
347 [FSM_EVENT_UP] = FSM_STATE_MAIN_PIDATT,
348 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_VTX,
349 [FSM_EVENT_RIGHT] = FSM_STATE_STICKLIMITS_ROLLA,
352 [FSM_STATE_MAIN_VTX] = {
353 .menu_fn = main_menu,
355 [FSM_EVENT_UP] = FSM_STATE_MAIN_STICKLIMITS,
356 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_STATS,
357 [FSM_EVENT_RIGHT] = FSM_STATE_VTX_BAND,
360 [FSM_STATE_MAIN_STATS] = {
361 .menu_fn = main_menu,
363 [FSM_EVENT_UP] = FSM_STATE_MAIN_VTX,
364 [FSM_EVENT_DOWN] = FSM_STATE_MAIN_BATTERY,
365 [FSM_EVENT_RIGHT] = FSM_STATE_STATS_EXIT,
368 [FSM_STATE_MAIN_BATTERY] = {
369 .menu_fn = main_menu,
371 [FSM_EVENT_UP] = FSM_STATE_MAIN_STATS,
372 [FSM_EVENT_DOWN] = FSM_STATE_TOP,
373 [FSM_EVENT_RIGHT] = FSM_STATE_BATTERY_CAPACITY,
377 #if defined(USE_STM32F4xx_BRAINFPVRE1)
378 [FSM_STATE_RE1_IR_PROTOCOL] = {
379 .menu_fn = brainre1_menu,
381 [FSM_EVENT_UP] = FSM_STATE_RE1_EXIT,
382 [FSM_EVENT_DOWN] = FSM_STATE_RE1_IR_IDILAP,
385 [FSM_STATE_RE1_IR_IDILAP] = {
386 .menu_fn = brainre1_menu,
388 [FSM_EVENT_UP] = FSM_STATE_RE1_IR_PROTOCOL,
389 [FSM_EVENT_DOWN] = FSM_STATE_RE1_IR_IDTRACKMATE,
392 [FSM_STATE_RE1_IR_IDTRACKMATE] = {
393 .menu_fn = brainre1_menu,
395 [FSM_EVENT_UP] = FSM_STATE_RE1_IR_IDILAP,
396 [FSM_EVENT_DOWN] = FSM_STATE_RE1_SAVEEXIT,
399 [FSM_STATE_RE1_SAVEEXIT] = {
400 .menu_fn = brainre1_menu,
402 [FSM_EVENT_UP] = FSM_STATE_RE1_IR_IDTRACKMATE,
403 [FSM_EVENT_DOWN] = FSM_STATE_RE1_EXIT,
404 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_RE1,
407 [FSM_STATE_RE1_EXIT] = {
408 .menu_fn = brainre1_menu,
410 [FSM_EVENT_UP] = FSM_STATE_RE1_SAVEEXIT,
411 [FSM_EVENT_DOWN] = FSM_STATE_RE1_IR_PROTOCOL,
412 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_RE1,
417 [FSM_STATE_RGB_DEFAULTCOLOR] = {
418 .menu_fn = rgbled_menu,
420 [FSM_EVENT_UP] = FSM_STATE_RGB_EXIT,
421 [FSM_EVENT_DOWN] = FSM_STATE_RGB_RANGECOLOR_BASE,
424 [FSM_STATE_RGB_RANGECOLOR_BASE] = {
425 .menu_fn = rgbled_menu,
427 [FSM_EVENT_UP] = FSM_STATE_RGB_DEFAULTCOLOR,
428 [FSM_EVENT_DOWN] = FSM_STATE_RGB_RANGECOLOR_END,
431 [FSM_STATE_RGB_RANGECOLOR_END] = {
432 .menu_fn = rgbled_menu,
434 [FSM_EVENT_UP] = FSM_STATE_RGB_RANGECOLOR_BASE,
435 [FSM_EVENT_DOWN] = FSM_STATE_RGB_SAVEEXIT,
438 [FSM_STATE_RGB_SAVEEXIT] = {
439 .menu_fn = rgbled_menu,
441 [FSM_EVENT_UP] = FSM_STATE_RGB_RANGECOLOR_END,
442 [FSM_EVENT_DOWN] = FSM_STATE_RGB_EXIT,
443 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_RGBLEDS,
446 [FSM_STATE_RGB_EXIT] = {
447 .menu_fn = rgbled_menu,
449 [FSM_EVENT_UP] = FSM_STATE_RGB_SAVEEXIT,
450 [FSM_EVENT_DOWN] = FSM_STATE_RGB_DEFAULTCOLOR,
451 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_RGBLEDS,
455 [FSM_STATE_FILTER_ATT] = {
456 .menu_fn = filter_menu,
458 [FSM_EVENT_UP] = FSM_STATE_FILTER_EXIT,
459 [FSM_EVENT_DOWN] = FSM_STATE_FILTER_NAV,
462 [FSM_STATE_FILTER_NAV] = {
463 .menu_fn = filter_menu,
465 [FSM_EVENT_UP] = FSM_STATE_FILTER_ATT,
466 [FSM_EVENT_DOWN] = FSM_STATE_FILTER_SAVEEXIT,
469 [FSM_STATE_FILTER_SAVEEXIT] = {
470 .menu_fn = filter_menu,
472 [FSM_EVENT_UP] = FSM_STATE_FILTER_NAV,
473 [FSM_EVENT_DOWN] = FSM_STATE_FILTER_EXIT,
474 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_FILTER,
477 [FSM_STATE_FILTER_EXIT] = {
478 .menu_fn = filter_menu,
480 [FSM_EVENT_UP] = FSM_STATE_FILTER_SAVEEXIT,
481 [FSM_EVENT_DOWN] = FSM_STATE_FILTER_ATT,
482 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_FILTER,
486 [FSM_STATE_FMODE_1] = {
487 .menu_fn = flightmode_menu,
489 [FSM_EVENT_UP] = FSM_STATE_FMODE_SAVEEXIT,
490 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_2,
493 [FSM_STATE_FMODE_2] = {
494 .menu_fn = flightmode_menu,
496 [FSM_EVENT_UP] = FSM_STATE_FMODE_1,
497 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_3,
500 [FSM_STATE_FMODE_3] = {
501 .menu_fn = flightmode_menu,
503 [FSM_EVENT_UP] = FSM_STATE_FMODE_2,
504 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_4,
507 [FSM_STATE_FMODE_4] = {
508 .menu_fn = flightmode_menu,
510 [FSM_EVENT_UP] = FSM_STATE_FMODE_3,
511 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_5,
514 [FSM_STATE_FMODE_5] = {
515 .menu_fn = flightmode_menu,
517 [FSM_EVENT_UP] = FSM_STATE_FMODE_4,
518 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_6,
521 [FSM_STATE_FMODE_6] = {
522 .menu_fn = flightmode_menu,
524 [FSM_EVENT_UP] = FSM_STATE_FMODE_5,
525 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_SAVEEXIT,
528 [FSM_STATE_FMODE_SAVEEXIT] = {
529 .menu_fn = flightmode_menu,
531 [FSM_EVENT_UP] = FSM_STATE_FMODE_6,
532 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_EXIT,
533 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_FMODE,
536 [FSM_STATE_FMODE_EXIT] = {
537 .menu_fn = flightmode_menu,
539 [FSM_EVENT_UP] = FSM_STATE_FMODE_SAVEEXIT,
540 [FSM_EVENT_DOWN] = FSM_STATE_FMODE_1,
541 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_FMODE,
545 [FSM_STATE_HOMELOC_SET] = {
546 .menu_fn = homeloc_menu,
548 [FSM_EVENT_UP] = FSM_STATE_HOMELOC_EXIT,
549 [FSM_EVENT_DOWN] = FSM_STATE_HOMELOC_EXIT,
552 [FSM_STATE_HOMELOC_EXIT] = {
553 .menu_fn = homeloc_menu,
555 [FSM_EVENT_UP] = FSM_STATE_HOMELOC_SET,
556 [FSM_EVENT_DOWN] = FSM_STATE_HOMELOC_SET,
557 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_HOMELOC,
561 [FSM_STATE_PIDRATE_ROLLP] = {
562 .menu_fn = pidrate_menu,
564 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_EXIT,
565 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_ROLLI,
568 [FSM_STATE_PIDRATE_ROLLI] = {
569 .menu_fn = pidrate_menu,
571 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_ROLLP,
572 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_ROLLD,
575 [FSM_STATE_PIDRATE_ROLLD] = {
576 .menu_fn = pidrate_menu,
578 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_ROLLI,
579 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_ROLLILIMIT,
582 [FSM_STATE_PIDRATE_ROLLILIMIT] = {
583 .menu_fn = pidrate_menu,
585 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_ROLLD,
586 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_PITCHP,
589 [FSM_STATE_PIDRATE_PITCHP] = {
590 .menu_fn = pidrate_menu,
592 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_ROLLD,
593 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_PITCHI,
596 [FSM_STATE_PIDRATE_PITCHI] = {
597 .menu_fn = pidrate_menu,
599 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_PITCHP,
600 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_PITCHD,
603 [FSM_STATE_PIDRATE_PITCHD] = {
604 .menu_fn = pidrate_menu,
606 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_PITCHI,
607 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_PITCHILIMIT,
610 [FSM_STATE_PIDRATE_PITCHILIMIT] = {
611 .menu_fn = pidrate_menu,
613 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_PITCHD,
614 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_YAWP,
617 [FSM_STATE_PIDRATE_YAWP] = {
618 .menu_fn = pidrate_menu,
620 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_PITCHD,
621 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_YAWI,
624 [FSM_STATE_PIDRATE_YAWI] = {
625 .menu_fn = pidrate_menu,
627 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_YAWP,
628 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_YAWD,
631 [FSM_STATE_PIDRATE_YAWD] = {
632 .menu_fn = pidrate_menu,
634 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_YAWI,
635 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_YAWILIMIT,
638 [FSM_STATE_PIDRATE_YAWILIMIT] = {
639 .menu_fn = pidrate_menu,
641 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_YAWD,
642 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_SAVEEXIT,
645 [FSM_STATE_PIDRATE_SAVEEXIT] = {
646 .menu_fn = pidrate_menu,
648 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_YAWILIMIT,
649 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_EXIT,
650 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_PIDRATE,
653 [FSM_STATE_PIDRATE_EXIT] = {
654 .menu_fn = pidrate_menu,
656 [FSM_EVENT_UP] = FSM_STATE_PIDRATE_SAVEEXIT,
657 [FSM_EVENT_DOWN] = FSM_STATE_PIDRATE_ROLLP,
658 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_PIDRATE,
662 [FSM_STATE_PIDATT_ROLLP] = {
663 .menu_fn = pidatt_menu,
665 [FSM_EVENT_UP] = FSM_STATE_PIDATT_EXIT,
666 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_ROLLI,
669 [FSM_STATE_PIDATT_ROLLI] = {
670 .menu_fn = pidatt_menu,
672 [FSM_EVENT_UP] = FSM_STATE_PIDATT_ROLLP,
673 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_ROLLILIMIT,
676 [FSM_STATE_PIDATT_ROLLILIMIT] = {
677 .menu_fn = pidatt_menu,
679 [FSM_EVENT_UP] = FSM_STATE_PIDATT_ROLLI,
680 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_PITCHP,
683 [FSM_STATE_PIDATT_PITCHP] = {
684 .menu_fn = pidatt_menu,
686 [FSM_EVENT_UP] = FSM_STATE_PIDATT_ROLLILIMIT,
687 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_PITCHI,
690 [FSM_STATE_PIDATT_PITCHI] = {
691 .menu_fn = pidatt_menu,
693 [FSM_EVENT_UP] = FSM_STATE_PIDATT_PITCHP,
694 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_PITCHILIMIT,
697 [FSM_STATE_PIDATT_PITCHILIMIT] = {
698 .menu_fn = pidatt_menu,
700 [FSM_EVENT_UP] = FSM_STATE_PIDATT_PITCHI,
701 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_YAWP,
704 [FSM_STATE_PIDATT_YAWP] = {
705 .menu_fn = pidatt_menu,
707 [FSM_EVENT_UP] = FSM_STATE_PIDATT_PITCHILIMIT,
708 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_YAWI,
711 [FSM_STATE_PIDATT_YAWI] = {
712 .menu_fn = pidatt_menu,
714 [FSM_EVENT_UP] = FSM_STATE_PIDATT_YAWP,
715 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_YAWILIMIT,
718 [FSM_STATE_PIDATT_YAWILIMIT] = {
719 .menu_fn = pidatt_menu,
721 [FSM_EVENT_UP] = FSM_STATE_PIDATT_YAWI,
722 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_SAVEEXIT,
725 [FSM_STATE_PIDATT_SAVEEXIT] = {
726 .menu_fn = pidatt_menu,
728 [FSM_EVENT_UP] = FSM_STATE_PIDATT_YAWILIMIT,
729 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_EXIT,
730 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_PIDATT,
733 [FSM_STATE_PIDATT_EXIT] = {
734 .menu_fn = pidatt_menu,
736 [FSM_EVENT_UP] = FSM_STATE_PIDATT_SAVEEXIT,
737 [FSM_EVENT_DOWN] = FSM_STATE_PIDATT_ROLLP,
738 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_PIDATT,
742 [FSM_STATE_STICKLIMITS_ROLLA] = {
743 .menu_fn = sticklimits_menu,
745 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_EXIT,
746 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_PITCHA,
749 [FSM_STATE_STICKLIMITS_PITCHA] = {
750 .menu_fn = sticklimits_menu,
752 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_ROLLA,
753 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_YAWA,
756 [FSM_STATE_STICKLIMITS_YAWA] = {
757 .menu_fn = sticklimits_menu,
759 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_PITCHA,
760 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_ROLLR,
763 [FSM_STATE_STICKLIMITS_ROLLR] = {
764 .menu_fn = sticklimits_menu,
766 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_YAWA,
767 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_PITCHR,
770 [FSM_STATE_STICKLIMITS_PITCHR] = {
771 .menu_fn = sticklimits_menu,
773 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_ROLLR,
774 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_YAWR,
777 [FSM_STATE_STICKLIMITS_YAWR] = {
778 .menu_fn = sticklimits_menu,
780 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_PITCHR,
781 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_ROLLEXR,
784 [FSM_STATE_STICKLIMITS_ROLLEXR] = {
785 .menu_fn = sticklimits_menu,
787 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_YAWR,
788 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_PITCHEXR,
791 [FSM_STATE_STICKLIMITS_PITCHEXR] = {
792 .menu_fn = sticklimits_menu,
794 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_ROLLEXR,
795 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_YAWEXR,
798 [FSM_STATE_STICKLIMITS_YAWEXR] = {
799 .menu_fn = sticklimits_menu,
801 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_PITCHEXR,
802 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_ROLLEXH,
805 [FSM_STATE_STICKLIMITS_ROLLEXH] = {
806 .menu_fn = sticklimits_menu,
808 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_YAWEXR,
809 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_PITCHEXH,
812 [FSM_STATE_STICKLIMITS_PITCHEXH] = {
813 .menu_fn = sticklimits_menu,
815 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_ROLLEXH,
816 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_YAWEXH,
819 [FSM_STATE_STICKLIMITS_YAWEXH] = {
820 .menu_fn = sticklimits_menu,
822 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_PITCHEXH,
823 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_MOTORPOWER,
826 [FSM_STATE_STICKLIMITS_MOTORPOWER] = {
827 .menu_fn = sticklimits_menu,
829 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_YAWEXH,
830 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_CAMERATILT,
833 [FSM_STATE_STICKLIMITS_CAMERATILT] = {
834 .menu_fn = sticklimits_menu,
836 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_MOTORPOWER,
837 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_SAVEEXIT,
840 [FSM_STATE_STICKLIMITS_SAVEEXIT] = {
841 .menu_fn = sticklimits_menu,
843 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_CAMERATILT,
844 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_EXIT,
845 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_STICKLIMITS,
848 [FSM_STATE_STICKLIMITS_EXIT] = {
849 .menu_fn = sticklimits_menu,
851 [FSM_EVENT_UP] = FSM_STATE_STICKLIMITS_SAVEEXIT,
852 [FSM_EVENT_DOWN] = FSM_STATE_STICKLIMITS_ROLLA,
853 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_STICKLIMITS,
857 [FSM_STATE_VTX_BAND] = {
860 [FSM_EVENT_UP] = FSM_STATE_VTX_EXIT,
861 [FSM_EVENT_DOWN] = FSM_STATE_VTX_CH,
864 [FSM_STATE_VTX_CH] = {
867 [FSM_EVENT_UP] = FSM_STATE_VTX_BAND,
868 [FSM_EVENT_DOWN] = FSM_STATE_VTX_POWER,
871 [FSM_STATE_VTX_POWER] = {
874 [FSM_EVENT_UP] = FSM_STATE_VTX_CH,
875 [FSM_EVENT_DOWN] = FSM_STATE_VTX_APPLY,
878 [FSM_STATE_VTX_APPLY] = {
881 [FSM_EVENT_UP] = FSM_STATE_VTX_POWER,
882 [FSM_EVENT_DOWN] = FSM_STATE_VTX_SAVEEXIT,
885 [FSM_STATE_VTX_SAVEEXIT] = {
888 [FSM_EVENT_UP] = FSM_STATE_VTX_APPLY,
889 [FSM_EVENT_DOWN] = FSM_STATE_VTX_EXIT,
890 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_VTX,
893 [FSM_STATE_VTX_EXIT] = {
896 [FSM_EVENT_UP] = FSM_STATE_VTX_SAVEEXIT,
897 [FSM_EVENT_DOWN] = FSM_STATE_VTX_BAND,
898 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_VTX,
902 [FSM_STATE_STATS_EXIT] = {
903 .menu_fn = stats_menu,
905 [FSM_EVENT_UP] = FSM_STATE_STATS_EXIT,
906 [FSM_EVENT_DOWN] = FSM_STATE_STATS_EXIT,
907 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_STATS,
911 [FSM_STATE_BATTERY_CAPACITY] = {
912 .menu_fn = battery_menu,
914 [FSM_EVENT_UP] = FSM_STATE_BATTERY_EXIT,
915 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_CELLCOUNT,
918 [FSM_STATE_BATTERY_CELLCOUNT] = {
919 .menu_fn = battery_menu,
921 [FSM_EVENT_UP] = FSM_STATE_BATTERY_CAPACITY,
922 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_WARNING,
925 [FSM_STATE_BATTERY_WARNING] = {
926 .menu_fn = battery_menu,
928 [FSM_EVENT_UP] = FSM_STATE_BATTERY_CELLCOUNT,
929 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_ALARM,
932 [FSM_STATE_BATTERY_ALARM] = {
933 .menu_fn = battery_menu,
935 [FSM_EVENT_UP] = FSM_STATE_BATTERY_WARNING,
936 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_WARN_TIME,
939 [FSM_STATE_BATTERY_WARN_TIME] = {
940 .menu_fn = battery_menu,
942 [FSM_EVENT_UP] = FSM_STATE_BATTERY_ALARM,
943 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_ALARM_TIME,
946 [FSM_STATE_BATTERY_ALARM_TIME] = {
947 .menu_fn = battery_menu,
949 [FSM_EVENT_UP] = FSM_STATE_BATTERY_WARN_TIME,
950 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_SAVEEXIT,
953 [FSM_STATE_BATTERY_SAVEEXIT] = {
954 .menu_fn = battery_menu,
956 [FSM_EVENT_UP] = FSM_STATE_BATTERY_ALARM,
957 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_EXIT,
958 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_BATTERY,
961 [FSM_STATE_BATTERY_EXIT] = {
962 .menu_fn = battery_menu,
964 [FSM_EVENT_UP] = FSM_STATE_BATTERY_SAVEEXIT,
965 [FSM_EVENT_DOWN] = FSM_STATE_BATTERY_CAPACITY,
966 [FSM_EVENT_RIGHT] = FSM_STATE_MAIN_BATTERY,
973 #define INPUT_THRESHOLD (0.2f)
974 enum menu_fsm_event get_controller_event()
977 ManualControlCommandRollGet(&roll);
978 ManualControlCommandPitchGet(&pitch);
981 if (pitch < -1 * INPUT_THRESHOLD)
983 if (pitch > INPUT_THRESHOLD)
984 return FSM_EVENT_DOWN;
985 if (roll < -1 * INPUT_THRESHOLD)
986 return FSM_EVENT_LEFT;
987 if (roll > INPUT_THRESHOLD)
988 return FSM_EVENT_RIGHT;
993 #define HELD_LONG_THRESHOLD 20
997 static enum menu_fsm_event last_fsm_event;
998 static uint32_t event_repeats = 0;
1001 current_event = get_controller_event();
1002 if (last_fsm_event == current_event) {
1008 last_fsm_event = current_event;
1009 held_long = (event_repeats > HELD_LONG_THRESHOLD);
1020 if ((!event_repeats || current_event != FSM_EVENT_RIGHT) && menu_fsm[
current_state].next_state[current_event])
1023 ManualControlSettingsArmingGet(&tmp);
1025 case MANUALCONTROLSETTINGS_ARMING_ROLLLEFTTHROTTLE:
1026 case MANUALCONTROLSETTINGS_ARMING_ROLLRIGHTTHROTTLE:
1033 FlightStatusArmedGet(&tmp);
1034 if (tmp != FLIGHTSTATUS_ARMED_DISARMED)
1039 #define MENU_LINE_SPACING 11
1040 #define MENU_LINE_Y 40
1041 #define MENU_LINE_X (GRAPHICS_LEFT + 10)
1042 #define MENU_FONT FONT8X10
1044 void draw_menu_title(
char* title)
1049 void draw_selected_icon(
int x,
int y)
1054 void main_menu(
void)
1056 int y_pos = MENU_LINE_Y;
1058 draw_menu_title(
"Main Menu");
1060 for (
enum menu_fsm_state s=FSM_STATE_TOP; s <= FSM_STATE_MAIN_BATTERY; s++) {
1062 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1065 #if defined(USE_STM32F4xx_BRAINFPVRE1)
1066 case FSM_STATE_MAIN_RE1:
1070 case FSM_STATE_MAIN_RGBLEDS:
1073 case FSM_STATE_MAIN_FILTER:
1076 case FSM_STATE_MAIN_FMODE:
1079 case FSM_STATE_MAIN_HOMELOC:
1082 case FSM_STATE_MAIN_PIDRATE:
1085 case FSM_STATE_MAIN_PIDATT:
1088 case FSM_STATE_MAIN_STICKLIMITS:
1091 case FSM_STATE_MAIN_VTX:
1094 case FSM_STATE_MAIN_STATS:
1097 case FSM_STATE_MAIN_BATTERY:
1103 y_pos += MENU_LINE_SPACING;
1107 #if defined(USE_STM32F4xx_BRAINFPVRE1)
1108 #include "hwbrainre1.h"
1110 const char * ir_protocol_names[HWBRAINRE1_IRPROTOCOL_MAXOPTVAL + 1] = {
1111 [HWBRAINRE1_IRPROTOCOL_DISABLED] =
"OFF",
1112 [HWBRAINRE1_IRPROTOCOL_ILAP] =
"I-Lap",
1113 [HWBRAINRE1_IRPROTOCOL_TRACKMATE] =
"Trackmate"
1116 #define MAX_ID_ILAP 9999999
1117 #define MAX_ID_TRACKMATE 0xfff
1123 uint16_t next_valid_trackmateid(uint16_t trackmate_id, int16_t step)
1127 trackmate_id += step;
1128 if (trackmate_id > MAX_ID_TRACKMATE) {
1133 trackmate_id = MAX_ID_TRACKMATE;
1137 nibble = (trackmate_id & 0x0F00) >> 8;
1138 if ((nibble == 0x00) || (nibble == 0x01) || (nibble == 0x08) || (nibble == 0x0F)) {
1141 trackmate_id += 256;
1144 trackmate_id -= 256;
1149 nibble = (trackmate_id & 0x00F0) >> 4;
1150 if ((nibble == 0x00) || (nibble == 0x0F)) {
1154 nibble = trackmate_id & 0x000F;
1155 if ((nibble == 0x00) || (nibble == 0x0F)) {
1162 return trackmate_id;
1165 void brainre1_menu(
void)
1167 HwBrainRE1Data
data;
1168 int y_pos = MENU_LINE_Y;
1169 char tmp_str[100] = {0};
1170 bool data_changed =
false;
1172 HwBrainRE1Get(&data);
1174 draw_menu_title(
"BrainFPV RE1 Settings");
1176 for (
enum menu_fsm_state s=FSM_STATE_RE1_IR_PROTOCOL; s <= FSM_STATE_RE1_EXIT; s++) {
1178 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1181 case FSM_STATE_RE1_IR_PROTOCOL:
1182 sprintf(tmp_str,
"IR Transponder Protocol: %s", ir_protocol_names[data.IRProtocol]);
1185 case FSM_STATE_RE1_IR_IDILAP:
1186 sprintf(tmp_str,
"IR Transponder ID I-Lap: %07d", (
int)data.IRIDILap);
1189 case FSM_STATE_RE1_IR_IDTRACKMATE:
1190 sprintf(tmp_str,
"IR Transponder ID Trackmate: %04d", (
int)data.IRIDTrackmate);
1193 case FSM_STATE_RE1_SAVEEXIT:
1196 case FSM_STATE_RE1_EXIT:
1202 y_pos += MENU_LINE_SPACING;
1206 case FSM_STATE_RE1_IR_PROTOCOL:
1207 if (current_event == FSM_EVENT_RIGHT) {
1208 if (data.IRProtocol == HWBRAINRE1_IRPROTOCOL_GLOBAL_MAXOPTVAL)
1209 data.IRProtocol = 0;
1211 data.IRProtocol += 1;
1212 data_changed =
true;
1214 if (current_event == FSM_EVENT_LEFT) {
1215 if (data.IRProtocol == 0)
1216 data.IRProtocol = HWBRAINRE1_IRPROTOCOL_GLOBAL_MAXOPTVAL;
1218 data.IRProtocol -= 1;
1219 data_changed =
true;
1222 case FSM_STATE_RE1_IR_IDILAP:
1224 int step = held_long ? 1000 : 1;
1225 if (current_event == FSM_EVENT_RIGHT) {
1226 data.IRIDILap += step;
1227 if (data.IRIDILap > MAX_ID_ILAP) {
1231 if (current_event == FSM_EVENT_LEFT) {
1232 data.IRIDILap -= step;
1233 if (data.IRIDILap > MAX_ID_ILAP) {
1234 data.IRIDILap = MAX_ID_ILAP;
1238 data_changed =
true;
1241 case FSM_STATE_RE1_IR_IDTRACKMATE:
1243 if ((current_event == FSM_EVENT_RIGHT) || (current_event == FSM_EVENT_LEFT)) {
1244 int16_t step = held_long ? 100 : 1;
1245 if (current_event == FSM_EVENT_LEFT) {
1248 data.IRIDTrackmate = next_valid_trackmateid(data.IRIDTrackmate, step);
1249 data_changed =
true;
1258 HwBrainRE1Set(&data);
1261 if ((
current_state == FSM_STATE_RE1_SAVEEXIT) && (current_event == FSM_EVENT_RIGHT)) {
1285 const uint8_t RGBLED_COLOR_VALUES[COLOR_MAXCOLOR + 1][3] = {
1286 [COLOR_OFF] = {0, 0, 0},
1287 [COLOR_WHITE] = {255, 255, 255},
1288 [COLOR_RED] = {255, 0, 0},
1289 [COLOR_ORANGE] = {255, 69, 0},
1290 [COLOR_YELLOW] = {255, 255, 0},
1291 [COLOR_GREEN] = {0, 255, 0},
1292 [COLOR_AQUA] = {0, 255, 255},
1293 [COLOR_BLUE] = {0, 0, 255},
1294 [COLOR_PURPLE] = {255, 0, 255},
1295 [COLOR_CUSTOM] = {0, 0, 0}
1298 const char * RGBLED_COLOR_NAMES[COLOR_MAXCOLOR + 1] = {
1299 [COLOR_OFF] =
"OFF",
1300 [COLOR_WHITE] =
"White",
1301 [COLOR_RED] =
"Red",
1302 [COLOR_ORANGE] =
"Orange",
1303 [COLOR_YELLOW] =
"Yellow",
1304 [COLOR_GREEN] =
"Green",
1305 [COLOR_AQUA] =
"Aqua",
1306 [COLOR_BLUE] =
"Blue",
1307 [COLOR_PURPLE] =
"Purple",
1308 [COLOR_CUSTOM] =
"Custom"
1312 enum RGBColor get_color(uint8_t * rgb)
1314 enum RGBColor color;
1315 for (color=COLOR_OFF; color<COLOR_MAXCOLOR; color++) {
1316 if ((rgb[0] == RGBLED_COLOR_VALUES[color][0]) && (rgb[1] == RGBLED_COLOR_VALUES[color][1])
1317 && (rgb[2] == RGBLED_COLOR_VALUES[color][2])) {
1321 return COLOR_CUSTOM;
1324 enum RGBColor get_next_color(
enum RGBColor color)
1326 if ((color == COLOR_PURPLE) || (color == COLOR_CUSTOM)) {
1332 enum RGBColor get_previous_color(
enum RGBColor color)
1334 if (color == COLOR_OFF) {
1335 return COLOR_PURPLE;
1340 void rgbled_menu(
void)
1342 int y_pos = MENU_LINE_Y;
1343 char tmp_str[100] = {0};
1344 bool data_changed =
false;
1346 draw_menu_title(
"RGB LED Settings");
1348 if (RGBLEDSettingsHandle()) {
1349 RGBLEDSettingsData
data;
1350 RGBLEDSettingsGet(&data);
1351 for (
enum menu_fsm_state s=FSM_STATE_RGB_DEFAULTCOLOR; s <= FSM_STATE_RGB_EXIT; s++) {
1353 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1356 case FSM_STATE_RGB_DEFAULTCOLOR:
1357 sprintf(tmp_str,
"Default color: %s", RGBLED_COLOR_NAMES[get_color(data.DefaultColor)]);
1360 case FSM_STATE_RGB_RANGECOLOR_BASE:
1361 sprintf(tmp_str,
"Range color base: %s", RGBLED_COLOR_NAMES[get_color(data.RangeBaseColor)]);
1364 case FSM_STATE_RGB_RANGECOLOR_END:
1365 sprintf(tmp_str,
"Range color end: %s", RGBLED_COLOR_NAMES[get_color(data.RangeEndColor)]);
1368 case FSM_STATE_RGB_SAVEEXIT:
1371 case FSM_STATE_RGB_EXIT:
1377 y_pos += MENU_LINE_SPACING;
1380 uint8_t * target = NULL;
1381 enum RGBColor color;
1383 case FSM_STATE_RGB_DEFAULTCOLOR:
1384 target = data.DefaultColor;
1385 case FSM_STATE_RGB_RANGECOLOR_BASE:
1386 if (target == NULL) {
1387 target = data.RangeBaseColor;
1389 case FSM_STATE_RGB_RANGECOLOR_END:
1390 if (target == NULL) {
1391 target = data.RangeEndColor;
1393 if (current_event == FSM_EVENT_RIGHT) {
1394 color = get_next_color(get_color(target));
1395 data_changed =
true;
1397 if (current_event == FSM_EVENT_LEFT) {
1398 color = get_previous_color(get_color(target));
1399 data_changed =
true;
1407 if (target != NULL) {
1408 target[0] = RGBLED_COLOR_VALUES[color][0];
1409 target[1] = RGBLED_COLOR_VALUES[color][1];
1410 target[2] = RGBLED_COLOR_VALUES[color][2];
1412 RGBLEDSettingsSet(&data);
1415 if ((
current_state == FSM_STATE_RGB_SAVEEXIT) && (current_event == FSM_EVENT_RIGHT)) {
1427 void filter_menu(
void)
1429 StateEstimationData
data;
1430 int y_pos = MENU_LINE_Y;
1432 char tmp_str[100] = {0};
1433 bool data_changed =
false;
1434 const char * att_filter_strings[4] = {
1435 [STATEESTIMATION_ATTITUDEFILTER_COMPLEMENTARY] =
"Complementary",
1436 [STATEESTIMATION_ATTITUDEFILTER_COMPLEMENTARYVELCOMPASS] =
"Comp+Velcomp",
1437 [STATEESTIMATION_ATTITUDEFILTER_INSINDOOR] =
"INSIndoor",
1438 [STATEESTIMATION_ATTITUDEFILTER_INSOUTDOOR] =
"INSOutdoor",
1440 const char * nav_filter_strings[3] = {
1441 [STATEESTIMATION_NAVIGATIONFILTER_NONE] =
"None",
1442 [STATEESTIMATION_NAVIGATIONFILTER_RAW] =
"Raw",
1443 [STATEESTIMATION_NAVIGATIONFILTER_INS] =
"INS",
1446 draw_menu_title(
"Filter Settings");
1447 StateEstimationGet(&data);
1449 for (
enum menu_fsm_state s=FSM_STATE_FILTER_ATT; s <= FSM_STATE_FILTER_EXIT; s++) {
1451 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1454 case FSM_STATE_FILTER_ATT:
1455 sprintf(tmp_str,
"Attitude Filter: %s", att_filter_strings[data.AttitudeFilter]);
1458 case FSM_STATE_FILTER_NAV:
1459 sprintf(tmp_str,
"Navigation Filter: %s", nav_filter_strings[data.NavigationFilter]);
1462 case FSM_STATE_FILTER_SAVEEXIT:
1465 case FSM_STATE_FILTER_EXIT:
1471 y_pos += MENU_LINE_SPACING;
1475 case FSM_STATE_FILTER_ATT:
1476 if (current_event == FSM_EVENT_RIGHT) {
1477 data.AttitudeFilter = ((int)(data.AttitudeFilter) + 1) %
NELEMENTS(att_filter_strings);;
1478 data_changed =
true;
1480 if (current_event == FSM_EVENT_LEFT) {
1481 tmp = (int)(data.AttitudeFilter) - 1;
1483 tmp =
NELEMENTS(att_filter_strings) - 1;
1484 data.AttitudeFilter = tmp;
1485 data_changed =
true;
1488 case FSM_STATE_FILTER_NAV:
1489 if (current_event == FSM_EVENT_RIGHT) {
1490 data.NavigationFilter = (data.NavigationFilter + 1) %
NELEMENTS(nav_filter_strings);
1491 data_changed =
true;
1493 if (current_event == FSM_EVENT_LEFT) {
1494 tmp = (int)(data.NavigationFilter) - 1;
1496 tmp =
NELEMENTS(nav_filter_strings) - 1;
1497 data.NavigationFilter = tmp;
1498 data_changed =
true;
1506 StateEstimationSet(&data);
1509 if ((
current_state == FSM_STATE_FILTER_SAVEEXIT) && (current_event == FSM_EVENT_RIGHT)) {
1515 static const char *nullstrwrap(
const char *str)
1523 void flightmode_menu(
void)
1525 int y_pos = MENU_LINE_Y;
1527 char tmp_str[100] = {0};
1528 bool data_changed =
false;
1529 const char* fmode_strings[] = {
1530 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_MANUAL] =
"Manual",
1531 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACRO] =
"Acro",
1532 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACRODYNE] =
"AcroDyne",
1533 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ACROPLUS] =
"AcroPlus",
1534 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LEVELING] =
"Leveling",
1535 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_HORIZON] =
"Horizon",
1536 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_AXISLOCK] =
"Axis Lock",
1537 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_VIRTUALBAR] =
"Virtualbar",
1538 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED1] =
"Stabilized1",
1539 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED2] =
"Stabilized2",
1540 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_STABILIZED3] =
"Stabilized3",
1541 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_AUTOTUNE] =
"Autotune",
1542 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_ALTITUDEHOLD] =
"Altitude Hold",
1543 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_POSITIONHOLD] =
"Position Hold",
1544 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_RETURNTOHOME] =
"Return to Home",
1545 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_PATHPLANNER] =
"Path Planner",
1546 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_TABLETCONTROL] =
"Tablet Control",
1547 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LQG] =
"LQG",
1548 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_LQGLEVELING] =
"LQG Leveling",
1549 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_FLIPREVERSED] =
"Flip Reverse",
1550 [MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_FAILSAFE] =
"Failsafe",
1553 uint8_t FlightModePosition[MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_NUMELEM];
1555 draw_menu_title(
"Flight Modes");
1557 ManualControlSettingsFlightModePositionGet(FlightModePosition);
1558 for (
enum menu_fsm_state s=FSM_STATE_FMODE_1; s <= FSM_STATE_FMODE_EXIT; s++) {
1560 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1563 case FSM_STATE_FMODE_1:
1564 sprintf(tmp_str,
"Position 1: %s", nullstrwrap(fmode_strings[FlightModePosition[0]]));
1567 case FSM_STATE_FMODE_2:
1568 sprintf(tmp_str,
"Position 2: %s", nullstrwrap(fmode_strings[FlightModePosition[1]]));
1571 case FSM_STATE_FMODE_3:
1572 sprintf(tmp_str,
"Position 3: %s", nullstrwrap(fmode_strings[FlightModePosition[2]]));
1575 case FSM_STATE_FMODE_4:
1576 sprintf(tmp_str,
"Position 4: %s", nullstrwrap(fmode_strings[FlightModePosition[3]]));
1579 case FSM_STATE_FMODE_5:
1580 sprintf(tmp_str,
"Position 5: %s", nullstrwrap(fmode_strings[FlightModePosition[4]]));
1583 case FSM_STATE_FMODE_6:
1584 sprintf(tmp_str,
"Position 6: %s", nullstrwrap(fmode_strings[FlightModePosition[5]]));
1587 case FSM_STATE_FMODE_SAVEEXIT:
1590 case FSM_STATE_FMODE_EXIT:
1596 y_pos += MENU_LINE_SPACING;
1599 for (
int i=0;
i < MANUALCONTROLSETTINGS_FLIGHTMODEPOSITION_NUMELEM;
i++) {
1601 if (current_event == FSM_EVENT_RIGHT) {
1602 FlightModePosition[
i] = ((int)(FlightModePosition[
i]) + 1) %
NELEMENTS(fmode_strings);
1603 data_changed =
true;
1605 if (current_event == FSM_EVENT_LEFT) {
1606 tmp = (int)(FlightModePosition[i]) -1;
1609 FlightModePosition[
i] = tmp;
1610 data_changed =
true;
1617 ManualControlSettingsFlightModePositionSet(FlightModePosition);
1620 if ((
current_state == FSM_STATE_FMODE_SAVEEXIT) && (current_event == FSM_EVENT_RIGHT)) {
1622 UAVObjSave(ManualControlSettingsHandle(), 0);
1627 void homeloc_menu(
void)
1629 int y_pos = MENU_LINE_Y;
1630 char tmp_str[100] = {0};
1631 HomeLocationData
data;
1634 draw_menu_title(
"Home Location");
1636 if (HomeLocationHandle()){
1637 HomeLocationSetGet(&home_set);
1639 if (home_set == HOMELOCATION_SET_TRUE) {
1640 HomeLocationGet(&data);
1641 sprintf(tmp_str,
"Home: %0.5f %0.5f Alt: %0.1fm", (
double)data.Latitude / 10000000.0, (
double)data.Longitude / 10000000.0, (
double)data.Altitude);
1648 y_pos += MENU_LINE_SPACING;
1651 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1652 if (current_event == FSM_EVENT_RIGHT) {
1653 home_set = HOMELOCATION_SET_FALSE;
1654 HomeLocationSetSet(&home_set);
1663 y_pos += MENU_LINE_SPACING;
1666 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1671 void draw_hscale(
int x1,
int x2,
int y,
float val_min,
float val_max,
float val)
1673 int width = x2 - x1;
1676 width2 =
LIMIT((
float)(width - 2) * (val - val_min) / (val_max - val_min), 0, width - 2);
1680 const char * axis_strings[] = {
"Roll ",
1683 const char * pid_strings[] = {
"P ",
1688 void pidrate_menu(
void)
1690 const float limits_high[] = {.01f, .05f, .01f, 1.f};
1691 const float increments[] = {1e-4
f, 1e-4
f, 1e-4
f, 1e-2f};
1693 float pid_arr[STABILIZATIONSETTINGS_ROLLRATEPID_NUMELEM];
1694 int y_pos = MENU_LINE_Y;
1695 enum menu_fsm_state my_state = FSM_STATE_PIDRATE_ROLLP;
1696 bool data_changed =
false;
1697 char tmp_str[100] = {0};
1699 draw_menu_title(
"PID Rate");
1701 for (
int i = 0; i < 3; i++) {
1702 data_changed =
false;
1705 StabilizationSettingsRollRatePIDGet(pid_arr);
1708 StabilizationSettingsPitchRatePIDGet(pid_arr);
1711 StabilizationSettingsYawRatePIDGet(pid_arr);
1714 for (
int j = 0;
j < 4;
j++) {
1715 sprintf(tmp_str,
"%s %s: %0.6f", axis_strings[i], pid_strings[
j], (
double)pid_arr[j]);
1717 float h_lim = ceilf(pid_arr[j] / limits_high[j]) * limits_high[
j];
1718 draw_hscale(180,
GRAPHICS_RIGHT - 5, y_pos + 2, 0.
f, h_lim, pid_arr[j]);
1720 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1721 if (current_event == FSM_EVENT_RIGHT) {
1722 pid_arr[
j] = pid_arr[
j] + increments[
j];
1723 data_changed =
true;
1725 if (current_event == FSM_EVENT_LEFT) {
1726 pid_arr[
j] =
MAX(0.
f, pid_arr[j] - increments[j]);
1727 data_changed =
true;
1732 StabilizationSettingsRollRatePIDSet(pid_arr);
1735 StabilizationSettingsPitchRatePIDSet(pid_arr);
1738 StabilizationSettingsYawRatePIDSet(pid_arr);
1743 y_pos += MENU_LINE_SPACING;
1750 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1751 if (current_event == FSM_EVENT_RIGHT)
1752 UAVObjSave(StabilizationSettingsHandle(), 0);
1755 y_pos += MENU_LINE_SPACING;
1758 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1762 const char * pid_strings_att[] = {
"P ",
1765 void pidatt_menu(
void)
1767 const float limits_high[] = {20.f, 20.f, 100.f};
1768 const float increments[] = {0.1f, 0.1f, 1.f};
1770 float pid_arr[STABILIZATIONSETTINGS_ROLLPI_NUMELEM];
1771 int y_pos = MENU_LINE_Y;
1772 enum menu_fsm_state my_state = FSM_STATE_PIDATT_ROLLP;
1773 bool data_changed =
false;
1774 char tmp_str[100] = {0};
1776 draw_menu_title(
"PID Attitude");
1778 for (
int i = 0; i < 3; i++) {
1779 data_changed =
false;
1782 StabilizationSettingsRollPIGet(pid_arr);
1785 StabilizationSettingsPitchPIGet(pid_arr);
1788 StabilizationSettingsYawPIGet(pid_arr);
1791 for (
int j = 0; j < 3; j++) {
1792 sprintf(tmp_str,
"%s %s: %2.1f", axis_strings[i], pid_strings_att[j], (
double)pid_arr[j]);
1794 float h_lim = ceilf(pid_arr[j] / limits_high[j]) * limits_high[
j];
1795 draw_hscale(170,
GRAPHICS_RIGHT - 5, y_pos + 2, 0.
f, h_lim, pid_arr[j]);
1797 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1798 if (current_event == FSM_EVENT_RIGHT) {
1799 pid_arr[
j] = pid_arr[
j] + increments[
j];
1800 data_changed =
true;
1802 if (current_event == FSM_EVENT_LEFT) {
1803 pid_arr[
j] =
MAX(0.
f, pid_arr[j] - increments[j]);
1804 data_changed =
true;
1809 StabilizationSettingsRollPISet(pid_arr);
1812 StabilizationSettingsPitchPISet(pid_arr);
1815 StabilizationSettingsYawPISet(pid_arr);
1820 y_pos += MENU_LINE_SPACING;
1827 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1828 if (current_event == FSM_EVENT_RIGHT) {
1829 UAVObjSave(StabilizationSettingsHandle(), 0);
1833 y_pos += MENU_LINE_SPACING;
1836 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1840 DONT_BUILD_IF(STABILIZATIONSETTINGS_MAXLEVELANGLE_ROLL != 0,
1841 LevelAngleConstantRoll);
1842 DONT_BUILD_IF(STABILIZATIONSETTINGS_MAXLEVELANGLE_PITCH != 1,
1843 LevelAngleConstantPitch);
1845 LevelAngleConstantYaw);
1847 #define MAX_STICK_RATE 1440
1848 void sticklimits_menu(
void)
1850 int y_pos = MENU_LINE_Y;
1851 enum menu_fsm_state my_state = FSM_STATE_STICKLIMITS_ROLLA;
1852 bool data_changed =
false;
1853 char tmp_str[100] = {0};
1855 draw_menu_title(
"Stick Limits and Expo");
1857 uint8_t level_angles[STABILIZATIONSETTINGS_MAXLEVELANGLE_NUMELEM];
1859 StabilizationSettingsMaxLevelAngleGet(level_angles);
1862 for (
int i = 0; i < 3; i++) {
1863 data_changed =
false;
1865 uint8_t angle = level_angles[
i];
1867 sprintf(tmp_str,
"Max Stick Angle %s: %d", axis_strings[i], angle);
1871 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1872 if (current_event == FSM_EVENT_RIGHT) {
1873 level_angles[
i] =
MIN(angle + 1, 90);
1874 data_changed =
true;
1876 if (current_event == FSM_EVENT_LEFT) {
1877 level_angles[
i] =
MAX((
int)angle - 1, 0);
1878 data_changed =
true;
1881 StabilizationSettingsMaxLevelAngleSet(level_angles);
1885 y_pos += MENU_LINE_SPACING;
1890 float rate_arr[STABILIZATIONSETTINGS_MANUALRATE_NUMELEM];
1891 StabilizationSettingsManualRateGet(rate_arr);
1892 data_changed =
false;
1893 for (
int i = 0; i < 3; i++) {
1894 sprintf(tmp_str,
"Max Stick Rate %s: %d", axis_strings[i], (
int)rate_arr[i]);
1896 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, MAX_STICK_RATE, rate_arr[i]);
1898 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1899 if (current_event == FSM_EVENT_RIGHT) {
1900 rate_arr[
i] =
MIN(rate_arr[i] + 10, MAX_STICK_RATE);
1901 data_changed =
true;
1903 if (current_event == FSM_EVENT_LEFT) {
1904 rate_arr[
i] =
MAX(rate_arr[i] - 10, 0);
1905 data_changed =
true;
1909 y_pos += MENU_LINE_SPACING;
1913 StabilizationSettingsManualRateSet(rate_arr);
1918 uint8_t expo_arr[STABILIZATIONSETTINGS_RATEEXPO_NUMELEM];
1919 StabilizationSettingsRateExpoGet(expo_arr);
1920 data_changed =
false;
1921 for (
int i = 0; i < 3; i++) {
1922 sprintf(tmp_str,
"Expo Rate %s: %d", axis_strings[i], (
int)expo_arr[i]);
1924 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, 100, expo_arr[i]);
1926 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1927 if (current_event == FSM_EVENT_RIGHT) {
1928 expo_arr[
i] =
MIN(expo_arr[i] + 1, 100);
1929 data_changed =
true;
1931 if (current_event == FSM_EVENT_LEFT) {
1932 expo_arr[
i] =
MAX(expo_arr[i] - 1, 0);
1933 data_changed =
true;
1937 y_pos += MENU_LINE_SPACING;
1941 StabilizationSettingsRateExpoSet(expo_arr);
1946 uint8_t expo_arr[STABILIZATIONSETTINGS_HORIZONEXPO_NUMELEM];
1947 StabilizationSettingsHorizonExpoGet(expo_arr);
1948 data_changed =
false;
1949 for (
int i = 0; i < 3; i++) {
1950 sprintf(tmp_str,
"Expo Horizon %s: %d", axis_strings[i], (
int)expo_arr[i]);
1952 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, 100, expo_arr[i]);
1954 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1955 if (current_event == FSM_EVENT_RIGHT) {
1956 expo_arr[
i] =
MIN(expo_arr[i] + 1, 100);
1957 data_changed =
true;
1959 if (current_event == FSM_EVENT_LEFT) {
1960 expo_arr[
i] =
MAX(expo_arr[i] - 1, 0);
1961 data_changed =
true;
1965 y_pos += MENU_LINE_SPACING;
1969 StabilizationSettingsHorizonExpoSet(expo_arr);
1975 ActuatorSettingsMotorInputOutputGainGet(&motor_gain);
1978 data_changed =
false;
1979 sprintf(tmp_str,
"Motor power scale: %d", (
int)motor_gain);
1981 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 50, 100, motor_gain);
1983 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
1984 if (current_event == FSM_EVENT_RIGHT) {
1985 motor_gain =
MIN(motor_gain + 1, 100);
1986 data_changed =
true;
1988 if (current_event == FSM_EVENT_LEFT) {
1989 motor_gain =
MAX(motor_gain - 1, 50);
1990 data_changed =
true;
1994 y_pos += MENU_LINE_SPACING;
1998 ActuatorSettingsMotorInputOutputGainSet(&motor_gain);
2005 StabilizationSettingsCameraTiltGet(&tilt);
2006 data_changed =
false;
2008 sprintf(tmp_str,
"Reproject Camera Tilt: %d", (
int)tilt);
2012 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2013 if (current_event == FSM_EVENT_RIGHT) {
2014 tilt =
MIN(tilt + 1, 85);
2015 data_changed =
true;
2017 if (current_event == FSM_EVENT_LEFT) {
2018 tilt =
MAX(tilt - 1, -85);
2019 data_changed =
true;
2024 y_pos += MENU_LINE_SPACING;
2027 StabilizationSettingsCameraTiltSet(&tilt);
2032 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2033 if (current_event == FSM_EVENT_RIGHT) {
2034 UAVObjSave(StabilizationSettingsHandle(), 0);
2039 y_pos += MENU_LINE_SPACING;
2042 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2048 const char *vtx_strings[] = {
2049 [VTXINFO_MODEL_NONE] =
"No VTX detected",
2050 [VTXINFO_MODEL_TBSUNIFYPRO5G8] =
"TBS Unify Pro 5G8",
2051 [VTXINFO_MODEL_TBSUNIFYPRO5G8HV] =
"TBS Unify Pro 5G8 HV",
2054 const char *band_strings[] = {
2055 [VTXSETTINGS_BAND_BAND5G8A] =
"A",
2056 [VTXSETTINGS_BAND_BAND5G8B] =
"B",
2057 [VTXSETTINGS_BAND_BAND5G8E] =
"E",
2058 [VTXSETTINGS_BAND_AIRWAVE] =
"Airwave",
2059 [VTXSETTINGS_BAND_RACEBAND] =
"Raceband",
2064 static bool settings_read =
false;
2066 draw_menu_title(
"Video Transmitter");
2067 int y_pos = MENU_LINE_Y;
2069 if ((VTXSettingsHandle() == NULL) || (VTXInfoHandle() == NULL)) {
2071 y_pos += MENU_LINE_SPACING;
2075 VTXInfoData vtxInfo;
2076 VTXInfoGet(&vtxInfo);
2077 char tmp_str[100] = {0};
2079 if (!settings_read) {
2080 VTXSettingsGet(&settings);
2081 settings_read =
true;
2084 y_pos += MENU_LINE_SPACING;
2085 sprintf(tmp_str,
"VTX Type: %s", vtx_strings[vtxInfo.Model]);
2088 y_pos += 2 * MENU_LINE_SPACING;
2091 y_pos += MENU_LINE_SPACING;
2092 sprintf(tmp_str,
" Frequency: %d MHz", vtxInfo.Frequency);
2095 y_pos += MENU_LINE_SPACING;
2096 sprintf(tmp_str,
" Power: %d mW", vtxInfo.Power);
2099 y_pos += 2 * MENU_LINE_SPACING;
2102 y_pos += MENU_LINE_SPACING;
2103 sprintf(tmp_str,
" Band: %s", band_strings[settings.Band]);
2106 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2108 if (current_event == FSM_EVENT_RIGHT) {
2109 if (settings.Band == VTXSETTINGS_BAND_MAXOPTVAL) {
2116 if (current_event == FSM_EVENT_LEFT) {
2117 if (settings.Band == 0) {
2118 settings.Band = VTXSETTINGS_BAND_MAXOPTVAL;
2128 const uint16_t *band_ptr;
2129 switch(settings.Band) {
2130 case VTXSETTINGS_BAND_BAND5G8A:
2132 max_val = VTXSETTINGS_BAND_5G8_A_FREQUENCY_MAXOPTVAL;
2133 target = &settings.Band_5G8_A_Frequency;
2135 case VTXSETTINGS_BAND_BAND5G8B:
2137 max_val = VTXSETTINGS_BAND_5G8_B_FREQUENCY_MAXOPTVAL;
2138 target = &settings.Band_5G8_B_Frequency;
2140 case VTXSETTINGS_BAND_BAND5G8E:
2142 max_val = VTXSETTINGS_BAND_5G8_E_FREQUENCY_MAXOPTVAL;
2143 target = &settings.Band_5G8_E_Frequency;
2145 case VTXSETTINGS_BAND_AIRWAVE:
2147 max_val = VTXSETTINGS_AIRWAVE_FREQUENCY_MAXOPTVAL;
2148 target = &settings.Airwave_Frequency;
2151 case VTXSETTINGS_BAND_RACEBAND:
2153 max_val = VTXSETTINGS_RACEBAND_FREQUENCY_MAXOPTVAL;
2154 target = &settings.Raceband_Frequency;
2157 y_pos += MENU_LINE_SPACING;
2159 sprintf(tmp_str,
" Channel: CH %d %d MHz", *target + 1, band_ptr[*target]);
2163 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2165 if (current_event == FSM_EVENT_RIGHT) {
2166 if (*target == max_val) {
2173 if (current_event == FSM_EVENT_LEFT) {
2183 y_pos += MENU_LINE_SPACING;
2188 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2190 if (current_event == FSM_EVENT_RIGHT) {
2191 if (settings.Power == VTXSETTINGS_POWER_MAXOPTVAL) {
2195 settings.Power += 1;
2198 if (current_event == FSM_EVENT_LEFT) {
2199 if (settings.Power == 0) {
2200 settings.Power = VTXSETTINGS_POWER_MAXOPTVAL;
2203 settings.Power -= 1;
2209 y_pos += 2 * MENU_LINE_SPACING;
2212 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2213 if (current_event == FSM_EVENT_RIGHT) {
2214 VTXSettingsSet(&settings);
2218 y_pos += MENU_LINE_SPACING;
2221 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2222 if (current_event == FSM_EVENT_RIGHT) {
2223 VTXSettingsSet(&settings);
2225 settings_read =
false;
2229 y_pos += MENU_LINE_SPACING;
2232 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2234 if (current_event == FSM_EVENT_RIGHT)
2235 settings_read =
false;
2247 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2251 void battery_menu(
void)
2253 int y_pos = MENU_LINE_Y;
2254 bool settings_changed =
false;
2255 char tmp_str[100] = {0};
2256 static FlightBatterySettingsData batterySettings;
2257 static bool settings_read =
false;
2260 draw_menu_title(
"Battery Settings");
2262 if (FlightBatterySettingsHandle()) {
2263 if (!settings_read) {
2264 FlightBatterySettingsGet(&batterySettings);
2265 settings_read =
true;
2268 sprintf(tmp_str,
"Capacity (mAh): %d", (
int)batterySettings.Capacity );
2270 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, 15000, batterySettings.Capacity);
2272 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2273 if (current_event == FSM_EVENT_RIGHT) {
2274 batterySettings.Capacity =
MIN(15000, batterySettings.Capacity + 50);
2275 settings_changed =
true;
2277 else if (current_event == FSM_EVENT_LEFT) {
2278 batterySettings.Capacity =
MAX(500, batterySettings.Capacity - 50);
2279 settings_changed =
true;
2283 y_pos += MENU_LINE_SPACING;
2284 sprintf(tmp_str,
"Cell Count : %d", (
int)batterySettings.NbCells );
2286 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 1, 10, batterySettings.NbCells);
2288 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2289 if (current_event == FSM_EVENT_RIGHT) {
2290 batterySettings.NbCells =
MIN(10, batterySettings.NbCells + 1);
2291 settings_changed =
true;
2293 else if (current_event == FSM_EVENT_LEFT) {
2294 batterySettings.NbCells =
MAX(1, batterySettings.NbCells - 1);
2295 settings_changed =
true;
2299 y_pos += MENU_LINE_SPACING;
2300 sprintf(tmp_str,
"Low Cell Warn V: %1.1f", (
double) batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] );
2302 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0.0
f, 4.5
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING]);
2304 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2305 if (current_event == FSM_EVENT_RIGHT) {
2306 batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] =
MIN(4.5
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] + 0.1f);
2307 settings_changed =
true;
2309 else if (current_event == FSM_EVENT_LEFT) {
2310 batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] =
MAX(3.0
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] - 0.1f);
2311 settings_changed =
true;
2316 y_pos += MENU_LINE_SPACING;
2317 sprintf(tmp_str,
"Low Cell Alarm V: %1.1f", (
double) batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] );
2319 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0.0
f, 4.5
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM]);
2321 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2322 if (current_event == FSM_EVENT_RIGHT) {
2323 batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] =
MIN(4.5
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] + 0.1f);
2324 settings_changed =
true;
2326 else if (current_event == FSM_EVENT_LEFT) {
2327 batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] =
MAX(3.0
f, batterySettings.CellVoltageThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] - 0.1f);
2328 settings_changed =
true;
2333 y_pos += MENU_LINE_SPACING;
2334 sprintf(tmp_str,
"Flight Warn Time : %d", batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] );
2336 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, 300, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING]);
2338 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2339 if (current_event == FSM_EVENT_RIGHT) {
2340 batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] =
MIN(4.5
f, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] + 1);
2341 settings_changed =
true;
2343 else if (current_event == FSM_EVENT_LEFT) {
2344 batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] =
MIN(4.5
f, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_WARNING] - 1);
2345 settings_changed =
true;
2350 y_pos += MENU_LINE_SPACING;
2351 sprintf(tmp_str,
"Flight Alarm Time : %d", batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] );
2353 draw_hscale(225,
GRAPHICS_RIGHT - 5, y_pos + 2, 0, 300, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM]);
2355 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2356 if (current_event == FSM_EVENT_RIGHT) {
2357 batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] =
MIN(4.5
f, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] + 1);
2358 settings_changed =
true;
2360 else if (current_event == FSM_EVENT_LEFT) {
2361 batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] =
MIN(4.5
f, batterySettings.FlightTimeThresholds[FLIGHTBATTERYSETTINGS_CELLVOLTAGETHRESHOLDS_ALARM] - 1);
2362 settings_changed =
true;
2366 if (settings_changed)
2367 FlightBatterySettingsSet(&batterySettings);
2370 y_pos += MENU_LINE_SPACING;
2373 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2375 if (current_event == FSM_EVENT_RIGHT ) {
2376 UAVObjSave(FlightBatterySettingsHandle(), 0);
2377 settings_read =
false;
2381 y_pos += MENU_LINE_SPACING;
2384 draw_selected_icon(MENU_LINE_X - 4, y_pos + 4);
2386 if (current_event == FSM_EVENT_RIGHT)
2387 settings_read =
false;
static const uint16_t BAND_5G8_A_FREQS[VTXSETTINGS_BAND_5G8_A_FREQUENCY_MAXOPTVAL+1]
void write_string(char *str, int x, int y, int xs, int ys, int va, int ha, int flags, int font)
int sprintf(char *out, const char *format,...)
void draw_image(uint16_t x, uint16_t y, const struct Image *image)
struct _msp_pid_item pitch
struct _msp_pid_item roll
static const struct Image image_menu_icon
int32_t UAVObjSave(UAVObjHandle obj_handle, uint16_t instId)
static const uint16_t RACEBAND_FREQS[VTXSETTINGS_RACEBAND_FREQUENCY_MAXOPTVAL+1]
uint8_t data[XFER_BYTES_PER_PACKET]
static const uint16_t AIRWAVE_FREQS[VTXSETTINGS_AIRWAVE_FREQUENCY_MAXOPTVAL+1]
static const uint16_t VTX_POWER[VTXSETTINGS_POWER_GLOBAL_MAXOPTVAL+1]
static volatile FlightStatsSettingsData settings
OSD gen module, handles OSD draw. Parts from CL-OSD and SUPEROSD projects.
#define GRAPHICS_X_MIDDLE
#define DONT_BUILD_IF(COND, MSG)
static const uint16_t BAND_5G8_E_FREQS[VTXSETTINGS_BAND_5G8_E_FREQUENCY_MAXOPTVAL+1]
static const uint16_t BAND_5G8_B_FREQS[VTXSETTINGS_BAND_5G8_B_FREQUENCY_MAXOPTVAL+1]
void write_filled_rectangle_lm(int x, int y, int width, int height, int lmode, int mmode)