Skip to content

Commit 308b243

Browse files
authored
Merge pull request #11552 from breadoven/abo_multifunction_refactor
Multifunction refactor
2 parents 0b92214 + 49e2776 commit 308b243

4 files changed

Lines changed: 239 additions & 240 deletions

File tree

src/main/fc/fc_msp_box.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,7 @@ void initActiveBoxIds(void)
190190
RESET_BOX_ID_COUNT;
191191
ADD_ACTIVE_BOX(BOXARM);
192192
ADD_ACTIVE_BOX(BOXPREARM);
193-
#ifdef USE_MULTI_FUNCTIONS
194193
ADD_ACTIVE_BOX(BOXMULTIFUNCTION);
195-
#endif
196194

197195
if (sensors(SENSOR_ACC) && STATE(ALTITUDE_CONTROL)) {
198196
ADD_ACTIVE_BOX(BOXANGLE);

src/main/fc/multifunction.c

Lines changed: 237 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,29 @@
2626
#include "build/debug.h"
2727
#include "drivers/time.h"
2828

29-
#ifdef USE_MULTI_FUNCTIONS
30-
29+
#include "fc/config.h"
3130
#include "fc/fc_core.h"
3231
#include "fc/multifunction.h"
3332
#include "fc/rc_modes.h"
34-
#include "fc/runtime_config.h"
33+
34+
#include "flight/imu.h"
3535

3636
#include "io/osd.h"
37+
3738
#include "navigation/navigation.h"
39+
#include "navigation/navigation_private.h"
40+
41+
#include "sensors/acceleration.h"
42+
#include "sensors/battery.h"
43+
#include "sensors/compass.h"
44+
#include "sensors/diagnostics.h"
45+
#include "sensors/pitotmeter.h"
46+
#include "sensors/sensors.h"
3847

48+
textAttributes_t osdGetMultiFunctionMessage(char *buff);
49+
multiFunctionWarning_t multiFunctionWarning;
50+
51+
#ifdef USE_MULTI_FUNCTIONS
3952
multi_function_e selectedItem = MULTI_FUNC_NONE;
4053
uint8_t multiFunctionFlags;
4154

@@ -49,27 +62,19 @@ static void multiFunctionApply(multi_function_e selectedItem)
4962
break;
5063
case MULTI_FUNC_2: // toggle Safehome suspend
5164
#if defined(USE_SAFE_HOME)
52-
if (navConfig()->general.flags.safehome_usage_mode != SAFEHOME_USAGE_OFF) {
53-
MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_SAFEHOMES) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_SAFEHOMES);
54-
}
65+
MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_SAFEHOMES) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_SAFEHOMES);
5566
#endif
5667
break;
5768
case MULTI_FUNC_3: // toggle RTH Trackback suspend
58-
if (navConfig()->general.flags.rth_trackback_mode != RTH_TRACKBACK_OFF) {
59-
MULTI_FUNC_FLAG(MF_SUSPEND_TRACKBACK) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_TRACKBACK) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_TRACKBACK);
60-
}
69+
MULTI_FUNC_FLAG(MF_SUSPEND_TRACKBACK) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_TRACKBACK) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_TRACKBACK);
6170
break;
62-
case MULTI_FUNC_4:
71+
case MULTI_FUNC_4: // toggle Turtle mode
6372
#ifdef USE_DSHOT
64-
if (!ARMING_FLAG(ARMED) && STATE(MULTIROTOR)) { // toggle Turtle mode
65-
MULTI_FUNC_FLAG(MF_TURTLE_MODE) ? MULTI_FUNC_FLAG_DISABLE(MF_TURTLE_MODE) : MULTI_FUNC_FLAG_ENABLE(MF_TURTLE_MODE);
66-
}
73+
MULTI_FUNC_FLAG(MF_TURTLE_MODE) ? MULTI_FUNC_FLAG_DISABLE(MF_TURTLE_MODE) : MULTI_FUNC_FLAG_ENABLE(MF_TURTLE_MODE);
6774
#endif
6875
break;
6976
case MULTI_FUNC_5: // emergency ARM
70-
if (!ARMING_FLAG(ARMED)) {
71-
emergencyArmingUpdate(true, true);
72-
}
77+
emergencyArmingUpdate(true, true);
7378
break;
7479
case MULTI_FUNC_6: // Calibrate compass/Zero yaw heading
7580
#if defined(USE_GPS) || defined(USE_MAG)
@@ -123,4 +128,220 @@ multi_function_e multiFunctionSelection(void)
123128

124129
return selectedItem;
125130
}
131+
#endif // multifunction
132+
133+
static bool osdCheckWarning(bool condition, uint8_t warningFlag)
134+
{
135+
static timeMs_t newWarningEndTime = 0;
136+
static uint8_t newWarningFlags = 0; // bitfield
137+
const timeMs_t currentTimeMs = millis();
138+
139+
/* New warnings dislayed individually for 10s with blinking after which
140+
* all current warnings displayed without blinking on 1 second cycle */
141+
if (condition) { // condition required to trigger warning
142+
if (!(multiFunctionWarning.osdWarningsFlags & warningFlag)) { // check for new warnings
143+
multiFunctionWarning.osdWarningsFlags |= warningFlag;
144+
newWarningFlags |= warningFlag;
145+
newWarningEndTime = currentTimeMs + 10000;
146+
multiFunctionWarning.newWarningActive = true;
147+
}
148+
#ifdef USE_DEV_TOOLS
149+
if (systemConfig()->groundTestMode) {
150+
return true;
151+
}
126152
#endif
153+
if (currentTimeMs < newWarningEndTime) {
154+
return (newWarningFlags & warningFlag); // filter out new warnings excluding older warnings
155+
} else {
156+
newWarningFlags = 0;
157+
multiFunctionWarning.newWarningActive = false;
158+
}
159+
return true;
160+
} else if (multiFunctionWarning.osdWarningsFlags & warningFlag) {
161+
multiFunctionWarning.osdWarningsFlags &= ~warningFlag;
162+
}
163+
164+
return false;
165+
}
166+
167+
textAttributes_t osdGetMultiFunctionMessage(char *buff)
168+
{
169+
/* Message length limit 10 char max */
170+
171+
textAttributes_t elemAttr = TEXT_ATTRIBUTES_NONE;
172+
const char *message = NULL;
173+
174+
#ifdef USE_MULTI_FUNCTIONS
175+
/* --- FUNCTIONS --- */
176+
multi_function_e selectedFunction = multiFunctionSelection();
177+
178+
if (selectedFunction) {
179+
multi_function_e activeFunction = selectedFunction;
180+
181+
switch (selectedFunction) {
182+
case MULTI_FUNC_NONE:
183+
case MULTI_FUNC_1:
184+
if (ARMING_FLAG(ARMED)) {
185+
message = posControl.flags.manualEmergLandActive ? "ABORT LAND" : "EMERG LAND";
186+
break;
187+
}
188+
activeFunction++;
189+
FALLTHROUGH;
190+
case MULTI_FUNC_2:
191+
#if defined(USE_SAFE_HOME)
192+
if (navConfig()->general.flags.safehome_usage_mode != SAFEHOME_USAGE_OFF) {
193+
message = MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) ? "USE SFHOME" : "SUS SFHOME";
194+
break;
195+
}
196+
#endif
197+
activeFunction++;
198+
FALLTHROUGH;
199+
case MULTI_FUNC_3:
200+
if (navConfig()->general.flags.rth_trackback_mode != RTH_TRACKBACK_OFF) {
201+
message = MULTI_FUNC_FLAG(MF_SUSPEND_TRACKBACK) ? "USE TKBACK" : "SUS TKBACK";
202+
break;
203+
}
204+
activeFunction++;
205+
FALLTHROUGH;
206+
case MULTI_FUNC_4:
207+
#ifdef USE_DSHOT
208+
if (!ARMING_FLAG(ARMED) && STATE(MULTIROTOR)) {
209+
message = MULTI_FUNC_FLAG(MF_TURTLE_MODE) ? "END TURTLE" : "USE TURTLE";
210+
break;
211+
}
212+
#endif
213+
activeFunction++;
214+
FALLTHROUGH;
215+
case MULTI_FUNC_5:
216+
if (!ARMING_FLAG(ARMED)) {
217+
message = "EMERG ARM ";
218+
break;
219+
}
220+
activeFunction++;
221+
FALLTHROUGH;
222+
case MULTI_FUNC_6:
223+
if (!ARMING_FLAG(ARMED)) {
224+
#if defined(USE_MAG)
225+
if (sensors(SENSOR_MAG)) {
226+
message = "CAL COMPAS";
227+
break;
228+
}
229+
#endif
230+
#if defined(USE_GPS)
231+
if (isYawZeroResetAllowed()) {
232+
message = "SET HEADIN";
233+
break;
234+
}
235+
#endif
236+
}
237+
activeFunction++;
238+
break;
239+
case MULTI_FUNC_END:
240+
message = "*FUNC SET*";
241+
break;
242+
}
243+
244+
if (activeFunction != selectedFunction) {
245+
if (selectedFunction == MULTI_FUNC_1 && activeFunction == MULTI_FUNC_END) { // no functions available so end process
246+
message = "*NO FUNCS*";
247+
setMultifunctionSelection(MULTI_FUNC_NONE);
248+
} else {
249+
setMultifunctionSelection(activeFunction);
250+
if (activeFunction == MULTI_FUNC_END) { // no messages to display so return
251+
return elemAttr;
252+
}
253+
}
254+
}
255+
256+
strcpy(buff, message);
257+
258+
return elemAttr;
259+
}
260+
#endif // MULTIFUNCTION - functions only, warnings always defined
261+
262+
/* --- WARNINGS --- */
263+
const char *messages[8];
264+
uint8_t messageCount = 0;
265+
bool warningCondition = false;
266+
uint8_t warningFlagID = 1;
267+
268+
// Low Battery Voltage
269+
const batteryState_e batteryVoltageState = checkBatteryVoltageState();
270+
warningCondition = batteryVoltageState == BATTERY_CRITICAL || batteryVoltageState == BATTERY_WARNING;
271+
if (osdCheckWarning(warningCondition, warningFlagID)) {
272+
messages[messageCount++] = batteryVoltageState == BATTERY_CRITICAL ? "VBATT LAND" : "VBATT LOW ";
273+
}
274+
275+
// Low Battery Capacity
276+
if (batteryUsesCapacityThresholds()) {
277+
const batteryState_e batteryState = getBatteryState();
278+
warningCondition = batteryState == BATTERY_CRITICAL || batteryState == BATTERY_WARNING;
279+
if (osdCheckWarning(warningCondition, warningFlagID <<= 1)) {
280+
messages[messageCount++] = batteryState == BATTERY_CRITICAL ? "BATT EMPTY" : "BATT DYING";
281+
}
282+
}
283+
#if defined(USE_GPS)
284+
// GPS Fix and Failure
285+
if (feature(FEATURE_GPS)) {
286+
if (osdCheckWarning(!STATE(GPS_FIX), warningFlagID <<= 1)) {
287+
bool gpsFailed = getHwGPSStatus() == HW_SENSOR_UNAVAILABLE;
288+
messages[messageCount++] = gpsFailed ? "GPS FAILED" : "NO GPS FIX";
289+
}
290+
}
291+
292+
// RTH sanity (warning if RTH heads 200m further away from home than closest point)
293+
warningCondition = NAV_Status.state == MW_NAV_STATE_RTH_ENROUTE && !posControl.flags.rthTrackbackActive &&
294+
(posControl.homeDistance - posControl.rthSanityChecker.minimalDistanceToHome) > 20000;
295+
if (osdCheckWarning(warningCondition, warningFlagID <<= 1)) {
296+
messages[messageCount++] = "RTH SANITY";
297+
}
298+
299+
// Altitude sanity (warning if significant mismatch between estimated and GPS altitude)
300+
if (osdCheckWarning(posControl.flags.gpsCfEstimatedAltitudeMismatch, warningFlagID <<= 1)) {
301+
messages[messageCount++] = "ALT SANITY";
302+
}
303+
#endif
304+
305+
#if defined(USE_MAG)
306+
// Magnetometer failure
307+
if (requestedSensors[SENSOR_INDEX_MAG] != MAG_NONE) {
308+
hardwareSensorStatus_e magStatus = getHwCompassStatus();
309+
if (osdCheckWarning(magStatus == HW_SENSOR_UNAVAILABLE || magStatus == HW_SENSOR_UNHEALTHY, warningFlagID <<= 1)) {
310+
messages[messageCount++] = "MAG FAILED";
311+
}
312+
}
313+
#endif
314+
315+
#if defined(USE_PITOT)
316+
// Pitot sensor validation failure (blocked/failed pitot tube)
317+
if (sensors(SENSOR_PITOT) && detectedSensors[SENSOR_INDEX_PITOT] != PITOT_VIRTUAL) {
318+
if (osdCheckWarning(pitotHasFailed(), warningFlagID <<= 1)) {
319+
messages[messageCount++] = "PITOT FAIL";
320+
}
321+
}
322+
#endif
323+
324+
// Vibration levels TODO - needs better vibration measurement to be useful
325+
// const float vibrationLevel = accGetVibrationLevel();
326+
// warningCondition = vibrationLevel > 1.5f;
327+
// if (osdCheckWarning(warningCondition, warningFlagID <<= 1, &warningsCount)) {
328+
// messages[messageCount++] = vibrationLevel > 2.5f ? "BAD VIBRTN" : "VIBRATION!";
329+
// }
330+
331+
#ifdef USE_DEV_TOOLS
332+
if (osdCheckWarning(systemConfig()->groundTestMode, warningFlagID <<= 1)) {
333+
messages[messageCount++] = "GRD TEST !";
334+
}
335+
#endif
336+
337+
if (messageCount) {
338+
message = messages[(millis() / 1000) % messageCount]; // display each warning on 1s cycle
339+
strcpy(buff, message);
340+
if (multiFunctionWarning.newWarningActive) {
341+
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
342+
}
343+
}
344+
345+
return elemAttr;
346+
}
347+

src/main/fc/multifunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#pragma once
2626

2727
#include <stdbool.h>
28+
#include "drivers/display.h"
2829

2930
typedef struct multiFunctionWarning_s {
3031
uint8_t osdWarningsFlags; // bitfield
@@ -61,3 +62,4 @@ typedef enum {
6162
multi_function_e multiFunctionSelection(void);
6263
void setMultifunctionSelection(multi_function_e item);
6364
#endif
65+
textAttributes_t osdGetMultiFunctionMessage(char *buff);

0 commit comments

Comments
 (0)