1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-25 17:25:20 +03:00

Move the receiver inter-frame measurements down into the protocol layer

Adds accuracy to the frame rate measurements used to configure RC smoothing. Prevents looptime delays and jitter from affecting the calculations. Significantly improves the accuracy of the measurement in cases where CPU load is high.

Implemented so that each protocol can individually provide the functionality if appropriate. If a protocol doesn't support the more granular measurement then the system will fallback to the original measurement calculated in the RX task.
This commit is contained in:
Bruce Luckcuck 2019-11-18 10:42:12 -05:00
parent 881a256980
commit 79dd6b6bcc
5 changed files with 44 additions and 6 deletions

View file

@ -166,8 +166,12 @@ static void taskUpdateRxMain(timeUs_t currentTimeUs)
return; return;
} }
currentRxRefreshRate = constrain(currentTimeUs - lastRxTimeUs, 1000, 30000); timeDelta_t rxFrameDeltaUs;
if (!rxGetFrameDelta(&rxFrameDeltaUs)) {
rxFrameDeltaUs = cmpTimeUs(currentTimeUs, lastRxTimeUs); // calculate a delta here if not supplied by the protocol
}
lastRxTimeUs = currentTimeUs; lastRxTimeUs = currentTimeUs;
currentRxRefreshRate = constrain(rxFrameDeltaUs, 1000, 30000);
isRXDataNew = true; isRXDataNew = true;
#ifdef USE_USB_CDC_HID #ifdef USE_USB_CDC_HID

View file

@ -64,10 +64,12 @@ 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;
static uint32_t crsfFrameStartAtUs = 0; static timeUs_t crsfFrameStartAtUs = 0;
static uint8_t telemetryBuf[CRSF_FRAME_SIZE_MAX]; static uint8_t telemetryBuf[CRSF_FRAME_SIZE_MAX];
static uint8_t telemetryBufLen = 0; static uint8_t telemetryBufLen = 0;
static timeDelta_t lastRcFrameDelta = 0;
/* /*
* CRSF protocol * CRSF protocol
* *
@ -231,13 +233,14 @@ STATIC_UNIT_TESTED void crsfDataReceive(uint16_t c, void *data)
UNUSED(data); UNUSED(data);
static uint8_t crsfFramePosition = 0; static uint8_t crsfFramePosition = 0;
const uint32_t currentTimeUs = micros(); const timeUs_t currentTimeUs = micros();
static timeUs_t lastRcFrameCompleteTimeUs = 0;
#ifdef DEBUG_CRSF_PACKETS #ifdef DEBUG_CRSF_PACKETS
debug[2] = currentTimeUs - crsfFrameStartAtUs; debug[2] = currentTimeUs - crsfFrameStartAtUs;
#endif #endif
if (currentTimeUs > crsfFrameStartAtUs + CRSF_TIME_NEEDED_PER_FRAME_US) { if (cmpTimeUs(currentTimeUs, crsfFrameStartAtUs) > CRSF_TIME_NEEDED_PER_FRAME_US) {
// We've received a character after max time needed to complete a frame, // We've received a character after max time needed to complete a frame,
// so this must be the start of a new frame. // so this must be the start of a new frame.
crsfFramePosition = 0; crsfFramePosition = 0;
@ -260,6 +263,8 @@ STATIC_UNIT_TESTED void crsfDataReceive(uint16_t c, void *data)
{ {
case CRSF_FRAMETYPE_RC_CHANNELS_PACKED: case CRSF_FRAMETYPE_RC_CHANNELS_PACKED:
if (crsfFrame.frame.deviceAddress == CRSF_ADDRESS_FLIGHT_CONTROLLER) { if (crsfFrame.frame.deviceAddress == CRSF_ADDRESS_FLIGHT_CONTROLLER) {
lastRcFrameDelta = cmpTimeUs(currentTimeUs, lastRcFrameCompleteTimeUs);
lastRcFrameCompleteTimeUs = currentTimeUs;
crsfFrameDone = true; crsfFrameDone = true;
memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame)); memcpy(&crsfChannelDataFrame, &crsfFrame, sizeof(crsfFrame));
} }
@ -369,6 +374,11 @@ void crsfRxSendTelemetryData(void)
} }
} }
static timeDelta_t crsfFrameDelta(void)
{
return lastRcFrameDelta;
}
bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState) bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
{ {
for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) { for (int ii = 0; ii < CRSF_MAX_CHANNEL; ++ii) {
@ -380,6 +390,7 @@ bool crsfRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
rxRuntimeState->rcReadRawFn = crsfReadRawRC; rxRuntimeState->rcReadRawFn = crsfReadRawRC;
rxRuntimeState->rcFrameStatusFn = crsfFrameStatus; rxRuntimeState->rcFrameStatusFn = crsfFrameStatus;
rxRuntimeState->rcFrameDeltaFn = crsfFrameDelta;
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL); const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL);
if (!portConfig) { if (!portConfig) {

View file

@ -862,3 +862,12 @@ bool isRssiConfigured(void)
{ {
return rssiSource != RSSI_SOURCE_NONE; return rssiSource != RSSI_SOURCE_NONE;
} }
bool rxGetFrameDelta(timeDelta_t *deltaUs)
{
if (rxRuntimeState.rcFrameDeltaFn) {
*deltaUs = rxRuntimeState.rcFrameDeltaFn();
return true;
}
return false; // No frame delta function available for protocol type
}

View file

@ -125,6 +125,7 @@ struct rxRuntimeState_s;
typedef uint16_t (*rcReadRawDataFnPtr)(const struct rxRuntimeState_s *rxRuntimeState, uint8_t chan); // used by receiver driver to return channel data typedef uint16_t (*rcReadRawDataFnPtr)(const struct rxRuntimeState_s *rxRuntimeState, uint8_t chan); // used by receiver driver to return channel data
typedef uint8_t (*rcFrameStatusFnPtr)(struct rxRuntimeState_s *rxRuntimeState); typedef uint8_t (*rcFrameStatusFnPtr)(struct rxRuntimeState_s *rxRuntimeState);
typedef bool (*rcProcessFrameFnPtr)(const struct rxRuntimeState_s *rxRuntimeState); typedef bool (*rcProcessFrameFnPtr)(const struct rxRuntimeState_s *rxRuntimeState);
typedef timeDelta_t (*rcGetFrameDeltaFnPtr)(void); // used to retrieve the time interval in microseconds for the last channel data frame
typedef enum { typedef enum {
RX_PROVIDER_NONE = 0, RX_PROVIDER_NONE = 0,
@ -143,6 +144,7 @@ typedef struct rxRuntimeState_s {
rcReadRawDataFnPtr rcReadRawFn; rcReadRawDataFnPtr rcReadRawFn;
rcFrameStatusFnPtr rcFrameStatusFn; rcFrameStatusFnPtr rcFrameStatusFn;
rcProcessFrameFnPtr rcProcessFrameFn; rcProcessFrameFnPtr rcProcessFrameFn;
rcGetFrameDeltaFnPtr rcFrameDeltaFn;
uint16_t *channelData; uint16_t *channelData;
void *frameData; void *frameData;
} rxRuntimeState_t; } rxRuntimeState_t;
@ -204,3 +206,5 @@ void suspendRxPwmPpmSignal(void);
void resumeRxPwmPpmSignal(void); void resumeRxPwmPpmSignal(void);
uint16_t rxGetRefreshRate(void); uint16_t rxGetRefreshRate(void);
bool rxGetFrameDelta(timeDelta_t *deltaUs);

View file

@ -108,15 +108,17 @@ typedef struct sbusFrameData_s {
bool done; bool done;
} sbusFrameData_t; } sbusFrameData_t;
static timeDelta_t lastFrameDelta = 0;
// Receive ISR callback // Receive ISR callback
static void sbusDataReceive(uint16_t c, void *data) static void sbusDataReceive(uint16_t c, void *data)
{ {
static timeUs_t lastFrameCompleteTimeUs = 0;
sbusFrameData_t *sbusFrameData = data; sbusFrameData_t *sbusFrameData = data;
const uint32_t nowUs = micros(); const timeUs_t nowUs = micros();
const int32_t sbusFrameTime = nowUs - sbusFrameData->startAtUs; const timeDelta_t sbusFrameTime = cmpTimeUs(nowUs, sbusFrameData->startAtUs);
if (sbusFrameTime > (long)(SBUS_TIME_NEEDED_PER_FRAME + 500)) { if (sbusFrameTime > (long)(SBUS_TIME_NEEDED_PER_FRAME + 500)) {
sbusFrameData->position = 0; sbusFrameData->position = 0;
@ -134,6 +136,8 @@ static void sbusDataReceive(uint16_t c, void *data)
if (sbusFrameData->position < SBUS_FRAME_SIZE) { if (sbusFrameData->position < SBUS_FRAME_SIZE) {
sbusFrameData->done = false; sbusFrameData->done = false;
} else { } else {
lastFrameDelta = cmpTimeUs(nowUs, lastFrameCompleteTimeUs);
lastFrameCompleteTimeUs = nowUs;
sbusFrameData->done = true; sbusFrameData->done = true;
DEBUG_SET(DEBUG_SBUS, DEBUG_SBUS_FRAME_TIME, sbusFrameTime); DEBUG_SET(DEBUG_SBUS, DEBUG_SBUS_FRAME_TIME, sbusFrameTime);
} }
@ -153,6 +157,11 @@ static uint8_t sbusFrameStatus(rxRuntimeState_t *rxRuntimeState)
return sbusChannelsDecode(rxRuntimeState, &sbusFrameData->frame.frame.channels); return sbusChannelsDecode(rxRuntimeState, &sbusFrameData->frame.frame.channels);
} }
static timeDelta_t sbusFrameDelta(void)
{
return lastFrameDelta;
}
bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState) bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
{ {
static uint16_t sbusChannelData[SBUS_MAX_CHANNEL]; static uint16_t sbusChannelData[SBUS_MAX_CHANNEL];
@ -174,6 +183,7 @@ bool sbusInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
} }
rxRuntimeState->rcFrameStatusFn = sbusFrameStatus; rxRuntimeState->rcFrameStatusFn = sbusFrameStatus;
rxRuntimeState->rcFrameDeltaFn = sbusFrameDelta;
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL); const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL);
if (!portConfig) { if (!portConfig) {