2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
25 #include "build/debug.h"
28 #include "pg/pg_ids.h"
31 #include "common/axis.h"
32 #include "common/maths.h"
33 #include "common/bitarray.h"
35 #include "fc/runtime_config.h"
36 #include "fc/rc_modes.h"
37 #include "fc/rc_controls.h"
40 #include "flight/failsafe.h"
42 #include "io/beeper.h"
44 #include "drivers/io.h"
47 extern boxBitmask_t rcModeActivationMask
;
50 #include "unittest_macros.h"
51 #include "gtest/gtest.h"
53 uint32_t testFeatureMask
= 0;
54 throttleStatus_e throttleStatus
= THROTTLE_HIGH
;
57 COUNTER_MW_DISARM
= 0,
59 #define CALL_COUNT_ITEM_COUNT 1
61 static int callCounts
[CALL_COUNT_ITEM_COUNT
];
63 #define CALL_COUNTER(item) (callCounts[item])
65 void resetCallCounters(void)
67 memset(&callCounts
, 0, sizeof(callCounts
));
70 #define TEST_MID_RC 1495 // something other than the default 1500 will suffice.
71 #define TEST_MIN_CHECK 1100;
72 #define PERIOD_OF_10_SCONDS 10000
73 #define DE_ACTIVATE_ALL_BOXES 0
75 uint32_t sysTickUptime
;
77 void configureFailsafe(void)
79 rxConfigMutable()->midrc
= TEST_MID_RC
;
80 rxConfigMutable()->mincheck
= TEST_MIN_CHECK
;
82 failsafeConfigMutable()->failsafe_delay
= 10; // 1 second
83 failsafeConfigMutable()->failsafe_landing_time
= 1; // 1.0 seconds
84 failsafeConfigMutable()->failsafe_switch_mode
= FAILSAFE_SWITCH_MODE_STAGE1
;
85 failsafeConfigMutable()->failsafe_throttle
= 1200;
86 failsafeConfigMutable()->failsafe_throttle_low_delay
= 100; // 10 seconds
87 failsafeConfigMutable()->failsafe_procedure
= FAILSAFE_PROCEDURE_AUTO_LANDING
;
88 // NB we don't have failsafe_recovery_delay so use PERIOD_RXDATA_RECOVERY (100ms)
92 void activateBoxFailsafe()
95 bitArraySet(&newMask
, BOXFAILSAFE
);
96 rcModeUpdate(&newMask
);
99 void deactivateBoxFailsafe()
101 boxBitmask_t newMask
;
102 memset(&newMask
, 0, sizeof(newMask
));
103 rcModeUpdate(&newMask
);
110 /****************************************************************************************/
111 TEST(FlightFailsafeTest
, TestFailsafeInitialState
)
116 DISABLE_ARMING_FLAG(ARMED
);
123 EXPECT_FALSE(failsafeIsMonitoring());
124 EXPECT_FALSE(failsafeIsActive());
125 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
128 /****************************************************************************************/
129 TEST(FlightFailsafeTest
, TestFailsafeStartMonitoring
)
132 failsafeStartMonitoring();
135 EXPECT_TRUE(failsafeIsMonitoring());
136 EXPECT_FALSE(failsafeIsActive());
137 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
140 /****************************************************************************************/
141 TEST(FlightFailsafeTest
, TestFailsafeFirstArmedCycle
)
144 ENABLE_ARMING_FLAG(ARMED
);
148 failsafeOnValidDataFailed(); // set last invalid sample to a non-zero value
149 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
+ 1; // adjust time to point just past the recovery time to
150 failsafeOnValidDataReceived(); // cause a recovered link
153 failsafeUpdateState();
156 EXPECT_FALSE(failsafeIsActive());
157 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
160 /****************************************************************************************/
161 TEST(FlightFailsafeTest
, TestFailsafeNotActivatedWhenReceivingData
)
164 for (sysTickUptime
= 0; sysTickUptime
< PERIOD_OF_10_SCONDS
; sysTickUptime
++) {
165 failsafeOnValidDataReceived();
167 failsafeUpdateState();
170 EXPECT_FALSE(failsafeIsActive());
171 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
175 /****************************************************************************************/
179 /****************************************************************************************/
180 TEST(FlightFailsafeTest
, TestFailsafeDetectsRxLossAndStartsLanding
)
186 DISABLE_ARMING_FLAG(ARMED
);
188 failsafeStartMonitoring();
191 EXPECT_TRUE(failsafeIsMonitoring());
192 EXPECT_FALSE(failsafeIsActive());
193 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
196 ENABLE_ARMING_FLAG(ARMED
);
197 throttleStatus
= THROTTLE_HIGH
; // throttle HIGH to go for a failsafe landing procedure
198 failsafeOnValidDataReceived();
201 failsafeUpdateState();
204 EXPECT_FALSE(failsafeIsActive());
205 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
206 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
207 EXPECT_FALSE(isArmingDisabled());
209 // simulate an Rx loss for the stage 1 duration
210 sysTickUptime
+= (failsafeConfig()->failsafe_delay
* MILLIS_PER_TENTH_SECOND
);
211 failsafeOnValidDataFailed();
212 failsafeUpdateState();
214 // should be in stage 1
215 EXPECT_FALSE(failsafeIsActive());
216 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
217 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
218 EXPECT_TRUE(isArmingDisabled());
220 sysTickUptime
++; // exceed the stage 1 period by one tick
221 failsafeOnValidDataFailed(); // confirm that we still have no valid data
223 failsafeUpdateState();
225 // we should now be in stage 2, landing phase
226 EXPECT_TRUE(failsafeIsActive());
227 EXPECT_EQ(FAILSAFE_LANDING
, failsafePhase());
230 /****************************************************************************************/
231 TEST(FlightFailsafeTest
, TestFailsafeCausesLanding
)
232 // note this test follows on from the previous test
234 // exceed the stage 2 landing time
235 sysTickUptime
+= (failsafeConfig()->failsafe_landing_time
* MILLIS_PER_SECOND
);
236 failsafeOnValidDataFailed(); // confirm that we still have no valid data
239 failsafeUpdateState();
241 // expect to still be in landing phase
242 EXPECT_TRUE(failsafeIsActive());
243 EXPECT_EQ(FAILSAFE_LANDING
, failsafePhase());
245 // adjust time to point just past the landing time
247 failsafeOnValidDataFailed(); // confirm that we still have no valid data
250 failsafeUpdateState();
252 // expect to be in monitoring mode
253 EXPECT_TRUE(failsafeIsActive());
254 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
255 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
256 EXPECT_TRUE(isArmingDisabled());
258 // let's wait 3 seconds and still get no signal
259 sysTickUptime
+= PERIOD_OF_3_SECONDS
;
260 failsafeOnValidDataFailed(); // confirm that we still have no valid data
262 failsafeUpdateState();
264 // nothing should change
265 EXPECT_TRUE(failsafeIsActive());
266 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
267 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
268 EXPECT_TRUE(isArmingDisabled());
270 // now lets get a signal while in monitoring mode
271 failsafeOnValidDataReceived();
272 // we must clear the first delay in failsafeOnValidDataReceived(), for which 200ms 'works'
273 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
274 failsafeOnValidDataReceived();
275 failsafeUpdateState();
277 // nothing should change
278 EXPECT_TRUE(failsafeIsActive());
279 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
280 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
281 EXPECT_TRUE(isArmingDisabled());
283 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
284 failsafeOnValidDataReceived();
285 failsafeUpdateState();
287 // nothing should change
288 EXPECT_TRUE(failsafeIsActive());
289 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
290 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
291 EXPECT_TRUE(isArmingDisabled());
295 failsafeOnValidDataReceived();
297 failsafeUpdateState();
299 // we expect failsafe to finish and to revert to idle
300 EXPECT_FALSE(failsafeIsActive());
301 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
302 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
)); // disarm not called repeatedly.
303 EXPECT_FALSE(isArmingDisabled());
306 /****************************************************************************************/
307 TEST(FlightFailsafeTest
, TestFailsafeDetectsRxLossAndJustDisarms
)
308 // Just Disarm is when throttle is low for >10s before signal loss
309 // we should exit stage 1 directly into failsafe monitoring mode, and not enter landing mode
311 ENABLE_ARMING_FLAG(ARMED
);
313 failsafeStartMonitoring();
315 // set to normal initial state
316 throttleStatus
= THROTTLE_HIGH
; // throttle HIGH to go for a failsafe landing procedure
317 failsafeConfigMutable()->failsafe_switch_mode
= FAILSAFE_SWITCH_MODE_KILL
;
319 sysTickUptime
+= PERIOD_OF_3_SECONDS
; // 3s of normality
320 failsafeOnValidDataReceived(); // we have a valid signal
322 failsafeUpdateState();
324 // confirm that we are in idle mode
325 EXPECT_FALSE(failsafeIsActive());
326 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
327 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
328 EXPECT_FALSE(isArmingDisabled());
331 // run throttle_low for 11s
332 throttleStatus
= THROTTLE_LOW
; // for failsafe 'just-disarm' procedure
333 sysTickUptime
+= 11000;
334 failsafeOnValidDataReceived(); // set the last valid signal to now
336 failsafeUpdateState();
338 // check that we are still in idle mode
339 EXPECT_FALSE(failsafeIsActive());
340 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
341 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
342 EXPECT_FALSE(isArmingDisabled());
344 // simulate an Rx loss for the stage 1 duration
345 sysTickUptime
+= (failsafeConfig()->failsafe_delay
* MILLIS_PER_TENTH_SECOND
);
346 failsafeOnValidDataFailed();
347 failsafeUpdateState();
349 // should remain in stage 1
350 EXPECT_FALSE(failsafeIsActive());
351 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
352 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
353 EXPECT_TRUE(isArmingDisabled());
355 sysTickUptime
++; // now we exceed stage 1
356 failsafeOnValidDataFailed(); // we still have no valid data
357 failsafeUpdateState();
359 // we should now be in stage 2 via Just Disarm, going direct to monitoring mode.
360 EXPECT_TRUE(failsafeIsActive());
361 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
362 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
363 EXPECT_TRUE(isArmingDisabled());
365 // now lets get a signal while in monitoring mode
366 failsafeOnValidDataReceived();
367 // we must clear the first delay in failsafeOnValidDataReceived(), for which 200ms 'works'
368 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
369 failsafeOnValidDataReceived();
370 failsafeUpdateState();
372 // nothing should change
373 EXPECT_TRUE(failsafeIsActive());
374 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
375 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
376 EXPECT_TRUE(isArmingDisabled());
378 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
379 failsafeOnValidDataReceived();
380 failsafeUpdateState();
382 // nothing should change
383 EXPECT_TRUE(failsafeIsActive());
384 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
385 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
386 EXPECT_TRUE(isArmingDisabled());
390 failsafeOnValidDataReceived();
392 failsafeUpdateState();
394 // we expect failsafe to finish and to revert to idle
395 EXPECT_FALSE(failsafeIsActive());
396 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
397 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
)); // disarm not called repeatedly.
398 EXPECT_FALSE(isArmingDisabled());}
400 /****************************************************************************************/
401 TEST(FlightFailsafeTest
, TestFailsafeSwitchModeKill
)
404 ENABLE_ARMING_FLAG(ARMED
);
406 failsafeStartMonitoring();
408 // set to normal initial state
409 throttleStatus
= THROTTLE_HIGH
; // throttle HIGH to go for a failsafe landing procedure
410 failsafeConfigMutable()->failsafe_switch_mode
= FAILSAFE_SWITCH_MODE_KILL
;
412 sysTickUptime
+= PERIOD_OF_3_SECONDS
; // 3s of normality
413 failsafeOnValidDataReceived(); // we have a valid signal
415 failsafeUpdateState();
417 // confirm that we are in idle mode
418 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
419 EXPECT_FALSE(failsafeIsActive());
420 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
423 activateBoxFailsafe(); // activate the Kill swith
426 failsafeUpdateState(); // should failsafe immediately the kill switch is hit
429 EXPECT_TRUE(failsafeIsActive());
430 EXPECT_TRUE(isArmingDisabled());
431 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
432 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
435 failsafeOnValidDataReceived(); // the link is active the whole time
437 // deactivate the kill switch
438 deactivateBoxFailsafe(); // receivingRxData is immediately true
440 // we should go to failsafe monitoring mode, via Landing
441 EXPECT_TRUE(failsafeIsActive());
442 EXPECT_TRUE(isArmingDisabled());
443 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
444 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
446 // since we didn't enter stage 2, we have one rxDataRecoveryPeriod delay to deal with
447 // while within rxDataRecoveryPeriod in monitoring mode...
448 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
449 failsafeOnValidDataReceived();
452 failsafeUpdateState();
454 // we should still be in failsafe monitoring mode
455 EXPECT_TRUE(failsafeIsActive());
456 EXPECT_TRUE(isArmingDisabled());
457 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
458 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
464 failsafeUpdateState();
466 // we should now have exited failsafe
467 EXPECT_FALSE(failsafeIsActive());
468 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
469 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
)); // disarm not called repeatedly.
470 EXPECT_FALSE(isArmingDisabled());
473 /****************************************************************************************/
475 TEST(FlightFailsafeTest
, TestFailsafeSwitchModeStage1OrStage2Drop
)
476 // should immediately stop motors and go to monitoring mode diretly
478 // given a clean start
479 ENABLE_ARMING_FLAG(ARMED
);
481 failsafeStartMonitoring();
483 // and set initial states
484 throttleStatus
= THROTTLE_HIGH
; // throttle HIGH to go for a failsafe landing procedure
485 failsafeConfigMutable()->failsafe_switch_mode
= FAILSAFE_SWITCH_MODE_STAGE2
;
486 failsafeConfigMutable()->failsafe_procedure
= FAILSAFE_PROCEDURE_DROP_IT
;
488 sysTickUptime
= 0; // restart time from 0
489 failsafeOnValidDataReceived(); // we have a valid signal
490 sysTickUptime
+= 3000; // 3s of normality
493 failsafeUpdateState();
495 // confirm that we are in idle mode
496 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
497 EXPECT_FALSE(failsafeIsActive());
498 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
501 activateBoxFailsafe(); // activate the stage 2 Drop switch
502 failsafeOnValidDataFailed(); // immediate stage 2 switch sets failsafeOnValidDataFailed
505 failsafeUpdateState(); // should activate stage2 immediately, even though signal is good
507 // expect to be in monitoring mode, and to have disarmed
508 EXPECT_TRUE(failsafeIsActive());
509 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
510 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
511 EXPECT_TRUE(isArmingDisabled());
513 // deactivate the failsafe switch
514 deactivateBoxFailsafe();
516 EXPECT_TRUE(failsafeIsActive());
517 EXPECT_TRUE(isArmingDisabled());
518 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
519 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
521 // by next evaluation we should be out of failsafe
523 // receivingRxData is immediately true because signal exists
524 failsafeOnValidDataReceived();
527 failsafeUpdateState();
529 // we should now have exited failsafe
530 EXPECT_FALSE(failsafeIsActive());
531 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
532 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
)); // disarm not called repeatedly.
533 EXPECT_FALSE(isArmingDisabled());
536 /****************************************************************************************/
538 TEST(FlightFailsafeTest
, TestFailsafeSwitchModeStage2Land
)
540 // given a clean start
541 ENABLE_ARMING_FLAG(ARMED
);
543 failsafeStartMonitoring();
546 throttleStatus
= THROTTLE_HIGH
; // throttle HIGH to go for a failsafe landing procedure
547 failsafeConfigMutable()->failsafe_switch_mode
= FAILSAFE_SWITCH_MODE_STAGE2
;
548 failsafeConfigMutable()->failsafe_procedure
= FAILSAFE_PROCEDURE_AUTO_LANDING
;
550 sysTickUptime
= 0; // restart time from 0
551 failsafeOnValidDataReceived(); // we have a valid signal
552 sysTickUptime
+= 3000; // 3s of normality
555 failsafeUpdateState();
557 // confirm that we are in idle mode
558 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
559 EXPECT_FALSE(failsafeIsActive());
560 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
563 activateBoxFailsafe(); // activate the stage 2 Drop switch
564 failsafeOnValidDataFailed(); // immediate stage 2 switch sets failsafeOnValidDataFailed
567 failsafeUpdateState(); // should activate stage2 immediately
569 // expect to immediately be in landing mode, and not disarmed
570 EXPECT_TRUE(failsafeIsActive()); // stick induced failsafe allows re-arming
571 EXPECT_EQ(FAILSAFE_LANDING
, failsafePhase());
572 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
574 // should stay in landing for failsafe_landing_time (stage 2 landing period) of 1s
575 sysTickUptime
+= failsafeConfig()->failsafe_landing_time
* MILLIS_PER_SECOND
;
578 failsafeUpdateState();
580 EXPECT_TRUE(failsafeIsActive()); // stick induced failsafe allows re-arming
581 EXPECT_EQ(FAILSAFE_LANDING
, failsafePhase());
582 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
584 // one tick later, landing time has elapsed
588 failsafeUpdateState();
590 // now should be in monitoring mode, with switch holding rxDataReceived false
591 EXPECT_TRUE(failsafeIsActive());
592 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
593 EXPECT_TRUE(isArmingDisabled());
594 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
597 sysTickUptime
+= PERIOD_OF_3_SECONDS
; // hang around a bit waiting for switch change
600 failsafeUpdateState();
602 // should still be in monitoring mode because switch is still forcing receivingRxData false
603 EXPECT_TRUE(failsafeIsActive());
604 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
605 EXPECT_TRUE(isArmingDisabled());
606 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
608 // deactivate the failsafe switch
609 deactivateBoxFailsafe();
611 // receivingRxData is immediately true
612 // we go directly to failsafe monitoring mode, via Landing
613 // however, because the switch also forces rxFlightChannelsValid false, emulating real failsafe
614 // we have two delays to deal with before we can re-arm
616 EXPECT_TRUE(failsafeIsActive());
617 EXPECT_TRUE(isArmingDisabled());
618 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
));
619 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING
, failsafePhase());
624 failsafeOnValidDataReceived();
627 failsafeUpdateState();
629 // we should now have exited failsafe
630 EXPECT_FALSE(failsafeIsActive());
631 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
632 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM
)); // disarm not called repeatedly.
633 EXPECT_FALSE(isArmingDisabled());
637 /****************************************************************************************/
641 /****************************************************************************************/
642 TEST(FlightFailsafeTest
, TestFailsafeNotActivatedWhenDisarmedAndRXLossIsDetected
)
651 // and ** WE ARE DISARMED **
652 DISABLE_ARMING_FLAG(ARMED
);
654 // when failsafe starts
655 failsafeStartMonitoring();
658 sysTickUptime
= 0; // restart time from 0
659 failsafeOnValidDataReceived(); // we have a valid signal
660 sysTickUptime
+= 3000; // 3s of normality
663 failsafeUpdateState();
665 // confirm that we are in idle mode
666 EXPECT_FALSE(failsafeIsActive());
667 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
668 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
670 // and that arming is not disabled
671 EXPECT_FALSE(isArmingDisabled());
673 // simulate an Rx loss for the stage 1 duration
674 sysTickUptime
+= (failsafeConfig()->failsafe_delay
* MILLIS_PER_TENTH_SECOND
);
675 failsafeOnValidDataFailed();
676 failsafeUpdateState();
678 // within stage 1 time from a true failsafe while disarmed, stage 2 should normally not be active
679 EXPECT_FALSE(failsafeIsActive());
680 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
681 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
683 // arming is disabled due to setArmingDisabled in stage 1 due to failsafeOnValidDataFailed()
684 EXPECT_FALSE(failsafeIsActive());
687 sysTickUptime
++; // adjust time to point just past stage 1
688 failsafeOnValidDataFailed(); // would normally enter stage 2, but we are disarmed
689 failsafeUpdateState();
691 // expect that we do not enter failsafe stage 2, ie no change from above
692 EXPECT_FALSE(failsafeIsActive());
693 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
694 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
696 // the lock on the aux channels persists at fixed stage 1 values until recovery time
697 EXPECT_TRUE(isArmingDisabled());
699 // allow signal received for the recovery time
700 sysTickUptime
+= PERIOD_RXDATA_RECOVERY
;
701 failsafeOnValidDataReceived();
702 failsafeUpdateState();
704 // no change in failsafe state (still idle)
705 EXPECT_FALSE(failsafeIsActive());
706 EXPECT_EQ(FAILSAFE_IDLE
, failsafePhase());
707 EXPECT_EQ(0, CALL_COUNTER(COUNTER_MW_DISARM
));
709 // but now arming is possible
710 EXPECT_FALSE(isArmingDisabled());
716 float rcData
[MAX_SUPPORTED_RC_CHANNEL_COUNT
];
718 int16_t debug
[DEBUG16_VALUE_COUNT
];
719 uint8_t debugMode
= 0;
720 bool isUsingSticksToArm
= true;
722 PG_REGISTER(rxConfig_t
, rxConfig
, PG_RX_CONFIG
, 0);
724 // Return system uptime in milliseconds (rollover in 49 days)
725 uint32_t millis(void)
727 return sysTickUptime
;
730 uint32_t micros(void)
732 return millis() * 1000;
735 throttleStatus_e
calculateThrottleStatus()
737 return throttleStatus
;
740 void delay(uint32_t) {}
742 bool featureIsEnabled(uint32_t mask
)
744 return (mask
& testFeatureMask
);
747 void disarm(flightLogDisarmReason_e
)
749 callCounts
[COUNTER_MW_DISARM
]++;
752 void beeper(beeperMode_e mode
)
757 bool isUsingSticksForArming(void)
759 return isUsingSticksToArm
;
762 bool areSticksActive(uint8_t stickPercentLimit
)
764 UNUSED(stickPercentLimit
);
768 void beeperConfirmationBeeps(uint8_t beepCount
) { UNUSED(beepCount
); }
770 bool crashRecoveryModeActive(void) { return false; }
771 void pinioBoxTaskControl(void) {}