diff --git a/src/main/fc/multifunction.c b/src/main/fc/multifunction.c index c217110842d..2ac3a558278 100644 --- a/src/main/fc/multifunction.c +++ b/src/main/fc/multifunction.c @@ -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); } diff --git a/src/main/fc/multifunction.h b/src/main/fc/multifunction.h index 93265ba1200..6e60da2bdd8 100644 --- a/src/main/fc/multifunction.h +++ b/src/main/fc/multifunction.h @@ -26,6 +26,13 @@ #include +typedef struct multiFunctionWarning_s { + uint8_t osdWarningsFlags; // bitfield + bool newWarningActive; +} multiFunctionWarning_t; + +extern multiFunctionWarning_t multiFunctionWarning; + #ifdef USE_MULTI_FUNCTIONS extern uint8_t multiFunctionFlags; @@ -47,7 +54,6 @@ typedef enum { MULTI_FUNC_3, MULTI_FUNC_4, MULTI_FUNC_5, - MULTI_FUNC_6, MULTI_FUNC_END, } multi_function_e; diff --git a/src/main/fc/settings.yaml b/src/main/fc/settings.yaml index 1e1932531e5..476dfe09ff7 100644 --- a/src/main/fc/settings.yaml +++ b/src/main/fc/settings.yaml @@ -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"] diff --git a/src/main/io/osd.c b/src/main/io/osd.c index 6ad55632c17..f4fe19a4040 100644 --- a/src/main/io/osd.c +++ b/src/main/io/osd.c @@ -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; @@ -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; @@ -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 @@ -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"; @@ -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"; @@ -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: @@ -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"; } @@ -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 @@ -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"; } } @@ -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"; } } @@ -6586,7 +6576,7 @@ 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 @@ -6594,10 +6584,9 @@ static textAttributes_t osdGetMultiFunctionMessage(char *buff) 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; diff --git a/src/main/io/osd.h b/src/main/io/osd.h index bbaa68f862d..88240ff84c0 100644 --- a/src/main/io/osd.h +++ b/src/main/io/osd.h @@ -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); /** diff --git a/src/main/sensors/battery.c b/src/main/sensors/battery.c index 38d410610e1..79706c8dba7 100644 --- a/src/main/sensors/battery.c +++ b/src/main/sensors/battery.c @@ -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(); @@ -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)