2 * This file is part of Betaflight.
4 * Betaflight 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 * Betaflight 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 Betaflight. If not, see <http://www.gnu.org/licenses/>.
24 #include "drivers/serial.h"
25 #include "drivers/time.h"
26 #include "io/serial.h"
29 #include "telemetry/telemetry.h"
30 #include "fc/rc_controls.h"
31 #include "fc/rc_modes.h"
32 #include "sensors/barometer.h"
33 #include "sensors/battery.h"
36 #include "unittest_macros.h"
37 #include "gtest/gtest.h"
41 uint8_t batteryCellCount
= 3;
42 float rcCommand
[4] = {0, 0, 0, 0};
43 int16_t telemTemperature1
= 0;
44 baro_t baro
= { .baroTemperature
= 50 };
45 telemetryConfig_t telemetryConfig_System
;
49 bool telemetryCheckRxPortShared(const serialPortConfig_t
*portConfig
, const SerialRXType serialrxProvider
)
53 UNUSED(serialrxProvider
);
58 serialPort_t
*telemetrySharedPort
= NULL
;
60 static uint16_t vbat
= 100;
61 uint16_t getVbat(void)
66 uint32_t microseconds_stub_value
= 0;
69 return microseconds_stub_value
;
72 uint32_t microsISR(void)
77 #define SERIAL_BUFFER_SIZE 256
78 #define SERIAL_PORT_DUMMY_IDENTIFIER (serialPortIdentifier_e)0x12
80 typedef struct serialPortStub_s
{
81 uint8_t buffer
[SERIAL_BUFFER_SIZE
];
86 static serialPort_t serialTestInstance
;
87 static serialPortConfig_t serialTestInstanceConfig
= {
88 .identifier
= SERIAL_PORT_DUMMY_IDENTIFIER
,
92 static serialReceiveCallbackPtr stub_serialRxCallback
;
93 static serialPortConfig_t
*findSerialPortConfig_stub_retval
;
94 static bool openSerial_called
= false;
95 static serialPortStub_t serialWriteStub
;
96 static bool portIsShared
= false;
98 static portMode_e serialExpectedMode
= MODE_RX
;
99 static portOptions_e serialExpectedOptions
= SERIAL_UNIDIR
;
102 const serialPortConfig_t
*findSerialPortConfig(serialPortFunction_e function
)
104 EXPECT_EQ(function
, FUNCTION_RX_SERIAL
);
105 return findSerialPortConfig_stub_retval
;
108 serialPort_t
*openSerialPort(
109 serialPortIdentifier_e identifier
,
110 serialPortFunction_e function
,
111 serialReceiveCallbackPtr callback
,
115 portOptions_e options
118 openSerial_called
= true;
119 EXPECT_FALSE(NULL
== callback
);
120 EXPECT_TRUE(NULL
== callbackData
);
121 EXPECT_EQ(identifier
, SERIAL_PORT_DUMMY_IDENTIFIER
);
122 EXPECT_EQ(options
, serialExpectedOptions
);
123 EXPECT_EQ(function
, FUNCTION_RX_SERIAL
);
124 EXPECT_EQ(baudrate
, 115200);
125 EXPECT_EQ(mode
, serialExpectedMode
);
126 stub_serialRxCallback
= callback
;
127 return &serialTestInstance
;
130 void serialWrite(serialPort_t
*instance
, uint8_t ch
)
132 EXPECT_EQ(instance
, &serialTestInstance
);
133 EXPECT_LT(serialWriteStub
.pos
, sizeof(serialWriteStub
.buffer
));
134 serialWriteStub
.buffer
[serialWriteStub
.pos
++] = ch
;
137 void serialTestResetPort()
139 openSerial_called
= false;
140 stub_serialRxCallback
= NULL
;
141 portIsShared
= false;
142 serialExpectedMode
= MODE_RX
;
143 serialExpectedOptions
= SERIAL_UNIDIR
;
146 class SumdRxInitUnitTest
: public ::testing::Test
151 serialTestResetPort();
156 TEST_F(SumdRxInitUnitTest
, Test_SumdRxNotEnabled
)
158 const rxConfig_t initialRxConfig
= {};
159 rxRuntimeState_t rxRuntimeState
= {};
160 findSerialPortConfig_stub_retval
= NULL
;
162 EXPECT_FALSE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
164 EXPECT_EQ(18, rxRuntimeState
.channelCount
);
165 EXPECT_EQ(11000, rxRuntimeState
.rxRefreshRate
);
166 EXPECT_FALSE(NULL
== rxRuntimeState
.rcReadRawFn
);
167 EXPECT_FALSE(NULL
== rxRuntimeState
.rcFrameStatusFn
);
171 TEST_F(SumdRxInitUnitTest
, Test_SumdRxEnabled
)
173 const rxConfig_t initialRxConfig
= {};
174 rxRuntimeState_t rxRuntimeState
= {};
175 findSerialPortConfig_stub_retval
= &serialTestInstanceConfig
;
177 EXPECT_TRUE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
179 EXPECT_EQ(18, rxRuntimeState
.channelCount
);
180 EXPECT_EQ(11000, rxRuntimeState
.rxRefreshRate
);
181 EXPECT_FALSE(NULL
== rxRuntimeState
.rcReadRawFn
);
182 EXPECT_FALSE(NULL
== rxRuntimeState
.rcFrameStatusFn
);
184 EXPECT_TRUE(openSerial_called
);
189 class SumdRxProtocollUnitTest
: public ::testing::Test
192 rxRuntimeState_t rxRuntimeState
= {};
195 serialTestResetPort();
197 const rxConfig_t initialRxConfig
= {};
198 findSerialPortConfig_stub_retval
= &serialTestInstanceConfig
;
200 EXPECT_TRUE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
201 microseconds_stub_value
+= 5000;
202 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
205 virtual void checkValidChannels()
207 //report frame complete once
208 EXPECT_EQ(RX_FRAME_COMPLETE
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
209 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
211 EXPECT_EQ(900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 0));
212 EXPECT_EQ(1100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 1));
213 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 2));
214 EXPECT_EQ(1900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 3));
215 EXPECT_EQ(2100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 4));
219 * the structure of a sumd packet is
220 * 0xA8 = sync byte, 0x01 = status byte, number of channels
221 * Channel data two bytes per channel
224 virtual void sendValidPacket()
226 uint8_t packet
[] = {0xA8, 0x01, 20,
227 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
228 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
229 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
230 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
234 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
235 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
236 stub_serialRxCallback(packet
[i
], NULL
);
238 checkValidChannels();
241 virtual void sendValidLongPacket()
243 uint8_t packet
[] = {0xA8, 0x01, 32,
244 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
245 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
246 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
247 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
248 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
249 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
250 0x1c, 0x20, 0x1c, 0x20,
254 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
255 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
256 stub_serialRxCallback(packet
[i
], NULL
);
258 checkValidChannels();
261 virtual void sendValidShortPacket()
263 uint8_t packet
[] = {0xA8, 0x01, 16,
264 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
265 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
266 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
271 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
272 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
273 stub_serialRxCallback(packet
[i
], NULL
);
276 checkValidChannels();
279 virtual void sendValidFsPacket()
282 uint8_t packet
[] = {0xA8, 0x81, 0x08,
283 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0,
287 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
288 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
289 stub_serialRxCallback(packet
[i
], NULL
);
292 EXPECT_EQ(RX_FRAME_COMPLETE
| RX_FRAME_FAILSAFE
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
293 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
295 for (size_t i
= 0; i
< 8; i
++) {
296 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, i
));
300 virtual void sendInvalidPacket()
302 uint8_t packet
[] = {0xA8, 0x01, 20,
303 0x1c, 0x21, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
304 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
305 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
306 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
310 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
311 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
312 stub_serialRxCallback(packet
[i
], NULL
);
315 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
317 EXPECT_EQ(900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 0));
318 EXPECT_EQ(1100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 1));
319 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 2));
320 EXPECT_EQ(1900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 3));
321 EXPECT_EQ(2100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 4));
324 virtual void sendIncompletePacket()
326 uint8_t packet
[] = {0xA8, 0x01, 20,
327 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0
330 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
331 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
332 stub_serialRxCallback(packet
[i
], NULL
);
335 microseconds_stub_value
+= 5000;
337 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
342 TEST_F(SumdRxProtocollUnitTest
, Test_OnePacketReceived
)
347 TEST_F(SumdRxProtocollUnitTest
, Test_MultiplePacketsReceived
)
353 TEST_F(SumdRxProtocollUnitTest
, Test_Resync
)
355 sendIncompletePacket();
359 TEST_F(SumdRxProtocollUnitTest
, Test_IgnoreInvalidCRC
)
365 TEST_F(SumdRxProtocollUnitTest
, Test_ShortPacketsReceived
)
367 sendValidShortPacket();
368 sendValidShortPacket();
371 TEST_F(SumdRxProtocollUnitTest
, TestShortPacketsReceivedWithFailsafe
)
376 TEST_F(SumdRxProtocollUnitTest
, Test_LongPacketsReceived
)
378 sendValidLongPacket();
379 sendValidLongPacket();