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/>.
19 * Based on https://github.com/ExpressLRS/ExpressLRS
20 * Thanks to AlessandroAU, original creator of the ExpressLRS project.
31 #include "drivers/io.h"
32 #include "common/filter.h"
35 #include "pg/pg_ids.h"
36 #include "pg/rx_spi.h"
37 #include "pg/rx_spi_expresslrs.h"
39 #include "rx/rx_spi.h"
40 #include "rx/expresslrs.h"
41 #include "rx/expresslrs_impl.h"
43 #include "drivers/rx/rx_sx127x.h"
44 #include "drivers/rx/rx_sx1280.h"
46 extern uint8_t FHSSsequence
[ELRS_NR_SEQUENCE_ENTRIES
];
47 extern uint16_t crc14tab
[ELRS_CRC_LEN
];
49 extern elrsReceiver_t receiver
;
50 static const elrsReceiver_t empty
= elrsReceiver_t();
52 static rxRuntimeState_t config
= rxRuntimeState_t();
53 static rxSpiExtiConfig_t extiConfig
;
54 static const rxSpiConfig_t injectedConfig
= {
55 .extiIoTag
= IO_TAG(PA0
),
59 #include "unittest_macros.h"
60 #include "gtest/gtest.h"
62 //make clean test_rx_spi_expresslrs_unittest
63 TEST(RxSpiExpressLrsUnitTest
, TestCrc14
)
65 uint16_t expectedCrc14Tab
[ELRS_CRC_LEN
] = {
66 0,28247,62201,40110,52133,42482,14684,22283,
67 38730,63773,26035,3044,23791,12984,44566,49217,
68 11924,16579,56429,45626,58673,35686,6088,31135,
69 47582,55177,19239,9584,29307,7212,32898,61141,
70 29567,7464,33158,61393,47322,54925,18979,9332,
71 58421,35426,5836,30875,12176,16839,56681,45886,
72 24043,13244,44818,49477,38478,63513,25783,2784,
73 51873,42230,14424,22031,260,28499,62461,40362,
74 51369,42750,14928,21511,780,27995,61941,40866,
75 24547,12724,44314,49997,37958,64017,26303,2280,
76 58941,34922,5316,31379,11672,17359,57185,45366,
77 29047,7968,33678,60889,47826,54405,18475,9852,
78 48086,54657,18735,10104,28787,7716,33418,60637,
79 11420,17099,56933,45106,59193,35182,5568,31639,
80 38210,64277,26555,2540,24295,12464,44062,49737,
81 520,27743,61681,40614,51629,43002,15188,21763,
82 37202,65285,25515,3580,23287,13472,43022,50777,
83 1560,26703,62689,39606,52669,41962,16196,20755,
84 49094,53649,19775,9064,29795,6708,34458,59597,
85 10380,18139,55925,46114,58153,36222,4560,32647,
86 57901,35962,4308,32387,10632,18399,56177,46374,
87 30055,6960,34718,59849,48834,53397,19515,8812,
88 52409,41710,15936,20503,1820,26955,62949,39858,
89 23539,13732,43274,51037,36950,65025,25263,3320,
90 23035,14252,43778,50517,37470,64521,24743,3824,
91 52913,41190,15432,21023,1300,27459,63469,39354,
92 30575,6456,34198,60353,48330,53917,20019,8292,
93 57381,36466,4828,31883,11136,17879,55673,46894,
94 10884,17619,55421,46634,57633,36726,5080,32143,
95 48590,54169,20279,8544,30315,6204,33938,60101,
96 1040,27207,63209,39102,53173,41442,15692,21275,
97 37722,64781,24995,4084,22783,13992,43526,50257
100 generateCrc14Table();
101 for (int i
= 0; i
< ELRS_CRC_LEN
; i
++) {
102 EXPECT_EQ(expectedCrc14Tab
[i
], crc14tab
[i
]);
106 TEST(RxSpiExpressLrsUnitTest
, TestFHSSTable
)
108 const uint8_t UID
[6] = {1, 2, 3, 4, 5, 6};
110 const uint8_t expectedSequence
[2][ELRS_NR_SEQUENCE_ENTRIES
] = {
112 40, 43, 39, 18, 52, 19, 36, 7, 1, 12,
113 71, 5, 42, 46, 50, 28, 49, 33, 76, 51,
114 60, 70, 47, 61, 0, 55, 72, 37, 53, 25,
115 3, 11, 41, 13, 35, 27, 9, 75, 48, 77,
116 73, 74, 69, 58, 14, 31, 10, 59, 66, 4,
117 78, 17, 44, 54, 29, 57, 21, 64, 22, 67,
118 62, 56, 15, 79, 6, 34, 23, 30, 32, 2,
119 68, 8, 63, 65, 45, 20, 24, 26, 16, 38,
120 40, 8, 52, 29, 57, 10, 6, 26, 19, 75,
121 21, 24, 1, 9, 50, 32, 69, 67, 2, 59,
122 28, 48, 77, 60, 41, 49, 68, 4, 5, 3,
123 44, 78, 58, 31, 16, 62, 35, 45, 73, 11,
124 33, 46, 42, 36, 64, 7, 34, 53, 17, 25,
125 37, 38, 54, 55, 15, 76, 18, 43, 23, 12,
126 39, 51, 22, 79, 74, 63, 27, 66, 65, 47,
127 70, 0, 30, 61, 13, 56, 14, 72, 71, 20,
128 40, 71, 68, 12, 57, 45, 10, 53, 21, 15,
129 69, 26, 54, 55, 73, 47, 35, 77, 1, 31,
130 20, 0, 38, 76, 5, 60, 6, 79, 3, 16,
131 50, 17, 52, 62, 18, 46, 28, 39, 29, 51,
132 43, 34, 49, 56, 32, 61, 74, 58, 25, 44,
133 2, 19, 65, 4, 13, 67, 11, 30, 66, 64,
134 36, 24, 75, 33, 59, 7, 41, 70, 48, 14,
135 42, 37, 8, 23, 78, 63, 22, 9, 72, 27
138 20, 37, 1, 3, 7, 26, 36, 29, 15, 35,
139 33, 24, 10, 34, 13, 31, 22, 9, 28, 23,
140 17, 38, 6, 27, 0, 32, 11, 5, 18, 25,
141 2, 4, 12, 19, 16, 8, 30, 14, 21, 39,
142 20, 2, 14, 7, 13, 33, 32, 28, 21, 11,
143 25, 17, 22, 9, 3, 4, 0, 31, 35, 38,
144 10, 34, 26, 39, 36, 6, 19, 16, 30, 27,
145 15, 24, 18, 1, 23, 37, 29, 8, 12, 5,
146 20, 19, 24, 29, 27, 2, 22, 14, 0, 3,
147 23, 13, 12, 35, 4, 25, 38, 18, 33, 36,
148 21, 16, 5, 31, 9, 32, 11, 1, 6, 7,
149 10, 15, 26, 34, 39, 37, 28, 17, 30, 8,
150 20, 7, 4, 24, 19, 16, 8, 13, 15, 10,
151 14, 36, 34, 0, 17, 12, 28, 21, 39, 22,
152 3, 2, 32, 33, 27, 6, 37, 18, 31, 38,
153 23, 25, 26, 30, 9, 1, 35, 5, 11, 29,
154 20, 1, 35, 22, 0, 10, 11, 27, 18, 37,
155 21, 31, 9, 19, 30, 17, 5, 38, 29, 36,
156 3, 2, 25, 34, 23, 6, 15, 4, 16, 26,
157 12, 24, 14, 13, 39, 8, 32, 7, 28, 33,
158 20, 36, 13, 5, 39, 37, 15, 8, 9, 4,
159 22, 12, 1, 6, 32, 25, 17, 18, 27, 28,
160 23, 19, 26, 3, 38, 16, 2, 34, 14, 30,
161 10, 11, 7, 0, 35, 24, 21, 33, 31, 29
165 FHSSrandomiseFHSSsequence(UID
, ISM2400
);
166 for (int i
= 0; i
< ELRS_NR_SEQUENCE_ENTRIES
; i
++) {
167 EXPECT_EQ(expectedSequence
[0][i
], FHSSsequence
[i
]);
170 FHSSrandomiseFHSSsequence(UID
, FCC915
);
171 for (int i
= 0; i
< ELRS_NR_SEQUENCE_ENTRIES
; i
++) {
172 EXPECT_EQ(expectedSequence
[1][i
], FHSSsequence
[i
]);
176 TEST(RxSpiExpressLrsUnitTest
, TestInitUnbound
)
178 const uint8_t bindUID
[6] = {0, 1, 2, 3, 4, 5};
181 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
183 //check initialization of elrsReceiver_t
184 EXPECT_TRUE(receiver
.inBindingMode
);
185 EXPECT_EQ(IO_NONE
, receiver
.resetPin
);
186 EXPECT_EQ(IO_NONE
, receiver
.busyPin
);
187 for (int i
= 0; i
< 6; i
++) {
188 EXPECT_EQ(bindUID
[i
], receiver
.UID
[i
]);
190 EXPECT_EQ(0, receiver
.nonceRX
);
191 EXPECT_EQ(0, receiver
.freqOffset
);
192 EXPECT_EQ(0, receiver
.lastValidPacketMs
);
194 const uint32_t initialFrequencies
[7] = {
195 FREQ_HZ_TO_REG_VAL_900(433920000),
196 FREQ_HZ_TO_REG_VAL_900(921500000),
197 FREQ_HZ_TO_REG_VAL_900(433925000),
198 FREQ_HZ_TO_REG_VAL_900(866425000),
199 FREQ_HZ_TO_REG_VAL_900(866425000),
200 FREQ_HZ_TO_REG_VAL_900(915500000),
201 FREQ_HZ_TO_REG_VAL_24(2440400000)
204 for (int i
= 0; i
< 7; i
++) {
206 rxExpressLrsSpiConfigMutable()->domain
= i
;
207 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
208 EXPECT_EQ(initialFrequencies
[i
], receiver
.currentFreq
);
211 // for unbound we need to initialize in 50HZ mode
213 rxExpressLrsSpiConfigMutable()->rateIndex
= 1;
214 rxExpressLrsSpiConfigMutable()->domain
= FCC915
;
215 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
216 EXPECT_EQ(airRateConfig
[0][2].index
, receiver
.modParams
->index
);
217 EXPECT_EQ(airRateConfig
[0][2].enumRate
, receiver
.modParams
->enumRate
);
218 EXPECT_EQ(airRateConfig
[0][2].bw
, receiver
.modParams
->bw
);
219 EXPECT_EQ(airRateConfig
[0][2].sf
, receiver
.modParams
->sf
);
220 EXPECT_EQ(airRateConfig
[0][2].cr
, receiver
.modParams
->cr
);
221 EXPECT_EQ(airRateConfig
[0][2].interval
, receiver
.modParams
->interval
);
222 EXPECT_EQ(airRateConfig
[0][2].tlmInterval
, receiver
.modParams
->tlmInterval
);
223 EXPECT_EQ(airRateConfig
[0][2].fhssHopInterval
, receiver
.modParams
->fhssHopInterval
);
224 EXPECT_EQ(airRateConfig
[0][2].preambleLen
, receiver
.modParams
->preambleLen
);
227 rxExpressLrsSpiConfigMutable()->rateIndex
= 1;
228 rxExpressLrsSpiConfigMutable()->domain
= ISM2400
;
229 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
230 EXPECT_EQ(airRateConfig
[1][3].index
, receiver
.modParams
->index
);
231 EXPECT_EQ(airRateConfig
[1][3].enumRate
, receiver
.modParams
->enumRate
);
232 EXPECT_EQ(airRateConfig
[1][3].bw
, receiver
.modParams
->bw
);
233 EXPECT_EQ(airRateConfig
[1][3].sf
, receiver
.modParams
->sf
);
234 EXPECT_EQ(airRateConfig
[1][3].cr
, receiver
.modParams
->cr
);
235 EXPECT_EQ(airRateConfig
[1][3].interval
, receiver
.modParams
->interval
);
236 EXPECT_EQ(airRateConfig
[1][3].tlmInterval
, receiver
.modParams
->tlmInterval
);
237 EXPECT_EQ(airRateConfig
[1][3].fhssHopInterval
, receiver
.modParams
->fhssHopInterval
);
238 EXPECT_EQ(airRateConfig
[1][3].preambleLen
, receiver
.modParams
->preambleLen
);
242 rxExpressLrsSpiConfigMutable()->switchMode
= SM_HYBRID
;
243 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
244 EXPECT_EQ(16, config
.channelCount
);
246 rxExpressLrsSpiConfigMutable()->switchMode
= SM_HYBRID_WIDE
;
247 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
248 EXPECT_EQ(16, config
.channelCount
);
251 TEST(RxSpiExpressLrsUnitTest
, TestInitBound
)
253 const uint8_t validUID
[6] = {0, 0, 1, 2, 3, 4};
255 memcpy(rxExpressLrsSpiConfigMutable()->UID
, validUID
, 6);
258 for (int i
= 0; i
< ELRS_RATE_MAX
; i
++) {
260 rxExpressLrsSpiConfigMutable()->rateIndex
= i
;
261 rxExpressLrsSpiConfigMutable()->domain
= FCC915
;
262 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
263 EXPECT_EQ(airRateConfig
[0][i
].index
, receiver
.modParams
->index
);
264 EXPECT_EQ(airRateConfig
[0][i
].enumRate
, receiver
.modParams
->enumRate
);
265 EXPECT_EQ(airRateConfig
[0][i
].bw
, receiver
.modParams
->bw
);
266 EXPECT_EQ(airRateConfig
[0][i
].sf
, receiver
.modParams
->sf
);
267 EXPECT_EQ(airRateConfig
[0][i
].cr
, receiver
.modParams
->cr
);
268 EXPECT_EQ(airRateConfig
[0][i
].interval
, receiver
.modParams
->interval
);
269 EXPECT_EQ(airRateConfig
[0][i
].tlmInterval
, receiver
.modParams
->tlmInterval
);
270 EXPECT_EQ(airRateConfig
[0][i
].fhssHopInterval
, receiver
.modParams
->fhssHopInterval
);
271 EXPECT_EQ(airRateConfig
[0][i
].preambleLen
, receiver
.modParams
->preambleLen
);
274 rxExpressLrsSpiConfigMutable()->rateIndex
= i
;
275 rxExpressLrsSpiConfigMutable()->domain
= ISM2400
;
276 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
277 EXPECT_EQ(airRateConfig
[1][i
].index
, receiver
.modParams
->index
);
278 EXPECT_EQ(airRateConfig
[1][i
].enumRate
, receiver
.modParams
->enumRate
);
279 EXPECT_EQ(airRateConfig
[1][i
].bw
, receiver
.modParams
->bw
);
280 EXPECT_EQ(airRateConfig
[1][i
].sf
, receiver
.modParams
->sf
);
281 EXPECT_EQ(airRateConfig
[1][i
].cr
, receiver
.modParams
->cr
);
282 EXPECT_EQ(airRateConfig
[1][i
].interval
, receiver
.modParams
->interval
);
283 EXPECT_EQ(airRateConfig
[1][i
].tlmInterval
, receiver
.modParams
->tlmInterval
);
284 EXPECT_EQ(airRateConfig
[1][i
].fhssHopInterval
, receiver
.modParams
->fhssHopInterval
);
285 EXPECT_EQ(airRateConfig
[1][i
].preambleLen
, receiver
.modParams
->preambleLen
);
288 expressLrsSpiInit(&injectedConfig
, &config
, &extiConfig
);
289 EXPECT_FALSE(receiver
.inBindingMode
);
290 for (int i
= 0; i
< 6; i
++) {
291 EXPECT_EQ(validUID
[i
], receiver
.UID
[i
]);
295 TEST(RxSpiExpressLrsUnitTest
, TestLQCalc
)
298 for (int i
= 1; i
<= 100; i
++) {
301 EXPECT_EQ(i
, lqGet());
305 EXPECT_EQ(100, lqGet());
306 for (int i
= 99; i
>= 0; i
--) {
308 EXPECT_EQ(i
, lqGet());
311 EXPECT_EQ(0, lqGet());
314 EXPECT_EQ(0, lqGet());
316 EXPECT_EQ(1, lqGet());
319 TEST(RxSpiExpressLrsUnitTest
, Test1bSwitchDecode
)
321 EXPECT_EQ(1000, convertSwitch1b(0));
322 EXPECT_EQ(2000, convertSwitch1b(1));
323 EXPECT_EQ(2000, convertSwitch1b(2));
324 EXPECT_EQ(2000, convertSwitch1b(255));
327 TEST(RxSpiExpressLrsUnitTest
, Test3bSwitchDecode
)
329 EXPECT_EQ(1000, convertSwitch3b(0));
330 EXPECT_EQ(1275, convertSwitch3b(1));
331 EXPECT_EQ(1425, convertSwitch3b(2));
332 EXPECT_EQ(1575, convertSwitch3b(3));
333 EXPECT_EQ(1725, convertSwitch3b(4));
334 EXPECT_EQ(2000, convertSwitch3b(5));
335 EXPECT_EQ(1500, convertSwitch3b(6));
336 EXPECT_EQ(1500, convertSwitch3b(7));
337 EXPECT_EQ(1500, convertSwitch3b(8));
338 EXPECT_EQ(1500, convertSwitch3b(123));
339 EXPECT_EQ(1500, convertSwitch3b(255));
342 TEST(RxSpiExpressLrsUnitTest
, Test4bSwitchDecode
)
344 EXPECT_EQ(1000, convertSwitchNb(0, 15));
345 EXPECT_EQ(1066, convertSwitchNb(1, 15));
346 EXPECT_EQ(1133, convertSwitchNb(2, 15));
347 EXPECT_EQ(1200, convertSwitchNb(3, 15));
348 EXPECT_EQ(1266, convertSwitchNb(4, 15));
349 EXPECT_EQ(1333, convertSwitchNb(5, 15));
350 EXPECT_EQ(1400, convertSwitchNb(6, 15));
351 EXPECT_EQ(1466, convertSwitchNb(7, 15));
352 EXPECT_EQ(1533, convertSwitchNb(8, 15));
353 EXPECT_EQ(1600, convertSwitchNb(9, 15));
354 EXPECT_EQ(1666, convertSwitchNb(10, 15));
355 EXPECT_EQ(1733, convertSwitchNb(11, 15));
356 EXPECT_EQ(1800, convertSwitchNb(12, 15));
357 EXPECT_EQ(1866, convertSwitchNb(13, 15));
358 EXPECT_EQ(1933, convertSwitchNb(14, 15));
359 EXPECT_EQ(2000, convertSwitchNb(15, 15));
360 EXPECT_EQ(1500, convertSwitchNb(16, 15));
361 EXPECT_EQ(1500, convertSwitchNb(255, 15));
364 TEST(RxSpiExpressLrsUnitTest
, TestAnalogDecode
)
366 EXPECT_EQ(988, convertAnalog(172));
367 EXPECT_EQ(1500, convertAnalog(992));
368 EXPECT_EQ(2012, convertAnalog(1811));
378 rssiSource_e rssiSource
;
379 linkQualitySource_e linkQualitySource
;
380 void setRssi(uint16_t , rssiSource_e
) {}
381 void setRssiDirect(uint16_t , rssiSource_e
) {}
383 uint32_t micros(void) { return 0; }
384 uint32_t millis(void) { return 0; }
386 bool IORead(IO_t
) { return true; }
387 IO_t
IOGetByTag(ioTag_t
) { return (IO_t
)1; }
390 void writeEEPROM(void) {}
392 void rxSpiCommonIOInit(const rxSpiConfig_t
*) {}
393 void rxSpiLedBlinkRxLoss(rx_spi_received_e
) {}
394 void rxSpiLedBlinkBind(void) {}
395 bool rxSpiCheckBindRequested(bool)
399 bool rxSpiExtiConfigured(void) { return true; }
401 bool sx1280IsBusy(void) { return false; }
402 void sx1280Config(const sx1280LoraBandwidths_e
, const sx1280LoraSpreadingFactors_e
, const sx1280LoraCodingRates_e
, const uint32_t , const uint8_t , const bool ) {}
403 void sx1280StartReceiving(void) {}
404 uint8_t sx1280ISR(uint32_t *timestamp
)
409 void sx1280TransmitData(const uint8_t *, const uint8_t ) {}
410 void sx1280ReceiveData(uint8_t *, const uint8_t ) {}
411 void sx1280SetFrequencyReg(const uint32_t ) {}
412 void sx1280GetLastPacketStats(int8_t *rssi
, int8_t *snr
)
417 void sx1280AdjustFrequency(int32_t , const uint32_t ) {}
418 bool sx1280Init(IO_t
, IO_t
) { return true; }
420 void sx127xConfig(const sx127xBandwidth_e
, const sx127xSpreadingFactor_e
, const sx127xCodingRate_e
, const uint32_t , const uint8_t , const bool ) {}
421 void sx127xStartReceiving(void) {}
422 uint8_t sx127xISR(uint32_t *timestamp
)
427 void sx127xTransmitData(const uint8_t *, const uint8_t ) {}
428 void sx127xReceiveData(uint8_t *, const uint8_t ) {}
429 void sx127xSetFrequencyReg(const uint32_t ) {}
430 void sx127xGetLastPacketStats(int8_t *rssi
, int8_t *snr
)
435 void sx127xAdjustFrequency(int32_t , const uint32_t ) {}
436 bool sx127xInit(IO_t
, IO_t
) { return true; }
438 int scaleRange(int x
, int srcFrom
, int srcTo
, int destFrom
, int destTo
) {
439 long int a
= ((long int) destTo
- (long int) destFrom
) * ((long int) x
- (long int) srcFrom
);
440 long int b
= (long int) srcTo
- (long int) srcFrom
;
441 return (a
/ b
) + destFrom
;
444 void expressLrsInitialiseTimer(TIM_TypeDef
*, elrsReceiver_t
*) {}
445 void expressLrsTimerEnableIRQs(void) {}
446 void expressLrsUpdateTimerInterval(uint16_t ) {}
447 void expressLrsUpdatePhaseShift(int32_t ) {}
448 void expressLrsTimerIncreaseFrequencyOffset(void) {}
449 void expressLrsTimerDecreaseFrequencyOffset(void) {}
450 void expressLrsTimerResetFrequencyOffset(void) {}
451 void expressLrsTimerStop(void) {}
452 void expressLrsTimerResume(void) {}
453 bool expressLrsTimerIsRunning(void) { return true; }
454 void expressLrsTimerDebug(void) {}
456 int32_t simpleLPFilterUpdate(simpleLowpassFilter_t
*, int32_t ) { return 0; }
457 void simpleLPFilterInit(simpleLowpassFilter_t
*, int32_t , int32_t ) {}
458 void dbgPinHi(int ) {}
459 void dbgPinLo(int ) {}
461 void initTelemetry(void) {}
462 bool getNextTelemetryPayload(uint8_t *, uint8_t **) { return false; }
464 void setTelemetryDataToTransmit(const uint8_t , uint8_t* , const uint8_t ) {}
465 bool isTelemetrySenderActive(void) { return false; }
466 void getCurrentTelemetryPayload(uint8_t *, uint8_t *, uint8_t **) {}
467 void confirmCurrentTelemetryPayload(const bool ) {}
468 void updateTelemetryRate(const uint16_t , const uint8_t , const uint8_t ) {}