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

Added protocol level RX frame rate measurement for FrSky FPort.

This commit is contained in:
mikeller 2020-02-23 13:10:31 +13:00
parent 53318e5e4d
commit dc5671f34c
9 changed files with 71 additions and 7 deletions

View file

@ -95,4 +95,5 @@ const char * const debugModeNames[DEBUG_COUNT] = {
"FF_INTERPOLATED", "FF_INTERPOLATED",
"BLACKBOX_OUTPUT", "BLACKBOX_OUTPUT",
"GYRO_SAMPLE", "GYRO_SAMPLE",
"RX_TIMING",
}; };

View file

@ -111,6 +111,7 @@ typedef enum {
DEBUG_FF_INTERPOLATED, DEBUG_FF_INTERPOLATED,
DEBUG_BLACKBOX_OUTPUT, DEBUG_BLACKBOX_OUTPUT,
DEBUG_GYRO_SAMPLE, DEBUG_GYRO_SAMPLE,
DEBUG_RX_TIMING,
DEBUG_COUNT DEBUG_COUNT
} debugType_e; } debugType_e;

View file

@ -742,6 +742,12 @@ bool processRx(timeUs_t currentTimeUs)
static bool sharedPortTelemetryEnabled = false; static bool sharedPortTelemetryEnabled = false;
#endif #endif
timeDelta_t frameAgeUs;
timeDelta_t frameDeltaUs = rxGetFrameDelta(&frameAgeUs);
DEBUG_SET(DEBUG_RX_TIMING, 0, MIN(frameDeltaUs / 10, INT16_MAX));
DEBUG_SET(DEBUG_RX_TIMING, 1, MIN(frameAgeUs / 10, INT16_MAX));
if (!calculateRxChannelsAndUpdateFailsafe(currentTimeUs)) { if (!calculateRxChannelsAndUpdateFailsafe(currentTimeUs)) {
return false; return false;
} }

View file

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

View file

@ -130,6 +130,8 @@ static const smartPortPayload_t emptySmartPortFrame = { .frameId = 0, .valueId =
typedef struct fportBuffer_s { typedef struct fportBuffer_s {
uint8_t data[BUFFER_SIZE]; uint8_t data[BUFFER_SIZE];
uint8_t length; uint8_t length;
timeUs_t frameStartTimeUsOrZero;
timeUs_t frameStartTimeUs;
} fportBuffer_t; } fportBuffer_t;
static fportBuffer_t rxBuffer[NUM_RX_BUFFERS]; static fportBuffer_t rxBuffer[NUM_RX_BUFFERS];
@ -150,6 +152,9 @@ static serialPort_t *fportPort;
static bool telemetryEnabled = false; static bool telemetryEnabled = false;
#endif #endif
static timeUs_t lastRcFrameTimeUsOrZero = 0;
static timeUs_t lastRcFrameTimeUs = 0;
static void reportFrameError(uint8_t errorReason) { static void reportFrameError(uint8_t errorReason) {
static volatile uint16_t frameErrors = 0; static volatile uint16_t frameErrors = 0;
@ -169,7 +174,7 @@ static void fportDataReceive(uint16_t c, void *data)
static timeUs_t lastFrameReceivedUs = 0; static timeUs_t lastFrameReceivedUs = 0;
static bool telemetryFrame = false; static bool telemetryFrame = false;
const timeUs_t currentTimeUs = micros(); const timeUs_t currentTimeUs = microsISR();
clearToSend = false; clearToSend = false;
@ -177,6 +182,7 @@ static void fportDataReceive(uint16_t c, void *data)
reportFrameError(DEBUG_FPORT_ERROR_TIMEOUT); reportFrameError(DEBUG_FPORT_ERROR_TIMEOUT);
framePosition = 0; framePosition = 0;
rxBuffer[rxBufferWriteIndex].frameStartTimeUsOrZero = 0;
} }
uint8_t val = (uint8_t)c; uint8_t val = (uint8_t)c;
@ -203,10 +209,15 @@ static void fportDataReceive(uint16_t c, void *data)
frameStartAt = currentTimeUs; frameStartAt = currentTimeUs;
framePosition = 1; framePosition = 1;
rxBuffer[rxBufferWriteIndex].frameStartTimeUsOrZero = currentTimeUs;
rxBuffer[rxBufferWriteIndex].frameStartTimeUs = currentTimeUs;
} else if (framePosition > 0) { } else if (framePosition > 0) {
if (framePosition >= BUFFER_SIZE + 1) { if (framePosition >= BUFFER_SIZE + 1) {
framePosition = 0; framePosition = 0;
rxBuffer[rxBufferWriteIndex].frameStartTimeUsOrZero = 0;
reportFrameError(DEBUG_FPORT_ERROR_OVERSIZE); reportFrameError(DEBUG_FPORT_ERROR_OVERSIZE);
} else { } else {
if (escapedCharacter) { if (escapedCharacter) {
@ -286,6 +297,11 @@ static uint8_t fportFrameStatus(rxRuntimeState_t *rxRuntimeState)
setRssi(scaleRange(frame->data.controlData.rssi, 0, 100, 0, RSSI_MAX_VALUE), RSSI_SOURCE_RX_PROTOCOL); setRssi(scaleRange(frame->data.controlData.rssi, 0, 100, 0, RSSI_MAX_VALUE), RSSI_SOURCE_RX_PROTOCOL);
lastRcFrameReceivedMs = millis(); lastRcFrameReceivedMs = millis();
if (!(result & (RX_FRAME_FAILSAFE | RX_FRAME_DROPPED))) {
lastRcFrameTimeUsOrZero = rxBuffer[rxBufferReadIndex].frameStartTimeUsOrZero;
lastRcFrameTimeUs = rxBuffer[rxBufferReadIndex].frameStartTimeUs;
}
} }
break; break;
@ -390,6 +406,19 @@ static bool fportProcessFrame(const rxRuntimeState_t *rxRuntimeState)
return true; return true;
} }
static timeUs_t fportFrameTimeUsOrZero(void)
{
const timeUs_t result = lastRcFrameTimeUsOrZero;
lastRcFrameTimeUsOrZero = 0;
return result;
}
static timeUs_t fportFrameTimeUs(void)
{
return lastRcFrameTimeUs;
}
bool fportRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState) bool fportRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
{ {
static uint16_t sbusChannelData[SBUS_MAX_CHANNEL]; static uint16_t sbusChannelData[SBUS_MAX_CHANNEL];
@ -401,6 +430,8 @@ bool fportRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
rxRuntimeState->rcFrameStatusFn = fportFrameStatus; rxRuntimeState->rcFrameStatusFn = fportFrameStatus;
rxRuntimeState->rcProcessFrameFn = fportProcessFrame; rxRuntimeState->rcProcessFrameFn = fportProcessFrame;
rxRuntimeState->rcFrameTimeUsOrZeroFn = fportFrameTimeUsOrZero;
rxRuntimeState->rcFrameTimeUsFn = fportFrameTimeUs;
const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL); const serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_RX_SERIAL);
if (!portConfig) { if (!portConfig) {

View file

@ -873,7 +873,7 @@ bool isRssiConfigured(void)
return rssiSource != RSSI_SOURCE_NONE; return rssiSource != RSSI_SOURCE_NONE;
} }
bool rxTryGetFrameDelta(timeDelta_t *deltaUs) bool rxTryGetFrameDeltaOrZero(timeDelta_t *deltaUs)
{ {
static timeUs_t previousFrameTimeUsOrZero = 0; static timeUs_t previousFrameTimeUsOrZero = 0;
bool result = false; bool result = false;
@ -891,3 +891,23 @@ bool rxTryGetFrameDelta(timeDelta_t *deltaUs)
} }
return result; // No frame delta function available for protocol type or frames have stopped return result; // No frame delta function available for protocol type or frames have stopped
} }
timeDelta_t rxGetFrameDelta(timeDelta_t *frameAgeUs)
{
static timeUs_t previousFrameTimeUs = 0;
static timeDelta_t frameTimeDeltaUs = 0;
if (rxRuntimeState.rcFrameTimeUsFn) {
const timeUs_t frameTimeUs = rxRuntimeState.rcFrameTimeUsFn();
*frameAgeUs = cmpTimeUs(micros(), frameTimeUs);
const timeDelta_t deltaUs = cmpTimeUs(frameTimeUs, previousFrameTimeUs);
if (deltaUs) {
frameTimeDeltaUs = deltaUs;
previousFrameTimeUs = frameTimeUs;
}
}
return frameTimeDeltaUs;
}

View file

@ -126,6 +126,7 @@ typedef uint16_t (*rcReadRawDataFnPtr)(const struct rxRuntimeState_s *rxRuntimeS
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 timeUs_t (*rcGetFrameTimeUsOrZeroFnPtr)(void); // used to retrieve the timestamp in microseconds for the last channel data frame, or 0, depending on suitablilty of the value for RC smoothing typedef timeUs_t (*rcGetFrameTimeUsOrZeroFnPtr)(void); // used to retrieve the timestamp in microseconds for the last channel data frame, or 0, depending on suitablilty of the value for RC smoothing
typedef timeUs_t rcGetFrameTimeUsFn(void); // used to retrieve the timestamp in microseconds for the last channel data frame
typedef enum { typedef enum {
RX_PROVIDER_NONE = 0, RX_PROVIDER_NONE = 0,
@ -145,6 +146,7 @@ typedef struct rxRuntimeState_s {
rcFrameStatusFnPtr rcFrameStatusFn; rcFrameStatusFnPtr rcFrameStatusFn;
rcProcessFrameFnPtr rcProcessFrameFn; rcProcessFrameFnPtr rcProcessFrameFn;
rcGetFrameTimeUsOrZeroFnPtr rcFrameTimeUsOrZeroFn; rcGetFrameTimeUsOrZeroFnPtr rcFrameTimeUsOrZeroFn;
rcGetFrameTimeUsFn *rcFrameTimeUsFn;
uint16_t *channelData; uint16_t *channelData;
void *frameData; void *frameData;
} rxRuntimeState_t; } rxRuntimeState_t;
@ -210,4 +212,5 @@ void resumeRxPwmPpmSignal(void);
uint16_t rxGetRefreshRate(void); uint16_t rxGetRefreshRate(void);
bool rxTryGetFrameDelta(timeDelta_t *deltaUs); bool rxTryGetFrameDeltaOrZero(timeDelta_t *deltaUs);
timeDelta_t rxGetFrameDelta(timeDelta_t *frameAgeUs);

View file

@ -1101,4 +1101,5 @@ extern "C" {
bool isUpright(void) { return mockIsUpright; } bool isUpright(void) { return mockIsUpright; }
void blackboxLogEvent(FlightLogEvent, union flightLogEventData_u *) {}; void blackboxLogEvent(FlightLogEvent, union flightLogEventData_u *) {};
void gyroFiltering(timeUs_t) {}; void gyroFiltering(timeUs_t) {};
timeDelta_t rxGetFrameDelta(timeDelta_t *) { return 0; }
} }

View file

@ -186,4 +186,5 @@ extern "C" {
bool isUpright(void) { return true; } bool isUpright(void) { return true; }
void blackboxLogEvent(FlightLogEvent, union flightLogEventData_u *) {}; void blackboxLogEvent(FlightLogEvent, union flightLogEventData_u *) {};
void gyroFiltering(timeUs_t) {}; void gyroFiltering(timeUs_t) {};
timeDelta_t rxGetFrameDelta(timeDelta_t *) { return 0; }
} }