diff --git a/src/main/rx/crsf.c b/src/main/rx/crsf.c index eac9d82b6b..5815fd8e6f 100644 --- a/src/main/rx/crsf.c +++ b/src/main/rx/crsf.c @@ -37,6 +37,7 @@ #include "fc/fc_debug.h" #endif +#include "build/build_config.h" #include "build/debug.h" #include "common/utils.h" @@ -54,14 +55,13 @@ #define CRSF_TIME_NEEDED_PER_FRAME_US 1500 //!! this needs checking -#define CRSF_MAX_CHANNEL 16 - #define CRSF_DIGITAL_CHANNEL_MIN 172 #define CRSF_DIGITAL_CHANNEL_MAX 1811 -static bool crsfFrameDone = false; +STATIC_UNIT_TESTED bool crsfFrameDone = false; +STATIC_UNIT_TESTED crsfFrame_t crsfFrame; -static uint32_t crsfChannelData[CRSF_MAX_CHANNEL]; +STATIC_UNIT_TESTED uint32_t crsfChannelData[CRSF_MAX_CHANNEL]; /* Structure @@ -101,19 +101,6 @@ struct crsfPayloadRcChannelsPacked_s { typedef struct crsfPayloadRcChannelsPacked_s crsfPayloadRcChannelsPacked_t; -typedef union crsfFrameDef_s { - uint8_t deviceAddress; - uint8_t frameLength; - uint8_t type; - uint8_t payload[CRSF_PAYLOAD_SIZE_MAX + 1]; // +1 for CRC at end of payload -} crsfFrameDef_t; - -typedef union crsfFrame_u { - uint8_t bytes[CRSF_FRAME_SIZE_MAX]; - crsfFrameDef_t frame; -} crsfFrame_t; - -static crsfFrame_t crsfFrame; // Receive ISR callback, called back from serial port static void crsfDataReceive(uint16_t c) @@ -123,7 +110,9 @@ static void crsfDataReceive(uint16_t c) const uint32_t now = micros(); const int32_t crsfFrameTime = now - crsfFrameStartAt; - DEBUG_SET(DEBUG_CRSF, 2, crsfFrameTime); +#ifdef DEBUG_CRSF_PACKETS + debug[2] = crsfFrameTime; +#endif if (crsfFrameTime > (long)(CRSF_TIME_NEEDED_PER_FRAME_US + 500)) { crsfFramePosition = 0; @@ -146,6 +135,7 @@ uint8_t crsfFrameStatus(void) if (crsfFrameDone) { crsfFrameDone = false; if (crsfFrame.frame.type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) { + crsfFrame.frame.frameLength = CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC; // unpack the RC channels const crsfPayloadRcChannelsPacked_t* rcChannels = (crsfPayloadRcChannelsPacked_t*)&crsfFrame.frame.payload; crsfChannelData[0] = rcChannels->chan0; diff --git a/src/main/rx/crsf.h b/src/main/rx/crsf.h index 75a82e5849..4f10c66e6b 100644 --- a/src/main/rx/crsf.h +++ b/src/main/rx/crsf.h @@ -17,8 +17,10 @@ #pragma once -#define CRSF_BAUDRATE 400000 -#define CRSF_PORT_OPTIONS (SERIAL_INVERTED | SERIAL_STOPBITS_1 | SERIAL_PARITY_NO) +#define CRSF_BAUDRATE 420000 +#define CRSF_PORT_OPTIONS (SERIAL_STOPBITS_1 | SERIAL_PARITY_NO) + +#define CRSF_MAX_CHANNEL 16 typedef enum { CRSF_FRAMETYPE_GPS = 0x02, @@ -45,6 +47,18 @@ enum { #define CRSF_PAYLOAD_SIZE_MAX 32 // !!TODO needs checking #define CRSF_FRAME_SIZE_MAX (CRSF_PAYLOAD_SIZE_MAX + 4) +typedef struct crsfFrameDef_s { + uint8_t deviceAddress; + uint8_t frameLength; + uint8_t type; + uint8_t payload[CRSF_PAYLOAD_SIZE_MAX + 1]; // +1 for CRC at end of payload +} crsfFrameDef_t; + +typedef union crsfFrame_u { + uint8_t bytes[CRSF_FRAME_SIZE_MAX]; + crsfFrameDef_t frame; +} crsfFrame_t; + uint8_t crsfFrameStatus(void); struct rxConfig_s; struct rxRuntimeConfig_s; diff --git a/src/test/Makefile b/src/test/Makefile index c65f812780..e07db09cb6 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -490,6 +490,31 @@ $(OBJECT_DIR)/rx_rx_unittest : \ $(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@ +$(OBJECT_DIR)/rx/crsf.o : \ + $(USER_DIR)/rx/crsf.c \ + $(USER_DIR)/rx/crsf.h \ + $(GTEST_HEADERS) + + @mkdir -p $(dir $@) + $(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/rx/crsf.c -o $@ + +$(OBJECT_DIR)/rx_crsf_unittest.o : \ + $(TEST_DIR)/rx_crsf_unittest.cc \ + $(USER_DIR)/rx/crsf.h \ + $(USER_DIR)/rx/crsf.c \ + $(GTEST_HEADERS) + + @mkdir -p $(dir $@) + $(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/rx_crsf_unittest.cc -o $@ + +$(OBJECT_DIR)/rx_crsf_unittest : \ + $(OBJECT_DIR)/rx/crsf.o \ + $(OBJECT_DIR)/rx_crsf_unittest.o \ + $(OBJECT_DIR)/common/maths.o \ + $(OBJECT_DIR)/gtest_main.a + + $(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@ + $(OBJECT_DIR)/telemetry/crsf.o : \ $(USER_DIR)/telemetry/crsf.c \ $(USER_DIR)/telemetry/crsf.h \ @@ -521,39 +546,6 @@ $(OBJECT_DIR)/telemetry_crsf_unittest : \ $(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@ -$(OBJECT_DIR)/rx/crsf.o : \ - $(USER_DIR)/rx/crsf.c \ - $(USER_DIR)/rx/crsf.h \ - $(GTEST_HEADERS) - - @mkdir -p $(dir $@) - $(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/rx/crsf.c -o $@ - -$(OBJECT_DIR)/telemetry/crsf.o : \ - $(USER_DIR)/telemetry/crsf.c \ - $(USER_DIR)/telemetry/crsf.h \ - $(GTEST_HEADERS) - - @mkdir -p $(dir $@) - $(CC) $(C_FLAGS) $(TEST_CFLAGS) -c $(USER_DIR)/telemetry/crsf.c -o $@ - -$(OBJECT_DIR)/rx_crsf_unittest.o : \ - $(TEST_DIR)/rx_crsf_unittest.cc \ - $(USER_DIR)/rx/crsf.h \ - $(USER_DIR)/rx/crsf.c \ - $(GTEST_HEADERS) - - @mkdir -p $(dir $@) - $(CXX) $(CXX_FLAGS) $(TEST_CFLAGS) -c $(TEST_DIR)/rx_crsf_unittest.cc -o $@ - -$(OBJECT_DIR)/rx_crsf_unittest : \ - $(OBJECT_DIR)/rx/crsf.o \ - $(OBJECT_DIR)/common/maths.o \ - $(OBJECT_DIR)/rx_crsf_unittest.o \ - $(OBJECT_DIR)/gtest_main.a - - $(CXX) $(CXX_FLAGS) $^ -o $(OBJECT_DIR)/$@ - $(OBJECT_DIR)/rx_ranges_unittest.o : \ $(TEST_DIR)/rx_ranges_unittest.cc \ $(USER_DIR)/rx/rx.h \ diff --git a/src/test/unit/platform.h b/src/test/unit/platform.h index 4b0e458c9f..4cec0f990a 100644 --- a/src/test/unit/platform.h +++ b/src/test/unit/platform.h @@ -65,6 +65,11 @@ uint8_t DMA_GetFlagStatus(void *); void DMA_Cmd(DMA_Channel_TypeDef*, FunctionalState ); void DMA_ClearFlag(uint32_t); +typedef struct +{ + void* test; +} USART_TypeDef; + #define WS2811_DMA_TC_FLAG (void *)1 #define WS2811_DMA_HANDLER_IDENTIFER 0 diff --git a/src/test/unit/rx_crsf_unittest.cc b/src/test/unit/rx_crsf_unittest.cc index 2d70a6eef2..5e347a79b9 100644 --- a/src/test/unit/rx_crsf_unittest.cc +++ b/src/test/unit/rx_crsf_unittest.cc @@ -24,14 +24,19 @@ extern "C" { #include - #include "config/parameter_group.h" - #include "config/parameter_group_ids.h" + #include "build/debug.h" - #include "rx/rx.h" - #include "fc/rc_controls.h" #include "common/maths.h" #include "common/utils.h" + #include "io/serial.h" + + #include "rx/rx.h" + #include "rx/crsf.h" + + extern bool crsfFrameDone; + extern crsfFrame_t crsfFrame; + extern uint32_t crsfChannelData[CRSF_MAX_CHANNEL]; } #include "unittest_macros.h" @@ -95,5 +100,92 @@ TEST(CrossFireTest, CRC) EXPECT_EQ(crc1, crc2); } +TEST(CrossFireTest, TestCrsfFrameStatus) +{ + crsfFrameDone = true; + crsfFrame.frame.deviceAddress = CRSF_RECEIVER_ADDRESS; + crsfFrame.frame.frameLength = 0; + crsfFrame.frame.type = CRSF_FRAMETYPE_RC_CHANNELS_PACKED; + memset(crsfFrame.frame.payload, 0, CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE); + + const uint8_t status = crsfFrameStatus(); + EXPECT_EQ(RX_FRAME_COMPLETE, status); + EXPECT_EQ(false, crsfFrameDone); + + EXPECT_EQ(CRSF_RECEIVER_ADDRESS, crsfFrame.frame.deviceAddress); + EXPECT_EQ(CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC, crsfFrame.frame.frameLength); + EXPECT_EQ(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type); + for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) { + EXPECT_EQ(0, crsfChannelData[ii]); + } +} + +TEST(CrossFireTest, TestCrsfFrameStatusUnpacking) +{ + crsfFrameDone = true; + crsfFrame.frame.deviceAddress = CRSF_RECEIVER_ADDRESS; + crsfFrame.frame.frameLength = 0; + crsfFrame.frame.type = CRSF_FRAMETYPE_RC_CHANNELS_PACKED; + // 16 11-bit channels packed into 22 bytes of data + crsfFrame.frame.payload[0] = 0xFF; + crsfFrame.frame.payload[1] = 0xFF; + // !!TODO add more test data + crsfFrame.frame.payload[2] = 0; + crsfFrame.frame.payload[3] = 0; + crsfFrame.frame.payload[4] = 0; + crsfFrame.frame.payload[5] = 0; + crsfFrame.frame.payload[6] = 0; + crsfFrame.frame.payload[7] = 0; + crsfFrame.frame.payload[8] = 0; + crsfFrame.frame.payload[9] = 0; + crsfFrame.frame.payload[10] = 0; + crsfFrame.frame.payload[11] = 0; + crsfFrame.frame.payload[12] = 0; + crsfFrame.frame.payload[13] = 0; + crsfFrame.frame.payload[14] = 0; + crsfFrame.frame.payload[15] = 0; + crsfFrame.frame.payload[16] = 0; + crsfFrame.frame.payload[17] = 0; + crsfFrame.frame.payload[18] = 0; + crsfFrame.frame.payload[19] = 0; + crsfFrame.frame.payload[20] = 0; + crsfFrame.frame.payload[21] = 0; + + const uint8_t status = crsfFrameStatus(); + EXPECT_EQ(RX_FRAME_COMPLETE, status); + EXPECT_EQ(false, crsfFrameDone); + + EXPECT_EQ(CRSF_RECEIVER_ADDRESS, crsfFrame.frame.deviceAddress); + EXPECT_EQ(CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC, crsfFrame.frame.frameLength); + EXPECT_EQ(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type); + EXPECT_EQ(0x7ff, crsfChannelData[0]); + EXPECT_EQ(0x1f, crsfChannelData[1]); + EXPECT_EQ(0, crsfChannelData[2]); + EXPECT_EQ(0, crsfChannelData[3]); + EXPECT_EQ(0, crsfChannelData[4]); + EXPECT_EQ(0, crsfChannelData[5]); + EXPECT_EQ(0, crsfChannelData[6]); + EXPECT_EQ(0, crsfChannelData[7]); + EXPECT_EQ(0, crsfChannelData[8]); + EXPECT_EQ(0, crsfChannelData[9]); + EXPECT_EQ(0, crsfChannelData[10]); + EXPECT_EQ(0, crsfChannelData[11]); + EXPECT_EQ(0, crsfChannelData[12]); + EXPECT_EQ(0, crsfChannelData[13]); + EXPECT_EQ(0, crsfChannelData[14]); + EXPECT_EQ(0, crsfChannelData[15]); +} // STUBS +extern "C" { + +int16_t debug[DEBUG16_VALUE_COUNT]; +uint32_t micros(void) {return 0;} +serialPort_t *openSerialPort(serialPortIdentifier_e, serialPortFunction_e, serialReceiveCallbackPtr, uint32_t, portMode_t, portOptions_t) +{ + return NULL; +} +serialPortConfig_t *findSerialPortConfig(serialPortFunction_e ) {return NULL;} +bool telemetryCheckRxPortShared(const serialPortConfig_t *) {return false;} +serialPort_t *telemetrySharedPort = NULL; +} diff --git a/src/test/unit/target.h b/src/test/unit/target.h index c2ebf479ed..57939047ed 100644 --- a/src/test/unit/target.h +++ b/src/test/unit/target.h @@ -23,6 +23,7 @@ #define BARO #define GPS #define DISPLAY +#define SERIAL_RX #define TELEMETRY #define LED_STRIP #define USE_SERVOS