Skip to content
Draft
2 changes: 1 addition & 1 deletion src/main/cms/cms.c
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
setServoOutputEnabled(true);

if ((exitType == CMS_EXIT_SAVEREBOOT) || (exitType == CMS_POPUP_SAVEREBOOT)) {
processDelayedSave();
processDelayedSave(true);
displayClearScreen(pDisplay);
displayWrite(pDisplay, 5, 3, "REBOOTING...");

Expand Down
14 changes: 7 additions & 7 deletions src/main/common/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

#pragma once

#define FEET_PER_MILE 5280
#define FEET_PER_NAUTICALMILE 6076.118f
#define FEET_PER_KILOFEET 1000 // Used for altitude
#define METERS_PER_KILOMETER 1000
#define METERS_PER_MILE 1609.344f
#define METERS_PER_FOOT 3.28084f
#define METERS_PER_NAUTICALMILE 1852.001f
#define FEET_PER_MILE 5280
#define FEET_PER_NAUTICALMILE 6076.118f
#define FEET_PER_KILOFEET 1000 // Used for altitude
#define METERS_PER_KILOMETER 1000
#define METERS_PER_MILE 1609.344f
#define METERS_PER_FOOT 3.28084f
#define METERS_PER_NAUTICALMILE 1852.001f
24 changes: 17 additions & 7 deletions src/main/fc/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@

#include "fc/config.h"
#include "fc/controlrate_profile.h"
#include "fc/fc_core.h"
#include "fc/rc_adjustments.h"
#include "fc/rc_controls.h"
#include "fc/rc_curves.h"
Expand Down Expand Up @@ -375,9 +376,6 @@ void ensureEEPROMContainsValidData(void)
*/
void saveConfigAndNotify(void)
{
#ifdef USE_OSD
osdStartedSaveProcess();
#endif
saveState = SAVESTATE_SAVEANDNOTIFY;
}

Expand All @@ -393,12 +391,24 @@ void saveConfig(void)
}
}

void processDelayedSave(void)
void processDelayedSave(bool readyToSave)
{
if (saveState == SAVESTATE_SAVEANDNOTIFY) {
processSaveConfigAndNotify();
saveState = SAVESTATE_NONE;
} else if (saveState == SAVESTATE_SAVEONLY) {
if (emergInflightRearmEnabled() || !readyToSave) {
// Do not process save if we are potentially still flying. Once armed, this function will not be called until the next disarm.
#ifdef USE_OSD
osdSaveWaitingProcess();
#endif
} else {
#ifdef USE_OSD
osdStartedSaveProcess();
#endif
if (readyToSave) {
processSaveConfigAndNotify();
saveState = SAVESTATE_NONE;
}
}
} else if (saveState == SAVESTATE_SAVEONLY && readyToSave) {
suspendRxSignal();
writeEEPROM();
resumeRxSignal();
Expand Down
2 changes: 1 addition & 1 deletion src/main/fc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void resetEEPROM(void);
void readEEPROM(void);
void writeEEPROM(void);
void ensureEEPROMContainsValidData(void);
void processDelayedSave(void);
void processDelayedSave(bool readyToSave);

void saveConfig(void);
void saveConfigAndNotify(void);
Expand Down
29 changes: 24 additions & 5 deletions src/main/fc/fc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "io/beeper.h"
#include "io/dashboard.h"
#include "io/gps.h"
#include "io/osd.h"
#include "io/serial.h"
#include "io/statusindicator.h"
#include "io/asyncfatfs/asyncfatfs.h"
Expand Down Expand Up @@ -499,12 +500,29 @@ bool emergencyArmingUpdate(bool armingSwitchIsOn, bool forceArm)
return counter >= EMERGENCY_ARMING_MIN_ARM_COUNT;
}

uint16_t emergencyInFlightRearmTimeMS(void)
{
uint16_t rearmMS = 0;

if (STATE(IN_FLIGHT_EMERG_REARM)) {
timeMs_t currentTimeMs = millis();
rearmMS = (uint16_t)((US2MS(lastDisarmTimeUs) + EMERGENCY_INFLIGHT_REARM_TIME_WINDOW_MS) - currentTimeMs);
}

return rearmMS;
}

bool emergInflightRearmEnabled(void)
{
/* Emergency rearm allowed within 5s timeout period after disarm if craft still flying */
// bool emergRearmActive = STATE(IN_FLIGHT_EMERG_REARM);
// DISABLE_STATE(IN_FLIGHT_EMERG_REARM);
timeMs_t currentTimeMs = millis();
emergRearmStabiliseTimeout = 0;

// if (ARMING_FLAG(ARMED) && emergRearmActive && (armTime < (1 * USECS_PER_SEC)))
// ENABLE_STATE(IN_FLIGHT_EMERG_REARM); // This stays active for 1 second after re-arming

if ((lastDisarmReason != DISARM_SWITCH) ||
(currentTimeMs > US2MS(lastDisarmTimeUs) + EMERGENCY_INFLIGHT_REARM_TIME_WINDOW_MS)) {
return false;
Expand Down Expand Up @@ -872,7 +890,6 @@ static void applyThrottleTiltCompensation(void)

void taskMainPidLoop(timeUs_t currentTimeUs)
{

cycleTime = getTaskDeltaTime(TASK_SELF);
dT = (float)cycleTime * 0.000001f;

Expand All @@ -885,13 +902,15 @@ void taskMainPidLoop(timeUs_t currentTimeUs)
if (!ARMING_FLAG(ARMED)) {
armTime = 0;

// Delay saving for 0.5s to allow other functions to process save actions on disarm
if (currentTimeUs - lastDisarmTimeUs > USECS_PER_SEC / 2) {
processDelayedSave();
}
// Delay saving for 0.5s to allow other functions to finish processing data to be stored on disarm
processDelayedSave((currentTimeUs - lastDisarmTimeUs > USECS_PER_SEC));
}

if (armTime > 1 * USECS_PER_SEC) { // reset in flight emerg rearm flag 1 sec after arming once it's served its purpose
#ifdef USE_OSD
if (STATE(IN_FLIGHT_EMERG_REARM))
osdSaveProcessAborted();
#endif
DISABLE_STATE(IN_FLIGHT_EMERG_REARM);
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/fc/fc_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ timeUs_t getLastDisarmTimeUs(void);
void tryArm(void);
disarmReason_t getDisarmReason(void);

uint16_t emergencyInFlightRearmTimeMS(void);
bool emergencyArmingUpdate(bool armingSwitchIsOn, bool forceArm);
bool emergInflightRearmEnabled(void);

bool areSensorsCalibrating(void);
float getFlightTime(void);
Expand Down
13 changes: 13 additions & 0 deletions src/main/fc/fc_msp.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,22 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
sbufWriteU8(dst, getConfigProfile());

if (cmdMSP == MSP_STATUS_EX) {
#if defined(USE_OSD) && defined(USE_MSP_OSD)
bool armingBit = bitArrayGet(mspBoxModeFlags.bits, BOXARM);
// If we are in emergency re-arm period and using MSP DisplayPort OSD, show that we are still Armed to prevent the VTX entering low power mode
if (feature(FEATURE_OSD) && emergInflightRearmEnabled())
bitArraySet(mspBoxModeFlags.bits, BOXARM);
#endif
sbufWriteU16(dst, averageSystemLoadPercent);
sbufWriteU16(dst, armingFlags);
sbufWriteU8(dst, accGetCalibrationAxisFlags());

#if defined(USE_OSD) && defined(USE_MSP_OSD)
if (armingBit)
bitArraySet(mspBoxModeFlags.bits, BOXARM);
else
bitArrayClr(mspBoxModeFlags.bits, BOXARM);
#endif
}
}
break;
Expand Down
3 changes: 1 addition & 2 deletions src/main/fc/rc_controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ void processRcStickPositions(bool isThrottleLow)
tryArm();
return;
}
}
else {
} else {
if (armingSwitchIsActive) {
rcDisarmTimeMs = currentTimeMs;
tryArm();
Expand Down
102 changes: 65 additions & 37 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,16 @@
#define OSD_MIN_FONT_VERSION 3

static timeMs_t linearDescentMessageMs = 0;

typedef enum {
OSD_SAVE_MESSAGE_NONE,
OSD_SAVE_MESSAGE_WAITING,
OSD_SAVE_MESSAGE_SAVING,
OSD_SAVE_MESSAGE_SAVED
} osd_saveMessage_e;

static timeMs_t notify_settings_saved = 0;
static bool savingSettings = false;
static uint8_t savingSettings = OSD_SAVE_MESSAGE_NONE;

static unsigned currentLayout = 0;
static int layoutOverride = -1;
Expand Down Expand Up @@ -226,12 +234,22 @@ static bool osdDisplayHasCanvas;
PG_REGISTER_WITH_RESET_TEMPLATE(osdConfig_t, osdConfig, PG_OSD_CONFIG, 9);
PG_REGISTER_WITH_RESET_FN(osdLayoutsConfig_t, osdLayoutsConfig, PG_OSD_LAYOUTS_CONFIG, 1);

void osdSaveProcessAborted(void) {
notify_settings_saved = 0;
savingSettings = OSD_SAVE_MESSAGE_NONE;
}

void osdSaveWaitingProcess(void) {
if (savingSettings == OSD_SAVE_MESSAGE_NONE)
savingSettings = OSD_SAVE_MESSAGE_WAITING;
}

void osdStartedSaveProcess(void) {
savingSettings = true;
savingSettings = OSD_SAVE_MESSAGE_SAVING;
}

void osdShowEEPROMSavedNotification(void) {
savingSettings = false;
savingSettings = OSD_SAVE_MESSAGE_SAVED;
notify_settings_saved = millis() + 5000;
}

Expand Down Expand Up @@ -5086,22 +5104,30 @@ static void osdShowStats(bool isSinglePageStatsCompatible, uint8_t page)
// The following has been commented out as it will be added in #9688
// uint16_t rearmMs = (emergInflightRearmEnabled()) ? emergencyInFlightRearmTimeMS() : 0;

if (savingSettings == true) {
if (savingSettings == OSD_SAVE_MESSAGE_SAVING) {
displayWrite(osdDisplayPort, (osdDisplayPort->cols - strlen(OSD_MESSAGE_STR(OSD_MSG_SAVING_SETTNGS))) / 2, row++, OSD_MESSAGE_STR(OSD_MSG_SAVING_SETTNGS));
/*} else if (rearmMs > 0) { // Show rearming time if settings not actively being saved. Ignore the settings saved message if rearm available.
char emReArmMsg[23];
tfp_sprintf(emReArmMsg, "** REARM PERIOD: ");
tfp_sprintf(emReArmMsg + strlen(emReArmMsg), "%02d", (uint8_t)MS2S(rearmMs));
strcat(emReArmMsg, " **\0");
displayWrite(osdDisplayPort, statNameX, top++, OSD_MESSAGE_STR(emReArmMsg));*/
} else if (savingSettings == OSD_SAVE_MESSAGE_WAITING) {
displayWrite(osdDisplayPort, (osdDisplayPort->cols - strlen(OSD_MESSAGE_STR(OSD_MSG_WAITING_TO_SAVE))) / 2, row++, OSD_MESSAGE_STR(OSD_MSG_WAITING_TO_SAVE));
} else if (notify_settings_saved > 0) {
if (millis() > notify_settings_saved) {
notify_settings_saved = 0;
} else {
savingSettings = OSD_SAVE_MESSAGE_NONE;
} else if (savingSettings == OSD_SAVE_MESSAGE_SAVED) {
displayWrite(osdDisplayPort, (osdDisplayPort->cols - strlen(OSD_MESSAGE_STR(OSD_MSG_SETTINGS_SAVED))) / 2, row++, OSD_MESSAGE_STR(OSD_MSG_SETTINGS_SAVED));
}
}

if (emergInflightRearmEnabled()) {
uint16_t rearmMs = emergencyInFlightRearmTimeMS();
if (rearmMs > 0) {
char emReArmMsg[23];
tfp_sprintf(emReArmMsg, "** REARM PERIOD: ");
tfp_sprintf(emReArmMsg + strlen(emReArmMsg), "%02d", (uint8_t)MS2S(rearmMs));
strcat(emReArmMsg, " **\0");
displayWrite(osdDisplayPort, statNameX, row++, OSD_MESSAGE_STR(emReArmMsg));
}
}

displayCommitTransaction(osdDisplayPort);
}

Expand Down Expand Up @@ -5393,9 +5419,10 @@ static void osdRefresh(timeUs_t currentTimeUs)
}

bool statsSinglePageCompatible = (osdDisplayPort->rows >= OSD_STATS_SINGLE_PAGE_MIN_ROWS);
static uint8_t statsCurrentPage = 0;
static bool statsDisplayed = false;
static bool statsAutoPagingEnabled = true;
static uint8_t statsCurrentPage = 0;
static timeMs_t statsRefreshTime = 0;
static bool statsDisplayed = false;
static bool statsAutoPagingEnabled = true;

// Detect arm/disarm
if (armState != ARMING_FLAG(ARMED)) {
Expand Down Expand Up @@ -5463,25 +5490,24 @@ static void osdRefresh(timeUs_t currentTimeUs)
// Alternate screens for multi-page stats.
// Also, refreshes screen at swap interval for single-page stats.
if (OSD_ALTERNATING_CHOICES((osdConfig()->stats_page_auto_swap_time * 1000), 2)) {
if (statsCurrentPage == 0) {
osdShowStats(statsSinglePageCompatible, statsCurrentPage);
if (statsCurrentPage == 0)
statsCurrentPage = 1;
}
} else {
if (statsCurrentPage == 1) {
osdShowStats(statsSinglePageCompatible, statsCurrentPage);
if (statsCurrentPage == 1)
statsCurrentPage = 0;
}
}
} else {
// Process manual page change events for multi-page stats.
if (manualPageUpRequested) {
osdShowStats(statsSinglePageCompatible, 1);
if (manualPageUpRequested)
statsCurrentPage = 1;
} else if (manualPageDownRequested) {
osdShowStats(statsSinglePageCompatible, 0);
else if (manualPageDownRequested)
statsCurrentPage = 0;
}
}

// Only refresh the stats every 1/4 of a second.
if (statsRefreshTime <= millis()) {
statsRefreshTime = millis() + 250;
osdShowStats(statsSinglePageCompatible, statsCurrentPage);
}
}

Expand Down Expand Up @@ -5838,26 +5864,28 @@ textAttributes_t osdGetSystemMessage(char *buff, size_t buff_size, bool isCenter
}

/* Messages that are shown regardless of Arming state */

// The following has been commented out as it will be added in #9688
// uint16_t rearmMs = (emergInflightRearmEnabled()) ? emergencyInFlightRearmTimeMS() : 0;

if (savingSettings == true) {
if (savingSettings == OSD_SAVE_MESSAGE_SAVING) {
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_SAVING_SETTNGS);
/*} else if (rearmMs > 0) { // Show rearming time if settings not actively being saved. Ignore the settings saved message if rearm available.
char emReArmMsg[23];
tfp_sprintf(emReArmMsg, "** REARM PERIOD: ");
tfp_sprintf(emReArmMsg + strlen(emReArmMsg), "%02d", (uint8_t)MS2S(rearmMs));
strcat(emReArmMsg, " **\0");
messages[messageCount++] = OSD_MESSAGE_STR(emReArmMsg);*/
} else if (savingSettings == OSD_SAVE_MESSAGE_WAITING) {
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_WAITING_TO_SAVE);
} else if (notify_settings_saved > 0) {
if (millis() > notify_settings_saved) {
notify_settings_saved = 0;
} else {
savingSettings = OSD_SAVE_MESSAGE_NONE;
} else if (savingSettings == OSD_SAVE_MESSAGE_SAVED) {
messages[messageCount++] = OSD_MESSAGE_STR(OSD_MSG_SETTINGS_SAVED);
}
}

uint16_t rearmMs = emergencyInFlightRearmTimeMS();
if (rearmMs > 0) {
char emReArmMsg[23];
tfp_sprintf(emReArmMsg, "** REARM PERIOD: ");
tfp_sprintf(emReArmMsg + strlen(emReArmMsg), "%02d", (uint8_t)MS2S(rearmMs));
strcat(emReArmMsg, " **\0");
messages[messageCount++] = OSD_MESSAGE_STR(emReArmMsg);
}

if (messageCount > 0) {
message = messages[OSD_ALTERNATING_CHOICES(systemMessageCycleTime(messageCount, messages), messageCount)];
if (message == failsafeInfoMessage) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
#define OSD_MSG_UNABLE_ARM "UNABLE TO ARM"
#define OSD_MSG_SAVING_SETTNGS "** SAVING SETTINGS **"
#define OSD_MSG_SETTINGS_SAVED "** SETTINGS SAVED **"
#define OSD_MSG_WAITING_TO_SAVE "** WAITING TO SAVE **"
#define OSD_MSG_ANGLEHOLD_ROLL "(ANGLEHOLD ROLL)"
#define OSD_MSG_ANGLEHOLD_PITCH "(ANGLEHOLD PITCH)"
#define OSD_MSG_ANGLEHOLD_LEVEL "(ANGLEHOLD LEVEL)"
Expand Down Expand Up @@ -492,6 +493,8 @@ int32_t osdGetAltitude(void);

bool osdUsingScaledThrottle(void);

void osdSaveProcessAborted(void);
void osdSaveWaitingProcess(void);
void osdStartedSaveProcess(void);
void osdShowEEPROMSavedNotification(void);

Expand Down
Loading