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
;
46 timeUs_t
rxFrameTimeUs(void) { return 0; }
50 bool telemetryCheckRxPortShared(const serialPortConfig_t
*portConfig
, const SerialRXType serialrxProvider
)
54 UNUSED(serialrxProvider
);
59 serialPort_t
*telemetrySharedPort
= NULL
;
61 static uint16_t vbat
= 100;
62 uint16_t getVbat(void)
67 uint32_t microseconds_stub_value
= 0;
70 return microseconds_stub_value
;
73 uint32_t microsISR(void)
78 #define SERIAL_BUFFER_SIZE 256
79 #define SERIAL_PORT_DUMMY_IDENTIFIER (serialPortIdentifier_e)0x12
81 typedef struct serialPortStub_s
{
82 uint8_t buffer
[SERIAL_BUFFER_SIZE
];
87 static serialPort_t serialTestInstance
;
88 static serialPortConfig_t serialTestInstanceConfig
= {
89 .identifier
= SERIAL_PORT_DUMMY_IDENTIFIER
,
93 static serialReceiveCallbackPtr stub_serialRxCallback
;
94 static serialPortConfig_t
*findSerialPortConfig_stub_retval
;
95 static bool openSerial_called
= false;
96 static serialPortStub_t serialWriteStub
;
97 static bool portIsShared
= false;
99 static portMode_e serialExpectedMode
= MODE_RX
;
100 static portOptions_e serialExpectedOptions
= SERIAL_UNIDIR
;
103 const serialPortConfig_t
*findSerialPortConfig(serialPortFunction_e function
)
105 EXPECT_EQ(function
, FUNCTION_RX_SERIAL
);
106 return findSerialPortConfig_stub_retval
;
109 serialPort_t
*openSerialPort(
110 serialPortIdentifier_e identifier
,
111 serialPortFunction_e function
,
112 serialReceiveCallbackPtr callback
,
116 portOptions_e options
119 openSerial_called
= true;
120 EXPECT_FALSE(NULL
== callback
);
121 EXPECT_TRUE(NULL
== callbackData
);
122 EXPECT_EQ(identifier
, SERIAL_PORT_DUMMY_IDENTIFIER
);
123 EXPECT_EQ(options
, serialExpectedOptions
);
124 EXPECT_EQ(function
, FUNCTION_RX_SERIAL
);
125 EXPECT_EQ(baudrate
, 115200);
126 EXPECT_EQ(mode
, serialExpectedMode
);
127 stub_serialRxCallback
= callback
;
128 return &serialTestInstance
;
131 void serialWrite(serialPort_t
*instance
, uint8_t ch
)
133 EXPECT_EQ(instance
, &serialTestInstance
);
134 EXPECT_LT(serialWriteStub
.pos
, sizeof(serialWriteStub
.buffer
));
135 serialWriteStub
.buffer
[serialWriteStub
.pos
++] = ch
;
138 void serialTestResetPort()
140 openSerial_called
= false;
141 stub_serialRxCallback
= NULL
;
142 portIsShared
= false;
143 serialExpectedMode
= MODE_RX
;
144 serialExpectedOptions
= SERIAL_UNIDIR
;
147 class SumdRxInitUnitTest
: public ::testing::Test
152 serialTestResetPort();
157 TEST_F(SumdRxInitUnitTest
, Test_SumdRxNotEnabled
)
159 const rxConfig_t initialRxConfig
= {};
160 rxRuntimeState_t rxRuntimeState
= {};
161 findSerialPortConfig_stub_retval
= NULL
;
163 EXPECT_FALSE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
165 EXPECT_EQ(18, rxRuntimeState
.channelCount
);
166 EXPECT_EQ(11000, rxRuntimeState
.rxRefreshRate
);
167 EXPECT_FALSE(NULL
== rxRuntimeState
.rcReadRawFn
);
168 EXPECT_FALSE(NULL
== rxRuntimeState
.rcFrameStatusFn
);
172 TEST_F(SumdRxInitUnitTest
, Test_SumdRxEnabled
)
174 const rxConfig_t initialRxConfig
= {};
175 rxRuntimeState_t rxRuntimeState
= {};
176 findSerialPortConfig_stub_retval
= &serialTestInstanceConfig
;
178 EXPECT_TRUE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
180 EXPECT_EQ(18, rxRuntimeState
.channelCount
);
181 EXPECT_EQ(11000, rxRuntimeState
.rxRefreshRate
);
182 EXPECT_FALSE(NULL
== rxRuntimeState
.rcReadRawFn
);
183 EXPECT_FALSE(NULL
== rxRuntimeState
.rcFrameStatusFn
);
185 EXPECT_TRUE(openSerial_called
);
190 class SumdRxProtocollUnitTest
: public ::testing::Test
193 rxRuntimeState_t rxRuntimeState
= {};
196 serialTestResetPort();
198 const rxConfig_t initialRxConfig
= {};
199 findSerialPortConfig_stub_retval
= &serialTestInstanceConfig
;
201 EXPECT_TRUE(sumdInit(&initialRxConfig
, &rxRuntimeState
));
202 microseconds_stub_value
+= 5000;
203 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
206 virtual void checkValidChannels()
208 //report frame complete once
209 EXPECT_EQ(RX_FRAME_COMPLETE
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
210 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
212 EXPECT_EQ(900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 0));
213 EXPECT_EQ(1100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 1));
214 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 2));
215 EXPECT_EQ(1900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 3));
216 EXPECT_EQ(2100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 4));
220 * the structure of a sumd packet is
221 * 0xA8 = sync byte, 0x01 = status byte, number of channels
222 * Channel data two bytes per channel
225 virtual void sendValidPacket()
227 uint8_t packet
[] = {0xA8, 0x01, 20,
228 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
229 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
230 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
231 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
235 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
236 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
237 stub_serialRxCallback(packet
[i
], NULL
);
239 checkValidChannels();
242 virtual void sendValidLongPacket()
244 uint8_t packet
[] = {0xA8, 0x01, 32,
245 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
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, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
251 0x1c, 0x20, 0x1c, 0x20,
255 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
256 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
257 stub_serialRxCallback(packet
[i
], NULL
);
259 checkValidChannels();
262 virtual void sendValidShortPacket()
264 uint8_t packet
[] = {0xA8, 0x01, 16,
265 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
266 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
267 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
272 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
273 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
274 stub_serialRxCallback(packet
[i
], NULL
);
277 checkValidChannels();
280 virtual void sendValidFsPacket()
283 uint8_t packet
[] = {0xA8, 0x81, 0x08,
284 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0, 0x2E, 0xE0,
288 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
289 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
290 stub_serialRxCallback(packet
[i
], NULL
);
293 EXPECT_EQ(RX_FRAME_COMPLETE
| RX_FRAME_FAILSAFE
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
294 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
296 for (size_t i
= 0; i
< 8; i
++) {
297 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, i
));
301 virtual void sendInvalidPacket()
303 uint8_t packet
[] = {0xA8, 0x01, 20,
304 0x1c, 0x21, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0,
305 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
306 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
307 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20,
311 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
312 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
313 stub_serialRxCallback(packet
[i
], NULL
);
316 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
318 EXPECT_EQ(900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 0));
319 EXPECT_EQ(1100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 1));
320 EXPECT_EQ(1500, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 2));
321 EXPECT_EQ(1900, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 3));
322 EXPECT_EQ(2100, rxRuntimeState
.rcReadRawFn(&rxRuntimeState
, 4));
325 virtual void sendIncompletePacket()
327 uint8_t packet
[] = {0xA8, 0x01, 20,
328 0x1c, 0x20, 0x22, 0x60, 0x2e, 0xe0, 0x3b, 0x60, 0x41, 0xa0
331 for (size_t i
= 0; i
< sizeof(packet
); i
++) {
332 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
333 stub_serialRxCallback(packet
[i
], NULL
);
336 microseconds_stub_value
+= 5000;
338 EXPECT_EQ(RX_FRAME_PENDING
, rxRuntimeState
.rcFrameStatusFn(&rxRuntimeState
));
343 TEST_F(SumdRxProtocollUnitTest
, Test_OnePacketReceived
)
348 TEST_F(SumdRxProtocollUnitTest
, Test_MultiplePacketsReceived
)
354 TEST_F(SumdRxProtocollUnitTest
, Test_Resync
)
356 sendIncompletePacket();
360 TEST_F(SumdRxProtocollUnitTest
, Test_IgnoreInvalidCRC
)
366 TEST_F(SumdRxProtocollUnitTest
, Test_ShortPacketsReceived
)
368 sendValidShortPacket();
369 sendValidShortPacket();
372 TEST_F(SumdRxProtocollUnitTest
, TestShortPacketsReceivedWithFailsafe
)
377 TEST_F(SumdRxProtocollUnitTest
, Test_LongPacketsReceived
)
379 sendValidLongPacket();
380 sendValidLongPacket();