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

Merge pull request #10360 from mikeller/immersionrc-irc-ghost-rssi-lq

Implement RSSI (dBm and Pct), LQ, in GHST driver
This commit is contained in:
Michael Keller 2020-11-24 00:28:00 +01:00 committed by GitHub
commit 6e60138725
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 90 additions and 31 deletions

View file

@ -449,7 +449,7 @@ static void osdResetStats(void)
stats.max_g_force = 0;
stats.max_esc_temp = 0;
stats.max_esc_rpm = 0;
stats.min_link_quality = (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_CRSF) ? 100 : 99; // percent
stats.min_link_quality = (linkQualitySource == LQ_SOURCE_NONE) ? 99 : 100; // percent
stats.min_rssi_dbm = CRSF_SNR_MAX;
}

View file

@ -984,6 +984,9 @@ static void osdElementLinkQuality(osdElementParms_t *element)
osdLinkQuality = rxGetLinkQuality();
const uint8_t osdRfMode = rxGetRfMode();
tfp_sprintf(element->buff, "%c%1d:%2d", SYM_LINK_QUALITY, osdRfMode, osdLinkQuality);
} else if (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_GHST) { // 0-100
osdLinkQuality = rxGetLinkQuality();
tfp_sprintf(element->buff, "%c%2d", SYM_LINK_QUALITY, osdLinkQuality);
} else { // 0-9
osdLinkQuality = rxGetLinkQuality() * 10 / LINK_QUALITY_MAX_VALUE;
if (osdLinkQuality >= 10) {

View file

@ -54,6 +54,9 @@
#define GHST_MAX_FRAME_TIME_US 500 // 14 bytes @ 420k = ~450us
#define GHST_TIME_BETWEEN_FRAMES_US 4500 // fastest frame rate = 222.22Hz, or 4500us
#define GHST_RSSI_DBM_MIN (-117) // Long Range mode value
#define GHST_RSSI_DBM_MAX (-60) // Typical RSSI with typical power levels, typical antennas, and a few feet/meters between Tx and Rx
// define the time window after the end of the last received packet where telemetry packets may be sent
// NOTE: This allows the Rx to double-up on Rx packets to transmit data other than servo data, but
// only if sent < 1ms after the servo data packet.
@ -212,40 +215,58 @@ static bool ghstProcessFrame(const rxRuntimeState_t *rxRuntimeState)
}
if (ghstValidatedFrameAvailable) {
int startIdx = 4;
switch (ghstValidatedFrame.frame.type) {
case GHST_UL_RC_CHANS_HS4_5TO8:
case GHST_UL_RC_CHANS_HS4_9TO12:
case GHST_UL_RC_CHANS_HS4_13TO16: {
const ghstPayloadPulses_t* const rcChannels = (ghstPayloadPulses_t*)&ghstValidatedFrame.frame.payload;
int startIdx = 0;
// all uplink frames contain CH1..4 data (12 bit)
ghstChannelData[0] = rcChannels->ch1 >> 1;
ghstChannelData[1] = rcChannels->ch2 >> 1;
ghstChannelData[2] = rcChannels->ch3 >> 1;
ghstChannelData[3] = rcChannels->ch4 >> 1;
if (ghstValidatedFrame.frame.type >= GHST_UL_RC_CHANS_HS4_FIRST &&
ghstValidatedFrame.frame.type <= GHST_UL_RC_CHANS_HS4_LAST) {
const ghstPayloadPulses_t* const rcChannels = (ghstPayloadPulses_t*)&ghstValidatedFrame.frame.payload;
// remainder of uplink frame contains 4 more channels (8 bit), sent in a round-robin fashion
switch(ghstValidatedFrame.frame.type) {
case GHST_UL_RC_CHANS_HS4_5TO8: startIdx = 4; break;
case GHST_UL_RC_CHANS_HS4_9TO12: startIdx = 8; break;
case GHST_UL_RC_CHANS_HS4_13TO16: startIdx = 12; break;
// all uplink frames contain CH1..4 data (12 bit)
ghstChannelData[0] = rcChannels->ch1to4.ch1 >> 1;
ghstChannelData[1] = rcChannels->ch1to4.ch2 >> 1;
ghstChannelData[2] = rcChannels->ch1to4.ch3 >> 1;
ghstChannelData[3] = rcChannels->ch1to4.ch4 >> 1;
switch(ghstValidatedFrame.frame.type) {
case GHST_UL_RC_CHANS_HS4_RSSI: {
const ghstPayloadPulsesRssi_t* const rssiFrame = (ghstPayloadPulsesRssi_t*)&ghstValidatedFrame.frame.payload;
if (rssiSource == RSSI_SOURCE_RX_PROTOCOL) {
// rssi sent sign-inverted
const uint16_t rssiPercentScaled = scaleRange(-rssiFrame->rssi, GHST_RSSI_DBM_MIN, 0, GHST_RSSI_DBM_MAX, RSSI_MAX_VALUE);
setRssi(rssiPercentScaled, RSSI_SOURCE_RX_PROTOCOL);
}
#ifdef USE_RX_RSSI_DBM
setRssiDbm(-rssiFrame->rssi, RSSI_SOURCE_RX_PROTOCOL);
#endif
#ifdef USE_RX_LINK_QUALITY_INFO
if (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_GHST) {
setLinkQualityDirect(rssiFrame->lq);
}
#endif
break;
}
case GHST_UL_RC_CHANS_HS4_5TO8: startIdx = 4; break;
case GHST_UL_RC_CHANS_HS4_9TO12: startIdx = 8; break;
case GHST_UL_RC_CHANS_HS4_13TO16: startIdx = 12; break;
}
if (startIdx > 0)
{
// remainder of uplink frame contains 4 more channels (8 bit), sent in a round-robin fashion
ghstChannelData[startIdx++] = rcChannels->cha << 3;
ghstChannelData[startIdx++] = rcChannels->chb << 3;
ghstChannelData[startIdx++] = rcChannels->chc << 3;
ghstChannelData[startIdx++] = rcChannels->chd << 3;
return true;
}
break;
default:
break;
}
}
return false;
return true;
}
STATIC_UNIT_TESTED uint16_t ghstReadRawRC(const rxRuntimeState_t *rxRuntimeState, uint8_t chan)
@ -306,6 +327,16 @@ bool ghstRxInit(const rxConfig_t *rxConfig, rxRuntimeState_t *rxRuntimeState)
);
serialPort->idleCallback = ghstIdle;
if (rssiSource == RSSI_SOURCE_NONE) {
rssiSource = RSSI_SOURCE_RX_PROTOCOL;
}
#ifdef USE_RX_LINK_QUALITY_INFO
if (linkQualitySource == LQ_SOURCE_NONE) {
linkQualitySource = LQ_SOURCE_RX_PROTOCOL_GHST;
}
#endif
return serialPort != NULL;
}

View file

@ -45,9 +45,15 @@ typedef enum {
} ghstAddr_e;
typedef enum {
GHST_UL_RC_CHANS_HS4_5TO8 = 0x10, // High Speed 4 channel, plus CH5-8
GHST_UL_RC_CHANS_HS4_9TO12 = 0x11, // High Speed 4 channel, plus CH9-12
GHST_UL_RC_CHANS_HS4_13TO16 = 0x12 // High Speed 4 channel, plus CH13-16
// frame types 0x10 - 0x1f always include 4 primary channels, plus either 4 aux channels,
// or other type-specific data. Expect types 0x14-0x1f to be added in the future, and even though
// not explicitly supported, the 4 primary channels should always be extracted.
GHST_UL_RC_CHANS_HS4_FIRST = 0x10, // First frame type including 4 primary channels
GHST_UL_RC_CHANS_HS4_5TO8 = 0x10, // primary 4 channel, plus CH5-8
GHST_UL_RC_CHANS_HS4_9TO12 = 0x11, // primary 4 channel, plus CH9-12
GHST_UL_RC_CHANS_HS4_13TO16 = 0x12, // primary 4 channel, plus CH13-16
GHST_UL_RC_CHANS_HS4_RSSI = 0x13, // primary 4 channel, plus RSSI, LQ, RF Mode, and Tx Power
GHST_UL_RC_CHANS_HS4_LAST = 0x1f // Last frame type including 4 primary channels
} ghstUl_e;
#define GHST_UL_RC_CHANS_SIZE 12 // 1 (type) + 10 (data) + 1 (crc)
@ -80,16 +86,34 @@ typedef union ghstFrame_u {
ghstFrameDef_t frame;
} ghstFrame_t;
/* Pulses payload (channel data). Includes 4x high speed control channels, plus 4 channels from CH5-CH12 */
typedef struct ghstPayloadPulses_s {
// 80 bits, or 10 bytes
/* Pulses payload (channel data), for 4x 12-bit channels */
typedef struct ghstPayloadServo4_s {
// 48 bits, or 6 bytes
unsigned int ch1: 12;
unsigned int ch2: 12;
unsigned int ch3: 12;
unsigned int ch4: 12;
} __attribute__ ((__packed__)) ghstPayloadServo4_t;
/* Pulses payload (channel data). Includes 4x high speed control channels, plus 4 channels from CH5-CH12 */
typedef struct ghstPayloadPulses_s {
// 80 bits, or 10 bytes
ghstPayloadServo4_t ch1to4;
unsigned int cha: 8;
unsigned int chb: 8;
unsigned int chc: 8;
unsigned int chd: 8;
} __attribute__ ((__packed__)) ghstPayloadPulses_t;
/* Pulses payload (channel data), with RSSI/LQ, and other related data */
typedef struct ghstPayloadPulsesRssi_s {
// 80 bits, or 10 bytes
ghstPayloadServo4_t ch1to4;
unsigned int lq: 8; // 0-100
unsigned int rssi: 8; // 0 - 128 sign inverted, dBm
unsigned int rfProtocol: 8;
signed int txPwrdBm: 8; // tx power in dBm, use lookup table to map to published mW values
} __attribute__ ((__packed__)) ghstPayloadPulsesRssi_t;

View file

@ -425,7 +425,7 @@ static void setLinkQuality(bool validFrame, timeDelta_t currentDeltaTimeUs)
static timeDelta_t resampleTimeUs = 0;
#ifdef USE_RX_LINK_QUALITY_INFO
if (linkQualitySource != LQ_SOURCE_RX_PROTOCOL_CRSF) {
if (linkQualitySource == LQ_SOURCE_NONE) {
// calculate new sample mean
linkQuality = updateLinkQualitySamples(validFrame ? LINK_QUALITY_MAX_VALUE : 0);
}
@ -871,7 +871,7 @@ uint8_t rxGetRfMode(void)
uint16_t rxGetLinkQualityPercent(void)
{
return (linkQualitySource == LQ_SOURCE_RX_PROTOCOL_CRSF) ? linkQuality : scaleRange(linkQuality, 0, LINK_QUALITY_MAX_VALUE, 0, 100);
return (linkQualitySource == LQ_SOURCE_NONE) ? scaleRange(linkQuality, 0, LINK_QUALITY_MAX_VALUE, 0, 100) : linkQuality;
}
#endif

View file

@ -166,6 +166,7 @@ extern rssiSource_e rssiSource;
typedef enum {
LQ_SOURCE_NONE = 0,
LQ_SOURCE_RX_PROTOCOL_CRSF,
LQ_SOURCE_RX_PROTOCOL_GHST,
} linkQualitySource_e;
extern linkQualitySource_e linkQualitySource;