Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/fc/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -4800,6 +4800,9 @@ static void cliUbloxPrintSatelites(char *arg)
}
cliPrintLinefeed();
}
// Print MON-RF noisePerMS if available
cliPrintLinef("MON-RF noisePerMS: %u", gpsGetMonRfNoisePerMs());
cliPrintLinef("MON-RF CW Suppression: %u", gpsGetMonRfCWSuppression());
}
#endif

Expand Down
61 changes: 61 additions & 0 deletions src/main/io/gps_ublox.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ static const char * baudInitDataNMEA[GPS_BAUDRATE_COUNT] = {

static ubx_nav_sig_info satelites[UBLOX_MAX_SIGNALS] = {};

// MON-RF noise value (noisePerMS) reported by UBX-MON-RF at payload offset 0x16
static uint8_t monRfNoisePerMs = 0;
static uint8_t monCWSuppresion = 0;

// Packet checksum accumulators
static uint8_t _ck_a;
static uint8_t _ck_b;
Expand Down Expand Up @@ -152,6 +156,14 @@ static union {
uint8_t bytes[UBLOX_BUFFER_SIZE];
} _buffer;

// OSD controlled flag: when true, OSD requests periodic MON-RF polling
static volatile bool osdMonRfWidgetEnabled = false;

void gpsSetOsdMonRfWidgetEnabled(bool enabled)
{
osdMonRfWidgetEnabled = enabled;
}

bool gpsUbloxHasGalileo(void)
{
return (ubx_capabilities.supported & UBX_MON_GNSS_GALILEO_MASK);
Expand Down Expand Up @@ -261,6 +273,28 @@ static void pollGnssCapabilities(void)
sendConfigMessageUBLOX();
}

// Poll UBX-MON-RF (no ACK expected) - used periodically for RF status on newer modules
static void pollMonRf(void)
{
uint8_t pkt[8];
uint8_t ck_a = 0, ck_b = 0;

pkt[0] = PREAMBLE1;
pkt[1] = PREAMBLE2;
pkt[2] = CLASS_MON;
pkt[3] = MSG_MON_RF;
pkt[4] = 0; // length LSB
pkt[5] = 0; // length MSB

// compute checksum over CLASS, ID and length (4 bytes)
ublox_update_checksum(&pkt[2], 4, &ck_a, &ck_b);
pkt[6] = ck_a;
pkt[7] = ck_b;

// send without forcing ACK state (so we don't disturb config ACK handling)
serialWriteBuf(gpsState.gpsPort, pkt, sizeof(pkt));
}


static const uint8_t default_payload[] = {
0xFF, 0xFF, 0x03, 0x03, 0x00, // CFG-NAV5 - Set engine settings (original MWII code)
Expand Down Expand Up @@ -732,6 +766,15 @@ static bool gpsParseFrameUBLOX(void)
}
}
break;
case MSG_MON_RF:
if (_class == CLASS_MON) {
// MON-RF payload contains various RF stats; noisePerMS is at offset 0x16 (22)
if (_payload_length > 0x10)
monRfNoisePerMs = _buffer.bytes[0x10];
if (_payload_length > 0x14)
monCWSuppresion = _buffer.bytes[0x14];
}
break;
case MSG_NAV_SAT:
if (_class == CLASS_NAV) {
static int satInfoCount = 0;
Expand Down Expand Up @@ -1220,10 +1263,19 @@ STATIC_PROTOTHREAD(gpsProtocolStateThread)
gpsSetProtocolTimeout(gpsState.baseTimeoutMs);

// GPS is ready - execute the gpsProcessNewSolutionData() based on gpsProtocolReceiverThread semaphore
static uint32_t lastMonRfMs = 0;
while (1) {
ptSemaphoreWait(semNewDataReady);
gpsProcessNewSolutionData(false);

/* Periodically poll MON-RF (~1s) for HW > UBLOX8 if OSD widget requested. Do not change ACK state. */
if (gpsState.hwVersion > UBX_HW_VERSION_UBLOX8 && osdMonRfWidgetEnabled) {
if ((millis() - lastMonRfMs) > 1000) {
lastMonRfMs = millis();
pollMonRf();
}
}

if (gpsState.gpsConfig->autoConfig) {
if ((millis() - gpsState.lastCapaPoolMs) > GPS_CAPA_INTERVAL) {
gpsState.lastCapaPoolMs = millis();
Expand Down Expand Up @@ -1313,4 +1365,13 @@ bool ubloxVersionE(uint8_t mj, uint8_t mn)
return gpsState.swVersionMajor == mj && gpsState.swVersionMinor == mn;
}

uint8_t gpsGetMonRfNoisePerMs(void)
{
return monRfNoisePerMs;
}
uint8_t gpsGetMonRfCWSuppression(void)
{
return monCWSuppresion;
}

#endif
11 changes: 10 additions & 1 deletion src/main/io/gps_ublox.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,8 @@ typedef enum {
MSG_CFG_SBAS = 0x16,
MSG_CFG_GNSS = 0x3e,
MSG_MON_GNSS = 0x28,
MSG_NAV_SIG = 0x43
MSG_NAV_SIG = 0x43,
MSG_MON_RF = 0x38
} ubx_protocol_bytes_t;

typedef enum {
Expand Down Expand Up @@ -548,6 +549,14 @@ bool ubloxVersionGT(uint8_t mj, uint8_t mn);
bool ubloxVersionGTE(uint8_t mj, uint8_t mn);
bool ubloxVersionE(uint8_t mj, uint8_t mn);

// MON-RF access Noise level
uint8_t gpsGetMonRfNoisePerMs(void);
// Called by OSD to enable/disable periodic MON-RF polling when widget is used
void gpsSetOsdMonRfWidgetEnabled(bool enabled);

// MON-RF access CW Suppression
uint8_t gpsGetMonRfCWSuppression(void);

#ifdef __cplusplus
}
#endif
65 changes: 63 additions & 2 deletions src/main/io/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "io/adsb.h"
#include "io/flashfs.h"
#include "io/gps.h"
#include "io/gps_ublox.h"
#include "io/osd.h"
#include "io/osd_common.h"
#include "io/osd_hud.h"
Expand Down Expand Up @@ -2258,6 +2259,65 @@ static bool osdDrawSingleElement(uint8_t item)
osdFormatCentiNumber(&buff[2], centiHDOP, 0, 1, 0, digits, false);
break;
}

case OSD_GPS_EXTRA_STATS:
{
gpsSetOsdMonRfWidgetEnabled(true);

// Collect satellite stats grouped by GNSS ID: 0,2,3,6
uint8_t stats[4][2] = { {0,0}, {0,0}, {0,0}, {0,0} }; // [group][0]=total, [group][1]=good
for (int i = 0; i < UBLOX_MAX_SIGNALS; ++i) {
const ubx_nav_sig_info *sat = gpsGetUbloxSatelite(i);
if (sat == NULL) continue;
int g = -1;
switch (sat->gnssId) {
case 0: g = 0; break; // GPS
case 2: g = 1; break; // GALILEO
case 3: g = 2; break; // BEIDOU
case 6: g = 3; break; // GLONASS
default: g = -1; break;
}
if (g < 0) continue;

if (sat->quality > UBLOX_SIG_QUALITY_SEARCHING && stats[g][0] < 255) { // Sat is visible
stats[g][0]++;
}

if (sat->quality >= UBLOX_SIG_QUALITY_CODE_LOCK_TIME_SYNC && stats[g][1] < 255) { // Sat is good enough for navigation
stats[g][1]++;
}
}

// Write directly to display using displayWriteChar so large symbol indices are handled correctly.
int x = elemPosX;
for (int g = 0; g < 4; ++g) {
uint8_t total = stats[g][0];
uint8_t good = stats[g][1];

// Hex nibble for total (cap at F)
char hexc;
if (total > 15) hexc = 'F';
else if (total < 10) hexc = '0' + total;
else hexc = 'A' + (total - 10);
displayWriteChar(osdDisplayPort, x++, elemPosY, (uint8_t)hexc);

// HUD signal icon based on number of good satellites (cap at 4)
uint8_t goodClamped = good > 4 ? 4 : good;
uint16_t sym = SYM_HUD_SIGNAL_0 + goodClamped;
displayWriteChar(osdDisplayPort, x++, elemPosY, sym);
}

// always show RF noise after the stats
{
uint8_t noise = gpsGetMonRfNoisePerMs();
char noiseBuff[4];
noiseBuff[0] = SYM_SNR;
tfp_sprintf(&noiseBuff[1], (noise > 99) ? "%02X" : "%02u", noise);
displayWrite(osdDisplayPort, x, elemPosY, noiseBuff);
}

return true; // already drawn
}
#ifdef USE_ADSB
case OSD_ADSB_WARNING:
{
Expand Down Expand Up @@ -4195,7 +4255,7 @@ uint8_t osdIncElementIndex(uint8_t elementIndex)

if (!feature(FEATURE_GPS)) {
if (elementIndex == OSD_GPS_HDOP || elementIndex == OSD_TRIP_DIST || elementIndex == OSD_3D_SPEED || elementIndex == OSD_MISSION ||
elementIndex == OSD_AZIMUTH || elementIndex == OSD_BATTERY_REMAINING_CAPACITY || elementIndex == OSD_EFFICIENCY_MAH_PER_KM) {
elementIndex == OSD_AZIMUTH || elementIndex == OSD_BATTERY_REMAINING_CAPACITY || elementIndex == OSD_EFFICIENCY_MAH_PER_KM || elementIndex == OSD_GPS_EXTRA_STATS ) {
elementIndex++;
}
if (elementIndex == OSD_HEADING_GRAPH && !sensors(SENSOR_MAG)) {
Expand Down Expand Up @@ -4454,7 +4514,8 @@ void pgResetFn_osdLayoutsConfig(osdLayoutsConfig_t *osdLayoutsConfig)

osdLayoutsConfig->item_pos[0][OSD_MISSION] = OSD_POS(0, 10);
osdLayoutsConfig->item_pos[0][OSD_GPS_SATS] = OSD_POS(0, 11) | OSD_VISIBLE_FLAG;
osdLayoutsConfig->item_pos[0][OSD_GPS_HDOP] = OSD_POS(0, 10);
osdLayoutsConfig->item_pos[0][OSD_GPS_HDOP] = OSD_POS(0, 10);
osdLayoutsConfig->item_pos[0][OSD_GPS_EXTRA_STATS] = OSD_POS(3, 11);

osdLayoutsConfig->item_pos[0][OSD_GPS_LAT] = OSD_POS(0, 12);
// Put this on top of the latitude, since it's very unlikely
Expand Down
1 change: 1 addition & 0 deletions src/main/io/osd.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ typedef enum {
OSD_NAV_FW_ALT_CONTROL_RESPONSE,
OSD_NAV_MIN_GROUND_SPEED,
OSD_THROTTLE_GAUGE,
OSD_GPS_EXTRA_STATS,
OSD_ITEM_COUNT // MUST BE LAST
} osd_items_e;

Expand Down