gps: fall back to generic NMEA when vendor probes go unanswered - #11407
gps: fall back to generic NMEA when vendor probes go unanswered#11407suteny0r wants to merge 2 commits into
Conversation
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).
📝 WalkthroughWalkthroughAdds 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. ChangesGAT562 Mesh Tracker Pro board support
Generic NMEA GNSS detection
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
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
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. Comment |
|
Closing: this PR was mis-targeted. My upstream is mtoolstec/mt-firmware, not meshtastic/firmware. Reopening against the correct repository. |
@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. Welcome to the team 😄 |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (5)
variants/nrf52840/gat562_mesh_tracker_pro/variant.h (2)
277-279: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReplace 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 valueStale 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 RAK4630if 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 winAlign the GAT562 Mesh Tracker Pro build settings.
Set
board_check = trueso CI includes this environment in board-check builds. Add-DRADIOLIB_EXCLUDE_LR2021=1because the variant uses only SX1262. Remove the unused-D GAT562_MESH_TRACKER_PROdefinition.🤖 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 winYield when the UART has no data.
When
_serial_gps->available()is false, this loop spins until the timeout. Add a shortdelay(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 winKeep 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
📒 Files selected for processing (6)
boards/gat562_mesh_tracker_pro.jsonsrc/gps/GPS.cppsrc/gps/GPS.hvariants/nrf52840/gat562_mesh_tracker_pro/platformio.inivariants/nrf52840/gat562_mesh_tracker_pro/variant.cppvariants/nrf52840/gat562_mesh_tracker_pro/variant.h
| // How long to listen for a streaming NMEA GNSS before giving up on the current baud rate | ||
| #define GPS_NMEA_PROBE_TIMEOUT_MS 500 |
There was a problem hiding this comment.
🎯 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.cppRepository: 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 --shortRepository: 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:
- 1: https://files.waveshare.com/upload/d/dd/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf
- 2: https://www.waveshare.com/wiki/L76K_GPS_Module
- 3: https://download.kamami.pl/p1195711-Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf
- 4: https://forums.quectel.com/uploads/short-url/kmb3zNuV2SldThkOOJoNg9th40S.pdf
- 5: https://download.kamami.pl/p1195711-Quectel_L76K_GNSS_%E5%8D%8F%E8%AE%AE%E8%A7%84%E8%8C%83_V1.0.pdf
- 6: https://raw.githubusercontent.com/Seeed-Projects/Seeed_L76K-GNSS_for_XIAO/fb74b715224e0ac153c3884e578ee8e024ed8946/docs/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf
🏁 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}")
PYRepository: 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.
| 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; |
There was a problem hiding this comment.
🎯 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.
| 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.
| 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; | ||
| } |
There was a problem hiding this comment.
🎯 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 --statRepository: 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:
- 1: https://files.waveshare.com/upload/d/dd/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf
- 2: https://forums.quectel.com/uploads/short-url/kmb3zNuV2SldThkOOJoNg9th40S.pdf
- 3: https://download.kamami.pl/p1195711-Quectel_L76K_GNSS_%E5%8D%8F%E8%AE%AE%E8%A7%84%E8%8C%83_V1.0.pdf
- 4: https://www.scribd.com/document/686588266/Quectel-L76K-L26K-GNSS-%E5%8D%8F%E8%AE%AE%E8%A7%84%E8%8C%83-V1-2
- 5: https://www.waveshare.com/wiki/L76K_GPS_Module
🏁 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.cppRepository: 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.
| // 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 |
There was a problem hiding this comment.
🩺 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 andEXTERNAL_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 thatinitVariant()no longer sets QSPI-owned pins toINPUT_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.
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
GNSS_MODEL_GENERIC_NMEA.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, returnGNSS_MODEL_GENERIC_NMEAfor that baud rate instead ofGNSS_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 Modulepath).Verification
Device serial log (
gat562_mesh_tracker_pro,2.7.23.b2bda3b):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:
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
$PCAS06and 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