mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-25 01:05:27 +03:00
Added RSNR to the OSD (#11062)
* Added RNSR to the OSD * filtering with pt1 * update pgconfig ver * rssi_smoothness and proper define wrapping * missing define wrap * smoothing moved to updateRSSI * minor comment update * fixed rx tests Co-authored-by: Tony Cabello <> Co-authored-by: J Blackman <blckmn@users.noreply.github.com>
This commit is contained in:
parent
b197d1d6bd
commit
22c5bf4eb3
17 changed files with 215 additions and 64 deletions
|
@ -745,6 +745,7 @@ const clivalue_t valueTable[] = {
|
|||
{ "rssi_offset", VAR_INT8 | MASTER_VALUE, .config.minmax = { -100, 100 }, PG_RX_CONFIG, offsetof(rxConfig_t, rssi_offset) },
|
||||
{ "rssi_invert", VAR_INT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_CONFIG, offsetof(rxConfig_t, rssi_invert) },
|
||||
{ "rssi_src_frame_lpf_period", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rssi_src_frame_lpf_period) },
|
||||
{ "rssi_smoothing", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, UINT8_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rssi_smoothing) },
|
||||
|
||||
#ifdef USE_RC_SMOOTHING_FILTER
|
||||
{ PARAM_NAME_RC_SMOOTHING, VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_CONFIG, offsetof(rxConfig_t, rc_smoothing_mode) },
|
||||
|
@ -773,11 +774,8 @@ const clivalue_t valueTable[] = {
|
|||
#if defined(USE_SERIALRX_SBUS)
|
||||
{ "sbus_baud_fast", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_CONFIG, offsetof(rxConfig_t, sbus_baud_fast) },
|
||||
#endif
|
||||
#if defined(USE_SERIALRX_CRSF)
|
||||
{ "crsf_use_rx_snr", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_CONFIG, offsetof(rxConfig_t, crsf_use_rx_snr) },
|
||||
#if defined(USE_CRSF_V3)
|
||||
{ "crsf_use_negotiated_baud", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_RX_CONFIG, offsetof(rxConfig_t, crsf_use_negotiated_baud) },
|
||||
#endif
|
||||
#endif
|
||||
{ "airmode_start_throttle_percent", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_RX_CONFIG, offsetof(rxConfig_t, airModeActivateThreshold) },
|
||||
{ "rx_min_usec", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { PWM_PULSE_MIN, PWM_PULSE_MAX }, PG_RX_CONFIG, offsetof(rxConfig_t, rx_min_usec) },
|
||||
|
@ -1315,7 +1313,10 @@ const clivalue_t valueTable[] = {
|
|||
{ "osd_link_quality_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_OSD_CONFIG, offsetof(osdConfig_t, link_quality_alarm) },
|
||||
#endif
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
{ "osd_rssi_dbm_alarm", VAR_INT16 | MASTER_VALUE, .config.minmax = { CRSF_RSSI_MIN, CRSF_SNR_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, rssi_dbm_alarm) },
|
||||
{ "osd_rssi_dbm_alarm", VAR_INT16 | MASTER_VALUE, .config.minmax = { CRSF_RSSI_MIN, CRSF_RSSI_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, rssi_dbm_alarm) },
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
{ "osd_rsnr_alarm", VAR_INT16 | MASTER_VALUE, .config.minmax = { CRSF_SNR_MIN, CRSF_SNR_MAX }, PG_OSD_CONFIG, offsetof(osdConfig_t, rsnr_alarm) },
|
||||
#endif
|
||||
{ "osd_cap_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 20000 }, PG_OSD_CONFIG, offsetof(osdConfig_t, cap_alarm) },
|
||||
{ "osd_alt_alarm", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 10000 }, PG_OSD_CONFIG, offsetof(osdConfig_t, alt_alarm) },
|
||||
|
@ -1346,6 +1347,9 @@ const clivalue_t valueTable[] = {
|
|||
#endif
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
{ "osd_rssi_dbm_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_RSSI_DBM_VALUE]) },
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
{ "osd_rsnr_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_RSNR_VALUE]) },
|
||||
#endif
|
||||
{ "osd_tim_1_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_ITEM_TIMER_1]) },
|
||||
{ "osd_tim_2_pos", VAR_UINT16 | MASTER_VALUE, .config.minmaxUnsigned = { 0, OSD_POSCFG_MAX }, PG_OSD_ELEMENT_CONFIG, offsetof(osdElementConfig_t, item_pos[OSD_ITEM_TIMER_2]) },
|
||||
|
|
|
@ -80,6 +80,9 @@ const OSD_Entry menuOsdActiveElemsEntries[] =
|
|||
{"RSSI", OME_VISIBLE | DYNAMIC, NULL, &osdConfig_item_pos[OSD_RSSI_VALUE]},
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
{"RSSI DBM", OME_VISIBLE | DYNAMIC, NULL, &osdConfig_item_pos[OSD_RSSI_DBM_VALUE]},
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
{"RSNR", OME_VISIBLE | DYNAMIC, NULL, &osdConfig_item_pos[OSD_RSNR_VALUE]},
|
||||
#endif
|
||||
{"BATTERY VOLTAGE", OME_VISIBLE | DYNAMIC, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_VOLTAGE]},
|
||||
{"BATTERY USAGE", OME_VISIBLE | DYNAMIC, NULL, &osdConfig_item_pos[OSD_MAIN_BATT_USAGE]},
|
||||
|
@ -184,6 +187,7 @@ static CMS_Menu menuOsdActiveElems = {
|
|||
static uint8_t osdConfig_rssi_alarm;
|
||||
static uint16_t osdConfig_link_quality_alarm;
|
||||
static int16_t osdConfig_rssi_dbm_alarm;
|
||||
static int16_t osdConfig_rsnr_alarm;
|
||||
static uint16_t osdConfig_cap_alarm;
|
||||
static uint16_t osdConfig_alt_alarm;
|
||||
static uint16_t osdConfig_distance_alarm;
|
||||
|
@ -197,6 +201,7 @@ static const void *menuAlarmsOnEnter(displayPort_t *pDisp)
|
|||
osdConfig_rssi_alarm = osdConfig()->rssi_alarm;
|
||||
osdConfig_link_quality_alarm = osdConfig()->link_quality_alarm;
|
||||
osdConfig_rssi_dbm_alarm = osdConfig()->rssi_dbm_alarm;
|
||||
osdConfig_rsnr_alarm = osdConfig()->rsnr_alarm;
|
||||
osdConfig_cap_alarm = osdConfig()->cap_alarm;
|
||||
osdConfig_alt_alarm = osdConfig()->alt_alarm;
|
||||
osdConfig_distance_alarm = osdConfig()->distance_alarm;
|
||||
|
@ -214,6 +219,7 @@ static const void *menuAlarmsOnExit(displayPort_t *pDisp, const OSD_Entry *self)
|
|||
osdConfigMutable()->rssi_alarm = osdConfig_rssi_alarm;
|
||||
osdConfigMutable()->link_quality_alarm = osdConfig_link_quality_alarm;
|
||||
osdConfigMutable()->rssi_dbm_alarm = osdConfig_rssi_dbm_alarm;
|
||||
osdConfigMutable()->rsnr_alarm = osdConfig_rsnr_alarm;
|
||||
osdConfigMutable()->cap_alarm = osdConfig_cap_alarm;
|
||||
osdConfigMutable()->alt_alarm = osdConfig_alt_alarm;
|
||||
osdConfigMutable()->distance_alarm = osdConfig_distance_alarm;
|
||||
|
@ -229,6 +235,7 @@ const OSD_Entry menuAlarmsEntries[] =
|
|||
{"RSSI", OME_UINT8, NULL, &(OSD_UINT8_t){&osdConfig_rssi_alarm, 5, 90, 5}},
|
||||
{"LINK QUALITY", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_link_quality_alarm, 5, 300, 5}},
|
||||
{"RSSI DBM", OME_INT16, NULL, &(OSD_INT16_t){&osdConfig_rssi_dbm_alarm, CRSF_RSSI_MIN, CRSF_SNR_MAX, 5}},
|
||||
{"RSNR", OME_INT16, NULL, &(OSD_INT16_t){&osdConfig_rsnr_alarm, CRSF_SNR_MIN, CRSF_SNR_MAX, 5}},
|
||||
{"MAIN BAT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_cap_alarm, 50, 30000, 50}},
|
||||
{"MAX ALT", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_alt_alarm, 1, 200, 1}},
|
||||
{"MAX DISTANCE", OME_UINT16, NULL, &(OSD_UINT16_t){&osdConfig_distance_alarm, 0, UINT16_MAX, 10}},
|
||||
|
|
|
@ -149,7 +149,7 @@ escSensorData_t *osdEscDataCombined;
|
|||
|
||||
STATIC_ASSERT(OSD_POS_MAX == OSD_POS(31,31), OSD_POS_MAX_incorrect);
|
||||
|
||||
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 10);
|
||||
PG_REGISTER_WITH_RESET_FN(osdConfig_t, osdConfig, PG_OSD_CONFIG, 11);
|
||||
|
||||
PG_REGISTER_WITH_RESET_FN(osdElementConfig_t, osdElementConfig, PG_OSD_ELEMENT_CONFIG, 1);
|
||||
|
||||
|
@ -185,6 +185,7 @@ const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT] = {
|
|||
OSD_STAT_MIN_LINK_QUALITY,
|
||||
OSD_STAT_MAX_FFT,
|
||||
OSD_STAT_MIN_RSSI_DBM,
|
||||
OSD_STAT_MIN_RSNR,
|
||||
OSD_STAT_TOTAL_FLIGHTS,
|
||||
OSD_STAT_TOTAL_TIME,
|
||||
OSD_STAT_TOTAL_DIST,
|
||||
|
@ -344,6 +345,7 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdWarnSetState(OSD_WARNING_RSSI, false);
|
||||
osdWarnSetState(OSD_WARNING_LINK_QUALITY, false);
|
||||
osdWarnSetState(OSD_WARNING_RSSI_DBM, false);
|
||||
osdWarnSetState(OSD_WARNING_RSNR, false);
|
||||
// turn off the over mah capacity warning
|
||||
osdWarnSetState(OSD_WARNING_OVER_CAP, false);
|
||||
|
||||
|
@ -370,6 +372,7 @@ void pgResetFn_osdConfig(osdConfig_t *osdConfig)
|
|||
osdConfig->profile[i][0] = '\0';
|
||||
}
|
||||
osdConfig->rssi_dbm_alarm = -60;
|
||||
osdConfig->rsnr_alarm = 4;
|
||||
osdConfig->gps_sats_show_hdop = false;
|
||||
|
||||
for (int i = 0; i < OSD_RCCHANNELS_COUNT; i++) {
|
||||
|
@ -501,7 +504,8 @@ static void osdResetStats(void)
|
|||
stats.max_esc_temp = 0;
|
||||
stats.max_esc_rpm = 0;
|
||||
stats.min_link_quality = (linkQualitySource == LQ_SOURCE_NONE) ? 99 : 100; // percent
|
||||
stats.min_rssi_dbm = CRSF_SNR_MAX;
|
||||
stats.min_rssi_dbm = CRSF_RSSI_MAX;
|
||||
stats.min_rsnr = CRSF_SNR_MAX;
|
||||
}
|
||||
|
||||
#if defined(USE_ESC_SENSOR) || defined(USE_DSHOT_TELEMETRY)
|
||||
|
@ -581,6 +585,13 @@ static void osdUpdateStats(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
value = getRsnr();
|
||||
if (stats.min_rsnr > value) {
|
||||
stats.min_rsnr = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_GPS
|
||||
if (STATE(GPS_FIX) && STATE(GPS_FIX_HOME)) {
|
||||
if (stats.max_distance < GPS_distanceToHome) {
|
||||
|
@ -876,6 +887,13 @@ static bool osdDisplayStat(int statistic, uint8_t displayRow)
|
|||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
case OSD_STAT_MIN_RSNR:
|
||||
tfp_sprintf(buff, "%3d", stats.min_rsnr);
|
||||
osdDisplayStatisticLabel(displayRow, "MIN RSNR", buff);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef USE_PERSISTENT_STATS
|
||||
case OSD_STAT_TOTAL_FLIGHTS:
|
||||
itoa(statsConfig()->stats_total_flights, buff, 10);
|
||||
|
|
|
@ -164,6 +164,7 @@ typedef enum {
|
|||
OSD_WATT_HOURS_DRAWN,
|
||||
OSD_AUX_VALUE,
|
||||
OSD_READY_MODE,
|
||||
OSD_RSNR_VALUE,
|
||||
OSD_ITEM_COUNT // MUST BE LAST
|
||||
} osd_items_e;
|
||||
|
||||
|
@ -204,6 +205,7 @@ typedef enum {
|
|||
OSD_STAT_TOTAL_DIST,
|
||||
OSD_STAT_MIN_RSSI_DBM,
|
||||
OSD_STAT_WATT_HOURS_DRAWN,
|
||||
OSD_STAT_MIN_RSNR,
|
||||
OSD_STAT_COUNT // MUST BE LAST
|
||||
} osd_stats_e;
|
||||
|
||||
|
@ -249,6 +251,7 @@ typedef enum {
|
|||
OSD_WARNING_LINK_QUALITY,
|
||||
OSD_WARNING_RSSI_DBM,
|
||||
OSD_WARNING_OVER_CAP,
|
||||
OSD_WARNING_RSNR,
|
||||
OSD_WARNING_COUNT // MUST BE LAST
|
||||
} osdWarningsFlags_e;
|
||||
|
||||
|
@ -296,6 +299,7 @@ typedef struct osdConfig_s {
|
|||
char profile[OSD_PROFILE_COUNT][OSD_PROFILE_NAME_LENGTH + 1];
|
||||
uint16_t link_quality_alarm;
|
||||
int16_t rssi_dbm_alarm;
|
||||
int16_t rsnr_alarm;
|
||||
uint8_t gps_sats_show_hdop;
|
||||
int8_t rcChannels[OSD_RCCHANNELS_COUNT]; // RC channel values to display, -1 if none
|
||||
uint8_t displayPortDevice; // osdDisplayPortDevice_e
|
||||
|
@ -338,6 +342,7 @@ typedef struct statistic_s {
|
|||
int32_t max_esc_rpm;
|
||||
uint16_t min_link_quality;
|
||||
int16_t min_rssi_dbm;
|
||||
int16_t min_rsnr;
|
||||
} statistic_t;
|
||||
|
||||
extern timeUs_t resumeRefreshAt;
|
||||
|
|
|
@ -1384,6 +1384,13 @@ static void osdElementRssiDbm(osdElementParms_t *element)
|
|||
}
|
||||
#endif // USE_RX_RSSI_DBM
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
static void osdElementRsnr(osdElementParms_t *element)
|
||||
{
|
||||
tfp_sprintf(element->buff, "%c%3d", SYM_RSSI, getRsnr());
|
||||
}
|
||||
#endif // USE_RX_RSNR
|
||||
|
||||
#ifdef USE_OSD_STICK_OVERLAY
|
||||
static void osdBackgroundStickOverlay(osdElementParms_t *element)
|
||||
{
|
||||
|
@ -1598,6 +1605,9 @@ static const uint8_t osdElementDisplayOrder[] = {
|
|||
#ifdef USE_RX_RSSI_DBM
|
||||
OSD_RSSI_DBM_VALUE,
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
OSD_RSNR_VALUE,
|
||||
#endif
|
||||
#ifdef USE_OSD_STICK_OVERLAY
|
||||
OSD_STICK_OVERLAY_LEFT,
|
||||
OSD_STICK_OVERLAY_RIGHT,
|
||||
|
@ -1724,6 +1734,9 @@ const osdElementDrawFn osdElementDrawFunction[OSD_ITEM_COUNT] = {
|
|||
#endif
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
[OSD_RSSI_DBM_VALUE] = osdElementRssiDbm,
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
[OSD_RSNR_VALUE] = osdElementRsnr,
|
||||
#endif
|
||||
[OSD_RC_CHANNELS] = osdElementRcChannels,
|
||||
#ifdef USE_GPS
|
||||
|
|
|
@ -186,6 +186,15 @@ void renderOsdWarning(char *warningText, bool *blinking, uint8_t *displayAttr)
|
|||
return;
|
||||
}
|
||||
#endif // USE_RX_RSSI_DBM
|
||||
#ifdef USE_RX_RSNR
|
||||
// rsnr
|
||||
if (osdWarnGetState(OSD_WARNING_RSNR) && (getRsnr() < osdConfig()->rsnr_alarm)) {
|
||||
tfp_sprintf(warningText, "RSNR LOW");
|
||||
*displayAttr = DISPLAYPORT_ATTR_WARNING;
|
||||
*blinking = true;
|
||||
return;
|
||||
}
|
||||
#endif // USE_RX_RSNR
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
// Link Quality
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "rx/rx.h"
|
||||
#include "rx/rx_spi.h"
|
||||
|
||||
PG_REGISTER_WITH_RESET_FN(rxConfig_t, rxConfig, PG_RX_CONFIG, 3);
|
||||
PG_REGISTER_WITH_RESET_FN(rxConfig_t, rxConfig, PG_RX_CONFIG, 4);
|
||||
void pgResetFn_rxConfig(rxConfig_t *rxConfig)
|
||||
{
|
||||
RESET_CONFIG_2(rxConfig_t, rxConfig,
|
||||
|
@ -56,6 +56,7 @@ void pgResetFn_rxConfig(rxConfig_t *rxConfig)
|
|||
.rssi_offset = 0,
|
||||
.rssi_invert = 0,
|
||||
.rssi_src_frame_lpf_period = 30,
|
||||
.rssi_smoothing = 125,
|
||||
.fpvCamAngleDegrees = 0,
|
||||
.airModeActivateThreshold = 25,
|
||||
.max_aux_channel = DEFAULT_AUX_CHANNEL_COUNT,
|
||||
|
@ -69,7 +70,6 @@ void pgResetFn_rxConfig(rxConfig_t *rxConfig)
|
|||
.srxl2_unit_id = 1,
|
||||
.srxl2_baud_fast = true,
|
||||
.sbus_baud_fast = false,
|
||||
.crsf_use_rx_snr = false,
|
||||
.msp_override_channels_mask = 0,
|
||||
.crsf_use_negotiated_baud = false,
|
||||
);
|
||||
|
|
|
@ -57,10 +57,10 @@ typedef struct rxConfig_s {
|
|||
uint8_t rc_smoothing_auto_factor_rpy; // Used to adjust the "smoothness" determined by the auto cutoff calculations
|
||||
uint8_t rc_smoothing_auto_factor_throttle; // Used to adjust the "smoothness" determined by the auto cutoff calculations
|
||||
uint8_t rssi_src_frame_lpf_period; // Period of the cutoff frequency for the source frame RSSI filter (in 0.1 s)
|
||||
uint8_t rssi_smoothing; // Smoothing factor to reduce jumpiness of rssi, rssiDbm and rsnr
|
||||
uint8_t srxl2_unit_id; // Spektrum SRXL2 RX unit id
|
||||
uint8_t srxl2_baud_fast; // Select Spektrum SRXL2 fast baud rate
|
||||
uint8_t sbus_baud_fast; // Select SBus fast baud rate
|
||||
uint8_t crsf_use_rx_snr; // Use RX SNR (in dB) instead of RSSI dBm for CRSF
|
||||
uint32_t msp_override_channels_mask; // Channels to override when the MSP override mode is enabled
|
||||
uint8_t crsf_use_negotiated_baud; // Use negotiated baud rate for CRSF V3
|
||||
} rxConfig_t;
|
||||
|
|
|
@ -229,24 +229,17 @@ static void handleCrsfLinkStatisticsFrame(const crsfLinkStatistics_t* statsPtr,
|
|||
lastLinkStatisticsFrameUs = currentTimeUs;
|
||||
int16_t rssiDbm = -1 * (stats.active_antenna ? stats.uplink_RSSI_2 : stats.uplink_RSSI_1);
|
||||
if (rssiSource == RSSI_SOURCE_RX_PROTOCOL_CRSF) {
|
||||
if (rxConfig()->crsf_use_rx_snr) {
|
||||
// -10dB of SNR mapped to 0 RSSI (fail safe is likely to happen at this measure)
|
||||
// 0dB of SNR mapped to 20 RSSI (default alarm)
|
||||
// 41dB of SNR mapped to 99 RSSI (SNR can climb to around 60, but showing that is not very meaningful)
|
||||
const uint16_t rsnrPercentScaled = constrain((stats.uplink_SNR + 10) * 20, 0, RSSI_MAX_VALUE);
|
||||
setRssi(rsnrPercentScaled, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
rssiDbm = stats.uplink_SNR;
|
||||
#endif
|
||||
} else {
|
||||
const uint16_t rssiPercentScaled = scaleRange(rssiDbm, CRSF_RSSI_MIN, 0, 0, RSSI_MAX_VALUE);
|
||||
setRssi(rssiPercentScaled, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
}
|
||||
const uint16_t rssiPercentScaled = scaleRange(rssiDbm, CRSF_RSSI_MIN, CRSF_RSSI_MAX, 0, RSSI_MAX_VALUE);
|
||||
setRssi(rssiPercentScaled, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
}
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
setRssiDbm(rssiDbm, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
setRsnr(stats.uplink_SNR);
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
if (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_CRSF) {
|
||||
setLinkQualityDirect(stats.uplink_Link_quality);
|
||||
|
@ -284,12 +277,13 @@ static void handleCrsfLinkStatisticsTxFrame(const crsfLinkStatisticsTx_t* statsP
|
|||
}
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
int16_t rssiDbm = -1 * stats.uplink_RSSI;
|
||||
if (rxConfig()->crsf_use_rx_snr) {
|
||||
rssiDbm = stats.uplink_SNR;
|
||||
}
|
||||
setRssiDbm(rssiDbm, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
setRsnr(stats.uplink_SNR);
|
||||
#endif
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
if (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_CRSF) {
|
||||
setLinkQualityDirect(stats.uplink_Link_quality);
|
||||
|
@ -312,11 +306,10 @@ static void crsfCheckRssi(uint32_t currentTimeUs)
|
|||
if (rssiSource == RSSI_SOURCE_RX_PROTOCOL_CRSF) {
|
||||
setRssiDirect(0, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
if (rxConfig()->crsf_use_rx_snr) {
|
||||
setRssiDbmDirect(CRSF_SNR_MIN, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
} else {
|
||||
setRssiDbmDirect(CRSF_RSSI_MIN, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
}
|
||||
setRssiDbmDirect(CRSF_RSSI_MIN, RSSI_SOURCE_RX_PROTOCOL_CRSF);
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
setRsnrDirect(CRSF_SNR_MIN);
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
|
|
|
@ -79,7 +79,10 @@ static uint8_t txPower = 0;
|
|||
static uint8_t wideSwitchIndex = 0;
|
||||
static uint8_t currTlmDenom = 1;
|
||||
static simpleLowpassFilter_t rssiFilter;
|
||||
static meanAccumulator_t snrFilter;
|
||||
#ifdef USE_RX_RSNR
|
||||
static simpleLowpassFilter_t rsnrFilter;
|
||||
#endif //USE_RX_RSNR
|
||||
static meanAccumulator_t snrFilter; //for dyn power purposes
|
||||
|
||||
static volatile DMA_DATA uint8_t dmaBuffer[ELRS_RX_TX_BUFF_SIZE];
|
||||
static volatile DMA_DATA uint8_t telemetryPacket[ELRS_RX_TX_BUFF_SIZE];
|
||||
|
@ -89,6 +92,9 @@ static volatile uint8_t *payload;
|
|||
static void rssiFilterReset(void)
|
||||
{
|
||||
simpleLPFilterInit(&rssiFilter, 2, 5);
|
||||
#ifdef USE_RX_RSNR
|
||||
simpleLPFilterInit(&rsnrFilter, 2, 5);
|
||||
#endif //USE_RX_RSNR
|
||||
}
|
||||
|
||||
#define PACKET_HANDLING_TO_TOCK_ISR_DELAY_US 250
|
||||
|
@ -568,6 +574,9 @@ static void initializeReceiver(void)
|
|||
receiver.configChanged = false;
|
||||
receiver.rssi = 0;
|
||||
receiver.rssiFiltered = 0;
|
||||
#ifdef USE_RX_RSNR
|
||||
receiver.rsnrFiltered = 0;
|
||||
#endif //USE_RX_RSNR
|
||||
receiver.snr = 0;
|
||||
receiver.uplinkLQ = 0;
|
||||
receiver.rateIndex = receiver.inBindingMode ? bindingRateIndex : rxExpressLrsSpiConfig()->rateIndex;
|
||||
|
@ -948,6 +957,9 @@ static void handleConnectionStateUpdate(const uint32_t timeStampMs)
|
|||
#ifdef USE_RX_RSSI_DBM
|
||||
setRssiDbmDirect(-130, RSSI_SOURCE_RX_PROTOCOL);
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
setRsnrDirect(-30);
|
||||
#endif
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
setLinkQualityDirect(0);
|
||||
#endif
|
||||
|
@ -1015,6 +1027,10 @@ static void handleLinkStatsUpdate(const uint32_t timeStampMs)
|
|||
#ifdef USE_RX_RSSI_DBM
|
||||
setRssiDbm(receiver.rssiFiltered, RSSI_SOURCE_RX_PROTOCOL);
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
receiver.rsnrFiltered = simpleLPFilterUpdate(&rsnrFilter, receiver.snr/4);
|
||||
setRsnr(receiver.rsnrFiltered);
|
||||
#endif
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
setLinkQualityDirect(receiver.uplinkLQ);
|
||||
#endif
|
||||
|
@ -1026,6 +1042,9 @@ static void handleLinkStatsUpdate(const uint32_t timeStampMs)
|
|||
#ifdef USE_RX_RSSI_DBM
|
||||
setRssiDbmDirect(-130, RSSI_SOURCE_RX_PROTOCOL);
|
||||
#endif
|
||||
#ifdef USE_RX_RSNR
|
||||
setRsnrDirect(-30);
|
||||
#endif
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
setLinkQualityDirect(0);
|
||||
#endif
|
||||
|
|
|
@ -68,6 +68,9 @@ typedef struct elrsReceiver_s {
|
|||
int8_t rssi;
|
||||
int8_t snr;
|
||||
int8_t rssiFiltered;
|
||||
#ifdef USE_RX_RSNR
|
||||
int8_t rsnrFiltered;
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
uint8_t uplinkLQ;
|
||||
|
||||
|
|
119
src/main/rx/rx.c
119
src/main/rx/rx.c
|
@ -76,10 +76,26 @@
|
|||
const char rcChannelLetters[] = "AERT12345678abcdefgh";
|
||||
|
||||
static uint16_t rssi = 0; // range: [0;1023]
|
||||
static int16_t rssiDbm = CRSF_RSSI_MIN; // range: [-130,20]
|
||||
static uint16_t rssiRaw = 0; // range: [0;1023]
|
||||
static timeUs_t lastRssiSmoothingUs = 0;
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
static int16_t rssiDbm = CRSF_RSSI_MIN; // range: [-130,0]
|
||||
static int16_t rssiDbmRaw = CRSF_RSSI_MIN; // range: [-130,0]
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
#ifdef USE_RX_RSNR
|
||||
static int16_t rsnr = CRSF_SNR_MIN; // range: [-30,20]
|
||||
static int16_t rsnrRaw = CRSF_SNR_MIN; // range: [-30,20]
|
||||
#endif //USE_RX_RSNR
|
||||
static timeUs_t lastMspRssiUpdateUs = 0;
|
||||
|
||||
static pt1Filter_t frameErrFilter;
|
||||
static pt1Filter_t rssiFilter;
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
static pt1Filter_t rssiDbmFilter;
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
#ifdef USE_RX_RSNR
|
||||
static pt1Filter_t rsnrFilter;
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
static uint16_t linkQuality = 0;
|
||||
|
@ -362,6 +378,19 @@ void rxInit(void)
|
|||
// Setup source frame RSSI filtering to take averaged values every FRAME_ERR_RESAMPLE_US
|
||||
pt1FilterInit(&frameErrFilter, pt1FilterGain(GET_FRAME_ERR_LPF_FREQUENCY(rxConfig()->rssi_src_frame_lpf_period), FRAME_ERR_RESAMPLE_US/1000000.0));
|
||||
|
||||
// Configurable amount of filtering to remove excessive jumpiness of the values on the osd
|
||||
float k = (256.0f - rxConfig()->rssi_smoothing) / 256.0f;
|
||||
|
||||
pt1FilterInit(&rssiFilter, k);
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
pt1FilterInit(&rssiDbmFilter, k);
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
pt1FilterInit(&rsnrFilter, k);
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
rxChannelCount = MIN(rxConfig()->max_aux_channel + NON_AUX_CHANNEL_COUNT, rxRuntimeState.channelCount);
|
||||
}
|
||||
|
||||
|
@ -764,20 +793,7 @@ void setRssiDirect(uint16_t newRssi, rssiSource_e source)
|
|||
}
|
||||
|
||||
rssi = newRssi;
|
||||
}
|
||||
|
||||
#define RSSI_SAMPLE_COUNT 16
|
||||
|
||||
static uint16_t updateRssiSamples(uint16_t value)
|
||||
{
|
||||
static uint16_t samples[RSSI_SAMPLE_COUNT];
|
||||
static uint8_t sampleIndex = 0;
|
||||
static unsigned sum = 0;
|
||||
|
||||
sum += value - samples[sampleIndex];
|
||||
samples[sampleIndex] = value;
|
||||
sampleIndex = (sampleIndex + 1) % RSSI_SAMPLE_COUNT;
|
||||
return sum / RSSI_SAMPLE_COUNT;
|
||||
rssiRaw = newRssi;
|
||||
}
|
||||
|
||||
void setRssi(uint16_t rssiValue, rssiSource_e source)
|
||||
|
@ -788,10 +804,9 @@ void setRssi(uint16_t rssiValue, rssiSource_e source)
|
|||
|
||||
// Filter RSSI value
|
||||
if (source == RSSI_SOURCE_FRAME_ERRORS) {
|
||||
rssi = pt1FilterApply(&frameErrFilter, rssiValue);
|
||||
rssiRaw = pt1FilterApply(&frameErrFilter, rssiValue);
|
||||
} else {
|
||||
// calculate new sample mean
|
||||
rssi = updateRssiSamples(rssiValue);
|
||||
rssiRaw = rssiValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,6 +867,37 @@ void updateRSSI(timeUs_t currentTimeUs)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmpTimeUs(currentTimeUs, lastRssiSmoothingUs) > 250000) { // 0.25s
|
||||
lastRssiSmoothingUs = currentTimeUs;
|
||||
} else {
|
||||
if (lastRssiSmoothingUs != currentTimeUs) { // avoid div by 0
|
||||
float k = (256.0f - rxConfig()->rssi_smoothing) / 256.0f;
|
||||
float factor = ((currentTimeUs - lastRssiSmoothingUs) / 1000000.0f) / (1.0f / 4.0f);
|
||||
float k2 = (k * factor) / ((k * factor) - k + 1);
|
||||
|
||||
if (rssi != rssiRaw) {
|
||||
pt1FilterUpdateCutoff(&rssiFilter, k2);
|
||||
rssi = pt1FilterApply(&rssiFilter, rssiRaw);
|
||||
}
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
if (rssiDbm != rssiDbmRaw) {
|
||||
pt1FilterUpdateCutoff(&rssiDbmFilter, k2);
|
||||
rssiDbm = pt1FilterApply(&rssiDbmFilter, rssiDbmRaw);
|
||||
}
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
if (rsnr != rsnrRaw) {
|
||||
pt1FilterUpdateCutoff(&rsnrFilter, k2);
|
||||
rsnr = pt1FilterApply(&rsnrFilter, rsnrRaw);
|
||||
}
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
lastRssiSmoothingUs = currentTimeUs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t getRssi(void)
|
||||
|
@ -871,32 +917,19 @@ uint8_t getRssiPercent(void)
|
|||
return scaleRange(getRssi(), 0, RSSI_MAX_VALUE, 0, 100);
|
||||
}
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
int16_t getRssiDbm(void)
|
||||
{
|
||||
return rssiDbm;
|
||||
}
|
||||
|
||||
#define RSSI_SAMPLE_COUNT_DBM 16
|
||||
|
||||
static int16_t updateRssiDbmSamples(int16_t value)
|
||||
{
|
||||
static int16_t samplesdbm[RSSI_SAMPLE_COUNT_DBM];
|
||||
static uint8_t sampledbmIndex = 0;
|
||||
static int sumdbm = 0;
|
||||
|
||||
sumdbm += value - samplesdbm[sampledbmIndex];
|
||||
samplesdbm[sampledbmIndex] = value;
|
||||
sampledbmIndex = (sampledbmIndex + 1) % RSSI_SAMPLE_COUNT_DBM;
|
||||
return sumdbm / RSSI_SAMPLE_COUNT_DBM;
|
||||
}
|
||||
|
||||
void setRssiDbm(int16_t rssiDbmValue, rssiSource_e source)
|
||||
{
|
||||
if (source != rssiSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
rssiDbm = updateRssiDbmSamples(rssiDbmValue);
|
||||
rssiDbmRaw = rssiDbmValue;
|
||||
}
|
||||
|
||||
void setRssiDbmDirect(int16_t newRssiDbm, rssiSource_e source)
|
||||
|
@ -906,7 +939,27 @@ void setRssiDbmDirect(int16_t newRssiDbm, rssiSource_e source)
|
|||
}
|
||||
|
||||
rssiDbm = newRssiDbm;
|
||||
rssiDbmRaw = newRssiDbm;
|
||||
}
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
int16_t getRsnr(void)
|
||||
{
|
||||
return rsnr;
|
||||
}
|
||||
|
||||
void setRsnr(int16_t rsnrValue)
|
||||
{
|
||||
rsnrRaw = rsnrValue;
|
||||
}
|
||||
|
||||
void setRsnrDirect(int16_t newRsnr)
|
||||
{
|
||||
rsnr = newRsnr;
|
||||
rsnrRaw = newRsnr;
|
||||
}
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
#ifdef USE_RX_LINK_QUALITY_INFO
|
||||
uint16_t rxGetLinkQuality(void)
|
||||
|
|
|
@ -201,9 +201,17 @@ uint16_t rxGetLinkQuality(void);
|
|||
void setLinkQualityDirect(uint16_t linkqualityValue);
|
||||
uint16_t rxGetLinkQualityPercent(void);
|
||||
|
||||
#ifdef USE_RX_RSSI_DBM
|
||||
int16_t getRssiDbm(void);
|
||||
void setRssiDbm(int16_t newRssiDbm, rssiSource_e source);
|
||||
void setRssiDbmDirect(int16_t newRssiDbm, rssiSource_e source);
|
||||
#endif //USE_RX_RSSI_DBM
|
||||
|
||||
#ifdef USE_RX_RSNR
|
||||
int16_t getRsnr(void);
|
||||
void setRsnr(int16_t newRsnr);
|
||||
void setRsnrDirect(int16_t newRsnr);
|
||||
#endif //USE_RX_RSNR
|
||||
|
||||
void rxSetRfMode(uint8_t rfModeValue);
|
||||
uint8_t rxGetRfMode(void);
|
||||
|
|
|
@ -362,6 +362,7 @@ extern uint8_t _dmaram_end__;
|
|||
#define USE_RX_MSP
|
||||
#define USE_ESC_SENSOR_INFO
|
||||
#define USE_RX_RSSI_DBM
|
||||
#define USE_RX_RSNR
|
||||
|
||||
#if !defined(CLOUD_BUILD)
|
||||
#define USE_CRSF_CMS_TELEMETRY
|
||||
|
|
|
@ -606,6 +606,12 @@ extern "C" {
|
|||
UNUSED(k);
|
||||
}
|
||||
|
||||
void pt1FilterUpdateCutoff(pt1Filter_t *filter, float k)
|
||||
{
|
||||
UNUSED(filter);
|
||||
UNUSED(k);
|
||||
}
|
||||
|
||||
float pt1FilterApply(pt1Filter_t *filter, float input)
|
||||
{
|
||||
UNUSED(filter);
|
||||
|
|
|
@ -253,6 +253,12 @@ void pt1FilterInit(pt1Filter_t *filter, float k)
|
|||
UNUSED(k);
|
||||
}
|
||||
|
||||
void pt1FilterUpdateCutoff(pt1Filter_t *filter, float k)
|
||||
{
|
||||
UNUSED(filter);
|
||||
UNUSED(k);
|
||||
}
|
||||
|
||||
float pt1FilterApply(pt1Filter_t *filter, float input)
|
||||
{
|
||||
UNUSED(filter);
|
||||
|
|
|
@ -259,6 +259,12 @@ extern "C" {
|
|||
UNUSED(k);
|
||||
}
|
||||
|
||||
void pt1FilterUpdateCutoff(pt1Filter_t *filter, float k)
|
||||
{
|
||||
UNUSED(filter);
|
||||
UNUSED(k);
|
||||
}
|
||||
|
||||
float pt1FilterApply(pt1Filter_t *filter, float input)
|
||||
{
|
||||
UNUSED(filter);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue