Add missing wifi targets for some DIY modules (#1210)
[ExpressLRS.git] / src / test / ota_native / test_switches.cpp
blobf0f29515f1e0e656d49e9ce494981f2b335073ed
1 /**
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()
8 */
11 #include <unity.h>
13 #include "targets.h"
14 // #include "common.h"
15 #include "CRSF.h"
16 #include <OTA.h>
18 CRSF crsf(NULL); // need an instance to provide the fields used by the code under test
20 void test_crsfToBit()
22 TEST_ASSERT_EQUAL(0, CRSF_to_BIT(CRSF_CHANNEL_VALUE_1000));
23 TEST_ASSERT_EQUAL(1, CRSF_to_BIT(CRSF_CHANNEL_VALUE_2000));
26 void test_bitToCrsf()
28 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000, BIT_to_CRSF(0));
29 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000, BIT_to_CRSF(1));
32 void test_crsfToN()
34 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_MIN, 64));
35 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_1000, 64));
36 TEST_ASSERT_EQUAL(0b100000, CRSF_to_N(CRSF_CHANNEL_VALUE_MID, 64));
37 TEST_ASSERT_EQUAL(0b111111, CRSF_to_N(CRSF_CHANNEL_VALUE_2000, 64));
38 TEST_ASSERT_EQUAL(0b111111, CRSF_to_N(CRSF_CHANNEL_VALUE_MAX, 64));
40 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_MIN, 128));
41 TEST_ASSERT_EQUAL(0, CRSF_to_N(CRSF_CHANNEL_VALUE_1000, 128));
42 TEST_ASSERT_EQUAL(0b1000000, CRSF_to_N(CRSF_CHANNEL_VALUE_MID, 128));
43 TEST_ASSERT_EQUAL(0b1111111, CRSF_to_N(CRSF_CHANNEL_VALUE_2000, 128));
44 TEST_ASSERT_EQUAL(0b1111111, CRSF_to_N(CRSF_CHANNEL_VALUE_MAX, 128));
47 void test_nToCrsf()
49 // 6-bit
50 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000, N_to_CRSF(0, 63));
51 TEST_ASSERT_EQUAL(1004, N_to_CRSF(0b100000, 63));
52 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000, N_to_CRSF(0b111111, 63));
54 // 7-bit
55 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_1000, N_to_CRSF(0, 127));
56 TEST_ASSERT_EQUAL(997, N_to_CRSF(0b1000000, 127));
57 TEST_ASSERT_EQUAL(CRSF_CHANNEL_VALUE_2000, N_to_CRSF(0b1111111, 127));
60 // ------------------------------------------------
61 // Test the hybrid8 encoding/decoding
63 /* Check the hybrid 8 encoding of a packet for OTA tx
65 void test_encodingHybrid8(bool highResChannel)
67 constexpr uint8_t N_SWITCHES = 8;
68 uint8_t UID[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
69 uint8_t expected;
70 uint8_t TXdataBuffer[8];
72 // Define the input data
73 // 4 channels of analog data
74 crsf.ChannelDataIn[0] = 0x0123;
75 crsf.ChannelDataIn[1] = 0x4567;
76 crsf.ChannelDataIn[2] = 0x89AB;
77 crsf.ChannelDataIn[3] = 0xCDEF;
79 // 8 switches
80 for(int i = 0; i < N_SWITCHES; i++) {
81 constexpr int CHANNELS[] =
82 { CRSF_CHANNEL_VALUE_1000, CRSF_CHANNEL_VALUE_MID, CRSF_CHANNEL_VALUE_2000 };
83 crsf.ChannelDataIn[4+i] = CHANNELS[i % 3];
86 // set the nextSwitchIndex so we know which switch to expect in the packet
87 if (highResChannel)
88 OtaSetHybrid8NextSwitchIndex(7-1);
89 else
90 OtaSetHybrid8NextSwitchIndex(3-1);
92 // encode it
93 OtaSetSwitchMode(smHybrid);
94 PackChannelData(TXdataBuffer, &crsf, false, 0, 0);
96 // check it looks right
97 // 1st byte is CRC & packet type
98 uint8_t header = RC_DATA_PACKET;
99 TEST_ASSERT_EQUAL(header, TXdataBuffer[0]);
101 // bytes 1 through 5 are 10 bit packed analog channels
102 for(int i = 0; i < 4; i++) {
103 expected = crsf.ChannelDataIn[i] >> 3; // most significant 8 bits
104 TEST_ASSERT_EQUAL(expected, TXdataBuffer[i + 1]);
107 // byte 5 is bits 1 and 2 of each analog channel
108 expected = 0;
109 for(int i = 0; i < 4; i++) {
110 expected = (expected <<2) | ((crsf.ChannelDataIn[i] >> 1) & 0b11);
112 TEST_ASSERT_EQUAL(expected, TXdataBuffer[5]);
114 // byte 6 is the switch encoding
115 TEST_ASSERT_EQUAL(CRSF_to_BIT(crsf.ChannelDataIn[4+0]), (TXdataBuffer[6] & 0b0100000)>>6);
116 // top bit is undefined
117 // expect switch 0 in bit 6
118 // index-1 in 3-5
119 // value in 0,1,2[,3]
120 if (highResChannel)
122 TEST_ASSERT_EQUAL(7, ((TXdataBuffer[6] & 0b110000)>>3) + 1);
123 TEST_ASSERT_EQUAL(CRSF_to_N(crsf.ChannelDataIn[4+7], 16), TXdataBuffer[6] & 0b1111);
125 else
127 TEST_ASSERT_EQUAL(3, ((TXdataBuffer[6] & 0b111000)>>3) + 1);
128 TEST_ASSERT_EQUAL(CRSF_to_N(crsf.ChannelDataIn[4+3], 6), TXdataBuffer[6] & 0b0111);
132 void test_encodingHybrid8_3()
134 test_encodingHybrid8(false);
137 void test_encodingHybrid8_7()
139 test_encodingHybrid8(true);
142 /* Check the decoding of a packet after rx
144 void test_decodingHybrid8(uint8_t forceSwitch, uint8_t switchval)
146 constexpr uint8_t N_SWITCHES = 8;
147 uint8_t UID[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
148 uint8_t TXdataBuffer[8];
149 // uint8_t expected;
151 // Define the input data
152 // 4 channels of analog data
153 crsf.ChannelDataIn[0] = 0x0123;
154 crsf.ChannelDataIn[1] = 0x4567;
155 crsf.ChannelDataIn[2] = 0x89AB;
156 crsf.ChannelDataIn[3] = 0xCDEF;
158 // 8 switches
159 for(int i = 0; i < N_SWITCHES; i++) {
160 constexpr int CHANNELS[] =
161 { CRSF_CHANNEL_VALUE_1000, CRSF_CHANNEL_VALUE_MID, CRSF_CHANNEL_VALUE_2000 };
162 crsf.ChannelDataIn[4+i] = CHANNELS[i % 3];
164 if (forceSwitch == 0)
165 crsf.ChannelDataIn[4+forceSwitch] = BIT_to_CRSF(switchval);
166 else if (forceSwitch == 7)
167 crsf.ChannelDataIn[4+forceSwitch] = N_to_CRSF(switchval, 15);
168 else
169 crsf.ChannelDataIn[4+forceSwitch] = SWITCH3b_to_CRSF(switchval);
171 // set the nextSwitchIndex so we know which switch to expect in the packet
172 if (forceSwitch == 0)
173 OtaSetHybrid8NextSwitchIndex(0);
174 else
175 OtaSetHybrid8NextSwitchIndex(forceSwitch-1);
177 // use the encoding method to pack it into TXdataBuffer
178 OtaSetSwitchMode(smHybrid);
179 PackChannelData(TXdataBuffer, &crsf, false, 0, 0);
181 // run the decoder, results in crsf->PackedRCdataOut
182 UnpackChannelData(TXdataBuffer, &crsf, 0, 0);
184 // compare the unpacked results with the input data
185 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[0] & 0b11111111110, crsf.PackedRCdataOut.ch0); // analog channels are truncated to 10 bits
186 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[1] & 0b11111111110, crsf.PackedRCdataOut.ch1); // analog channels are truncated to 10 bits
187 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[2] & 0b11111111110, crsf.PackedRCdataOut.ch2); // analog channels are truncated to 10 bits
188 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[3] & 0b11111111110, crsf.PackedRCdataOut.ch3); // analog channels are truncated to 10 bits
190 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[4+0], crsf.PackedRCdataOut.ch4); // Switch 0 is sent on every packet
191 if (forceSwitch == 7)
192 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[4+forceSwitch], crsf.PackedRCdataOut.ch11); // We forced switch 1 to be sent as the sequential field
193 else if (forceSwitch != 0)
195 uint16_t ch;
196 switch (forceSwitch)
198 case 1: ch = crsf.PackedRCdataOut.ch5; break;
199 case 2: ch = crsf.PackedRCdataOut.ch6; break;
200 case 3: ch = crsf.PackedRCdataOut.ch7; break;
201 case 4: ch = crsf.PackedRCdataOut.ch8; break;
202 case 5: ch = crsf.PackedRCdataOut.ch9; break;
203 case 6: ch = crsf.PackedRCdataOut.ch10; break;
204 default:
205 TEST_FAIL_MESSAGE("forceSwitch not handled");
207 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[4+forceSwitch], ch);
211 void test_decodingHybrid8_all()
213 // Switch 0 is 2 pos
214 test_decodingHybrid8(0, 0);
215 test_decodingHybrid8(0, 1);
216 // Switch X in 6-pos mode (includes 3-pos low/high)
217 for (uint8_t val=0; val<6; ++val)
218 test_decodingHybrid8(3, val);
219 // // Switch X in 3-pos mode center
220 // test_decodingHybrid8(3, 7);
221 // // Switch 7 is 16 pos
222 // for (uint8_t val=0; val<16; ++val)
223 // test_decodingHybrid8(7, val);
226 /* Check the HybridWide encoding of a packet for OTA tx
228 void test_encodingHybridWide(bool highRes, uint8_t nonce)
230 uint8_t UID[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
231 uint8_t expected;
232 uint8_t TXdataBuffer[8];
234 // Define the input data
235 // 4 channels of analog data
236 crsf.ChannelDataIn[0] = 0x0123;
237 crsf.ChannelDataIn[1] = 0x4567;
238 crsf.ChannelDataIn[2] = 0x89AB;
239 crsf.ChannelDataIn[3] = 0xCDEF;
241 // 8 switches
242 constexpr int N_SWITCHES = 8;
243 for(int i = 0; i < N_SWITCHES; i++) {
244 constexpr int CHANNELS[] =
245 { CRSF_CHANNEL_VALUE_1000, CRSF_CHANNEL_VALUE_MID, CRSF_CHANNEL_VALUE_2000 };
246 crsf.ChannelDataIn[4+i] = CHANNELS[i % 3];
249 // Uplink data
250 crsf.LinkStatistics.uplink_TX_Power = 3; // 100mW
252 // encode it
253 uint8_t tlmDenom = (highRes) ? 64 : 4;
254 OtaSetSwitchMode(smHybridWide);
255 PackChannelData(TXdataBuffer, &crsf, nonce % 2, nonce, tlmDenom);
257 // check it looks right
258 // 1st byte is CRC & packet type
259 uint8_t header = RC_DATA_PACKET;
260 TEST_ASSERT_EQUAL(header, TXdataBuffer[0]);
262 // bytes 1 through 5 are 10 bit packed analog channels
263 for(int i = 0; i < 4; i++) {
264 expected = crsf.ChannelDataIn[i] >> 3; // most significant 8 bits
265 TEST_ASSERT_EQUAL(expected, TXdataBuffer[i + 1]);
268 // byte 5 is bits 1 and 2 of each analog channel
269 expected = 0;
270 for(int i = 0; i < 4; i++) {
271 expected = (expected <<2) | ((crsf.ChannelDataIn[i] >> 1) & 0b11);
273 TEST_ASSERT_EQUAL(expected, TXdataBuffer[5]);
275 // byte 6 is the switches encoded
276 uint8_t switches = TXdataBuffer[6];
277 uint8_t switchIdx = nonce % 8;
279 // High bit should be AUX1
280 TEST_ASSERT_EQUAL(CRSF_to_BIT(crsf.ChannelDataIn[4]), switches >> 7);
281 // If low res or slot 7, the bit 6 should be the telemetryack bit
282 if (!highRes || switchIdx == 7)
283 TEST_ASSERT_EQUAL(nonce % 2, (switches >> 6) & 1);
285 // If slot 7, the uplink_TX_Power should be in the low 6 bits
286 if (switchIdx == 7)
287 TEST_ASSERT_EQUAL(crsf.LinkStatistics.uplink_TX_Power, switches & 0b111111);
288 else
290 uint16_t ch = crsf.ChannelDataIn[5+switchIdx];
291 if (highRes)
292 TEST_ASSERT_EQUAL(CRSF_to_N(ch, 128), switches & 0b1111111); // 7-bit
293 else
294 TEST_ASSERT_EQUAL(CRSF_to_N(ch, 64), switches & 0b111111); // 6-bit
298 void test_encodingHybridWide_high()
300 constexpr int N_SWITCHES = 8;
301 for (int i=0; i<N_SWITCHES; ++i)
302 test_encodingHybridWide(true, i);
305 void test_encodingHybridWide_low()
307 constexpr int N_SWITCHES = 8;
308 for (int i=0; i<N_SWITCHES; ++i)
309 test_encodingHybridWide(false, i);
312 /* Check the decoding of a packet after rx in HybridWide mode
314 void test_decodingHybridWide(bool highRes, uint8_t nonce, uint8_t forceSwitch, uint16_t forceVal)
316 uint8_t UID[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE};
317 uint8_t TXdataBuffer[8];
318 // uint8_t expected;
320 // Define the input data
321 // 4 channels of analog data
322 crsf.ChannelDataIn[0] = 0x0123;
323 crsf.ChannelDataIn[1] = 0x4567;
324 crsf.ChannelDataIn[2] = 0x89AB;
325 crsf.ChannelDataIn[3] = 0xCDEF;
327 // 8 switches
328 constexpr int N_SWITCHES = 8;
329 for(int i = 0; i < N_SWITCHES; i++) {
330 constexpr int CHANNELS[] =
331 { CRSF_CHANNEL_VALUE_1000, CRSF_CHANNEL_VALUE_MID, CRSF_CHANNEL_VALUE_2000 };
332 if (i == forceSwitch)
333 crsf.ChannelDataIn[4+i] = forceVal;
334 else
335 crsf.ChannelDataIn[4+i] = CHANNELS[i % 3];
338 // Uplink data
339 crsf.LinkStatistics.uplink_TX_Power = 3; // 100mW
341 // encode it
342 uint8_t tlmDenom = (highRes) ? 64 : 4;
343 OtaSetSwitchMode(smHybridWide);
344 PackChannelData(TXdataBuffer, &crsf, nonce % 2, nonce, tlmDenom);
346 // Clear the LinkStatistics to receive it from the encoding
347 crsf.LinkStatistics.uplink_TX_Power = 0;
349 // run the decoder, results in crsf->PackedRCdataOut
350 bool telemResult = UnpackChannelData(TXdataBuffer, &crsf, nonce, tlmDenom);
352 // compare the unpacked results with the input data
353 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[0] & 0b11111111110, crsf.PackedRCdataOut.ch0); // analog channels are truncated to 10 bits
354 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[1] & 0b11111111110, crsf.PackedRCdataOut.ch1); // analog channels are truncated to 10 bits
355 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[2] & 0b11111111110, crsf.PackedRCdataOut.ch2); // analog channels are truncated to 10 bits
356 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[3] & 0b11111111110, crsf.PackedRCdataOut.ch3); // analog channels are truncated to 10 bits
358 // Switch 0 is sent on every packet
359 TEST_ASSERT_EQUAL(crsf.ChannelDataIn[4], crsf.PackedRCdataOut.ch4);
361 uint8_t switchIdx = nonce % 8;
362 // Validate the telemResult was unpacked properly
363 if (!highRes || switchIdx == 7)
364 TEST_ASSERT_EQUAL(telemResult, nonce % 2);
366 if (switchIdx == 7)
368 TEST_ASSERT_EQUAL(crsf.LinkStatistics.uplink_TX_Power, 3);
370 else
372 uint16_t ch;
373 switch (switchIdx)
375 case 0: ch = crsf.PackedRCdataOut.ch5; break;
376 case 1: ch = crsf.PackedRCdataOut.ch6; break;
377 case 2: ch = crsf.PackedRCdataOut.ch7; break;
378 case 3: ch = crsf.PackedRCdataOut.ch8; break;
379 case 4: ch = crsf.PackedRCdataOut.ch9; break;
380 case 5: ch = crsf.PackedRCdataOut.ch10; break;
381 case 6: ch = crsf.PackedRCdataOut.ch11; break;
382 default:
383 TEST_FAIL_MESSAGE("switchIdx not handled");
385 if (highRes)
386 TEST_ASSERT_EQUAL(N_to_CRSF(CRSF_to_N(crsf.ChannelDataIn[5+switchIdx], 128), 127), ch);
387 else
388 TEST_ASSERT_EQUAL(N_to_CRSF(CRSF_to_N(crsf.ChannelDataIn[5+switchIdx], 64), 63), ch);
392 void test_decodingHybridWide_AUX1()
394 // Switch 0 is 2 pos, also tests the uplink_TX_Power
395 test_decodingHybridWide(true, 7, 0, CRSF_CHANNEL_VALUE_1000);
396 test_decodingHybridWide(true, 7, 0, CRSF_CHANNEL_VALUE_2000);
399 void test_decodingHybridWide_AUXX_high()
401 constexpr int N_SWITCHES = 8;
402 for (int i=0; i<N_SWITCHES; ++i)
403 test_decodingHybridWide(true, i, 0, CRSF_CHANNEL_VALUE_1000);
406 void test_decodingHybridWide_AUXX_low()
408 constexpr int N_SWITCHES = 8;
409 for (int i=0; i<N_SWITCHES; ++i)
410 test_decodingHybridWide(false, i, 0, CRSF_CHANNEL_VALUE_1000);
413 int main(int argc, char **argv)
415 UNITY_BEGIN();
416 RUN_TEST(test_crsfToBit);
417 RUN_TEST(test_bitToCrsf);
418 RUN_TEST(test_crsfToN);
419 RUN_TEST(test_nToCrsf);
421 RUN_TEST(test_encodingHybrid8_3);
422 RUN_TEST(test_encodingHybrid8_7);
423 RUN_TEST(test_decodingHybrid8_all);
425 RUN_TEST(test_encodingHybridWide_high);
426 RUN_TEST(test_encodingHybridWide_low);
427 RUN_TEST(test_decodingHybridWide_AUX1);
428 RUN_TEST(test_decodingHybridWide_AUXX_high);
429 RUN_TEST(test_decodingHybridWide_AUXX_low);
431 UNITY_END();
433 return 0;