mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 16:25:31 +03:00
Merge pull request #4416 from codecae/crsf_rx_telemetry_tune
Tuned CRSF rx and telemetry
This commit is contained in:
commit
a44c2c34c5
3 changed files with 41 additions and 36 deletions
|
@ -45,8 +45,8 @@
|
||||||
|
|
||||||
#include "telemetry/crsf.h"
|
#include "telemetry/crsf.h"
|
||||||
|
|
||||||
#define CRSF_TIME_NEEDED_PER_FRAME_US 1000
|
#define CRSF_TIME_NEEDED_PER_FRAME_US 1100 // 700 ms + 400 ms for potential ad-hoc request
|
||||||
#define CRSF_TIME_BETWEEN_FRAMES_US 4000 // a frame is sent by the transmitter every 4 milliseconds
|
#define CRSF_TIME_BETWEEN_FRAMES_US 6667 // At fastest, frames are sent by the transmitter every 6.667 milliseconds, 150 Hz
|
||||||
|
|
||||||
#define CRSF_DIGITAL_CHANNEL_MIN 172
|
#define CRSF_DIGITAL_CHANNEL_MIN 172
|
||||||
#define CRSF_DIGITAL_CHANNEL_MAX 1811
|
#define CRSF_DIGITAL_CHANNEL_MAX 1811
|
||||||
|
@ -149,17 +149,28 @@ STATIC_UNIT_TESTED void crsfDataReceive(uint16_t c)
|
||||||
crsfFrameDone = crsfFramePosition < fullFrameLength ? false : true;
|
crsfFrameDone = crsfFramePosition < fullFrameLength ? false : true;
|
||||||
if (crsfFrameDone) {
|
if (crsfFrameDone) {
|
||||||
crsfFramePosition = 0;
|
crsfFramePosition = 0;
|
||||||
#if defined(USE_MSP_OVER_TELEMETRY)
|
if (crsfFrame.frame.type != CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
|
||||||
if (crsfFrame.frame.type == CRSF_FRAMETYPE_MSP_REQ || crsfFrame.frame.type == CRSF_FRAMETYPE_MSP_WRITE) {
|
|
||||||
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)
|
||||||
|
{
|
||||||
|
#if defined(USE_MSP_OVER_TELEMETRY)
|
||||||
|
case CRSF_FRAMETYPE_MSP_REQ:
|
||||||
|
case CRSF_FRAMETYPE_MSP_WRITE: ;
|
||||||
uint8_t *frameStart = (uint8_t *)&crsfFrame.frame.payload + CRSF_FRAME_ORIGIN_DEST_SIZE;
|
uint8_t *frameStart = (uint8_t *)&crsfFrame.frame.payload + CRSF_FRAME_ORIGIN_DEST_SIZE;
|
||||||
if (bufferCrsfMspFrame(frameStart, CRSF_FRAME_RX_MSP_FRAME_SIZE)) {
|
if (bufferCrsfMspFrame(frameStart, CRSF_FRAME_RX_MSP_FRAME_SIZE)) {
|
||||||
crsfScheduleMspResponse();
|
crsfScheduleMspResponse();
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
case CRSF_FRAMETYPE_DEVICE_PING:
|
||||||
|
crsfScheduleDeviceInfoResponse();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,7 +185,6 @@ STATIC_UNIT_TESTED uint8_t crsfFrameStatus(void)
|
||||||
if (crc != crsfFrame.frame.payload[CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE]) {
|
if (crc != crsfFrame.frame.payload[CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE]) {
|
||||||
return RX_FRAME_PENDING;
|
return RX_FRAME_PENDING;
|
||||||
}
|
}
|
||||||
crsfFrame.frame.frameLength = CRSF_FRAME_RC_CHANNELS_PAYLOAD_SIZE + CRSF_FRAME_LENGTH_TYPE_CRC;
|
|
||||||
// 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*)&crsfFrame.frame.payload;
|
||||||
crsfChannelData[0] = rcChannels->chan0;
|
crsfChannelData[0] = rcChannels->chan0;
|
||||||
|
@ -194,9 +204,6 @@ STATIC_UNIT_TESTED uint8_t crsfFrameStatus(void)
|
||||||
crsfChannelData[14] = rcChannels->chan14;
|
crsfChannelData[14] = rcChannels->chan14;
|
||||||
crsfChannelData[15] = rcChannels->chan15;
|
crsfChannelData[15] = rcChannels->chan15;
|
||||||
return RX_FRAME_COMPLETE;
|
return RX_FRAME_COMPLETE;
|
||||||
} else if (crsfFrame.frame.type == CRSF_FRAMETYPE_DEVICE_PING) {
|
|
||||||
crsfScheduleDeviceInfoResponse();
|
|
||||||
return RX_FRAME_COMPLETE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RX_FRAME_PENDING;
|
return RX_FRAME_PENDING;
|
||||||
|
@ -227,15 +234,6 @@ void crsfRxSendTelemetryData(void)
|
||||||
{
|
{
|
||||||
// if there is telemetry data to write
|
// if there is telemetry data to write
|
||||||
if (telemetryBufLen > 0) {
|
if (telemetryBufLen > 0) {
|
||||||
// check that we are not in bi dir mode or that we are not currently receiving data (ie in the middle of an RX frame)
|
|
||||||
// and that there is time to send the telemetry frame before the next RX frame arrives
|
|
||||||
if (rxConfig()->halfDuplex) {
|
|
||||||
const uint32_t timeSinceStartOfFrameUs = micros() - crsfFrameStartAtUs;
|
|
||||||
if ((timeSinceStartOfFrameUs < CRSF_TIME_NEEDED_PER_FRAME_US) ||
|
|
||||||
(timeSinceStartOfFrameUs > CRSF_TIME_BETWEEN_FRAMES_US - CRSF_TIME_NEEDED_PER_FRAME_US)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serialWriteBuf(serialPort, telemetryBuf, telemetryBufLen);
|
serialWriteBuf(serialPort, telemetryBuf, telemetryBufLen);
|
||||||
telemetryBufLen = 0; // reset telemetry buffer
|
telemetryBufLen = 0; // reset telemetry buffer
|
||||||
}
|
}
|
||||||
|
@ -248,7 +246,7 @@ bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
rxRuntimeConfig->channelCount = CRSF_MAX_CHANNEL;
|
rxRuntimeConfig->channelCount = CRSF_MAX_CHANNEL;
|
||||||
rxRuntimeConfig->rxRefreshRate = 11000; //!!TODO this needs checking
|
rxRuntimeConfig->rxRefreshRate = CRSF_TIME_BETWEEN_FRAMES_US; //!!TODO this needs checking
|
||||||
|
|
||||||
rxRuntimeConfig->rcReadRawFn = crsfReadRawRC;
|
rxRuntimeConfig->rcReadRawFn = crsfReadRawRC;
|
||||||
rxRuntimeConfig->rcFrameStatusFn = crsfFrameStatus;
|
rxRuntimeConfig->rcFrameStatusFn = crsfFrameStatus;
|
||||||
|
@ -263,7 +261,7 @@ bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeConfig_t *rxRuntimeConfig)
|
||||||
crsfDataReceive,
|
crsfDataReceive,
|
||||||
CRSF_BAUDRATE,
|
CRSF_BAUDRATE,
|
||||||
CRSF_PORT_MODE,
|
CRSF_PORT_MODE,
|
||||||
CRSF_PORT_OPTIONS | (rxConfig->serialrx_inverted ? SERIAL_INVERTED : 0) | (rxConfig->halfDuplex ? SERIAL_BIDIR : 0)
|
CRSF_PORT_OPTIONS | (rxConfig->serialrx_inverted ? SERIAL_INVERTED : 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
return serialPort != NULL;
|
return serialPort != NULL;
|
||||||
|
|
|
@ -400,7 +400,9 @@ void initCrsfTelemetry(void)
|
||||||
if (sensors(SENSOR_ACC)) {
|
if (sensors(SENSOR_ACC)) {
|
||||||
crsfSchedule[index++] = BV(CRSF_FRAME_ATTITUDE_INDEX);
|
crsfSchedule[index++] = BV(CRSF_FRAME_ATTITUDE_INDEX);
|
||||||
}
|
}
|
||||||
|
if (batteryConfig()->voltageMeterSource != VOLTAGE_METER_NONE || batteryConfig()->currentMeterSource != CURRENT_METER_NONE) {
|
||||||
crsfSchedule[index++] = BV(CRSF_FRAME_BATTERY_SENSOR_INDEX);
|
crsfSchedule[index++] = BV(CRSF_FRAME_BATTERY_SENSOR_INDEX);
|
||||||
|
}
|
||||||
crsfSchedule[index++] = BV(CRSF_FRAME_FLIGHT_MODE_INDEX);
|
crsfSchedule[index++] = BV(CRSF_FRAME_FLIGHT_MODE_INDEX);
|
||||||
if (feature(FEATURE_GPS)) {
|
if (feature(FEATURE_GPS)) {
|
||||||
crsfSchedule[index++] = BV(CRSF_FRAME_GPS_INDEX);
|
crsfSchedule[index++] = BV(CRSF_FRAME_GPS_INDEX);
|
||||||
|
@ -429,15 +431,15 @@ void handleCrsfTelemetry(timeUs_t currentTimeUs)
|
||||||
// in between the RX frames.
|
// in between the RX frames.
|
||||||
crsfRxSendTelemetryData();
|
crsfRxSendTelemetryData();
|
||||||
|
|
||||||
|
// Send ad-hoc response frames as soon as possible
|
||||||
#if defined(USE_MSP_OVER_TELEMETRY)
|
#if defined(USE_MSP_OVER_TELEMETRY)
|
||||||
if (mspReplyPending) {
|
if (mspReplyPending) {
|
||||||
mspReplyPending = handleCrsfMspFrameBuffer(CRSF_FRAME_TX_MSP_FRAME_SIZE, &crsfSendMspResponse);
|
mspReplyPending = handleCrsfMspFrameBuffer(CRSF_FRAME_TX_MSP_FRAME_SIZE, &crsfSendMspResponse);
|
||||||
|
crsfLastCycleTime = currentTimeUs; // reset telemetry timing due to ad-hoc request
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Actual telemetry data only needs to be sent at a low frequency, ie 10Hz
|
|
||||||
if (currentTimeUs >= crsfLastCycleTime + CRSF_CYCLETIME_US) {
|
|
||||||
crsfLastCycleTime = currentTimeUs;
|
|
||||||
if (deviceInfoReplyPending) {
|
if (deviceInfoReplyPending) {
|
||||||
sbuf_t crsfPayloadBuf;
|
sbuf_t crsfPayloadBuf;
|
||||||
sbuf_t *dst = &crsfPayloadBuf;
|
sbuf_t *dst = &crsfPayloadBuf;
|
||||||
|
@ -445,9 +447,15 @@ void handleCrsfTelemetry(timeUs_t currentTimeUs)
|
||||||
crsfFrameDeviceInfo(dst);
|
crsfFrameDeviceInfo(dst);
|
||||||
crsfFinalize(dst);
|
crsfFinalize(dst);
|
||||||
deviceInfoReplyPending = false;
|
deviceInfoReplyPending = false;
|
||||||
} else {
|
crsfLastCycleTime = currentTimeUs; // reset telemetry timing due to ad-hoc request
|
||||||
processCrsf();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actual telemetry data only needs to be sent at a low frequency, ie 10Hz
|
||||||
|
// Spread out scheduled frames evenly so each frame is sent at the same frequency.
|
||||||
|
if (currentTimeUs >= crsfLastCycleTime + (CRSF_CYCLETIME_US / crsfScheduleCount)) {
|
||||||
|
crsfLastCycleTime = currentTimeUs;
|
||||||
|
processCrsf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,6 @@ TEST(CrossFireTest, TestCrsfFrameStatus)
|
||||||
EXPECT_EQ(false, crsfFrameDone);
|
EXPECT_EQ(false, crsfFrameDone);
|
||||||
|
|
||||||
EXPECT_EQ(CRSF_ADDRESS_CRSF_RECEIVER, crsfFrame.frame.deviceAddress);
|
EXPECT_EQ(CRSF_ADDRESS_CRSF_RECEIVER, 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(CRSF_FRAMETYPE_RC_CHANNELS_PACKED, crsfFrame.frame.type);
|
||||||
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
|
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
|
||||||
EXPECT_EQ(0, crsfChannelData[ii]);
|
EXPECT_EQ(0, crsfChannelData[ii]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue