Skip to content

gps: configure u-blox F10 receivers with the signals they have - #11965

Open
MrScothh wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
MrScothh:fix/ublox-glonass-keys
Open

MrScothh wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
MrScothh:fix/ublox-glonass-keys

Conversation

@MrScothh

@MrScothh MrScothh commented Sep 17, 2026

Copy link
Copy Markdown

What happens

A u-blox F10 reports hwVersion 000A0000, the same string an M10 reports, so INAV correctly identifies it as protocol 27+ and configures it through CFG-VALSET. It then sends two things that receiver cannot accept.

Its configuration database has no Glonass group at all. The F10 interface description (UBX-23002975) shows the CFG-SIGNAL group jumping straight from CFG-SIGNAL-QZSS_ENA (0x10310024) to CFG-SIGNAL-NAVIC_ENA (0x10310026): key 0x10310025, which is CFG-SIGNAL-GLO_ENA on an M10, is not there, and neither is 0x10310018.

And its Beidou L1 signal is B1C, not B1I. configureGNSS10() picks B1I unless Glonass is on, which on an F10 both enables a signal it cannot receive and turns off the one it uses. The NEO-F10N integration manual is explicit about what happens then:

For constellations with dual-band support, it is not possible to disable one of the bands. Both bands must be enabled and disabled at once. [...] Unsupported combinations are rejected with a UBX-ACK-NAK message.

A CFG-VALSET is all or nothing, so either of those makes the receiver answer NAK and apply none of the message. SBAS, Galileo, BeiDou and QZSS go down with them, and INAV then resets gps_ublox_use_galileo, gps_ublox_use_beidou and gps_ublox_use_glonass to their defaults.

This is the whole F10 family: NEO-F10N, DAN-F10N and the boards built on them. What a real NEO-F10N answers to MON-VER:

swVersion  EXT SPGL1L5 6.00 (041e8a)
hwVersion  000A0000
           FWVER=SPGL1L5 6.00
           PROTVER=40.00
           MOD=NEO-F10N
           GPS;GAL;BDS
           SBAS;QZSS
           NAVIC

GPS;GAL;BDS, with no GLO, and SPGL1L5 for the dual band firmware.

The change

Both pieces of information are already on hand.

INAV polls UBX-MON-GNSS before the configuration starts and keeps the supported-constellation mask, and gpsUbloxHasGlonass() is already there. The two Glonass keys are last in the array, so leaving them out makes the message shorter rather than different. They are only dropped when the mask says so: an empty mask means MON-GNSS never answered, nothing is known, and every key goes out as before.

The MON-VER extensions are already being walked for the constellation list and the protocol version, so the same walk now notices L1L5 and the Beidou choice follows it.

Nothing changes for a receiver that reports Glonass, and the M8/M9 path through configureGNSS() is untouched.

Testing

SITL on Windows against an emulated u-blox that answers MON-VER and MON-GNSS and streams NAV-PVT. The F10 emulator applies its manual's rules and NAKs the message if it sees a Glonass key, B1I enabled, or B1C turned off while B2a is on. What reaches the receiver in the constellation VALSET:

emulated receiver keys Glonass keys Beidou L1 NAK fix
M10 12 2 B1I 0 3D
M10, gps_ublox_use_glonass = ON 12 2 B1C 0 3D
F10 10 0 B1C 0 3D
F10, gps_ublox_use_glonass = ON 10 0 B1C 0 3D

Before the change the two F10 cases were rejected, the first for both reasons and the second for the Glonass keys alone, and no part of the constellation configuration reached the receiver. The two M10 cases are byte for byte what they were.

Also checked, because the capability state outlives a protocol restart: an M10 that goes quiet long enough for the state machine to restart, then comes back with its MON-GNSS reply lost, still gets all 12 keys, exactly as it does on maintenance-10.x.

Not tested on hardware yet. The F10 emulator follows the published rules, but a real NEO-F10N would be worth a check.

@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Avoid unsupported GLONASS keys on u-blox F10 receivers

🐞 Bug fix 🕐 Less than 10 minutes

Grey Divider

AI Description

• Omits Glonass CFG-VALSET keys when MON-GNSS confirms Glonass is unavailable.
• Preserves existing configuration when capabilities are unknown or Glonass is supported.
• Prevents F10 receivers rejecting unrelated SBAS, Galileo, BeiDou, and QZSS settings.
Diagram

graph TD
    A["MON-GNSS Poll"] --> B["Capability Mask"] --> C{"Glonass known absent?"}
    C -- Yes --> D["10-key VALSET"] --> F["Receiver Config"]
    C -- No --> E["12-key VALSET"] --> F
Loading
High-Level Assessment

The chosen approach is optimal: it reuses the authoritative MON-GNSS capability response and safely truncates trailing Glonass entries without duplicating payload definitions. Detecting F10 models from version strings would be more brittle, while always omitting Glonass would regress supported M10 receivers.

Files changed (1) +7 / -2

Bug fix (1) +7 / -2
gps_ublox.cExclude unsupported Glonass keys from CFG-VALSET +7/-2

Exclude unsupported Glonass keys from CFG-VALSET

• Checks the previously populated MON-GNSS capability state before configuring protocol 27+ receivers. When capabilities explicitly report no Glonass support, the payload omits the final two Glonass keys; otherwise, the existing 12-key behavior remains unchanged.

src/main/io/gps_ublox.c

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 17, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Receiver restarts skip Glonass setup ✓ Resolved 🐞 Bug ≡ Correctness
Description
noGlonass treats a nonzero capMaxGnss as proof of a current capability response, but the
initialization path clears supported without clearing the previously cached capMaxGnss. After
communication loss restarts the protocol, the capability wait therefore completes immediately with
an empty support mask and configureGNSS10() omits both Glonass keys from a Glonass-capable
receiver.
Code

src/main/io/gps_ublox.c[478]

+        const bool noGlonass = (gpsUbloxMaxGnss() != 0) && !gpsUbloxHasGlonass();
Evidence
The protocol initialization clears only supported, enabledGnss, and defaultGnss, while its
wait condition uses capMaxGnss; gpsRestartUBLOX() reruns this initialization after the GPS state
machine detects lost communication. Since the added predicate combines the stale nonzero maximum
with the newly cleared support mask, it evaluates noGlonass as true before the fresh MON-GNSS
reply is processed.

src/main/io/gps_ublox.c[1269-1277]
src/main/io/gps_ublox.c[1319-1331]
src/main/io/gps.c[591-617]
src/main/io/gps_ublox.c[178-181]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Glonass-key decision can consume mismatched capability state after a GPS protocol restart because `supported` is cleared while `capMaxGnss` remains nonzero from the previous session. This makes configuration proceed before the new MON-GNSS response and incorrectly classify the receiver as lacking Glonass.
## Fix Focus Areas
- src/main/io/gps_ublox.c[1269-1277]
- src/main/io/gps_ublox.c[478-480]
## Recommended Fix
Reset `ubx_capabilities.capMaxGnss` alongside the three capability masks before polling MON-GNSS. This restores the intended wait for a fresh response while retaining the existing fallback that sends all keys if polling exhausts its retries.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/main/io/gps_ublox.c Outdated
@MrScothh
MrScothh force-pushed the fix/ublox-glonass-keys branch from cc20741 to 42e8c23 Compare September 17, 2026 21:19
@MrScothh

Copy link
Copy Markdown
Author

Good catch, and it reproduces.

Measured in SITL with an emulated M10 that answers everything, then goes silent long enough for the protocol to restart, then comes back but loses the one MON-GNSS reply. The constellation VALSET that reaches the receiver after the restart:

build keys of which Glonass
maintenance-10.x 12 2
this PR as first pushed 10 0

So the report is right. capMaxGnss survives the restart while the masks are cleared, the wait passes on the stale value, and the predicate then read an empty mask as "no Glonass".

I did not take the suggested fix, though. Clearing capMaxGnss with the masks does remove the mismatch, but it also changes what happens when that reply goes missing: the wait times out and the state machine restarts instead of configuring. Same scenario, measured:

build keys of which Glonass
this PR with capMaxGnss cleared 0, no constellation VALSET at all 0

That trades one regression for a worse one.

The decision now reads the support mask directly, which is cleared in the same place the other masks are:

const bool noGlonass = ubx_capabilities.supported && !gpsUbloxHasGlonass();

An empty mask means MON-GNSS never answered, so nothing is known and every key goes out, exactly as before this PR. No new state, no change to the wait, no change in timing.

After the change:

scenario keys of which Glonass
M10, MON-GNSS answers 12 2
F10, MON-GNSS without Glonass 10 0
F10 with gps_ublox_use_glonass = ON 10 0
restart, MON-GNSS answers 12 2
restart, MON-GNSS reply lost 12 2

Branch force pushed.

An F10 reports the M10 hardware version, so INAV takes the CFG-VALSET path
for it, and then sends two things it cannot accept. Its configuration
database has no Glonass group at all, and its Beidou L1 signal is B1C, not
the B1I that INAV picks by default. Either one makes the receiver reject the
whole message, so SBAS, Galileo, BeiDou and QZSS never get applied.

UBX-MON-GNSS is already polled before the configuration starts and reports
which constellations the receiver has, so leave the Glonass keys out when it
says there are none. An empty mask means MON-GNSS never answered, and then
nothing is known, so every key goes out as before.

The dual band receivers name themselves in the MON-VER extensions, which are
already being read for the constellation list, so pick B1C there. It is what
they have, and their two bands cannot be configured apart.
@MrScothh
MrScothh force-pushed the fix/ublox-glonass-keys branch from 42e8c23 to e8f77e1 Compare September 17, 2026 21:39
@MrScothh MrScothh changed the title gps: do not send Glonass keys to a receiver that has none gps: configure u-blox F10 receivers with the signals they have Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant