Skip to content

Commit 562e7e7

Browse files
committed
Added unit tests, moved more functions to OTA.cpp
Added unit tests for sequential switches, and moved the corresponding functions to OTA.cpp so that we can test them. Signed-off-by: JBKingdon <[email protected]>
1 parent e73f3d2 commit 562e7e7

6 files changed

Lines changed: 350 additions & 150 deletions

File tree

src/lib/OTA/OTA.cpp

Lines changed: 136 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
#include "OTA.h"
66

7-
#ifdef HYBRID_SWITCHES_8
7+
#if defined HYBRID_SWITCHES_8 or defined UNIT_TEST
88

99
/**
10-
* Hybrid switches packet
11-
* Replaces Generate4ChannelData_11bit
10+
* Hybrid switches packet encoding for sending over the air
11+
*
1212
* Analog channels are reduced to 10 bits to allow for switch encoding
1313
* Switch[0] is sent on every packet.
1414
* A 3 bit switch index and 2 bit value is used to send the remaining switches
@@ -48,4 +48,136 @@ void ICACHE_RAM_ATTR GenerateChannelDataHybridSwitch8(SX127xDriver *Radio, CRSF
4848
// update the sent value
4949
crsf->setSentSwitch(i, value);
5050
}
51-
#endif
51+
52+
/**
53+
* Hybrid switches decoding of over the air data
54+
*
55+
* Hybrid switches uses 10 bits for each analog channel,
56+
* 2 bits for the low latency switch[0]
57+
* 3 bits for the round-robin switch index and 2 bits for the value
58+
*
59+
* Input: Radio->RXdataBuffer
60+
* Output: crsf->PackedRCdataOut
61+
*/
62+
void ICACHE_RAM_ATTR UnpackChannelDataHybridSwitches8(SX127xDriver *Radio, CRSF *crsf)
63+
{
64+
// The analog channels
65+
crsf->PackedRCdataOut.ch0 = (Radio->RXdataBuffer[1] << 3) + ((Radio->RXdataBuffer[5] & 0b11000000) >> 5);
66+
crsf->PackedRCdataOut.ch1 = (Radio->RXdataBuffer[2] << 3) + ((Radio->RXdataBuffer[5] & 0b00110000) >> 3);
67+
crsf->PackedRCdataOut.ch2 = (Radio->RXdataBuffer[3] << 3) + ((Radio->RXdataBuffer[5] & 0b00001100) >> 1);
68+
crsf->PackedRCdataOut.ch3 = (Radio->RXdataBuffer[4] << 3) + ((Radio->RXdataBuffer[5] & 0b00000011) << 1);
69+
70+
// The low latency switch
71+
crsf->PackedRCdataOut.ch4 = SWITCH2b_to_CRSF((Radio->RXdataBuffer[6] & 0b01100000) >> 5);
72+
73+
// The round-robin switch
74+
uint8_t switchIndex = (Radio->RXdataBuffer[6] & 0b11100) >> 2;
75+
uint16_t switchValue = SWITCH2b_to_CRSF(Radio->RXdataBuffer[6] & 0b11);
76+
77+
switch (switchIndex) {
78+
case 0: // we should never get index 0 here since that is the low latency switch
79+
Serial.println("BAD switchIndex 0");
80+
break;
81+
case 1:
82+
crsf->PackedRCdataOut.ch5 = switchValue;
83+
break;
84+
case 2:
85+
crsf->PackedRCdataOut.ch6 = switchValue;
86+
break;
87+
case 3:
88+
crsf->PackedRCdataOut.ch7 = switchValue;
89+
break;
90+
case 4:
91+
crsf->PackedRCdataOut.ch8 = switchValue;
92+
break;
93+
case 5:
94+
crsf->PackedRCdataOut.ch9 = switchValue;
95+
break;
96+
case 6:
97+
crsf->PackedRCdataOut.ch10 = switchValue;
98+
break;
99+
case 7:
100+
crsf->PackedRCdataOut.ch11 = switchValue;
101+
break;
102+
}
103+
}
104+
105+
#endif // HYBRID_SWITCHES_8
106+
107+
#if defined SEQ_SWITCHES or defined UNIT_TEST
108+
109+
/**
110+
* Sequential switches packet encoding
111+
*
112+
* Channel 3 is reduced to 10 bits to allow a 3 bit switch index and 2 bit value
113+
* We cycle through 8 switches on successive packets. If any switches have changed
114+
* we take the lowest indexed one and send that, hence lower indexed switches have
115+
* higher priority in the event that several are changed at once.
116+
*/
117+
void ICACHE_RAM_ATTR GenerateChannelDataSeqSwitch(SX127xDriver *Radio, CRSF *crsf, uint8_t addr)
118+
{
119+
uint8_t PacketHeaderAddr;
120+
PacketHeaderAddr = (addr << 2) + RC_DATA_PACKET;
121+
Radio->TXdataBuffer[0] = PacketHeaderAddr;
122+
Radio->TXdataBuffer[1] = ((crsf->ChannelDataIn[0]) >> 3);
123+
Radio->TXdataBuffer[2] = ((crsf->ChannelDataIn[1]) >> 3);
124+
Radio->TXdataBuffer[3] = ((crsf->ChannelDataIn[2]) >> 3);
125+
Radio->TXdataBuffer[4] = ((crsf->ChannelDataIn[3]) >> 3);
126+
Radio->TXdataBuffer[5] = ((crsf->ChannelDataIn[0] & 0b00000111) << 5) + ((crsf->ChannelDataIn[1] & 0b111) << 2) + ((crsf->ChannelDataIn[2] & 0b110) >> 1);
127+
Radio->TXdataBuffer[6] = ((crsf->ChannelDataIn[2] & 0b001) << 7) + ((crsf->ChannelDataIn[3] & 0b110) << 4);
128+
129+
// find the next switch to send
130+
uint8_t i = crsf->getNextSwitchIndex() & 0b111; // mask for paranoia
131+
uint8_t value = crsf->currentSwitches[i] & 0b11; // mask for paranoia
132+
133+
// put the bits into buf[6]
134+
Radio->TXdataBuffer[6] += (i << 2) + value;
135+
136+
// update the sent value
137+
crsf->setSentSwitch(i, value);
138+
}
139+
140+
141+
/**
142+
* Sequential switches decoding of over the air packet
143+
*
144+
* Seq switches uses 10 bits for ch3, 3 bits for the switch index and 2 bits for the switch value
145+
*/
146+
void ICACHE_RAM_ATTR UnpackChannelDataSeqSwitches(SX127xDriver *Radio, CRSF *crsf)
147+
{
148+
crsf->PackedRCdataOut.ch0 = (Radio->RXdataBuffer[1] << 3) + ((Radio->RXdataBuffer[5] & 0b11100000) >> 5);
149+
crsf->PackedRCdataOut.ch1 = (Radio->RXdataBuffer[2] << 3) + ((Radio->RXdataBuffer[5] & 0b00011100) >> 2);
150+
crsf->PackedRCdataOut.ch2 = (Radio->RXdataBuffer[3] << 3) + ((Radio->RXdataBuffer[5] & 0b00000011) << 1) + (Radio->RXdataBuffer[6] & 0b10000000 >> 7);
151+
crsf->PackedRCdataOut.ch3 = (Radio->RXdataBuffer[4] << 3) + ((Radio->RXdataBuffer[6] & 0b01100000) >> 4);
152+
153+
uint8_t switchIndex = (Radio->RXdataBuffer[6] & 0b11100) >> 2;
154+
uint16_t switchValue = SWITCH2b_to_CRSF(Radio->RXdataBuffer[6] & 0b11);
155+
156+
switch (switchIndex) {
157+
case 0:
158+
crsf->PackedRCdataOut.ch4 = switchValue;
159+
break;
160+
case 1:
161+
crsf->PackedRCdataOut.ch5 = switchValue;
162+
break;
163+
case 2:
164+
crsf->PackedRCdataOut.ch6 = switchValue;
165+
break;
166+
case 3:
167+
crsf->PackedRCdataOut.ch7 = switchValue;
168+
break;
169+
case 4:
170+
crsf->PackedRCdataOut.ch8 = switchValue;
171+
break;
172+
case 5:
173+
crsf->PackedRCdataOut.ch9 = switchValue;
174+
break;
175+
case 6:
176+
crsf->PackedRCdataOut.ch10 = switchValue;
177+
break;
178+
case 7:
179+
crsf->PackedRCdataOut.ch11 = switchValue;
180+
break;
181+
}
182+
}
183+
#endif // SEQ_SWITCHES

src/lib/OTA/OTA.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@
1414
#define TLM_PACKET 0b11
1515
#define SYNC_PACKET 0b10
1616

17-
#ifdef HYBRID_SWITCHES_8
17+
#if defined HYBRID_SWITCHES_8 or defined UNIT_TEST
18+
1819
void GenerateChannelDataHybridSwitch8(SX127xDriver *Radio, CRSF *crsf, uint8_t addr);
19-
#endif
20+
void UnpackChannelDataHybridSwitches8(SX127xDriver *Radio, CRSF *crsf);
21+
22+
#endif // HYBRID_SWITCHES_8
23+
24+
#if defined SEQ_SWITCHES or defined UNIT_TEST
25+
26+
void ICACHE_RAM_ATTR GenerateChannelDataSeqSwitch(SX127xDriver *Radio, CRSF *crsf, uint8_t addr);
27+
void UnpackChannelDataSeqSwitches(SX127xDriver *Radio, CRSF *crsf);
28+
29+
#endif // SEQ_SWITCHES
30+
2031

21-
#endif
32+
#endif // H_OTA

src/src/rx_main.cpp

Lines changed: 6 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -238,98 +238,7 @@ void ICACHE_RAM_ATTR UnpackChannelData_11bit()
238238
#endif
239239
}
240240

241-
#ifdef SEQ_SWITCHES
242-
/**
243-
* Seq switches uses 10 bits for ch3, 3 bits for the switch index and 2 bits for the switch value
244-
*/
245-
void ICACHE_RAM_ATTR UnpackChannelDataSeqSwitches()
246-
{
247-
crsf.PackedRCdataOut.ch0 = (Radio.RXdataBuffer[1] << 3) + ((Radio.RXdataBuffer[5] & 0b11100000) >> 5);
248-
crsf.PackedRCdataOut.ch1 = (Radio.RXdataBuffer[2] << 3) + ((Radio.RXdataBuffer[5] & 0b00011100) >> 2);
249-
crsf.PackedRCdataOut.ch2 = (Radio.RXdataBuffer[3] << 3) + ((Radio.RXdataBuffer[5] & 0b00000011) << 1) + (Radio.RXdataBuffer[6] & 0b10000000 >> 7);
250-
crsf.PackedRCdataOut.ch3 = (Radio.RXdataBuffer[4] << 3) + ((Radio.RXdataBuffer[6] & 0b01100000) >> 4);
251-
252-
uint8_t switchIndex = (Radio.RXdataBuffer[6] & 0b11100) >> 2;
253-
uint16_t switchValue = SWITCH2b_to_CRSF(Radio.RXdataBuffer[6] & 0b11);
254-
255-
switch (switchIndex) {
256-
case 0:
257-
crsf.PackedRCdataOut.ch4 = switchValue;
258-
break;
259-
case 1:
260-
crsf.PackedRCdataOut.ch5 = switchValue;
261-
break;
262-
case 2:
263-
crsf.PackedRCdataOut.ch6 = switchValue;
264-
break;
265-
case 3:
266-
crsf.PackedRCdataOut.ch7 = switchValue;
267-
break;
268-
case 4:
269-
crsf.PackedRCdataOut.ch8 = switchValue;
270-
break;
271-
case 5:
272-
crsf.PackedRCdataOut.ch9 = switchValue;
273-
break;
274-
case 6:
275-
crsf.PackedRCdataOut.ch10 = switchValue;
276-
break;
277-
case 7:
278-
crsf.PackedRCdataOut.ch11 = switchValue;
279-
break;
280-
}
281-
}
282-
#endif
283241

284-
#ifdef HYBRID_SWITCHES_8
285-
/**
286-
* Hybrid switches uses 10 bits for each analog channel,
287-
* 2 bits for the low latency switch[0]
288-
* 3 bits for the round-robin switch index and 2 bits for the value
289-
*/
290-
void ICACHE_RAM_ATTR UnpackChannelDataHybridSwitches8()
291-
{
292-
// The analog channels
293-
crsf.PackedRCdataOut.ch0 = (Radio.RXdataBuffer[1] << 3) + ((Radio.RXdataBuffer[5] & 0b11000000) >> 5);
294-
crsf.PackedRCdataOut.ch1 = (Radio.RXdataBuffer[2] << 3) + ((Radio.RXdataBuffer[5] & 0b00110000) >> 3);
295-
crsf.PackedRCdataOut.ch2 = (Radio.RXdataBuffer[3] << 3) + ((Radio.RXdataBuffer[5] & 0b00001100) >> 1);
296-
crsf.PackedRCdataOut.ch3 = (Radio.RXdataBuffer[4] << 3) + ((Radio.RXdataBuffer[5] & 0b00000011) << 1);
297-
298-
// The low latency switch
299-
crsf.PackedRCdataOut.ch4 = SWITCH2b_to_CRSF((Radio.RXdataBuffer[6] & 0b01100000) >> 5);
300-
301-
// The round-robin switch
302-
uint8_t switchIndex = (Radio.RXdataBuffer[6] & 0b11100) >> 2;
303-
uint16_t switchValue = SWITCH2b_to_CRSF(Radio.RXdataBuffer[6] & 0b11);
304-
305-
switch (switchIndex) {
306-
case 0: // we should never get index 0 here since that is the low latency switch
307-
Serial.println("BAD switchIndex 0");
308-
break;
309-
case 1:
310-
crsf.PackedRCdataOut.ch5 = switchValue;
311-
break;
312-
case 2:
313-
crsf.PackedRCdataOut.ch6 = switchValue;
314-
break;
315-
case 3:
316-
crsf.PackedRCdataOut.ch7 = switchValue;
317-
break;
318-
case 4:
319-
crsf.PackedRCdataOut.ch8 = switchValue;
320-
break;
321-
case 5:
322-
crsf.PackedRCdataOut.ch9 = switchValue;
323-
break;
324-
case 6:
325-
crsf.PackedRCdataOut.ch10 = switchValue;
326-
break;
327-
case 7:
328-
crsf.PackedRCdataOut.ch11 = switchValue;
329-
break;
330-
}
331-
}
332-
#endif
333242

334243

335244
void ICACHE_RAM_ATTR UnpackChannelData_10bit()
@@ -376,13 +285,13 @@ void ICACHE_RAM_ATTR ProcessRFPacket()
376285
switch (type)
377286
{
378287
case RC_DATA_PACKET: //Standard RC Data Packet
379-
#if defined SEQ_SWITCHES
380-
UnpackChannelDataSeqSwitches();
381-
#elif defined HYBRID_SWITCHES_8
382-
UnpackChannelDataHybridSwitches8();
383-
#else
288+
#if defined SEQ_SWITCHES
289+
UnpackChannelDataSeqSwitches(&Radio, &crsf);
290+
#elif defined HYBRID_SWITCHES_8
291+
UnpackChannelDataHybridSwitches8(&Radio, &crsf);
292+
#else
384293
UnpackChannelData_11bit();
385-
#endif
294+
#endif
386295
crsf.sendRCFrameToFC();
387296
break;
388297

src/src/tx_main.cpp

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -209,40 +209,6 @@ void ICACHE_RAM_ATTR Generate4ChannelData_11bit()
209209
#endif
210210
}
211211

212-
#ifdef SEQ_SWITCHES
213-
/**
214-
* Sequential switches packet
215-
* Replaces Generate4ChannelData_11bit
216-
* Channel 3 is reduced to 10 bits to allow a 3 bit switch index and 2 bit value
217-
* We cycle through 8 switches on successive packets. If any switches have changed
218-
* we take the lowest indexed one and send that, hence lower indexed switches have
219-
* higher priority in the event that several are changed at once.
220-
*/
221-
void ICACHE_RAM_ATTR GenerateChannelDataSeqSwitch()
222-
{
223-
uint8_t PacketHeaderAddr;
224-
PacketHeaderAddr = (DeviceAddr << 2) + RC_DATA_PACKET;
225-
Radio.TXdataBuffer[0] = PacketHeaderAddr;
226-
Radio.TXdataBuffer[1] = ((crsf.ChannelDataIn[0]) >> 3);
227-
Radio.TXdataBuffer[2] = ((crsf.ChannelDataIn[1]) >> 3);
228-
Radio.TXdataBuffer[3] = ((crsf.ChannelDataIn[2]) >> 3);
229-
Radio.TXdataBuffer[4] = ((crsf.ChannelDataIn[3]) >> 3);
230-
Radio.TXdataBuffer[5] = ((crsf.ChannelDataIn[0] & 0b00000111) << 5) + ((crsf.ChannelDataIn[1] & 0b111) << 2) + ((crsf.ChannelDataIn[2] & 0b110) >> 1);
231-
Radio.TXdataBuffer[6] = ((crsf.ChannelDataIn[2] & 0b001) << 7) + ((crsf.ChannelDataIn[3] & 0b110) << 4);
232-
233-
// find the next switch to send
234-
uint8_t i = crsf.getNextSwitchIndex() & 0b111; // mask for paranoia
235-
uint8_t value = crsf.currentSwitches[i] & 0b11; // mask for paranoia
236-
237-
// put the bits into buf[6]
238-
Radio.TXdataBuffer[6] += (i << 2) + value;
239-
240-
// update the sent value
241-
crsf.setSentSwitch(i, value);
242-
}
243-
#endif
244-
245-
246212
void ICACHE_RAM_ATTR GenerateSwitchChannelData()
247213
{
248214
uint8_t PacketHeaderAddr;
@@ -377,11 +343,11 @@ void ICACHE_RAM_ATTR SendRCdataToRF()
377343
}
378344
else
379345
{
380-
#if defined HYBRID_SWITCHES_8
346+
#if defined HYBRID_SWITCHES_8
381347
GenerateChannelDataHybridSwitch8(&Radio, &crsf, DeviceAddr);
382-
#elif defined SEQ_SWITCHES
383-
GenerateChannelDataSeqSwitch();
384-
#else
348+
#elif defined SEQ_SWITCHES
349+
GenerateChannelDataSeqSwitch(&Radio, &crsf, DeviceAddr);
350+
#else
385351
if ((millis() > (SWITCH_PACKET_SEND_INTERVAL + SwitchPacketLastSent)) || Channels5to8Changed)
386352
{
387353
Channels5to8Changed = false;
@@ -392,7 +358,7 @@ void ICACHE_RAM_ATTR SendRCdataToRF()
392358
{
393359
Generate4ChannelData_11bit();
394360
}
395-
#endif
361+
#endif
396362
}
397363

398364
///// Next, Calculate the CRC and put it into the buffer /////

src/test/test_main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <unity.h>
33
#include "mock_serial.h"
44
#include "msp_tests.h"
5+
#include "test_switches.h"
56

67
void setup() {
78
// NOTE!!! Wait for >2 secs
@@ -12,6 +13,8 @@ void setup() {
1213

1314
RUN_TEST(test_msp_receive);
1415
RUN_TEST(test_msp_send);
16+
17+
setup_switches();
1518
}
1619

1720
void loop() {

0 commit comments

Comments
 (0)