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/>.
28 #include "common/axis.h"
29 #include "common/maths.h"
31 #include "config/runtime_config.h"
33 #include "io/beeper.h"
34 #include "io/rc_controls.h"
37 #include "flight/failsafe.h"
39 failsafeState_t* failsafeInit(rxConfig_t *intialRxConfig);
42 #include "unittest_macros.h"
43 #include "gtest/gtest.h"
45 uint32_t testFeatureMask = 0;
46 uint16_t flightModeFlags = 0;
47 uint16_t testMinThrottle = 0;
48 throttleStatus_e throttleStatus = THROTTLE_HIGH;
51 COUNTER_MW_DISARM = 0,
53 #define CALL_COUNT_ITEM_COUNT 1
55 static int callCounts[CALL_COUNT_ITEM_COUNT];
57 #define CALL_COUNTER(item) (callCounts[item])
59 void resetCallCounters(void) {
60 memset(&callCounts, 0, sizeof(callCounts));
63 #define TEST_MID_RC 1495 // something other than the default 1500 will suffice.
64 #define TEST_MIN_CHECK 1100;
65 #define PERIOD_OF_10_SCONDS 10000
66 #define DE_ACTIVATE_ALL_BOXES 0
69 failsafeConfig_t failsafeConfig;
70 uint32_t sysTickUptime;
72 void configureFailsafe(void)
74 memset(&rxConfig, 0, sizeof(rxConfig));
75 rxConfig.midrc = TEST_MID_RC;
76 rxConfig.mincheck = TEST_MIN_CHECK;
78 memset(&failsafeConfig, 0, sizeof(failsafeConfig));
79 failsafeConfig.failsafe_delay = 10; // 1 second
80 failsafeConfig.failsafe_off_delay = 50; // 5 seconds
81 failsafeConfig.failsafe_kill_switch = false;
82 failsafeConfig.failsafe_throttle = 1200;
83 failsafeConfig.failsafe_throttle_low_delay = 50; // 5 seconds
90 /****************************************************************************************/
91 TEST(FlightFailsafeTest, TestFailsafeInitialState)
96 DISABLE_ARMING_FLAG(ARMED);
99 useFailsafeConfig(&failsafeConfig);
100 failsafeInit(&rxConfig);
103 EXPECT_EQ(false, failsafeIsMonitoring());
104 EXPECT_EQ(false, failsafeIsActive());
105 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
108 /****************************************************************************************/
109 TEST(FlightFailsafeTest, TestFailsafeStartMonitoring)
112 failsafeStartMonitoring();
115 EXPECT_EQ(true, failsafeIsMonitoring());
116 EXPECT_EQ(false, failsafeIsActive());
117 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
120 /****************************************************************************************/
121 TEST(FlightFailsafeTest, TestFailsafeFirstArmedCycle)
124 ENABLE_ARMING_FLAG(ARMED);
127 failsafeOnValidDataFailed(); // set last invalid sample at current time
128 sysTickUptime += PERIOD_RXDATA_RECOVERY + 1; // adjust time to point just past the recovery time to
129 failsafeOnValidDataReceived(); // cause a recovered link
132 failsafeUpdateState();
135 EXPECT_EQ(false, failsafeIsActive());
136 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
139 /****************************************************************************************/
140 TEST(FlightFailsafeTest, TestFailsafeNotActivatedWhenReceivingData)
143 for (sysTickUptime = 0; sysTickUptime < PERIOD_OF_10_SCONDS; sysTickUptime++) {
144 failsafeOnValidDataReceived();
146 failsafeUpdateState();
149 EXPECT_EQ(false, failsafeIsActive());
150 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
154 /****************************************************************************************/
155 TEST(FlightFailsafeTest, TestFailsafeDetectsRxLossAndStartsLanding)
158 ENABLE_ARMING_FLAG(ARMED);
161 failsafeStartMonitoring();
162 throttleStatus = THROTTLE_HIGH; // throttle HIGH to go for a failsafe landing procedure
163 sysTickUptime = 0; // restart time from 0
164 failsafeOnValidDataReceived(); // set last valid sample at current time
167 for (sysTickUptime = 0; sysTickUptime < (uint32_t)(failsafeConfig.failsafe_delay * MILLIS_PER_TENTH_SECOND + PERIOD_RXDATA_FAILURE); sysTickUptime++) {
168 failsafeOnValidDataFailed();
170 failsafeUpdateState();
173 EXPECT_EQ(false, failsafeIsActive());
174 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
178 sysTickUptime++; // adjust time to point just past the failure time to
179 failsafeOnValidDataFailed(); // cause a lost link
182 failsafeUpdateState();
185 EXPECT_EQ(FAILSAFE_LANDING, failsafePhase());
186 EXPECT_EQ(true, failsafeIsActive());
189 /****************************************************************************************/
190 TEST(FlightFailsafeTest, TestFailsafeCausesLanding)
193 sysTickUptime += failsafeConfig.failsafe_off_delay * MILLIS_PER_TENTH_SECOND;
197 // no call to failsafeOnValidDataReceived();
198 failsafeUpdateState();
201 EXPECT_EQ(true, failsafeIsActive());
202 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING, failsafePhase());
203 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM));
204 EXPECT_TRUE(ARMING_FLAG(PREVENT_ARMING));
207 failsafeOnValidDataFailed(); // set last invalid sample at current time
208 sysTickUptime += PERIOD_RXDATA_RECOVERY + 1; // adjust time to point just past the recovery time to
209 failsafeOnValidDataReceived(); // cause a recovered link
212 failsafeUpdateState();
215 EXPECT_EQ(true, failsafeIsActive());
216 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING, failsafePhase());
217 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM));
218 EXPECT_TRUE(ARMING_FLAG(PREVENT_ARMING));
221 sysTickUptime += PERIOD_OF_30_SECONDS + 1; // adjust time to point just past the required additional recovery time
222 failsafeOnValidDataReceived();
225 failsafeUpdateState();
228 EXPECT_EQ(false, failsafeIsActive());
229 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
230 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM)); // disarm not called repeatedly.
231 EXPECT_FALSE(ARMING_FLAG(PREVENT_ARMING));
234 /****************************************************************************************/
235 TEST(FlightFailsafeTest, TestFailsafeDetectsRxLossAndJustDisarms)
238 DISABLE_ARMING_FLAG(ARMED);
242 failsafeStartMonitoring();
243 throttleStatus = THROTTLE_LOW; // throttle LOW to go for a failsafe just-disarm procedure
244 sysTickUptime = 0; // restart time from 0
245 failsafeOnValidDataReceived(); // set last valid sample at current time
248 for (sysTickUptime = 0; sysTickUptime < (uint32_t)(failsafeConfig.failsafe_delay * MILLIS_PER_TENTH_SECOND + PERIOD_RXDATA_FAILURE); sysTickUptime++) {
249 failsafeOnValidDataFailed();
251 failsafeUpdateState();
254 EXPECT_EQ(false, failsafeIsActive());
255 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
259 sysTickUptime++; // adjust time to point just past the failure time to
260 failsafeOnValidDataFailed(); // cause a lost link
261 ENABLE_ARMING_FLAG(ARMED); // armed from here (disarmed state has cleared throttleLowPeriod).
264 failsafeUpdateState();
267 EXPECT_EQ(true, failsafeIsActive());
268 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING, failsafePhase());
269 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM));
270 EXPECT_TRUE(ARMING_FLAG(PREVENT_ARMING));
273 failsafeOnValidDataFailed(); // set last invalid sample at current time
274 sysTickUptime += PERIOD_RXDATA_RECOVERY + 1; // adjust time to point just past the recovery time to
275 failsafeOnValidDataReceived(); // cause a recovered link
278 failsafeUpdateState();
281 EXPECT_EQ(true, failsafeIsActive());
282 EXPECT_EQ(FAILSAFE_RX_LOSS_MONITORING, failsafePhase());
283 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM));
284 EXPECT_TRUE(ARMING_FLAG(PREVENT_ARMING));
287 sysTickUptime += PERIOD_OF_3_SECONDS + 1; // adjust time to point just past the required additional recovery time
288 failsafeOnValidDataReceived();
291 failsafeUpdateState();
294 EXPECT_EQ(false, failsafeIsActive());
295 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
296 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM)); // disarm not called repeatedly.
297 EXPECT_FALSE(ARMING_FLAG(PREVENT_ARMING));
300 /****************************************************************************************/
302 // Additional non-stepwise tests
304 /****************************************************************************************/
305 TEST(FlightFailsafeTest, TestFailsafeNotActivatedWhenDisarmedAndRXLossIsDetected)
311 useFailsafeConfig(&failsafeConfig);
312 failsafeInit(&rxConfig);
315 DISABLE_ARMING_FLAG(ARMED);
318 failsafeStartMonitoring();
321 sysTickUptime = 0; // restart time from 0
322 failsafeOnValidDataReceived(); // set last valid sample at current time
325 for (sysTickUptime = 0; sysTickUptime < PERIOD_RXDATA_FAILURE; sysTickUptime++) {
326 failsafeOnValidDataFailed();
328 failsafeUpdateState();
331 EXPECT_EQ(false, failsafeIsActive());
332 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
336 sysTickUptime++; // adjust time to point just past the failure time to
337 failsafeOnValidDataFailed(); // cause a lost link
340 failsafeUpdateState();
343 EXPECT_EQ(true, failsafeIsMonitoring());
344 EXPECT_EQ(false, failsafeIsActive());
345 EXPECT_EQ(FAILSAFE_IDLE, failsafePhase());
346 EXPECT_EQ(1, CALL_COUNTER(COUNTER_MW_DISARM));
347 EXPECT_FALSE(ARMING_FLAG(PREVENT_ARMING));
353 int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
355 int16_t rcCommand[4];
356 uint32_t rcModeActivationMask;
357 int32_t debug[DEBUG32_VALUE_COUNT];
358 bool isUsingSticksToArm = true;
361 // Return system uptime in milliseconds (rollover in 49 days)
362 uint32_t millis(void)
364 return sysTickUptime;
367 throttleStatus_e calculateThrottleStatus(rxConfig_t *rxConfig, uint16_t mid_throttle_deadband)
370 UNUSED(mid_throttle_deadband);
371 return throttleStatus;
374 void delay(uint32_t) {}
376 bool feature(uint32_t mask) {
377 return (mask & testFeatureMask);
380 void mwDisarm(void) {
381 callCounts[COUNTER_MW_DISARM]++;
384 void beeper(beeperMode_e mode) {
388 uint16_t enableFlightMode(flightModeFlags_e mask)
390 flightModeFlags |= (mask);
391 return flightModeFlags;
394 uint16_t disableFlightMode(flightModeFlags_e mask)
396 flightModeFlags &= ~(mask);
397 return flightModeFlags;
400 uint16_t getCurrentMinthrottle(void)
402 return testMinThrottle;