Skip to content

Sync upstream/dev d495d2ed (GPS rework #3753) - #55

Merged
marcelverdult merged 51 commits into
integrationfrom
claude/sync-upstream-dev-20261110-b58e97
Nov 10, 2026
Merged

marcelverdult merged 51 commits into
integrationfrom
claude/sync-upstream-dev-20261110-b58e97

Conversation

@marcelverdult

Copy link
Copy Markdown
Owner

Merges upstream/dev d495d2e (50 commits) into integration. It includes the GPS rework meshcore-dev#3753.

The merge had 41 conflicts. Upstream's GPS design is taken as it is. The fork keeps its command tables, shared prefs and shared radio setup. Every resolution is listed in docs/refactoring/sync-upstream-dev-20261110.md.

Checks:

  • All 28 native environments: 2447 test cases, 1 skipped, 0 failed.
  • 109 firmware environments build. On upstream/dev itself, Heltec_mesh_solar_companion_radio_ble fails to build.
  • Sizes against upstream/dev are in sync-build-sizes-20261110.tsv.

Not verified: no board run. GpsGuard and RakLocationProvider have no host test. 102 of the 211 environments were not built.

agessaman and others added 30 commits August 17, 2026 21:04
A RAK4631 core paired with a RAK13302 leaves the core's own SX1262
powered but never initialized, idling in STDBY_RC for the life of the
board. Firmware cannot cut its supply -- P1.05 is the RF switch rail,
not the radio's -- so bring it up on its own pins just long enough to
issue a cold sleep, before std_init() repins SPI onto the RAK13302.

Gated behind RAK4631_ONBOARD_SX1262_SLEEP and exposed through seven
RAK_4631_13302_* envs, so RAK_3401_* artifacts are unchanged.

The sleep is issued regardless of what begin() returns: Module::init()
runs first, so SPI stays usable even if TCXO calibration fails. NSS is
then held high, since the SX1262 wakes on an NSS falling edge.

Verified on RAK19007 + RAK4631 + RAK13302: begin=0 sleep=0, RAK13302
init clean (device_errors=0x0000), TX and RX both confirmed. The
current saving itself is derived from the datasheet (600 uA STDBY_RC
-> 160 nA cold sleep) and is not measured.
BUSY is driven low in STDBY_RC and high while asleep, so reading it either
side of the sleep gives a non-invasive readback of the state the chip was
found in and the state it was left in. Confirmed on hardware.

This is what makes the sleep observable at all. The only other symptom of
a failed sleep is ~600 uA, which is below what an inline USB meter can
resolve, so without this a regression would be silent.

It immediately earned itself: busy_before reads 0 on every boot, showing
the cold sleep does not survive an MCU reset. GPIOs revert to input during
reset, NSS stops being driven high, and the falling edge wakes the chip.
The helper re-sleeps it, so this is self-healing, but it means the chip is
never found already asleep.
Use the existing RAK3401 firmware roles for RAK4631 cores paired with a
RAK13302. Probe the optional onboard radio and put it into cold sleep
before handing SPI to the primary radio, removing seven duplicate build
environments.

Preserve BUSY startup readiness, release probe pulls before sleep, and
disconnect unused GPIO input buffers during cleanup. Add focused tests
for sequencing, missing signatures, timeouts, and failed sleep readback.

Validated with four native tests, seven firmware-role builds, and repeater
boot checks on RAK4631 + RAK13302. Supply current was not measured.
Move the onboard radio probe into RAK3401Board::begin() so a low-voltage
SYSTEMOFF at boot no longer leaves the RAK4631's onboard SX1262 in
standby. Add board startup tests and run them in CI.
Adds WioTrackerL1Eink_repeater, based on the OLED WioTrackerL1_repeater
env but using the E-Ink base config and GxEPDDisplay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uhHFHwrigVgmzkD9GFAfA
Add a board variant for the DFRobot DFR1195 (ESP32-S3-WROOM-1-N4, SX1262, 80x160 ST7735S) and a Companion BLE environment. The display and radio use separate SPI controllers: the SX1262 is on FSPI and the ST7735 is on HSPI. ST7735Display selects that HSPI bus and the 160x80 init sequence only when DFROBOT_LORAWAN_ESP32S3 is defined.
Compile out code when the corresponding macro defines are missing.
Failing builds: comp_radio_usb, repeatr, room_svr,
terminal_chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use GxEPD2's busy callback to run the mesh, interface and sensor loops
(loopCore(), shared with loop()) while the panel refreshes, instead of
blocking the main loop. Covers the partial refresh in endFrame(), the
full wipe in startFrame(), and the sleep icon / blank refresh on turnOff().
Only builds that define EINK_REFRESH_LOOP install the busy hook; for now
the T-Echo companion BLE/USB envs.
The room server gated its filesystem paths on NRF52_PLATFORM only, so an
STM32 build fell through to the ESP32 branch and failed to compile:

  MyMesh.cpp:147: no matching function for call to
    'Adafruit_LittleFS::open(const char*&, const char [2], bool)'
  main.cpp:69:   'store' was not declared in this scope

STM32 uses the same InternalFS / Adafruit_LittleFS API as nRF52, including
append semantics (FILE_O_WRITE opens LFS_O_RDWR|LFS_O_CREAT and then seeks
to the end), so the nRF52 branch is already correct for it. Add
STM32_PLATFORM alongside NRF52_PLATFORM in the four remaining gates;
saveIdentity() already did this.

This unblocks the room_server example on the existing STM32WL boards
(wio-e5-mini, wio-e5-dev, rak3x72, tiny_relay) as well as new ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds repeater, room_server, companion_radio_usb and kiss_modem
environments for the NUCLEO-WL55JC1 (STM32WL55JC, integrated SubGHz radio).

Notes on the board setup:

- Uses the upstream nucleo_wl55jc board. PlatformIO's boards_remap maps it
  to the core's NUCLEO_WL55JC1 variant, so the LEDs, user buttons and the
  LPUART1 -> ST-LINK VCP serial mapping all come from the core rather than
  being redefined here.
- The RF switch table is built from the core's LORAWAN_RFSWITCH_* macros
  (SP3T front end on PC3/PC4/PC5) so it tracks upstream if those are ever
  revised. Both RFO_LP and RFO_HP are registered, so RadioLib selects HP
  above 14 dBm and LP below it.
- board_build.extra_flags pins the device to STM32WL55xx. The stock board
  manifest declares product_line STM32WL55xx but extra_flags -DSTM32WLE5xx;
  that only works because every #elif chain happens to test WL55xx first.
- The Nucleo's LD1..LD3 are driven active HIGH, so the TX LED hooks are
  inverted relative to STM32Board's active-LOW default.
- 32 KB reserved at the top of flash for LittleFS, as on the other
  STM32WL variants.

Verified on hardware: all four environments build; repeater and room_server
flash and run over ST-LINK; identity and prefs persist across reboot and
across a firmware swap; and GPIOC reads back the documented RX levels at
idle, confirming the front-end switch is driven correctly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds the new variant to the PR build matrix, next to the existing STM32
entry, so it is covered by CI going forward.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The refactor no longer calls Serial1.setPins() on nRF52, so Serial1 uses
PIN_SERIAL1_RX/TX directly. Those were swapped (the GPS transmits on
P0.20), so no data was received. Fix them and define PIN_GPS_TX/RX by the
gps module's side, as other variants do.

The ATGM336H keeps its NMEA output config across power cycles, and other
firmware may leave every sentence disabled. Re-enable GGA + RMC after each
power-up.
- more consistency with other cli commands
- new format for gps fix
- gps format accepts postfix (s/m/d/h)
- documentation
On a RAK19007 the RAK12501's supply is 3V3_S, switched by WB_IO2, so
gps off, periodic mode and shutdown left it powered. Pass WB_IO2 to the
NMEA driver as peripheralPower under GPS_RAIL_POWER_CONTROL, set by the
new RAK_4631_repeater_gps_power env. It is opt-in because the rail feeds
every slot module, and refused with ETHERNET_ENABLED (RAK13800).

The RAK12500 (I2C) driver keeps switching its own power pin, so this
only applies on the NMEA path.

RefCountedDigitalPin now sets OUTPUT on claim and release: WB_IO2 left
as an input (as probeRak12500() leaves it after a failed probe) keeps
3V3_S in its last state, so writing the latch alone did not cut it.

Measured with a KM003C, battery and panel out: gps off 40.5 -> 12.4 mA,
shutdown 29.7 -> 1.30 mA.
Repeaters, room servers and sensors already let the battery ADC multiplier be tuned with 'set adc.multiplier' (CommonCLI). The companion firmware had no equivalent, so a board whose divider differs from the build default (common on DIY ProMicro / Faketec boards) always reported a wrong battery voltage.

Adds the same command to the companion CLI. The value is stored in the companion prefs (comp.adc_mult, 0 = board default) and applied at startup via MainBoard::setAdcMultiplier().
AlexandrTyshchenko and others added 21 commits November 8, 2026 23:24
…TECT)

Bytes arriving on the UART does not mean the baud rate is right: at the
wrong rate the parser only sees garbage and never gets a fix. Modules
such as the M5Stack GROVE GPS now default to 115200, while boards
configure 9600.

With GPS_BAUD_AUTODETECT, detect() probes common GNSS rates, starting
with the configured one, and keeps the first one that yields an NMEA
sentence with a valid checksum. The rate is stored in the driver, so
later power cycles reopen the UART with it. Without the flag nothing
changes.

Ported from meshcore-dev#3729 onto the GpsDriver refactor.
A spoofed GPS signal can move a fixed node anywhere and set its clock to
any time; the clock only moves forward, so a time pushed into the future
breaks timestamps and replay protection until fixed by hand.

With GPS_GUARD, MicroNMEALocationProvider asks a GpsGuard before a fix is
stored as the last fix (satellites, HDOP, optional region box, fence
around the configured position, jump speed, N stable fixes) and before
GPS time is written to the clock (trusted fix current, not before the
build date, small steps once the clock is valid, drift-sized after the
first sync). Without a trusted fix no live position is reported.

CLI in CommonGpsPrefs: 'gps guard', 'gps guard accept', 'gps fence',
'gps ref'; CommonCLI keeps the reference on set lat/lon and gps setloc,
resets the time anchor on manual clock sets and adds 'time force'.

Ported from meshcore-dev#3736 onto the GpsDriver/LocationProvider refactor.
…tect-refactor

NmeaGpsDriver: optional UART baud rate detection from a per-board list
GPS: optional anti-spoofing guard for position and time (GPS_GUARD)
…companion-adc-multiplier

Companion: set/get adc.multiplier CLI command
Add variant for ST Nucleo-WL55JC1 (STM32WL55JC) 🤖🤖
…no-lora-build

Fix Generic_ESPNOW_* builds on boards without a LoRa radio
…eink-busy-hook-v2

companion: keep mesh/BLE running during e-ink refresh
…o-onboard-sleep

feat(rak3401): automatically sleep the RAK4631’s onboard SX1262 when paired with a RAK13302
Add DFRobot LoRaWAN ESP32-S3 Companion BLE firmware
…-repeater

Add repeater environment for Wio Tracker L1 E-Ink
Takes upstream's GPS rework (meshcore-dev#3753) over the series' GPS prefs variants,
keeps the command tables, shared prefs and shared radio setup.
Conflicts, test changes and measurements: docs/refactoring/sync-upstream-dev-20261110.md
@marcelverdult
marcelverdult merged commit 6940258 into integration Nov 10, 2026
1 check passed
marcelverdult added a commit that referenced this pull request Nov 10, 2026
…261110b-b58e97

Sync upstream/dev b8ae75d (follow-up to #55)
@marcelverdult
marcelverdult deleted the claude/sync-upstream-dev-20261110-b58e97 branch November 10, 2026 17:40
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.