Restructure CRSF frame processing and RC channel handling
Prevents channel data packet corruption if other packets are receved before processing can complete.
This commit is contained in:
parent
dd0b45dc87
commit
09406ad9d9
|
@ -60,6 +60,7 @@
|
||||||
|
|
||||||
STATIC_UNIT_TESTED bool crsfFrameDone = false;
|
STATIC_UNIT_TESTED bool crsfFrameDone = false;
|
||||||
STATIC_UNIT_TESTED crsfFrame_t crsfFrame;
|
STATIC_UNIT_TESTED crsfFrame_t crsfFrame;
|
||||||
|
STATIC_UNIT_TESTED crsfFrame_t crsfChannelDataFrame;
|
||||||
STATIC_UNIT_TESTED uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
STATIC_UNIT_TESTED uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
||||||
|
|
||||||
static serialPort_t *serialPort;
|
static serialPort_t *serialPort;
|
||||||
|
@ -251,14 +252,19 @@ STATIC_UNIT_TESTED void crsfDataReceive(uint16_t c, void *data)
|
||||||
|
|
||||||
if (crsfFramePosition < fullFrameLength) {
|
if (crsfFramePosition < fullFrameLength) {
|
||||||
crsfFrame.bytes[crsfFramePosition++] = (uint8_t)c;
|
crsfFrame.bytes[crsfFramePosition++] = (uint8_t)c;
|
||||||
crsfFrameDone = crsfFramePosition < fullFrameLength ? false : true;
|
if (crsfFramePosition >= fullFrameLength) {
|
||||||
if (crsfFrameDone) {
|
|
||||||
crsfFramePosition = 0;
|
crsfFramePosition = 0;
|
||||||
if (crsfFrame.frame.type != CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
|
|
||||||
const uint8_t crc = crsfFrameCRC();
|
const uint8_t crc = crsfFrameCRC();
|
||||||
if (crc == crsfFrame.bytes[fullFrameLength - 1]) {
|
if (crc == crsfFrame.bytes[fullFrameLength - 1]) {
|
||||||
switch (crsfFrame.frame.type)
|
switch (crsfFrame.frame.type)
|
||||||
{
|
{
|
||||||
|
case CRSF_FRAMETYPE_RC_CHANNELS_PACKED:
|
||||||
|
if (crsfFrame.frame.deviceAddress == CRSF_ADDRESS_FLIGHT_CONTROLLER) {
|
||||||
|
crsfFrameDone = true;
|
||||||
|
memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#if defined(USE_TELEMETRY_CRSF) && defined(USE_MSP_OVER_TELEMETRY)
|
#if defined(USE_TELEMETRY_CRSF) && defined(USE_MSP_OVER_TELEMETRY)
|
||||||
case CRSF_FRAMETYPE_MSP_REQ:
|
case CRSF_FRAMETYPE_MSP_REQ:
|
||||||
case CRSF_FRAMETYPE_MSP_WRITE: {
|
case CRSF_FRAMETYPE_MSP_WRITE: {
|
||||||
|
@ -299,7 +305,6 @@ STATIC_UNIT_TESTED void crsfDataReceive(uint16_t c, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
STATIC_UNIT_TESTED uint8_t crsfFrameStatus(rxRuntimeState_t *rxRuntimeState)
|
STATIC_UNIT_TESTED uint8_t crsfFrameStatus(rxRuntimeState_t *rxRuntimeState)
|
||||||
{
|
{
|
||||||
|
@ -310,14 +315,9 @@ STATIC_UNIT_TESTED uint8_t crsfFrameStatus(rxRuntimeState_t *rxRuntimeState)
|
||||||
#endif
|
#endif
|
||||||
if (crsfFrameDone) {
|
if (crsfFrameDone) {
|
||||||
crsfFrameDone = false;
|
crsfFrameDone = false;
|
||||||
if (crsfFrame.frame.type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
|
|
||||||
// CRC includes type and payload of each frame
|
|
||||||
const uint8_t crc = crsfFrameCRC();
|
|
||||||
if (crc != crsfFrame.frame.payload[CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE]) {
|
|
||||||
return RX_FRAME_PENDING;
|
|
||||||
}
|
|
||||||
// unpack the RC channels
|
// unpack the RC channels
|
||||||
const crsfPayloadRcChannelsPacked_t* const rcChannels = (crsfPayloadRcChannelsPacked_t*)&crsfFrame.frame.payload;
|
const crsfPayloadRcChannelsPacked_t* const rcChannels = (crsfPayloadRcChannelsPacked_t*)&crsfChannelDataFrame.frame.payload;
|
||||||
crsfChannelData[0] = rcChannels->chan0;
|
crsfChannelData[0] = rcChannels->chan0;
|
||||||
crsfChannelData[1] = rcChannels->chan1;
|
crsfChannelData[1] = rcChannels->chan1;
|
||||||
crsfChannelData[2] = rcChannels->chan2;
|
crsfChannelData[2] = rcChannels->chan2;
|
||||||
|
@ -336,7 +336,6 @@ STATIC_UNIT_TESTED uint8_t crsfFrameStatus(rxRuntimeState_t *rxRuntimeState)
|
||||||
crsfChannelData[15] = rcChannels->chan15;
|
crsfChannelData[15] = rcChannels->chan15;
|
||||||
return RX_FRAME_COMPLETE;
|
return RX_FRAME_COMPLETE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return RX_FRAME_PENDING;
|
return RX_FRAME_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ extern "C" {
|
||||||
|
|
||||||
extern bool crsfFrameDone;
|
extern bool crsfFrameDone;
|
||||||
extern crsfFrame_t crsfFrame;
|
extern crsfFrame_t crsfFrame;
|
||||||
|
extern crsfFrame_t crsfChannelDataFrame;
|
||||||
extern uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
extern uint32_t crsfChannelData[CRSF_MAX_CHANNEL];
|
||||||
|
|
||||||
uint32_t dummyTimeUs;
|
uint32_t dummyTimeUs;
|
||||||
|
@ -178,6 +179,7 @@ TEST(CrossFireTest, TestCrsfFrameStatusUnpacking)
|
||||||
const uint8_t crc = crsfFrameCRC();
|
const uint8_t crc = crsfFrameCRC();
|
||||||
crsfFrame.frame.payload[CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE] = crc;
|
crsfFrame.frame.payload[CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE] = crc;
|
||||||
|
|
||||||
|
memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame));
|
||||||
const uint8_t status = crsfFrameStatus();
|
const uint8_t status = crsfFrameStatus();
|
||||||
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
||||||
EXPECT_EQ(false, crsfFrameDone);
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
@ -222,6 +224,7 @@ TEST(CrossFireTest, TestCapturedData)
|
||||||
const crsfRcChannelsFrame_t *framePtr = (const crsfRcChannelsFrame_t*)capturedData;
|
const crsfRcChannelsFrame_t *framePtr = (const crsfRcChannelsFrame_t*)capturedData;
|
||||||
crsfFrame = *(const crsfFrame_t*)framePtr;
|
crsfFrame = *(const crsfFrame_t*)framePtr;
|
||||||
crsfFrameDone = true;
|
crsfFrameDone = true;
|
||||||
|
memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame));
|
||||||
uint8_t status = crsfFrameStatus();
|
uint8_t status = crsfFrameStatus();
|
||||||
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
||||||
EXPECT_EQ(false, crsfFrameDone);
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
@ -244,6 +247,7 @@ TEST(CrossFireTest, TestCapturedData)
|
||||||
++framePtr;
|
++framePtr;
|
||||||
crsfFrame = *(const crsfFrame_t*)framePtr;
|
crsfFrame = *(const crsfFrame_t*)framePtr;
|
||||||
crsfFrameDone = true;
|
crsfFrameDone = true;
|
||||||
|
memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame));
|
||||||
status = crsfFrameStatus();
|
status = crsfFrameStatus();
|
||||||
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
EXPECT_EQ(RX_FRAME_COMPLETE, status);
|
||||||
EXPECT_EQ(false, crsfFrameDone);
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
@ -268,7 +272,7 @@ TEST(CrossFireTest, TestCrsfDataReceive)
|
||||||
for (unsigned int ii = 0; ii < sizeof(crsfRcChannelsFrame_t); ++ii) {
|
for (unsigned int ii = 0; ii < sizeof(crsfRcChannelsFrame_t); ++ii) {
|
||||||
crsfDataReceive(*pData++);
|
crsfDataReceive(*pData++);
|
||||||
}
|
}
|
||||||
EXPECT_EQ(true, crsfFrameDone);
|
EXPECT_EQ(false, crsfFrameDone); // data is not a valid rc channels frame so don't expect crsfFrameDone to be true
|
||||||
EXPECT_EQ(CRSF_ADDRESS_BROADCAST, crsfFrame.frame.deviceAddress);
|
EXPECT_EQ(CRSF_ADDRESS_BROADCAST, crsfFrame.frame.deviceAddress);
|
||||||
EXPECT_EQ(CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC, crsfFrame.frame.frameLength);
|
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(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type);
|
||||||
|
|
Loading…
Reference in New Issue