Skip to content

Commit 64299e2

Browse files
committed
Merge branch 'emuflight-1.0.0-master' into 20220329_cherry_pick_Smith_Predictor
2 parents 372c608 + fa4d3d6 commit 64299e2

20 files changed

+267
-166
lines changed

src/main/cli/cli.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6162,8 +6162,8 @@ static void cliDshotTelemetryInfo(const char *cmdName, char *cmdline)
61626162
if (useDshotTelemetry) {
61636163
cliPrintLinef("Dshot reads: %u", dshotTelemetryState.readCount);
61646164
cliPrintLinef("Dshot invalid pkts: %u", dshotTelemetryState.invalidPacketCount);
6165-
uint32_t directionChangeCycles = dshotDMAHandlerCycleCounters.changeDirectionCompletedAt - dshotDMAHandlerCycleCounters.irqAt;
6166-
uint32_t directionChangeDurationUs = clockCyclesToMicros(directionChangeCycles);
6165+
int32_t directionChangeCycles = cmp32(dshotDMAHandlerCycleCounters.changeDirectionCompletedAt, dshotDMAHandlerCycleCounters.irqAt);
6166+
int32_t directionChangeDurationUs = clockCyclesToMicros(directionChangeCycles);
61676167
cliPrintLinef("Dshot directionChange cycles: %u, micros: %u", directionChangeCycles, directionChangeDurationUs);
61686168
cliPrintLinefeed();
61696169

src/main/drivers/dshot_bitbang.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t
751751
#if defined(STM32F4) || defined(STM32F3)
752752
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, bbPuPdMode);
753753
#elif defined(STM32F7) || defined(STM32G4) || defined(STM32H7)
754-
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, bbPuPdMode);
754+
bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_LOW, bbPuPdMode);
755755
#endif
756756

757757
IOInit(io, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));

src/main/drivers/system.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ uint32_t getCycleCounter(void)
153153
return DWT->CYCCNT;
154154
}
155155

156-
uint32_t clockCyclesToMicros(uint32_t clockCycles)
156+
int32_t clockCyclesToMicros(int32_t clockCycles)
157157
{
158158
return clockCycles / usTicks;
159159
}

src/main/drivers/system.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ void systemReset(void);
6565
void systemResetToBootloader(bootloaderRequestType_e requestType);
6666
bool isMPUSoftReset(void);
6767
void cycleCounterInit(void);
68-
uint32_t clockCyclesToMicros(uint32_t clockCycles);
68+
int32_t clockCyclesToMicros(int32_t clockCycles);
6969
int32_t clockCyclesTo10thMicros(int32_t clockCycles);
7070
uint32_t clockMicrosToCycles(uint32_t micros);
7171
uint32_t getCycleCounter(void);

src/main/fc/core.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -744,12 +744,6 @@ bool isAirmodeActivated()
744744
*/
745745
bool processRx(timeUs_t currentTimeUs)
746746
{
747-
timeDelta_t frameAgeUs;
748-
timeDelta_t frameDeltaUs = rxGetFrameDelta(&frameAgeUs);
749-
750-
DEBUG_SET(DEBUG_RX_TIMING, 0, MIN(frameDeltaUs / 10, INT16_MAX));
751-
DEBUG_SET(DEBUG_RX_TIMING, 1, MIN(frameAgeUs / 10, INT16_MAX));
752-
753747
if (!calculateRxChannelsAndUpdateFailsafe(currentTimeUs)) {
754748
return false;
755749
}

src/main/fc/rc.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,13 +298,18 @@ void updateRcRefreshRate(timeUs_t currentTimeUs)
298298
static timeUs_t lastRxTimeUs;
299299

300300
timeDelta_t frameAgeUs;
301-
timeDelta_t refreshRateUs = rxGetFrameDelta(&frameAgeUs);
302-
if (!refreshRateUs || cmpTimeUs(currentTimeUs, lastRxTimeUs) <= frameAgeUs) {
303-
refreshRateUs = cmpTimeUs(currentTimeUs, lastRxTimeUs); // calculate a delta here if not supplied by the protocol
301+
timeDelta_t frameDeltaUs = rxGetFrameDelta(&frameAgeUs);
302+
303+
if (!frameDeltaUs || cmpTimeUs(currentTimeUs, lastRxTimeUs) <= frameAgeUs) {
304+
frameDeltaUs = cmpTimeUs(currentTimeUs, lastRxTimeUs); // calculate a delta here if not supplied by the protocol
304305
}
306+
307+
DEBUG_SET(DEBUG_RX_TIMING, 0, MIN(frameDeltaUs / 10, INT16_MAX));
308+
DEBUG_SET(DEBUG_RX_TIMING, 1, MIN(frameAgeUs / 10, INT16_MAX));
309+
305310
lastRxTimeUs = currentTimeUs;
306-
isRxRateValid = (refreshRateUs >= RC_RX_RATE_MIN_US && refreshRateUs <= RC_RX_RATE_MAX_US);
307-
currentRxRefreshRate = constrain(refreshRateUs, RC_RX_RATE_MIN_US, RC_RX_RATE_MAX_US);
311+
isRxRateValid = (frameDeltaUs >= RC_RX_RATE_MIN_US && frameDeltaUs <= RC_RX_RATE_MAX_US);
312+
currentRxRefreshRate = constrain(frameDeltaUs, RC_RX_RATE_MIN_US, RC_RX_RATE_MAX_US);
308313
}
309314

310315
uint16_t getCurrentRxRefreshRate(void)

src/main/flight/failsafe.c

Lines changed: 85 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ PG_REGISTER_WITH_RESET_TEMPLATE(failsafeConfig_t, failsafeConfig, PG_FAILSAFE_CO
6565
PG_RESET_TEMPLATE(failsafeConfig_t, failsafeConfig,
6666
.failsafe_throttle = 1000, // default throttle off.
6767
.failsafe_throttle_low_delay = 100, // default throttle low delay for "just disarm" on failsafe condition
68-
.failsafe_delay = 4, // 0,4sec
69-
.failsafe_off_delay = 10, // 1sec
70-
.failsafe_switch_mode = 0, // default failsafe switch action is identical to rc link loss
68+
.failsafe_delay = 10, // 1 sec, can regain control on signal recovery, at idle in drop mode
69+
.failsafe_off_delay = 10, // 1 sec in landing phase, if enabled
70+
.failsafe_switch_mode = FAILSAFE_SWITCH_MODE_STAGE1, // default failsafe switch action is identical to rc link loss
7171
.failsafe_procedure = FAILSAFE_PROCEDURE_DROP_IT,// default full failsafe procedure is 0: auto-landing
72-
.failsafe_recovery_delay = 20, // 2 sec of valid rx data (plus 200ms) needed to allow recovering from failsafe procedure
72+
.failsafe_recovery_delay = 10, // 1 sec of valid rx data needed to allow recovering from failsafe procedure
7373
.failsafe_stick_threshold = 30 // 30 percent of stick deflection to exit GPS Rescue procedure
7474
);
7575

@@ -86,8 +86,12 @@ const char * const failsafeProcedureNames[FAILSAFE_PROCEDURE_COUNT] = {
8686
*/
8787
void failsafeReset(void)
8888
{
89-
failsafeState.rxDataFailurePeriod = PERIOD_RXDATA_FAILURE + failsafeConfig()->failsafe_delay * MILLIS_PER_TENTH_SECOND;
90-
failsafeState.rxDataRecoveryPeriod = PERIOD_RXDATA_RECOVERY + failsafeConfig()->failsafe_recovery_delay * MILLIS_PER_TENTH_SECOND;
89+
failsafeState.rxDataFailurePeriod = failsafeConfig()->failsafe_delay * MILLIS_PER_TENTH_SECOND; // time to start stage2
90+
failsafeState.rxDataRecoveryPeriod = failsafeConfig()->failsafe_recovery_delay * MILLIS_PER_TENTH_SECOND;
91+
if (failsafeState.rxDataRecoveryPeriod < PERIOD_RXDATA_RECOVERY){
92+
// PERIOD_RXDATA_RECOVERY (200ms) is the minimum allowed RxData recovery time
93+
failsafeState.rxDataRecoveryPeriod = PERIOD_RXDATA_RECOVERY;
94+
}
9195
failsafeState.validRxDataReceivedAt = 0;
9296
failsafeState.validRxDataFailedAt = 0;
9397
failsafeState.throttleLowPeriod = 0;
@@ -121,6 +125,13 @@ bool failsafeIsActive(void)
121125
return failsafeState.active;
122126
}
123127

128+
#ifdef USE_GPS_RESCUE
129+
bool failsafePhaseIsGpsRescue(void)
130+
{
131+
return failsafeState.phase == FAILSAFE_GPS_RESCUE;
132+
}
133+
#endif
134+
124135
void failsafeStartMonitoring(void)
125136
{
126137
failsafeState.monitoring = true;
@@ -138,26 +149,12 @@ static void failsafeActivate(void)
138149
failsafeState.phase = FAILSAFE_LANDING;
139150

140151
ENABLE_FLIGHT_MODE(FAILSAFE_MODE);
152+
141153
failsafeState.landingShouldBeFinishedAt = millis() + failsafeConfig()->failsafe_off_delay * MILLIS_PER_TENTH_SECOND;
142154

143155
failsafeState.events++;
144156
}
145157

146-
static void failsafeApplyControlInput(void)
147-
{
148-
#ifdef USE_GPS_RESCUE
149-
if (failsafeConfig()->failsafe_procedure == FAILSAFE_PROCEDURE_GPS_RESCUE) {
150-
ENABLE_FLIGHT_MODE(GPS_RESCUE_MODE);
151-
return;
152-
}
153-
#endif
154-
155-
for (int i = 0; i < 3; i++) {
156-
rcData[i] = rxConfig()->midrc;
157-
}
158-
rcData[THROTTLE] = failsafeConfig()->failsafe_throttle;
159-
}
160-
161158
bool failsafeIsReceivingRxData(void)
162159
{
163160
return (failsafeState.rxLinkState == FAILSAFE_RXLINK_UP);
@@ -177,42 +174,61 @@ void failsafeOnRxResume(void)
177174
void failsafeOnValidDataReceived(void)
178175
{
179176
failsafeState.validRxDataReceivedAt = millis();
180-
if ((failsafeState.validRxDataReceivedAt - failsafeState.validRxDataFailedAt) > failsafeState.rxDataRecoveryPeriod) {
177+
if ((cmp32(failsafeState.validRxDataReceivedAt, failsafeState.validRxDataFailedAt) > (int32_t)failsafeState.rxDataRecoveryPeriod) ||
178+
(cmp32(failsafeState.validRxDataFailedAt, failsafeState.validRxDataReceivedAt) > 0)) {
179+
// rxDataRecoveryPeriod defaults to 1.0s with minimum of PERIOD_RXDATA_RECOVERY (200ms)
181180
failsafeState.rxLinkState = FAILSAFE_RXLINK_UP;
181+
// Allow arming now we have an RX link
182182
unsetArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
183183
}
184184
}
185185

186186
void failsafeOnValidDataFailed(void)
187187
{
188-
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE); // To prevent arming with no RX link
189188
failsafeState.validRxDataFailedAt = millis();
190-
if ((failsafeState.validRxDataFailedAt - failsafeState.validRxDataReceivedAt) > failsafeState.rxDataFailurePeriod) {
189+
if ((cmp32(failsafeState.validRxDataFailedAt, failsafeState.validRxDataReceivedAt) > (int32_t)failsafeState.rxDataFailurePeriod)) {
190+
// rxDataFailurePeriod is stage 1 guard time
191191
failsafeState.rxLinkState = FAILSAFE_RXLINK_DOWN;
192+
// Prevent arming with no RX link
193+
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
192194
}
193195
}
194196

195197
void failsafeCheckDataFailurePeriod(void)
198+
// forces link down directly from scheduler?
196199
{
197200
if (cmp32(millis(), failsafeState.validRxDataReceivedAt) > (int32_t)failsafeState.rxDataFailurePeriod) {
198-
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE); // To prevent arming with no RX link
199201
failsafeState.rxLinkState = FAILSAFE_RXLINK_DOWN;
202+
// Prevent arming with no RX link
203+
setArmingDisabled(ARMING_DISABLED_RX_FAILSAFE);
200204
}
201205
}
202206

207+
uint32_t failsafeFailurePeriodMs(void)
208+
{
209+
return failsafeState.rxDataFailurePeriod;
210+
}
211+
203212
FAST_CODE_NOINLINE void failsafeUpdateState(void)
213+
// triggered directly, and ONLY, by the cheduler, at 10ms = PERIOD_RXDATA_FAILURE - intervals
204214
{
205215
if (!failsafeIsMonitoring()) {
206216
return;
207217
}
208218

209219
bool receivingRxData = failsafeIsReceivingRxData();
220+
// should be true when FAILSAFE_RXLINK_UP
221+
// FAILSAFE_RXLINK_UP is set in failsafeOnValidDataReceived
222+
// failsafeOnValidDataReceived runs from detectAndApplySignalLossBehaviour
223+
210224
bool armed = ARMING_FLAG(ARMED);
211225
bool failsafeSwitchIsOn = IS_RC_MODE_ACTIVE(BOXFAILSAFE);
212226
beeperMode_e beeperMode = BEEPER_SILENCE;
213227

214-
if (failsafeSwitchIsOn && failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_STAGE2) {
215-
receivingRxData = false; // force Stage2
228+
if (failsafeSwitchIsOn && (failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_STAGE2)) {
229+
// Aux switch set to failsafe stage2 emulates loss of signal without waiting
230+
failsafeOnValidDataFailed();
231+
receivingRxData = false;
216232
}
217233

218234
// Beep RX lost only if we are not seeing data and we have been armed earlier
@@ -232,23 +248,27 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
232248
if (THROTTLE_HIGH == calculateThrottleStatus()) {
233249
failsafeState.throttleLowPeriod = millis() + failsafeConfig()->failsafe_throttle_low_delay * MILLIS_PER_TENTH_SECOND;
234250
}
235-
// Kill switch logic (must be independent of receivingRxData to skip PERIOD_RXDATA_FAILURE delay before disarming)
236-
if (failsafeSwitchIsOn && failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_KILL) {
237-
// KillswitchEvent: failsafe switch is configured as KILL switch and is switched ON
251+
if (failsafeSwitchIsOn && (failsafeConfig()->failsafe_switch_mode == FAILSAFE_SWITCH_MODE_KILL)) {
252+
// Failsafe switch is configured as KILL switch and is switched ON
238253
failsafeActivate();
239-
failsafeState.phase = FAILSAFE_LANDED; // skip auto-landing procedure
240-
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_1_SECONDS; // require 1 seconds of valid rxData
254+
// Skip auto-landing procedure
255+
failsafeState.phase = FAILSAFE_LANDED;
256+
// Require 3 seconds of valid rxData
257+
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_3_SECONDS;
241258
reprocessState = true;
242259
} else if (!receivingRxData) {
243260
if (millis() > failsafeState.throttleLowPeriod
244261
#ifdef USE_GPS_RESCUE
245262
&& failsafeConfig()->failsafe_procedure != FAILSAFE_PROCEDURE_GPS_RESCUE
246263
#endif
247264
) {
248-
// JustDisarm: throttle was LOW for at least 'failsafe_throttle_low_delay' seconds
265+
// JustDisarm: throttle was LOW for at least 'failsafe_throttle_low_delay' seconds before failsafe
266+
// protects against false arming when the Tx is powered up after the quad
249267
failsafeActivate();
250-
failsafeState.phase = FAILSAFE_LANDED; // skip auto-landing procedure
251-
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_3_SECONDS; // require 3 seconds of valid rxData
268+
// skip auto-landing procedure
269+
failsafeState.phase = FAILSAFE_LANDED;
270+
// re-arm at rxDataRecoveryPeriod - default is 1.0 seconds
271+
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
252272
} else {
253273
failsafeState.phase = FAILSAFE_RX_LOSS_DETECTED;
254274
}
@@ -279,7 +299,10 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
279299
case FAILSAFE_PROCEDURE_DROP_IT:
280300
// Drop the craft
281301
failsafeActivate();
282-
failsafeState.phase = FAILSAFE_LANDED; // skip auto-landing procedure
302+
// re-arm at rxDataRecoveryPeriod - default is 1.0 seconds
303+
failsafeState.receivingRxDataPeriodPreset = failsafeState.rxDataRecoveryPeriod;
304+
// skip auto-landing procedure
305+
failsafeState.phase = FAILSAFE_LANDED;
283306
break;
284307
#ifdef USE_GPS_RESCUE
285308
case FAILSAFE_PROCEDURE_GPS_RESCUE:
@@ -296,37 +319,42 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
296319
if (receivingRxData) {
297320
failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED;
298321
reprocessState = true;
299-
}
300-
if (armed) {
301-
failsafeApplyControlInput();
302-
beeperMode = BEEPER_RX_LOST_LANDING;
303-
}
304-
if (failsafeShouldHaveCausedLandingByNow() || crashRecoveryModeActive() || !armed) {
305-
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_30_SECONDS; // require 30 seconds of valid rxData
306-
failsafeState.phase = FAILSAFE_LANDED;
307-
reprocessState = true;
322+
} else {
323+
if (armed) {
324+
beeperMode = BEEPER_RX_LOST_LANDING;
325+
}
326+
if (failsafeShouldHaveCausedLandingByNow() || crashRecoveryModeActive() || !armed) {
327+
// require 3 seconds of valid rxData
328+
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_3_SECONDS;
329+
failsafeState.phase = FAILSAFE_LANDED;
330+
reprocessState = true;
331+
}
308332
}
309333
break;
310334
#ifdef USE_GPS_RESCUE
311335
case FAILSAFE_GPS_RESCUE:
312336
if (receivingRxData) {
313337
if (areSticksActive(failsafeConfig()->failsafe_stick_threshold)) {
338+
// hence we must allow stick inputs during FAILSAFE_GPS_RESCUE see PR #7936 for rationale
314339
failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED;
315340
reprocessState = true;
316341
}
317-
}
318-
if (armed) {
319-
failsafeApplyControlInput();
320-
beeperMode = BEEPER_RX_LOST_LANDING;
321342
} else {
322-
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_30_SECONDS; // require 30 seconds of valid rxData
323-
failsafeState.phase = FAILSAFE_LANDED;
324-
reprocessState = true;
343+
if (armed) {
344+
ENABLE_FLIGHT_MODE(GPS_RESCUE_MODE);
345+
beeperMode = BEEPER_RX_LOST_LANDING;
346+
} else {
347+
// require 3 seconds of valid rxData
348+
failsafeState.receivingRxDataPeriodPreset = PERIOD_OF_3_SECONDS;
349+
failsafeState.phase = FAILSAFE_LANDED;
350+
reprocessState = true;
351+
}
325352
}
326353
break;
327354
#endif
328355
case FAILSAFE_LANDED:
329-
setArmingDisabled(ARMING_DISABLED_FAILSAFE); // To prevent accidently rearming by an intermittent rx link
356+
// Prevent accidently rearming by an intermittent rx link
357+
setArmingDisabled(ARMING_DISABLED_FAILSAFE);
330358
disarm(DISARM_REASON_FAILSAFE);
331359
failsafeState.receivingRxDataPeriod = millis() + failsafeState.receivingRxDataPeriodPreset; // set required period of valid rxData
332360
failsafeState.phase = FAILSAFE_RX_LOSS_MONITORING;
@@ -337,12 +365,9 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
337365
// Monitoring the rx link to allow rearming when it has become good for > `receivingRxDataPeriodPreset` time.
338366
if (receivingRxData) {
339367
if (millis() > failsafeState.receivingRxDataPeriod) {
340-
// rx link is good now, when arming via ARM switch, it must be OFF first
341-
if (!(!isUsingSticksForArming() && IS_RC_MODE_ACTIVE(BOXARM))) {
342-
unsetArmingDisabled(ARMING_DISABLED_FAILSAFE);
343-
failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED;
344-
reprocessState = true;
345-
}
368+
// rx link is good now
369+
failsafeState.phase = FAILSAFE_RX_LOSS_RECOVERED;
370+
reprocessState = true;
346371
}
347372
} else {
348373
failsafeState.receivingRxDataPeriod = millis() + failsafeState.receivingRxDataPeriodPreset;
@@ -357,6 +382,7 @@ FAST_CODE_NOINLINE void failsafeUpdateState(void)
357382
failsafeState.phase = FAILSAFE_IDLE;
358383
failsafeState.active = false;
359384
DISABLE_FLIGHT_MODE(FAILSAFE_MODE);
385+
unsetArmingDisabled(ARMING_DISABLED_FAILSAFE);
360386
reprocessState = true;
361387
break;
362388

0 commit comments

Comments
 (0)