2 * This file is part of ExpressLRS
3 * See https://github.com/AlessandroAU/ExpressLRS
5 * Unit tests for over the air packet encoding, decoding and associated utilities
7 * Entry point is setup_switches()
18 #include "POWERMGNT.h"
20 #include "crsf_sysmocks.h"
22 CRSF crsf
; // need an instance to provide the fields used by the code under test
23 uint32_t ChannelData
[CRSF_NUM_CHANNELS
]; // Current state of channels, CRSF format
24 uint8_t UID
[6] = {1,2,3,4,5,6};
26 void test_crsf_endpoints()
28 // Validate 988us and 2012us convert to approprate CRSF values. Spoiler: They don't
29 TEST_ASSERT_EQUAL(-1024, Us_to_OpenTx(988));
30 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_MIN
+1, OpenTx_to_Crsf(-1024)); // NOTE: 988 comes from OpenTX as 173, not 172!
31 TEST_ASSERT_EQUAL(1024, Us_to_OpenTx(2012));
32 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_MAX
, OpenTx_to_Crsf(1024));
34 // Validate CRSF values convert to their expected values in OpenTX
35 TEST_ASSERT_EQUAL(988, Crsf_to_OpenTx_to_Us(CRSF_CHANNEL_VALUE_MIN
));
36 TEST_ASSERT_EQUAL(2012-1, Crsf_to_OpenTx_to_Us(CRSF_CHANNEL_VALUE_MAX
)); // NOTE: Feeding the 2012 CRSF value back into OpenTX would give 2011
38 // Validate CRSF values convert to their expected values in Betaflight
39 TEST_ASSERT_EQUAL(988, Crsf_to_BfUs(CRSF_CHANNEL_VALUE_MIN
));
40 TEST_ASSERT_EQUAL(2012, Crsf_to_BfUs(CRSF_CHANNEL_VALUE_MAX
));
42 // Validate important values are still the same value when mapped and umapped from their 10-bit representations
43 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_MIN
, Crsf_to_Uint10_to_Crsf(CRSF_CHANNEL_VALUE_MIN
));
44 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000
, Crsf_to_Uint10_to_Crsf(CRSF_CHANNEL_VALUE_1000
));
45 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_MID
, Crsf_to_Uint10_to_Crsf(CRSF_CHANNEL_VALUE_MID
));
46 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000
, Crsf_to_Uint10_to_Crsf(CRSF_CHANNEL_VALUE_2000
));
47 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_MAX
, Crsf_to_Uint10_to_Crsf(CRSF_CHANNEL_VALUE_MAX
));
52 TEST_ASSERT_EQUAL(0, CRSF_to_BIT(CRSF_CHANNEL_VALUE_1000
));
53 TEST_ASSERT_EQUAL(1, CRSF_to_BIT(CRSF_CHANNEL_VALUE_2000
));
58 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000
, BIT_to_CRSF(0));
59 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000
, BIT_to_CRSF(1));
64 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_MIN
, 64));
65 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_1000
, 64));
66 TEST_ASSERT_EQUAL(0b100000, CRSF_to_N(CRSF_CHANNEL_VALUE_MID
, 64));
67 TEST_ASSERT_EQUAL(0b111111, CRSF_to_N(CRSF_CHANNEL_VALUE_2000
, 64));
68 TEST_ASSERT_EQUAL(0b111111, CRSF_to_N(CRSF_CHANNEL_VALUE_MAX
, 64));
70 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_MIN
, 128));
71 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_1000
, 128));
72 TEST_ASSERT_EQUAL(0b1000000, CRSF_to_N(CRSF_CHANNEL_VALUE_MID
, 128));
73 TEST_ASSERT_EQUAL(0b1111111, CRSF_to_N(CRSF_CHANNEL_VALUE_2000
, 128));
74 TEST_ASSERT_EQUAL(0b1111111, CRSF_to_N(CRSF_CHANNEL_VALUE_MAX
, 128));
80 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000
, N_to_CRSF(0, 63));
81 TEST_ASSERT_EQUAL(1004, N_to_CRSF(0b100000, 63));
82 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000
, N_to_CRSF(0b111111, 63));
85 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000
, N_to_CRSF(0, 127));
86 TEST_ASSERT_EQUAL(997, N_to_CRSF(0b1000000, 127));
87 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000
, N_to_CRSF(0b1111111, 127));
90 // ------------------------------------------------
91 // Test the hybrid8 encoding/decoding
93 /* Check the hybrid 8 encoding of a packet for OTA tx
95 void test_encodingHybrid8(bool highResChannel
)
97 constexpr uint8_t N_SWITCHES
= 8;
98 uint8_t UID
[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
99 uint8_t TXdataBuffer
[OTA4_PACKET_SIZE
] = {0};
100 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
102 // Define the input data
103 // 4 channels of 11-bit analog data
104 ChannelData
[0] = 0x0123 & 0b11111111111;
105 ChannelData
[1] = 0x4567 & 0b11111111111;
106 ChannelData
[2] = 0x89AB & 0b11111111111;
107 ChannelData
[3] = 0xCDEF & 0b11111111111;
110 OTA_Channels_4x10 ch
;
125 for(int i
= 0; i
< N_SWITCHES
; i
++) {
126 constexpr int CHANNELS
[] =
127 { CRSF_CHANNEL_VALUE_1000
, CRSF_CHANNEL_VALUE_MID
, CRSF_CHANNEL_VALUE_2000
};
128 ChannelData
[4+i
] = CHANNELS
[i
% 3];
131 // set the nextSwitchIndex so we know which switch to expect in the packet
133 OtaSetHybrid8NextSwitchIndex(7-1);
135 OtaSetHybrid8NextSwitchIndex(3-1);
138 OtaUpdateSerializers(smHybridOr16ch
, OTA4_PACKET_SIZE
);
139 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
141 // check it looks right
142 // 1st byte is CRC & packet type
143 uint8_t header
= PACKET_TYPE_RCDATA
;
144 TEST_ASSERT_EQUAL(header
, TXdataBuffer
[0]);
146 // bytes 1 through 5 are 10 bit packed analog channels representing 998-2012 (CRSF_CHANNEL_VALUE_MIN-CRSF_CHANNEL_VALUE_MAX)
147 uint8_t expected
[5] = { 0x4a, 0xd0, 0xfb, 0x49, 0xd2 };
148 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[1], 5);
150 // byte 6 is the switch encoding
151 TEST_ASSERT_EQUAL(CRSF_to_BIT(ChannelData
[4+0]), TXdataBuffer
[6] >> 7);
152 // top bit is undefined
153 // expect switch 0 in bit 6
155 // value in 0,1,2[,3]
158 TEST_ASSERT_EQUAL(7, ((TXdataBuffer
[6] & 0b110000)>>3) + 1);
159 TEST_ASSERT_EQUAL(CRSF_to_N(ChannelData
[4+7], 16), TXdataBuffer
[6] & 0b1111);
163 TEST_ASSERT_EQUAL(3, ((TXdataBuffer
[6] & 0b111000)>>3) + 1);
164 TEST_ASSERT_EQUAL(CRSF_to_N(ChannelData
[4+3], 6), TXdataBuffer
[6] & 0b0111);
168 void test_encodingHybrid8_3()
170 test_encodingHybrid8(false);
173 void test_encodingHybrid8_7()
175 test_encodingHybrid8(true);
178 /* Check the decoding of a packet after rx
180 void test_decodingHybrid8(uint8_t forceSwitch
, uint8_t switchval
)
182 constexpr uint8_t N_SWITCHES
= 8;
183 uint8_t UID
[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
184 uint8_t TXdataBuffer
[OTA4_PACKET_SIZE
] = {0};
185 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
186 uint32_t ChannelsIn
[16];
187 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
189 // Define the input data
190 // 4 channels of 11-bit analog data
191 ChannelData
[0] = 0x0123 & 0b11111111111;
192 ChannelData
[1] = 0x4567 & 0b11111111111;
193 ChannelData
[2] = 0x89AB & 0b11111111111;
194 ChannelData
[3] = 0xCDEF & 0b11111111111;
197 for(int i
= 0; i
< N_SWITCHES
; i
++) {
198 constexpr int CHANNELS
[] =
199 { CRSF_CHANNEL_VALUE_1000
, CRSF_CHANNEL_VALUE_MID
, CRSF_CHANNEL_VALUE_2000
};
200 ChannelData
[4+i
] = CHANNELS
[i
% 3];
202 if (forceSwitch
== 0)
203 ChannelData
[4+forceSwitch
] = BIT_to_CRSF(switchval
);
204 else if (forceSwitch
== 7)
205 ChannelData
[4+forceSwitch
] = N_to_CRSF(switchval
, 15);
207 ChannelData
[4+forceSwitch
] = SWITCH3b_to_CRSF(switchval
);
209 // set the nextSwitchIndex so we know which switch to expect in the packet
210 if (forceSwitch
== 0)
211 OtaSetHybrid8NextSwitchIndex(0);
213 OtaSetHybrid8NextSwitchIndex(forceSwitch
-1);
215 // Save the channels since they go into the same place
216 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
217 // use the encoding method to pack it into TXdataBuffer
218 OtaUpdateSerializers(smHybridOr16ch
, OTA4_PACKET_SIZE
);
219 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
221 // run the decoder, results in crsf->PackedRCdataOut
222 OtaUnpackChannelData(otaPktPtr
, ChannelData
, 0);
224 // compare the unpacked results with the input data
225 TEST_ASSERT_EQUAL(ChannelsIn
[0], ChannelData
[0]);
226 TEST_ASSERT_EQUAL(ChannelsIn
[1], ChannelData
[1]);
227 TEST_ASSERT_EQUAL(ChannelsIn
[2], ChannelData
[2]);
228 TEST_ASSERT_EQUAL(ChannelsIn
[3], ChannelData
[3]);
230 TEST_ASSERT_EQUAL(ChannelsIn
[4+0], ChannelData
[4]); // Switch 0 is sent on every packet
231 if (forceSwitch
== 7)
232 TEST_ASSERT_EQUAL(ChannelsIn
[4+forceSwitch
], ChannelData
[11]); // We forced switch 1 to be sent as the sequential field
233 else if (forceSwitch
!= 0)
234 TEST_ASSERT_EQUAL(ChannelData
[4+forceSwitch
], ChannelData
[4+forceSwitch
]);
237 void test_decodingHybrid8_all()
240 test_decodingHybrid8(0, 0);
241 test_decodingHybrid8(0, 1);
242 // Switch X in 6-pos mode (includes 3-pos low/high)
243 for (uint8_t val
=0; val
<6; ++val
)
244 test_decodingHybrid8(3, val
);
245 // // Switch X in 3-pos mode center
246 // test_decodingHybrid8(3, 7);
247 // // Switch 7 is 16 pos
248 // for (uint8_t val=0; val<16; ++val)
249 // test_decodingHybrid8(7, val);
252 /* Check the HybridWide encoding of a packet for OTA tx
254 void test_encodingHybridWide(bool highRes
, uint8_t nonce
)
256 uint8_t UID
[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
257 uint8_t TXdataBuffer
[OTA4_PACKET_SIZE
] = {0};
258 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
259 uint32_t ChannelsIn
[16];
260 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
262 // Define the input data
263 // 4 channels of 11-bit analog data
264 ChannelData
[0] = 0x0123 & 0b11111111111;
265 ChannelData
[1] = 0x4567 & 0b11111111111;
266 ChannelData
[2] = 0x89AB & 0b11111111111;
267 ChannelData
[3] = 0xCDEF & 0b11111111111;
270 constexpr int N_SWITCHES
= 8;
271 for(int i
= 0; i
< N_SWITCHES
; i
++) {
272 constexpr unsigned CHANNELS
[] =
273 { CRSF_CHANNEL_VALUE_1000
, CRSF_CHANNEL_VALUE_MID
, CRSF_CHANNEL_VALUE_2000
};
274 ChannelData
[4+i
] = CHANNELS
[i
% 3];
278 CRSF::LinkStatistics
.uplink_TX_Power
= 3; // 100mW
280 // Save the channels since they go into the same place
281 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
283 uint8_t tlmDenom
= (highRes
) ? 64 : 4;
284 OtaUpdateSerializers(smWideOr8ch
, OTA4_PACKET_SIZE
);
286 OtaPackChannelData(otaPktPtr
, ChannelData
, nonce
% 2, tlmDenom
);
288 // check it looks right
289 // 1st byte is CRC & packet type
290 uint8_t header
= PACKET_TYPE_RCDATA
;
291 TEST_ASSERT_EQUAL(header
, TXdataBuffer
[0]);
293 // bytes 1 through 5 are 10 bit packed analog channels representing 998-2012 (CRSF_CHANNEL_VALUE_MIN-CRSF_CHANNEL_VALUE_MAX)
294 uint8_t expected
[5] = { 0x4a, 0xd0, 0xfb, 0x49, 0xd2 };
295 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[1], 5);
297 // byte 6 is the switches encoded
298 uint8_t switches
= TXdataBuffer
[6];
299 uint8_t switchIdx
= nonce
% 8;
301 // High bit should be AUX1
302 TEST_ASSERT_EQUAL(CRSF_to_BIT(ChannelsIn
[4]), switches
>> 7);
303 // If low res or slot 7, the bit 6 should be the telemetryack bit
304 if (!highRes
|| switchIdx
== 7)
305 TEST_ASSERT_EQUAL(nonce
% 2, (switches
>> 6) & 1);
307 // If slot 7, the uplink_TX_Power should be in the low 6 bits
309 TEST_ASSERT_EQUAL(CRSF::LinkStatistics
.uplink_TX_Power
, switches
& 0b111111);
312 uint16_t ch
= ChannelData
[5+switchIdx
];
314 TEST_ASSERT_EQUAL(CRSF_to_N(ch
, 128), switches
& 0b1111111); // 7-bit
316 TEST_ASSERT_EQUAL(CRSF_to_N(ch
, 64), switches
& 0b111111); // 6-bit
320 void test_encodingHybridWide_high()
322 constexpr int N_SWITCHES
= 8;
323 for (int i
=0; i
<N_SWITCHES
; ++i
)
324 test_encodingHybridWide(true, i
);
327 void test_encodingHybridWide_low()
329 constexpr int N_SWITCHES
= 8;
330 for (int i
=0; i
<N_SWITCHES
; ++i
)
331 test_encodingHybridWide(false, i
);
334 /* Check the decoding of a packet after rx in HybridWide mode
336 void test_decodingHybridWide(bool highRes
, uint8_t nonce
, uint8_t forceSwitch
, uint16_t forceVal
)
338 uint8_t UID
[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
339 uint8_t TXdataBuffer
[OTA4_PACKET_SIZE
] = {0};
340 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
341 uint32_t ChannelsIn
[16];
342 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
344 // Define the input data
345 // 4 channels of 11-bit analog data
346 ChannelData
[0] = 0x0123 & 0b11111111111;
347 ChannelData
[1] = 0x4567 & 0b11111111111;
348 ChannelData
[2] = 0x89AB & 0b11111111111;
349 ChannelData
[3] = 0xCDEF & 0b11111111111;
352 constexpr int N_SWITCHES
= 8;
353 for(int i
= 0; i
< N_SWITCHES
; i
++) {
354 constexpr unsigned CHANNELS
[] =
355 { CRSF_CHANNEL_VALUE_1000
, CRSF_CHANNEL_VALUE_MID
, CRSF_CHANNEL_VALUE_2000
};
356 if (i
== forceSwitch
)
357 ChannelData
[4+i
] = forceVal
;
359 ChannelData
[4+i
] = CHANNELS
[i
% 3];
363 CRSF::LinkStatistics
.uplink_TX_Power
= 3; // 100mW
365 // Save the channels since they go into the same place
366 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
368 uint8_t tlmDenom
= (highRes
) ? 64 : 4;
369 OtaUpdateSerializers(smWideOr8ch
, OTA4_PACKET_SIZE
);
371 OtaPackChannelData(otaPktPtr
, ChannelData
, nonce
% 2, tlmDenom
);
373 // Clear the LinkStatistics to receive it from the encoding
374 CRSF::LinkStatistics
.uplink_TX_Power
= 0;
376 // run the decoder, results in crsf->PackedRCdataOut
377 bool telemResult
= OtaUnpackChannelData(otaPktPtr
, ChannelData
, tlmDenom
);
379 // compare the unpacked results with the input data
380 TEST_ASSERT_EQUAL(ChannelsIn
[0], ChannelData
[0]);
381 TEST_ASSERT_EQUAL(ChannelsIn
[1], ChannelData
[1]);
382 TEST_ASSERT_EQUAL(ChannelsIn
[2], ChannelData
[2]);
383 TEST_ASSERT_EQUAL(ChannelsIn
[3], ChannelData
[3]);
385 // Switch 0 is sent on every packet
386 TEST_ASSERT_EQUAL(ChannelData
[4], ChannelData
[4]);
388 uint8_t switchIdx
= nonce
% 8;
389 // Validate the telemResult was unpacked properly
390 if (!highRes
|| switchIdx
== 7)
391 TEST_ASSERT_EQUAL(telemResult
, nonce
% 2);
395 TEST_ASSERT_EQUAL(CRSF::LinkStatistics
.uplink_TX_Power
, 3);
400 TEST_ASSERT_EQUAL(N_to_CRSF(CRSF_to_N(ChannelData
[5+switchIdx
], 128), 127), ChannelData
[5+switchIdx
]);
402 TEST_ASSERT_EQUAL(N_to_CRSF(CRSF_to_N(ChannelData
[5+switchIdx
], 64), 63), ChannelData
[5+switchIdx
]);
406 void fullres_fillChannelData()
408 // Define the input data
409 // 16 channels of 11-bit analog data
410 ChannelData
[0] = 0x0123 & 0b11111111111;
411 ChannelData
[1] = 0x4567 & 0b11111111111;
412 ChannelData
[2] = 0x89AB & 0b11111111111;
413 ChannelData
[3] = 0xCDEF & 0b11111111111;
414 ChannelData
[4] = 0x3210 & 0b11111111111;
415 ChannelData
[5] = 0x7654 & 0b11111111111;
416 ChannelData
[6] = 0xBA98 & 0b11111111111;
417 ChannelData
[7] = 0xFEDC & 0b11111111111;
419 ChannelData
[8] = 0x2301 & 0b11111111111;
420 ChannelData
[9] = 0x6745 & 0b11111111111;
421 ChannelData
[10] = 0xAB89 & 0b11111111111;
422 ChannelData
[11] = 0xEFCD & 0b11111111111;
423 ChannelData
[12] = 0x1023 & 0b11111111111;
424 ChannelData
[13] = 0x5476 & 0b11111111111;
425 ChannelData
[14] = 0x98BA & 0b11111111111;
426 ChannelData
[15] = 0xDCFE & 0b11111111111;
429 void test_encodingFullresPowerLevels()
431 uint8_t TXdataBuffer
[OTA8_PACKET_SIZE
] = {0};
432 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
433 uint32_t ChannelsIn
[16];
434 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
436 OtaUpdateSerializers(smWideOr8ch
, OTA8_PACKET_SIZE
);
438 for (uint8_t pwr
=PWR_10mW
; pwr
<PWR_COUNT
; ++pwr
)
440 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
));
441 fullres_fillChannelData();
443 // This is what we're testing here, just the power
444 uint8_t crsfPower
= powerToCrsfPower((PowerLevels_e
)pwr
);
445 CRSF::LinkStatistics
.uplink_TX_Power
= crsfPower
;
447 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
448 OtaUnpackChannelData(otaPktPtr
, ChannelData
, 0);
450 TEST_ASSERT_EQUAL(crsfPower
, CRSF::LinkStatistics
.uplink_TX_Power
);
454 void test_encodingFullres8ch()
456 uint8_t TXdataBuffer
[OTA8_PACKET_SIZE
] = {0};
457 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
458 uint32_t ChannelsIn
[16];
459 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
461 fullres_fillChannelData();
462 CRSF::LinkStatistics
.uplink_TX_Power
= PWR_250mW
;
464 // Save the channels since they go into the same place
465 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
466 OtaUpdateSerializers(smWideOr8ch
, OTA8_PACKET_SIZE
);
467 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
471 expected
[0] = ((ChannelsIn
[0] >> 1) >> 0);
472 expected
[1] = ((ChannelsIn
[0] >> 1) >> 8) | ((ChannelsIn
[1] >> 1) << 2);
473 expected
[2] = ((ChannelsIn
[1] >> 1) >> 6) | ((ChannelsIn
[2] >> 1) << 4);
474 expected
[3] = ((ChannelsIn
[2] >> 1) >> 4) | ((ChannelsIn
[3] >> 1) << 6);
475 expected
[4] = ((ChannelsIn
[3] >> 1) >> 2);
476 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chLow
)], 5);
477 // High 4ch, skip AUX1 (CH6-CH9)
478 expected
[0] = ((ChannelsIn
[5] >> 1) >> 0);
479 expected
[1] = ((ChannelsIn
[5] >> 1) >> 8) | ((ChannelsIn
[6] >> 1) << 2);
480 expected
[2] = ((ChannelsIn
[6] >> 1) >> 6) | ((ChannelsIn
[7] >> 1) << 4);
481 expected
[3] = ((ChannelsIn
[7] >> 1) >> 4) | ((ChannelsIn
[8] >> 1) << 6);
482 expected
[4] = ((ChannelsIn
[8] >> 1) >> 2);
483 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chHigh
)], 5);
485 // Check the header bits
486 TEST_ASSERT_EQUAL(PACKET_TYPE_RCDATA
, otaPktPtr
->full
.rc
.packetType
);
487 TEST_ASSERT_EQUAL(false, otaPktPtr
->full
.rc
.telemetryStatus
);
488 TEST_ASSERT_EQUAL(PWR_250mW
, otaPktPtr
->full
.rc
.uplinkPower
+ 1);
489 TEST_ASSERT_EQUAL(false, otaPktPtr
->full
.rc
.isHighAux
);
490 TEST_ASSERT_EQUAL(CRSF_to_BIT(ChannelsIn
[4]), otaPktPtr
->full
.rc
.ch4
);
493 void test_encodingFullres16ch()
495 uint8_t TXdataBuffer
[OTA8_PACKET_SIZE
] = {0};
496 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
497 uint32_t ChannelsIn
[16];
498 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
500 fullres_fillChannelData();
502 // Save the channels since they go into the same place
503 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
504 OtaUpdateSerializers(smHybridOr16ch
, OTA8_PACKET_SIZE
);
505 OtaSetFullResNextChannelSet(false);
508 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
509 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
512 expected
[0] = ((ChannelsIn
[0] >> 1) >> 0);
513 expected
[1] = ((ChannelsIn
[0] >> 1) >> 8) | ((ChannelsIn
[1] >> 1) << 2);
514 expected
[2] = ((ChannelsIn
[1] >> 1) >> 6) | ((ChannelsIn
[2] >> 1) << 4);
515 expected
[3] = ((ChannelsIn
[2] >> 1) >> 4) | ((ChannelsIn
[3] >> 1) << 6);
516 expected
[4] = ((ChannelsIn
[3] >> 1) >> 2);
517 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chLow
)], 5);
518 // High 4ch, includes AUX1 (CH5-CH8)
519 expected
[0] = ((ChannelsIn
[4] >> 1) >> 0);
520 expected
[1] = ((ChannelsIn
[4] >> 1) >> 8) | ((ChannelsIn
[5] >> 1) << 2);
521 expected
[2] = ((ChannelsIn
[5] >> 1) >> 6) | ((ChannelsIn
[6] >> 1) << 4);
522 expected
[3] = ((ChannelsIn
[6] >> 1) >> 4) | ((ChannelsIn
[7] >> 1) << 6);
523 expected
[4] = ((ChannelsIn
[7] >> 1) >> 2);
524 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chHigh
)], 5);
527 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
528 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
529 // Low 4ch (CH9-CH12)
530 expected
[0] = ((ChannelsIn
[8] >> 1) >> 0);
531 expected
[1] = ((ChannelsIn
[8] >> 1) >> 8) | ((ChannelsIn
[9] >> 1) << 2);
532 expected
[2] = ((ChannelsIn
[9] >> 1) >> 6) | ((ChannelsIn
[10] >> 1) << 4);
533 expected
[3] = ((ChannelsIn
[10] >> 1) >> 4) | ((ChannelsIn
[11] >> 1) << 6);
534 expected
[4] = ((ChannelsIn
[11] >> 1) >> 2);
535 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chLow
)], 5);
536 // High 4ch (CH13-CH16)
537 expected
[0] = ((ChannelsIn
[12] >> 1) >> 0);
538 expected
[1] = ((ChannelsIn
[12] >> 1) >> 8) | ((ChannelsIn
[13] >> 1) << 2);
539 expected
[2] = ((ChannelsIn
[13] >> 1) >> 6) | ((ChannelsIn
[14] >> 1) << 4);
540 expected
[3] = ((ChannelsIn
[14] >> 1) >> 4) | ((ChannelsIn
[15] >> 1) << 6);
541 expected
[4] = ((ChannelsIn
[15] >> 1) >> 2);
542 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chHigh
)], 5);
545 void test_encodingFullres12ch()
547 uint8_t TXdataBuffer
[OTA8_PACKET_SIZE
] = {0};
548 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
549 uint32_t ChannelsIn
[16];
550 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
552 fullres_fillChannelData();
554 // Save the channels since they go into the same place
555 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
556 OtaUpdateSerializers(sm12ch
, OTA8_PACKET_SIZE
);
557 OtaSetFullResNextChannelSet(false);
560 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
561 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
564 expected
[0] = ((ChannelsIn
[0] >> 1) >> 0);
565 expected
[1] = ((ChannelsIn
[0] >> 1) >> 8) | ((ChannelsIn
[1] >> 1) << 2);
566 expected
[2] = ((ChannelsIn
[1] >> 1) >> 6) | ((ChannelsIn
[2] >> 1) << 4);
567 expected
[3] = ((ChannelsIn
[2] >> 1) >> 4) | ((ChannelsIn
[3] >> 1) << 6);
568 expected
[4] = ((ChannelsIn
[3] >> 1) >> 2);
569 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chLow
)], 5);
570 // High 4ch, skips AUX1 (CH6-CH9)
571 expected
[0] = ((ChannelsIn
[5] >> 1) >> 0);
572 expected
[1] = ((ChannelsIn
[5] >> 1) >> 8) | ((ChannelsIn
[6] >> 1) << 2);
573 expected
[2] = ((ChannelsIn
[6] >> 1) >> 6) | ((ChannelsIn
[7] >> 1) << 4);
574 expected
[3] = ((ChannelsIn
[7] >> 1) >> 4) | ((ChannelsIn
[8] >> 1) << 6);
575 expected
[4] = ((ChannelsIn
[8] >> 1) >> 2);
576 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chHigh
)], 5);
579 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
580 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
582 expected
[0] = ((ChannelsIn
[0] >> 1) >> 0);
583 expected
[1] = ((ChannelsIn
[0] >> 1) >> 8) | ((ChannelsIn
[1] >> 1) << 2);
584 expected
[2] = ((ChannelsIn
[1] >> 1) >> 6) | ((ChannelsIn
[2] >> 1) << 4);
585 expected
[3] = ((ChannelsIn
[2] >> 1) >> 4) | ((ChannelsIn
[3] >> 1) << 6);
586 expected
[4] = ((ChannelsIn
[3] >> 1) >> 2);
587 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chLow
)], 5);
588 // Other high 4ch, skip AUX1 (CH10-CH13)
589 expected
[0] = ((ChannelsIn
[9] >> 1) >> 0);
590 expected
[1] = ((ChannelsIn
[9] >> 1) >> 8) | ((ChannelsIn
[10] >> 1) << 2);
591 expected
[2] = ((ChannelsIn
[10] >> 1) >> 6) | ((ChannelsIn
[11] >> 1) << 4);
592 expected
[3] = ((ChannelsIn
[11] >> 1) >> 4) | ((ChannelsIn
[12] >> 1) << 6);
593 expected
[4] = ((ChannelsIn
[12] >> 1) >> 2);
594 TEST_ASSERT_EQUAL_UINT8_ARRAY(expected
, &TXdataBuffer
[offsetof(OTA_Packet8_s
, rc
.chHigh
)], 5);
597 void test_decodingFullres16chLow()
599 uint8_t TXdataBuffer
[OTA8_PACKET_SIZE
] = {0};
600 OTA_Packet_s
* const otaPktPtr
= (OTA_Packet_s
*)TXdataBuffer
;
601 uint32_t ChannelsIn
[16];
602 TEST_ASSERT_EQUAL(sizeof(ChannelData
), sizeof(ChannelsIn
));
604 fullres_fillChannelData();
606 // Save the channels since they go into the same place
607 memcpy(ChannelsIn
, ChannelData
, sizeof(ChannelData
));
608 OtaUpdateSerializers(smHybridOr16ch
, OTA8_PACKET_SIZE
);
609 OtaSetFullResNextChannelSet(false);
612 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
613 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
614 OtaUnpackChannelData(otaPktPtr
, ChannelData
, 0);
615 for (unsigned ch
=0; ch
<8; ++ch
)
617 TEST_ASSERT_EQUAL(ChannelsIn
[ch
] & 0b11111111110, ChannelData
[ch
]);
621 memset(TXdataBuffer
, 0, sizeof(TXdataBuffer
)); // "destChannels4x10 must be zeroed"
622 OtaPackChannelData(otaPktPtr
, ChannelData
, false, 0);
623 OtaUnpackChannelData(otaPktPtr
, ChannelData
, 0);
624 for (unsigned ch
=9; ch
<16; ++ch
)
626 TEST_ASSERT_EQUAL(ChannelsIn
[ch
] & 0b11111111110, ChannelData
[ch
]);
630 void test_decodingHybridWide_AUX1()
632 // Switch 0 is 2 pos, also tests the uplink_TX_Power
633 test_decodingHybridWide(true, 7, 0, CRSF_CHANNEL_VALUE_1000
);
634 test_decodingHybridWide(true, 7, 0, CRSF_CHANNEL_VALUE_2000
);
637 void test_decodingHybridWide_AUXX_high()
639 constexpr int N_SWITCHES
= 8;
640 for (int i
=0; i
<N_SWITCHES
; ++i
)
641 test_decodingHybridWide(true, i
, 0, CRSF_CHANNEL_VALUE_1000
);
644 void test_decodingHybridWide_AUXX_low()
646 constexpr int N_SWITCHES
= 8;
647 for (int i
=0; i
<N_SWITCHES
; ++i
)
648 test_decodingHybridWide(false, i
, 0, CRSF_CHANNEL_VALUE_1000
);
651 // Unity setup/teardown
655 int main(int argc
, char **argv
)
658 RUN_TEST(test_crsf_endpoints
);
659 RUN_TEST(test_crsfToBit
);
660 RUN_TEST(test_bitToCrsf
);
661 RUN_TEST(test_crsfToN
);
662 RUN_TEST(test_nToCrsf
);
664 RUN_TEST(test_encodingHybrid8_3
);
665 RUN_TEST(test_encodingHybrid8_7
);
666 RUN_TEST(test_decodingHybrid8_all
);
668 RUN_TEST(test_encodingHybridWide_high
);
669 RUN_TEST(test_encodingHybridWide_low
);
670 RUN_TEST(test_decodingHybridWide_AUX1
);
671 RUN_TEST(test_decodingHybridWide_AUXX_high
);
672 RUN_TEST(test_decodingHybridWide_AUXX_low
);
674 RUN_TEST(test_encodingFullresPowerLevels
);
675 RUN_TEST(test_encodingFullres8ch
);
676 RUN_TEST(test_encodingFullres16ch
);
677 RUN_TEST(test_encodingFullres12ch
);
678 RUN_TEST(test_decodingFullres16chLow
);