Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions src/main/fc/multifunction.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,32 +45,29 @@ static void multiFunctionApply(multi_function_e selectedItem)
switch (selectedItem) {
case MULTI_FUNC_NONE:
break;
case MULTI_FUNC_1: // redisplay current warnings
osdResetWarningFlags();
break;
case MULTI_FUNC_2: // control manual emergency landing
case MULTI_FUNC_1: // control manual emergency landing
checkManualEmergencyLandingControl(ARMING_FLAG(ARMED));
break;
case MULTI_FUNC_3: // toggle Safehome suspend
case MULTI_FUNC_2: // toggle Safehome suspend
#if defined(USE_SAFE_HOME)
if (navConfig()->general.flags.safehome_usage_mode != SAFEHOME_USAGE_OFF) {
MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_SAFEHOMES) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_SAFEHOMES);
}
#endif
break;
case MULTI_FUNC_4: // toggle RTH Trackback suspend
case MULTI_FUNC_3: // toggle RTH Trackback suspend
if (navConfig()->general.flags.rth_trackback_mode != RTH_TRACKBACK_OFF) {
MULTI_FUNC_FLAG(MF_SUSPEND_TRACKBACK) ? MULTI_FUNC_FLAG_DISABLE(MF_SUSPEND_TRACKBACK) : MULTI_FUNC_FLAG_ENABLE(MF_SUSPEND_TRACKBACK);
}
break;
case MULTI_FUNC_5:
case MULTI_FUNC_4:
#ifdef USE_DSHOT
if (STATE(MULTIROTOR)) { // toggle Turtle mode
MULTI_FUNC_FLAG(MF_TURTLE_MODE) ? MULTI_FUNC_FLAG_DISABLE(MF_TURTLE_MODE) : MULTI_FUNC_FLAG_ENABLE(MF_TURTLE_MODE);
}
#endif
break;
case MULTI_FUNC_6: // emergency ARM
case MULTI_FUNC_5: // emergency ARM
if (!ARMING_FLAG(ARMED)) {
emergencyArmingUpdate(true, true);
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/fc/multifunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@

#include <stdbool.h>

typedef struct multiFunctionWarning_s {
uint8_t osdWarningsFlags; // bitfield
bool newWarningActive;
} multiFunctionWarning_t;

extern multiFunctionWarning_t multiFunctionWarning;

#ifdef USE_MULTI_FUNCTIONS

extern uint8_t multiFunctionFlags;
Expand All @@ -47,7 +54,6 @@ typedef enum {
MULTI_FUNC_3,
MULTI_FUNC_4,
MULTI_FUNC_5,
MULTI_FUNC_6,
MULTI_FUNC_END,
} multi_function_e;

Expand Down
1 change: 1 addition & 0 deletions src/main/fc/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3904,6 +3904,7 @@ groups:
field: osd_switch_indicators_align_left
type: bool
default_value: ON

- name: PG_OSD_COMMON_CONFIG
type: osdCommonConfig_t
headers: ["io/osd_common.h"]
Expand Down
99 changes: 44 additions & 55 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ static bool fullRedraw = false;

static uint8_t armState;

// Multifunction
static textAttributes_t osdGetMultiFunctionMessage(char *buff);
static uint8_t osdWarningsFlags = 0;
multiFunctionWarning_t multiFunctionWarning;

typedef struct osdMapData_s {
uint32_t scale;
Expand Down Expand Up @@ -6405,49 +6406,35 @@ textAttributes_t osdGetSystemMessage(char *buff, size_t buff_size, bool isCenter
return elemAttr;
}

void osdResetWarningFlags(void)
static bool osdCheckWarning(bool condition, uint8_t warningFlag)
{
osdWarningsFlags = 0;
}

static bool osdCheckWarning(bool condition, uint8_t warningFlag, uint8_t *warningsCount)
{
#define WARNING_REDISPLAY_DURATION 5000; // milliseconds

static timeMs_t newWarningEndTime = 0;
static uint8_t newWarningFlags = 0; // bitfield
const timeMs_t currentTimeMs = millis();
static timeMs_t warningDisplayStartTime = 0;
static timeMs_t redisplayStartTimeMs = 0;
static uint16_t osdWarningTimerDuration;
static uint8_t newWarningFlags;

/* New warnings dislayed individually for 10s with blinking after which
* all current warnings displayed without blinking on 1 second cycle */
if (condition) { // condition required to trigger warning
if (!(osdWarningsFlags & warningFlag)) {
osdWarningsFlags |= warningFlag;
if (!(multiFunctionWarning.osdWarningsFlags & warningFlag)) { // check for new warnings
multiFunctionWarning.osdWarningsFlags |= warningFlag;
newWarningFlags |= warningFlag;
redisplayStartTimeMs = 0;
newWarningEndTime = currentTimeMs + 10000;
multiFunctionWarning.newWarningActive = true;
}
#ifdef USE_DEV_TOOLS
if (systemConfig()->groundTestMode) {
return true;
}
#endif
/* Warnings displayed in full for set time before shrinking down to alert symbol with warning count only.
* All current warnings then redisplayed for 5s on 30s rolling cycle.
* New warnings dislayed individually for 10s */
if (currentTimeMs > redisplayStartTimeMs) {
warningDisplayStartTime = currentTimeMs;
osdWarningTimerDuration = newWarningFlags ? 10000 : WARNING_REDISPLAY_DURATION;
redisplayStartTimeMs = currentTimeMs + osdWarningTimerDuration + 30000;
}

if (currentTimeMs - warningDisplayStartTime < osdWarningTimerDuration) {
return (newWarningFlags & warningFlag) || osdWarningTimerDuration == WARNING_REDISPLAY_DURATION;
if (currentTimeMs < newWarningEndTime) {
return (newWarningFlags & warningFlag); // filter out new warnings excluding older warnings
} else {
newWarningFlags = 0;
multiFunctionWarning.newWarningActive = false;
}
*warningsCount += 1;
} else if (osdWarningsFlags & warningFlag) {
osdWarningsFlags &= ~warningFlag;
return true;
} else if (multiFunctionWarning.osdWarningsFlags & warningFlag) {
multiFunctionWarning.osdWarningsFlags &= ~warningFlag;
}

return false;
Expand All @@ -6458,7 +6445,6 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
/* Message length limit 10 char max */

textAttributes_t elemAttr = TEXT_ATTRIBUTES_NONE;
static uint8_t warningsCount;
const char *message = NULL;

#ifdef USE_MULTI_FUNCTIONS
Expand All @@ -6471,12 +6457,9 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
switch (selectedFunction) {
case MULTI_FUNC_NONE:
case MULTI_FUNC_1:
message = warningsCount ? "WARNINGS !" : "0 WARNINGS";
break;
case MULTI_FUNC_2:
message = posControl.flags.manualEmergLandActive ? "ABORT LAND" : "EMERG LAND";
break;
case MULTI_FUNC_3:
case MULTI_FUNC_2:
#if defined(USE_SAFE_HOME)
if (navConfig()->general.flags.safehome_usage_mode != SAFEHOME_USAGE_OFF) {
message = MULTI_FUNC_FLAG(MF_SUSPEND_SAFEHOMES) ? "USE SFHOME" : "SUS SFHOME";
Expand All @@ -6485,14 +6468,14 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
#endif
activeFunction++;
FALLTHROUGH;
case MULTI_FUNC_4:
case MULTI_FUNC_3:
if (navConfig()->general.flags.rth_trackback_mode != RTH_TRACKBACK_OFF) {
message = MULTI_FUNC_FLAG(MF_SUSPEND_TRACKBACK) ? "USE TKBACK" : "SUS TKBACK";
break;
}
activeFunction++;
FALLTHROUGH;
case MULTI_FUNC_5:
case MULTI_FUNC_4:
#ifdef USE_DSHOT
if (STATE(MULTIROTOR)) {
message = MULTI_FUNC_FLAG(MF_TURTLE_MODE) ? "END TURTLE" : "USE TURTLE";
Expand All @@ -6501,7 +6484,7 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
#endif
activeFunction++;
FALLTHROUGH;
case MULTI_FUNC_6:
case MULTI_FUNC_5:
message = ARMING_FLAG(ARMED) ? "NOW ARMED " : "EMERG ARM ";
break;
case MULTI_FUNC_END:
Expand All @@ -6524,23 +6507,30 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
#endif // MULTIFUNCTION - functions only, warnings always defined

/* --- WARNINGS --- */
const char *messages[7];
const char *messages[8];
uint8_t messageCount = 0;
bool warningCondition = false;
warningsCount = 0;
uint8_t warningFlagID = 1;

// Low Battery
const batteryState_e batteryState = getBatteryState();
warningCondition = batteryState == BATTERY_CRITICAL || batteryState == BATTERY_WARNING;
if (osdCheckWarning(warningCondition, warningFlagID, &warningsCount)) {
messages[messageCount++] = batteryState == BATTERY_CRITICAL ? "BATT EMPTY" : "BATT LOW !";
// Low Battery Voltage
const batteryState_e batteryVoltageState = checkBatteryVoltageState();
warningCondition = batteryVoltageState == BATTERY_CRITICAL || batteryVoltageState == BATTERY_WARNING;
if (osdCheckWarning(warningCondition, warningFlagID)) {
messages[messageCount++] = batteryVoltageState == BATTERY_CRITICAL ? "VBATT LAND" : "VBATT LOW ";
}

// Low Battery Capacity
if (batteryUsesCapacityThresholds()) {
const batteryState_e batteryState = getBatteryState();
warningCondition = batteryState == BATTERY_CRITICAL || batteryState == BATTERY_WARNING;
if (osdCheckWarning(warningCondition, warningFlagID <<= 1)) {
messages[messageCount++] = batteryState == BATTERY_CRITICAL ? "BATT EMPTY" : "BATT DYING";
}
}
#if defined(USE_GPS)
// GPS Fix and Failure
if (feature(FEATURE_GPS)) {
if (osdCheckWarning(!STATE(GPS_FIX), warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(!STATE(GPS_FIX), warningFlagID <<= 1)) {
bool gpsFailed = getHwGPSStatus() == HW_SENSOR_UNAVAILABLE;
messages[messageCount++] = gpsFailed ? "GPS FAILED" : "NO GPS FIX";
}
Expand All @@ -6549,12 +6539,12 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
// RTH sanity (warning if RTH heads 200m further away from home than closest point)
warningCondition = NAV_Status.state == MW_NAV_STATE_RTH_ENROUTE && !posControl.flags.rthTrackbackActive &&
(posControl.homeDistance - posControl.rthSanityChecker.minimalDistanceToHome) > 20000;
if (osdCheckWarning(warningCondition, warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(warningCondition, warningFlagID <<= 1)) {
messages[messageCount++] = "RTH SANITY";
}

// Altitude sanity (warning if significant mismatch between estimated and GPS altitude)
if (osdCheckWarning(posControl.flags.gpsCfEstimatedAltitudeMismatch, warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(posControl.flags.gpsCfEstimatedAltitudeMismatch, warningFlagID <<= 1)) {
messages[messageCount++] = "ALT SANITY";
}
#endif
Expand All @@ -6563,7 +6553,7 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
// Magnetometer failure
if (requestedSensors[SENSOR_INDEX_MAG] != MAG_NONE) {
hardwareSensorStatus_e magStatus = getHwCompassStatus();
if (osdCheckWarning(magStatus == HW_SENSOR_UNAVAILABLE || magStatus == HW_SENSOR_UNHEALTHY, warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(magStatus == HW_SENSOR_UNAVAILABLE || magStatus == HW_SENSOR_UNHEALTHY, warningFlagID <<= 1)) {
messages[messageCount++] = "MAG FAILED";
}
}
Expand All @@ -6572,7 +6562,7 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
#if defined(USE_PITOT)
// Pitot sensor validation failure (blocked/failed pitot tube)
if (sensors(SENSOR_PITOT) && detectedSensors[SENSOR_INDEX_PITOT] != PITOT_VIRTUAL) {
if (osdCheckWarning(pitotHasFailed(), warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(pitotHasFailed(), warningFlagID <<= 1)) {
messages[messageCount++] = "PITOT FAIL";
}
}
Expand All @@ -6586,18 +6576,17 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff)
// }

#ifdef USE_DEV_TOOLS
if (osdCheckWarning(systemConfig()->groundTestMode, warningFlagID <<= 1, &warningsCount)) {
if (osdCheckWarning(systemConfig()->groundTestMode, warningFlagID <<= 1)) {
messages[messageCount++] = "GRD TEST !";
}
#endif

if (messageCount) {
message = messages[OSD_ALTERNATING_CHOICES(1000, messageCount)]; // display each warning on 1s cycle
strcpy(buff, message);
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
} else if (warningsCount) {
buff[0] = SYM_ALERT;
tfp_sprintf(buff + 1, "%u ", warningsCount);
if (multiFunctionWarning.newWarningActive) {
TEXT_ATTRIBUTES_ADD_BLINK(elemAttr);
}
}

return elemAttr;
Expand Down
2 changes: 0 additions & 2 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,6 @@ int osdFormatVelocityStr(char* buff, int32_t vel, osd_SpeedTypes_e speedType, bo
// Returns a heading angle in degrees normalized to [0, 360).
int osdGetHeadingAngle(int angle);

void osdResetWarningFlags(void);

int16_t osdGetPanServoOffset(void);

/**
Expand Down
16 changes: 9 additions & 7 deletions src/main/sensors/battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ static void updateBatteryVoltage(timeUs_t timeDelta, bool justConnected)
}
break;
#endif

#if defined(USE_FAKE_BATT_SENSOR)
case VOLTAGE_SENSOR_FAKE:
vbat = fakeBattSensorGetVBat();
Expand Down Expand Up @@ -328,30 +328,32 @@ static void updateBatteryVoltage(timeUs_t timeDelta, bool justConnected)
batteryState_e checkBatteryVoltageState(void)
{
uint16_t stateVoltage = getBatteryVoltage();
switch (batteryState)
static batteryState_e currentBatteryVoltageState = BATTERY_OK;

switch (currentBatteryVoltageState)
{
case BATTERY_OK:
if (stateVoltage <= (batteryWarningVoltage - VBATT_HYSTERESIS)) {
return BATTERY_WARNING;
currentBatteryVoltageState = BATTERY_WARNING;
}
break;
case BATTERY_WARNING:
if (stateVoltage <= (batteryCriticalVoltage - VBATT_HYSTERESIS)) {
return BATTERY_CRITICAL;
currentBatteryVoltageState = BATTERY_CRITICAL;
} else if (stateVoltage > (batteryWarningVoltage + VBATT_HYSTERESIS)){
return BATTERY_OK;
currentBatteryVoltageState = BATTERY_OK;
}
break;
case BATTERY_CRITICAL:
if (stateVoltage > (batteryCriticalVoltage + VBATT_HYSTERESIS)) {
return BATTERY_WARNING;
currentBatteryVoltageState = BATTERY_WARNING;
}
break;
default:
break;
}

return batteryState;
return currentBatteryVoltageState;
}

static void checkBatteryCapacityState(void)
Expand Down