Skip to content

gps: fall back to generic NMEA when vendor probes go unanswered - #11407

Closed
suteny0r wants to merge 2 commits into
meshtastic:developfrom
suteny0r:gps-generic-nmea-fallback
Closed

gps: fall back to generic NMEA when vendor probes go unanswered#11407
suteny0r wants to merge 2 commits into
meshtastic:developfrom
suteny0r:gps-generic-nmea-fallback

Conversation

@suteny0r

@suteny0r suteny0r commented Aug 11, 2026

Copy link
Copy Markdown

Summary

GPS fix: when the GNSS probe fails to get a vendor-specific response but a valid NMEA stream is arriving on the GPS UART, select a new generic-NMEA driver instead of concluding "no GPS".

Problem

Some GNSS modules auto-stream standard NMEA but never answer chip-specific probe commands. The GAT562 Mesh Tracker Pro's L76K (CASIC-family) module is one such case: it runs in its default 9600 baud multi-GNSS (GPS + BeiDou) mode and streams $GNGGA / $GNRMC / $GPGSV, but it does not reply to any of the vendor probes Meshtastic sends ($PUBX, $PMTK605, $PCAS06, $PQTMVERNO, $PDTINFO, $PAIR021, UBX config, ...).

GPS::probe() / GPS::setup() interpret the silence as "no GNSS present", so the module's NMEA is never fed to the TinyGPS++ parser and no positions ever reach the mesh.

Fix

  • Add GNSS_MODEL_GENERIC_NMEA.
  • In GPS::probe(), at the end of each baud-rate attempt where no chip responded to any probe command, listen for a short window (500 ms) for known NMEA sentence types (GGA, RMC, GSV, GSA, VTG, GLL, ZDA). If a stream is detected, return GNSS_MODEL_GENERIC_NMEA for that baud rate instead of GNSS_MODEL_UNKNOWN.
  • GPS::setup() sends no chip-specific init for the generic driver (u-blox / MTK / L76K / Airoha / ATGM / Unicore configuration is all skipped) and feeds the streaming sentences straight to the standard TinyGPS++ parser.

The check only fires when a known NMEA stream is actually present, so true "no GPS" devices are unaffected (they still fall through to the existing No GNSS Module path).

Verification

Device serial log (gat562_mesh_tracker_pro, 2.7.23.b2bda3b):

[GPS] Trying $PDTINFO (Unicore Family)...
[GPS] Trying $PCAS06,1*1A (ATGM33xx Family)...
[GPS] Trying $PAIR021*39 (Airoha Family)...
[GPS] Trying $PQTMVERNO*58 (LC86)...
[GPS] Trying $PCAS06,0*1B (L76K)...
[GPS] Trying $PMTK605*31 (MTK Family)...
[GPS] GNSS: no probe response, but NMEA stream detected at 9600 baud - using generic NMEA driver
[GPS] GNSS: using generic NMEA stream, skipping chip-specific init
[GPS] NMEA GPS time set ...

The NMEA stream is parsed (time source acquired from GPS); a position fix then depends on normal cold-start satellite acquisition.

Should be pushed upstream to Meshtastic

This fix belongs in upstream Meshtastic, not just the GAT562 fork. It likely benefits other hardware:

  • Any GNSS module that streams NMEA but ignores vendor probe commands.
  • Boards with one-way UART wiring (MCU RX to GNSS TX only), where probe commands can never reach the module but NMEA still arrives.
  • Modules running in generic NMEA mode where a vendor driver was never selected.

The fallback is conservative (only activates on a confirmed NMEA stream) and requires no config or wiring changes.

Question for the board manufacturer (GAT / gat-iot.com)

On the GAT562 Mesh Tracker Pro, is the MCU's GPS TX (GPIO16 / P0.16) actually wired to the L76K module's UART RX input?

The probe phase transmits $PCAS06 and every other vendor probe command, and none get a reply while NMEA continues to stream in. That is exactly the behavior expected if the MCU-to-L76K TX path is omitted on the PCB (one-way UART: the L76K talks, but the MCU cannot send to it). If the TX line is absent, this generic-NMEA fallback is required (and is the only way) to obtain positions from this board.

Summary by CodeRabbit

  • New Features
    • Added support for the GAT562 Mesh Tracker Pro board, including display, LoRa, GPS, battery monitoring, USB, power, and trackball features.
    • Added automatic detection for GNSS modules that provide standard NMEA data without vendor-specific responses.
    • Generic NMEA-compatible receivers can now initialize without chip-specific configuration.

Some GNSS modules (e.g. the GAT562's L76K in its default 9600 multi-GNSS mode) auto-stream standard NMEA but never answer chip-specific probe commands. The GNSS detection previously concluded 'no GPS' and never fed the module's NMEA to the position parser.

At the end of each baud-rate attempt where no chip responded to any probe command, listen briefly for known NMEA sentence types (GGA/RMC/GSV/GSA/VTG/GLL/ZDA). If a stream is present, select the new GNSS_MODEL_GENERIC_NMEA driver, which skips all chip-specific init and just runs the standard TinyGPS++ parser.
Adds the GAT562 Mesh Tracker Pro board definition and variant: nRF52840, SX1262, SSD1306 OLED, trackball input, L76K GNSS on Serial1 (9600 baud).
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds GAT562 Mesh Tracker Pro board support for nRF52840 hardware. Extends GNSS probing to detect generic NMEA streams and bypass chip-specific setup for those devices.

Changes

GAT562 Mesh Tracker Pro board support

Layer / File(s) Summary
Board hardware contract
variants/nrf52840/gat562_mesh_tracker_pro/variant.h, variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp
Defines board metadata, pin mappings, peripherals, radio, GPS, power, battery, display, flash, and trackball settings. Startup configures LEDs, 3V3 power, and trackball inputs.
PlatformIO and board build integration
boards/gat562_mesh_tracker_pro.json, variants/nrf52840/gat562_mesh_tracker_pro/platformio.ini
Adds nRF52840 board metadata and the PlatformIO environment, including build flags, source paths, upload settings, and library configuration.

Generic NMEA GNSS detection

Layer / File(s) Summary
Generic NMEA model and stream probe
src/gps/GPS.h, src/gps/GPS.cpp
Adds GNSS_MODEL_GENERIC_NMEA and probes for known NMEA sentences after vendor-specific probes fail.
Generic NMEA setup handling
src/gps/GPS.cpp
Logs generic NMEA detection and skips chip-specific GNSS initialization.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GPS
  participant GNSSSerial
  participant GNSSModule
  GPS->>GNSSSerial: send vendor-specific probe
  GNSSModule-->>GNSSSerial: no supported probe response
  GPS->>GNSSSerial: read NMEA stream
  GNSSModule-->>GNSSSerial: return known NMEA sentence
  GPS-->>GPS: select GNSS_MODEL_GENERIC_NMEA
  GPS-->>GPS: skip chip-specific initialization
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary GPS change: generic NMEA fallback after vendor probes fail.
Description check ✅ Passed The description clearly explains the problem, implementation, affected hardware, verification, and upstream rationale; it omits the template attestation checklist.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch gps-generic-nmea-fallback
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@suteny0r

Copy link
Copy Markdown
Author

Closing: this PR was mis-targeted. My upstream is mtoolstec/mt-firmware, not meshtastic/firmware. Reopening against the correct repository.

@suteny0r suteny0r closed this Aug 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@suteny0r, Welcome to Meshtastic!

Thanks for opening your first pull request. We really appreciate it.

We discuss work as a team in discord, please join us in the #firmware channel.
There's a big backlog of patches at the moment. If you have time,
please help us with some code review and testing of other PRs!

Welcome to the team 😄

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
variants/nrf52840/gat562_mesh_tracker_pro/variant.h (2)

277-279: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the corrupted banner characters.

Lines 277 and 279 contain ? sequences from a broken character encoding. Use plain ASCII, or a short one-line comment.

✏️ Proposed cleanup
-// ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-//  Trackball Configuration
-// ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
+// Trackball configuration
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/nrf52840/gat562_mesh_tracker_pro/variant.h` around lines 277 - 279,
Replace the corrupted question-mark banner surrounding the “Trackball
Configuration” comment with plain ASCII banner characters or a concise one-line
comment, while preserving the existing section label.

22-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale RAK-specific comments describe a different board.

The file keeps RAK5005-O and RAK1910 documentation blocks copied from the RAK4631 variant. Line 22 also references LED pin 2, which does not match PIN_LED1 (35). Remove the blocks that do not apply to the GAT562 Mesh Tracker Pro. Keep #define RAK4630 if the module is a RAK4630 core, and add one line that states this.

As per coding guidelines, "Keep code comments minimal—one or two lines maximum—and comment only when the reason is not obvious".

Also applies to: 165-178, 231-244

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/nrf52840/gat562_mesh_tracker_pro/variant.h` around lines 22 - 23,
Clean up the board documentation comments in variant.h by removing the stale
RAK5005-O, RAK1910, and incorrect LED pin references, including the blocks
around the noted ranges. Retain `#define` RAK4630 and add a single concise comment
stating that this board uses a RAK4630 core.

Source: Coding guidelines

variants/nrf52840/gat562_mesh_tracker_pro/platformio.ini (1)

4-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align the GAT562 Mesh Tracker Pro build settings.

Set board_check = true so CI includes this environment in board-check builds. Add -DRADIOLIB_EXCLUDE_LR2021=1 because the variant uses only SX1262. Remove the unused -D GAT562_MESH_TRACKER_PRO definition.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/nrf52840/gat562_mesh_tracker_pro/platformio.ini` around lines 4 -
13, Update the GAT562 Mesh Tracker Pro environment settings by adding
board_check = true, adding the -DRADIOLIB_EXCLUDE_LR2021=1 build flag, and
removing the unused -D GAT562_MESH_TRACKER_PRO definition while preserving the
existing SX1262-related exclusions.
src/gps/GPS.cpp (2)

1576-1591: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Yield when the UART has no data.

When _serial_gps->available() is false, this loop spins until the timeout. Add a short delay(1) or use the project's non-blocking scheduling pattern in the no-data path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gps/GPS.cpp` around lines 1576 - 1591, Update the loop around
_serial_gps->available() to yield when no UART data is available by adding the
project’s short non-blocking delay in the false branch, while preserving the
existing sentence parsing and timeout behavior.

832-834: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the new comments within two lines.

Both blocks use three comment lines. Condense each block to one or two lines. Keep only the reason that is not obvious from the code.

As per coding guidelines: keep code comments minimal—normally one or two lines—and comment only when the reason is not obvious.

Also applies to: 1567-1569

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gps/GPS.cpp` around lines 832 - 834, Condense the explanatory comment
near the GPS auto-streaming setup and the corresponding block near the second
occurrence to no more than two lines each. Retain only the non-obvious reason—no
chip-specific initialization is needed because the module streams NMEA directly
to TinyGPS++—and remove redundant device or mode details.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/gps/GPS.cpp`:
- Around line 79-85: Update isKnownNMEASentence so it accepts the supported BD
and QZ talker prefixes in addition to G, while preserving the existing
sentence-type checks for RMC, GGA, GSV, GSA, VTG, GLL, and ZDA.
- Around line 1410-1415: Update the GPS detection flow around probeForNMEA() so
generic NMEA detection occurs before the L76K all-zero $PCAS03 command can
disable NMEA output, or restore NMEA output before each generic probe. Preserve
the existing GNSS_MODEL_GENERIC_NMEA return path and apply the fix to both
probeForNMEA() call sites.
- Around line 74-75: Update the GPS_NMEA_PROBE_TIMEOUT_MS constant in GPS.cpp to
a value greater than 1000 ms, ensuring the GNSS probe waits through at least one
complete 1 Hz NMEA sentence interval before reporting no module.

In `@variants/nrf52840/gat562_mesh_tracker_pro/variant.h`:
- Around line 283-290: The trackball pin map overlaps QSPI flash pins while
external flash is enabled. In
variants/nrf52840/gat562_mesh_tracker_pro/variant.h:283-290, assign TB_LEFT,
TB_UP, and TB_PRESS to non-QSPI pins, or remove the QSPI and EXTERNAL_FLASH_*
definitions if the board has no external flash; in
variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp:46-53, verify
initVariant() no longer configures QSPI-owned pins as INPUT_PULLUP after the map
is corrected.

---

Nitpick comments:
In `@src/gps/GPS.cpp`:
- Around line 1576-1591: Update the loop around _serial_gps->available() to
yield when no UART data is available by adding the project’s short non-blocking
delay in the false branch, while preserving the existing sentence parsing and
timeout behavior.
- Around line 832-834: Condense the explanatory comment near the GPS
auto-streaming setup and the corresponding block near the second occurrence to
no more than two lines each. Retain only the non-obvious reason—no chip-specific
initialization is needed because the module streams NMEA directly to
TinyGPS++—and remove redundant device or mode details.

In `@variants/nrf52840/gat562_mesh_tracker_pro/platformio.ini`:
- Around line 4-13: Update the GAT562 Mesh Tracker Pro environment settings by
adding board_check = true, adding the -DRADIOLIB_EXCLUDE_LR2021=1 build flag,
and removing the unused -D GAT562_MESH_TRACKER_PRO definition while preserving
the existing SX1262-related exclusions.

In `@variants/nrf52840/gat562_mesh_tracker_pro/variant.h`:
- Around line 277-279: Replace the corrupted question-mark banner surrounding
the “Trackball Configuration” comment with plain ASCII banner characters or a
concise one-line comment, while preserving the existing section label.
- Around line 22-23: Clean up the board documentation comments in variant.h by
removing the stale RAK5005-O, RAK1910, and incorrect LED pin references,
including the blocks around the noted ranges. Retain `#define` RAK4630 and add a
single concise comment stating that this board uses a RAK4630 core.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e3de8471-5f32-4a74-8643-cec564c1c4c7

📥 Commits

Reviewing files that changed from the base of the PR and between c6a2081 and d1dcba5.

📒 Files selected for processing (6)
  • boards/gat562_mesh_tracker_pro.json
  • src/gps/GPS.cpp
  • src/gps/GPS.h
  • variants/nrf52840/gat562_mesh_tracker_pro/platformio.ini
  • variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp
  • variants/nrf52840/gat562_mesh_tracker_pro/variant.h

Comment thread src/gps/GPS.cpp
Comment on lines +74 to +75
// How long to listen for a streaming NMEA GNSS before giving up on the current baud rate
#define GPS_NMEA_PROBE_TIMEOUT_MS 500

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- file locations ---'
fd -i 'GPS.cpp|GPS.h|.*L76.*|.*gps.*' src
printf '%s\n' '--- symbol locations ---'
rg -n -C 8 'GPS_NMEA_PROBE_TIMEOUT_MS|probeForNMEA|isKnownNMEASentence|No GNSS Module|PCAS03|NMEA' src/gps/GPS.cpp src/gps 2>/dev/null || true
printf '%s\n' '--- focused source ---'
sed -n '50,95p' src/gps/GPS.cpp
sed -n '780,860p' src/gps/GPS.cpp
sed -n '1360,1435p' src/gps/GPS.cpp
sed -n '1470,1525p' src/gps/GPS.cpp
sed -n '1535,1610p' src/gps/GPS.cpp

Repository: meshtastic/firmware

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- probe state machine ---'
sed -n '1240,1520p' src/gps/GPS.cpp
printf '%s\n' '--- probe helpers and timing primitives ---'
sed -n '1515,1600p' src/gps/GPS.cpp
rg -n -C 4 'currentStep|probe\(|GNSS_MODEL_GENERIC_NMEA|serialSpeed' src/gps/GPS.cpp src/gps/GPS.h | head -220
printf '%s\n' '--- relevant history summary ---'
git diff --stat
git status --short

Repository: meshtastic/firmware

Length of output: 30262


🌐 Web query:

Quectel L76K protocol specification NMEA output interval 1 Hz PCAS03

💡 Result:

In the Quectel L76K GNSS module, the NMEA output interval (positioning frequency) is configured using the PCAS02 command, not PCAS03 [1][2]. The PCAS03 command is specifically used to configure the output type and frequency (rate) of individual NMEA sentences [1][3]. PCAS02 Command (Positioning Frequency) To set the positioning frequency, use the $PCAS02 command [2]. The interval is specified in milliseconds [1]: - 1000 = 1 Hz - 500 = 2 Hz - 200 = 5 Hz Example: To set the positioning frequency to 1 Hz, use $PCAS02,1000*XX (where XX is the checksum). PCAS03 Command (NMEA Sentence Output) The PCAS03 command configures which NMEA sentences are output and how often (every Nth fix) they appear [1][4]. Its format is: $PCAS03,,,,,,,,,,,,,,*CS Parameters for PCAS03: - through : Define the output frequency for each sentence type. Setting these to 1 means outputting the sentence every fix; 0 means no output [1][5]. - Values 1–9 indicate the sentence will be output once every N position fixes [1][4]. - Leaving a field blank (null) keeps the previous configuration [1][3]. Note: When setting a positioning frequency higher than 1 Hz (i.e., interval < 1000), it is recommended to increase the serial baud rate to 115200 bps to ensure stable data transmission [6].

Citations:


🏁 Script executed:

#!/bin/bash
set -e
python3 - <<'PY'
# Read-only timing model for probeForNMEA's [start, start + timeout)
interval_ms = 1000
timeouts = (500, 1000, 1001, 1100)
phases = (0, 100, 499, 500, 750, 999, 1000)

for timeout in timeouts:
    misses = []
    for phase in phases:
        # A sentence starts at phase and then every interval. The probe starts at t=0.
        detected = any(0 <= phase + n * interval_ms < timeout for n in range(-2, 4))
        if not detected:
            misses.append(phase)
    print(f"timeout={timeout}ms; missed phases={misses}")

# A phase just after the half-second window demonstrates the 500 ms failure.
phase = 750
timeout = 500
print(f"example: first sentence at {phase}ms, detected={phase < timeout}")
PY

Repository: meshtastic/firmware

Length of output: 350


Wait for at least one complete NMEA interval. When the L76K emits sentences at 1 Hz, a 500 ms window can expire before the next sentence arrives, causing the No GNSS Module path. Set GPS_NMEA_PROBE_TIMEOUT_MS above 1000 ms.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gps/GPS.cpp` around lines 74 - 75, Update the GPS_NMEA_PROBE_TIMEOUT_MS
constant in GPS.cpp to a value greater than 1000 ms, ensuring the GNSS probe
waits through at least one complete 1 Hz NMEA sentence interval before reporting
no module.

Comment thread src/gps/GPS.cpp
Comment on lines +79 to +85
static bool isKnownNMEASentence(const char *id)
{
if (id[0] != 'G')
return false;
return strncmp(id + 2, "RMC", 3) == 0 || strncmp(id + 2, "GGA", 3) == 0 || strncmp(id + 2, "GSV", 3) == 0 ||
strncmp(id + 2, "GSA", 3) == 0 || strncmp(id + 2, "VTG", 3) == 0 || strncmp(id + 2, "GLL", 3) == 0 ||
strncmp(id + 2, "ZDA", 3) == 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Accept the non-G talker IDs listed by the helper.

isKnownNMEASentence() returns false when id[0] != 'G'. The comment lists BD and QZ as supported prefixes. Therefore $BDGGA and $QZRMC are ignored.

Proposed fix
-    if (id[0] != 'G')
+    const bool isKnownTalker = id[0] == 'G' || (id[0] == 'B' && id[1] == 'D') ||
+                                (id[0] == 'Q' && id[1] == 'Z');
+    if (!isKnownTalker)
         return false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static bool isKnownNMEASentence(const char *id)
{
if (id[0] != 'G')
return false;
return strncmp(id + 2, "RMC", 3) == 0 || strncmp(id + 2, "GGA", 3) == 0 || strncmp(id + 2, "GSV", 3) == 0 ||
strncmp(id + 2, "GSA", 3) == 0 || strncmp(id + 2, "VTG", 3) == 0 || strncmp(id + 2, "GLL", 3) == 0 ||
strncmp(id + 2, "ZDA", 3) == 0;
static bool isKnownNMEASentence(const char *id)
{
const bool isKnownTalker = id[0] == 'G' || (id[0] == 'B' && id[1] == 'D') ||
(id[0] == 'Q' && id[1] == 'Z');
if (!isKnownTalker)
return false;
return strncmp(id + 2, "RMC", 3) == 0 || strncmp(id + 2, "GGA", 3) == 0 || strncmp(id + 2, "GSV", 3) == 0 ||
strncmp(id + 2, "GSA", 3) == 0 || strncmp(id + 2, "VTG", 3) == 0 || strncmp(id + 2, "GLL", 3) == 0 ||
strncmp(id + 2, "ZDA", 3) == 0;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gps/GPS.cpp` around lines 79 - 85, Update isKnownNMEASentence so it
accepts the supported BD and QZ talker prefixes in addition to G, while
preserving the existing sentence-type checks for RMC, GGA, GSV, GSA, VTG, GLL,
and ZDA.

Comment thread src/gps/GPS.cpp
Comment on lines +1410 to +1415
if (probeForNMEA(GPS_NMEA_PROBE_TIMEOUT_MS)) {
LOG_INFO("GNSS: no probe response, but NMEA stream detected at %d baud - using generic NMEA driver",
serialSpeed);
currentStep = 0;
return GNSS_MODEL_GENERIC_NMEA;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- GPS.cpp relevant ranges ---'
sed -n '1280,1430p' src/gps/GPS.cpp
sed -n '1470,1610p' src/gps/GPS.cpp
printf '%s\n' '--- related declarations and constants ---'
rg -n -C 4 'GPS_NMEA_PROBE_TIMEOUT_MS|probeForNMEA|PCAS03|isKnownNMEASentence|GENERIC_NMEA|serialSpeed' src/gps/GPS.cpp src/gps
printf '%s\n' '--- repository status summary ---'
git diff --stat

Repository: meshtastic/firmware

Length of output: 36658


🌐 Web query:

Quectel L76K protocol specification PCAS03 output rate 0 no output

💡 Result:

According to the Quectel L76K GNSS Protocol Specification, the $PCAS03 command is used to configure the output type and frequency of NMEA sentences [1][2][3]. Regarding your query about the "0" output rate: - Setting a parameter to "0" for any NMEA sentence (GGA, GLL, GSA, GSV, RMC, VTG, ZDA, or ANT) in the $PCAS03 command explicitly disables the output of that specific sentence [1][4][3]. - If you set a field to "0", the module will no longer output the corresponding NMEA sentence [1][2]. - Leaving a field empty (e.g., $PCAS03,1,,,,,,,,,0,002) instead of providing a value generally indicates that the previous configuration for that specific sentence should be retained [1][4]. For example, if you send $PCAS03,0,0,0,0,0,0,0,0,0,0,,,,0,0xx, you would effectively disable all primary NMEA sentence outputs listed in the command structure [1][3]. If you are experiencing "no output" after configuring the device, verify that you have not inadvertently set all sentence frequencies to 0, or that you have not misconfigured the serial port baud rate using the $PCAS01 command [5]. If the module is not outputting any data at all, ensure the hardware connection is correct and check the baud rate settings, as the PCAS03 command only controls the NMEA sentence frequency, not the physical serial port transmission itself [5].

Citations:


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- probe call/state flow ---'
sed -n '500,545p' src/gps/GPS.cpp
sed -n '1385,1515p' src/gps/GPS.cpp
printf '%s\n' '--- PCAS03 references ---'
rg -n -C 3 '\$PCAS03|PCAS03' .
printf '%s\n' '--- NMEA predicate exact source ---'
sed -n '68,95p' src/gps/GPS.cpp

Repository: meshtastic/firmware

Length of output: 10022


Probe for generic NMEA before disabling output.

If a L76K accepts the all-zero $PCAS03 command at line 1332, it disables all NMEA sentences before probeForNMEA() runs at lines 1410 and 1504. Move generic detection before this command, or restore NMEA output before probing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gps/GPS.cpp` around lines 1410 - 1415, Update the GPS detection flow
around probeForNMEA() so generic NMEA detection occurs before the L76K all-zero
$PCAS03 command can disable NMEA output, or restore NMEA output before each
generic probe. Preserve the existing GNSS_MODEL_GENERIC_NMEA return path and
apply the fix to both probeForNMEA() call sites.

Comment on lines +283 to +290
// Trackball pins
#define HAS_TRACKBALL 1
#define TB_LEFT 30 // P0.30
#define TB_DOWN 4 // P0.04
#define TB_RIGHT 31 // P0.31
#define TB_UP 28 // P0.28
#define TB_PRESS 26 // P0.26 (SELECT)
#define TB_DIRECTION FALLING

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Trackball pins overlap the QSPI flash pins on this variant. The pin map assigns TB_LEFT (30), TB_UP (28), and TB_PRESS (26) to the same pins as PIN_QSPI_IO0, PIN_QSPI_IO2, and PIN_QSPI_CS, while EXTERNAL_FLASH_USE_QSPI is enabled. Boot-time pin configuration then drives these shared pins.

  • variants/nrf52840/gat562_mesh_tracker_pro/variant.h#L283-L290: correct the trackball pin numbers, or remove the QSPI and EXTERNAL_FLASH_* defines if the board has no external flash.
  • variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp#L46-L53: after the pin map is corrected, verify that initVariant() no longer sets QSPI-owned pins to INPUT_PULLUP.
📍 Affects 2 files
  • variants/nrf52840/gat562_mesh_tracker_pro/variant.h#L283-L290 (this comment)
  • variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp#L46-L53
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@variants/nrf52840/gat562_mesh_tracker_pro/variant.h` around lines 283 - 290,
The trackball pin map overlaps QSPI flash pins while external flash is enabled.
In variants/nrf52840/gat562_mesh_tracker_pro/variant.h:283-290, assign TB_LEFT,
TB_UP, and TB_PRESS to non-QSPI pins, or remove the QSPI and EXTERNAL_FLASH_*
definitions if the board has no external flash; in
variants/nrf52840/gat562_mesh_tracker_pro/variant.cpp:46-53, verify
initVariant() no longer configures QSPI-owned pins as INPUT_PULLUP after the map
is corrected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant