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:
parent
53318e5e4d
commit
dc5671f34c
9 changed files with 71 additions and 7 deletions
|
@ -95,4 +95,5 @@ const char * const debugModeNames[DEBUG_COUNT] = {
|
||||||
"FF_INTERPOLATED",
|
"FF_INTERPOLATED",
|
||||||
"BLACKBOX_OUTPUT",
|
"BLACKBOX_OUTPUT",
|
||||||
"GYRO_SAMPLE",
|
"GYRO_SAMPLE",
|
||||||
|
"RX_TIMING",
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue