feat(lora+gps): Add components for gps, sx126x lora radio. Add preliminary meshtastic component (ai-generated), and update bsps to start testing - #678
Conversation
…eliminary meshtastic component (ai-generated), and update bsps to start testing
|
✅Static analysis result - no issues found! ✅ |
There was a problem hiding this comment.
Pull request overview
Adds a new “wireless” documentation section and introduces new gps, sx126x (LoRa radio), and preliminary meshtastic components, then wires LoRa/GPS support into the LilyGo T-Deck and M5Stack Cardputer-Adv BSPs and examples so they can be built/tested in CI.
Changes:
- Add new components:
gps(UART NMEA GNSS),sx126x(SX1261/2/LLCC68 LoRa driver),meshtastic(radio-agnostic Meshtastic-compatible node + example). - Update BSPs/examples (
t-deck,m5stack-cardputer) to initialize and demonstrate LoRa + GPS (plus shared-bus handling on the Cardputer Cap). - Update docs (new
doc/en/wireless/*) and CI/component publishing lists to include the new components and examples.
Reviewed changes
Copilot reviewed 68 out of 68 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| doc/en/wireless/index.rst | Introduces the “Wireless & Radio APIs” doc section and links new wireless component pages. |
| doc/en/wireless/sx126x.rst | Adds SX126x component documentation entry and API include hooks. |
| doc/en/wireless/gps.rst | Adds GPS component documentation entry and API include hooks. |
| doc/en/wireless/meshtastic.rst | Adds Meshtastic component documentation entry and API include hooks. |
| doc/en/index.rst | Adds the wireless docs section to the top-level docs index. |
| doc/Doxyfile | Adds new components’ headers/examples to Doxygen inputs/example paths. |
| components/sx126x/CMakeLists.txt | Registers the sx126x component build. |
| components/sx126x/include/sx126x.hpp | Defines the public SX126x driver API/types/config. |
| components/sx126x/src/sx126x.cpp | Implements the SX126x driver (SPI command layer + LoRa modem support). |
| components/sx126x/README.md | Adds SX126x component overview and feature list. |
| components/sx126x/idf_component.yml | Adds SX126x component manager metadata (deps/tags/docs link). |
| components/sx126x/example/CMakeLists.txt | Adds SX126x example project configuration. |
| components/sx126x/example/sdkconfig.defaults | Adds SX126x example default sdkconfig. |
| components/sx126x/example/README.md | Adds SX126x example usage documentation. |
| components/sx126x/example/main/CMakeLists.txt | Registers the SX126x example “main” component. |
| components/sx126x/example/main/Kconfig.projbuild | Adds SX126x example menuconfig options (hardware/pins/frequency/etc.). |
| components/sx126x/example/main/sx126x_example.cpp | Adds SX126x example app (bring-up + RX + periodic TX ping). |
| components/gps/CMakeLists.txt | Registers the gps component build. |
| components/gps/include/gps.hpp | Defines the UART-attached GPS driver public API. |
| components/gps/include/nmea_parser.hpp | Defines the platform-independent NMEA parser API. |
| components/gps/include/gps_fix.hpp | Defines the parsed fix struct and timestamp conversion helper. |
| components/gps/src/gps.cpp | Implements the UART driver + background read/parsing task. |
| components/gps/src/nmea_parser.cpp | Implements NMEA parsing/checksum and fix extraction. |
| components/gps/README.md | Adds GPS component overview and capabilities. |
| components/gps/idf_component.yml | Adds GPS component manager metadata (deps/tags/docs link). |
| components/gps/example/CMakeLists.txt | Adds GPS example project configuration. |
| components/gps/example/sdkconfig.defaults | Adds GPS example default sdkconfig. |
| components/gps/example/README.md | Adds GPS example usage documentation. |
| components/gps/example/main/CMakeLists.txt | Registers the GPS example “main” component. |
| components/gps/example/main/Kconfig.projbuild | Adds GPS example menuconfig options (hardware/pins/baud). |
| components/gps/example/main/gps_example.cpp | Adds GPS example app (print fixes). |
| components/meshtastic/CMakeLists.txt | Registers the meshtastic component build. |
| components/meshtastic/include/meshtastic.hpp | Defines MeshtasticNode public API/config/callbacks. |
| components/meshtastic/include/meshtastic_types.hpp | Adds protocol constants and message structs. |
| components/meshtastic/include/meshtastic_protocol.hpp | Declares channel hashing/modem config/header pack/unpack helpers. |
| components/meshtastic/include/meshtastic_crypto.hpp | Declares PSK expansion and AES-CTR payload crypt helpers. |
| components/meshtastic/include/meshtastic_protobuf.hpp | Declares minimal protobuf encode/decode helpers for used messages. |
| components/meshtastic/src/meshtastic.cpp | Implements node behavior (send/receive/dedup/rebroadcast). |
| components/meshtastic/src/meshtastic_protocol.cpp | Implements region/preset-based modem config + header pack/unpack + hashes. |
| components/meshtastic/src/meshtastic_crypto.cpp | Implements PSK expansion and AES-CTR crypt via mbedtls. |
| components/meshtastic/src/meshtastic_protobuf.cpp | Implements minimal protobuf wire-format encode/decode for required messages. |
| components/meshtastic/README.md | Adds Meshtastic component overview/scope/licensing notes. |
| components/meshtastic/idf_component.yml | Adds Meshtastic component manager metadata (deps/tags/docs link). |
| components/meshtastic/example/CMakeLists.txt | Adds Meshtastic example project configuration. |
| components/meshtastic/example/sdkconfig.defaults | Adds Meshtastic example default sdkconfig. |
| components/meshtastic/example/README.md | Adds Meshtastic example usage documentation. |
| components/meshtastic/example/main/CMakeLists.txt | Registers the Meshtastic example “main” component. |
| components/meshtastic/example/main/Kconfig.projbuild | Adds Meshtastic example menuconfig options (hardware/region/intervals/etc.). |
| components/meshtastic/example/main/meshtastic_example.cpp | Adds Meshtastic node example using BSP-provided SX1262 radio. |
| components/t-deck/CMakeLists.txt | Adds gps/sx126x to T-Deck component requirements. |
| components/t-deck/idf_component.yml | Adds gps/sx126x dependencies to the T-Deck component manifest. |
| components/t-deck/include/t-deck.hpp | Adds LoRa + GPS APIs/pins/state to the T-Deck BSP. |
| components/t-deck/src/lora.cpp | Implements T-Deck LoRa + GPS initialization. |
| components/t-deck/example/README.md | Updates T-Deck example docs to include LoRa demo behavior. |
| components/t-deck/example/main/t_deck_example.cpp | Adds LoRa tab/demo wiring and non-blocking TX dispatch via main loop. |
| components/t-deck/example/main/gui.hpp | Extends T-Deck example GUI API to support a LoRa tab and logging. |
| components/t-deck/example/main/gui.cpp | Implements the new LoRa tab UI and thread-safe message/status updates. |
| components/m5stack-cardputer/CMakeLists.txt | Adds gps/sx126x to Cardputer component requirements. |
| components/m5stack-cardputer/idf_component.yml | Adds gps/sx126x dependencies to the Cardputer component manifest. |
| components/m5stack-cardputer/include/m5stack-cardputer.hpp | Adds LoRa+GPS Cap APIs/pins/state and new helper methods. |
| components/m5stack-cardputer/src/lora_gps_cap.cpp | Implements LoRa+GPS Cap SPI-bus bring-up and LoRa/GPS initialization. |
| components/m5stack-cardputer/src/sdcard.cpp | Adjusts SD init to reuse the shared expansion SPI bus when LoRa is present. |
| components/m5stack-cardputer/example/README.md | Updates Cardputer example docs for new tabbed UI + LoRa/GPS features. |
| components/m5stack-cardputer/example/main/m5stack_cardputer_example.cpp | Wires LoRa+GPS demos into the example and updates tab/shortcut behavior. |
| components/m5stack-cardputer/example/main/gui.hpp | Refactors Cardputer GUI into tabbed layout with LoRa/GPS/Sys tabs. |
| components/m5stack-cardputer/example/main/gui.cpp | Implements tabbed UI, LoRa log/status rendering, and new per-tab helpers. |
| .github/workflows/build.yml | Adds gps/meshtastic/sx126x examples to CI build matrix. |
| .github/workflows/upload_components.yml | Adds gps/meshtastic/sx126x to component upload list. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 71 out of 71 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
components/t-deck/example/main/t_deck_example.cpp:1
std::transformis used but<algorithm>is not included in this file, which can cause compilation failures depending on toolchain/headers. Add#include <algorithm>alongside the other standard includes.
components/t-deck/example/main/t_deck_example.cpp:1std::transformis used but<algorithm>is not included in this file, which can cause compilation failures depending on toolchain/headers. Add#include <algorithm>alongside the other standard includes.
components/meshtastic/src/meshtastic_protobuf.cpp:1pos + length > sizecan overflow whenlengthis a large varint (and then incorrectly pass the bounds check), and(size_t)lengthtruncation can produce a span smaller than intended. Use an overflow-safe bounds check (e.g.,length > (size - pos)after validatinglength <= SIZE_MAX) before creating the span and advancingpos.
| void Gps::handle_line(std::string_view line) { | ||
| logger_.debug("NMEA: {}", line); | ||
| if (!NmeaParser::checksum_valid(line)) { | ||
| return; | ||
| } | ||
| if (config_.on_sentence) { | ||
| config_.on_sentence(line); | ||
| } | ||
| bool is_rmc = line.size() > 6 && line.substr(3, 3) == "RMC"; | ||
| GpsFix fix_copy; | ||
| { | ||
| std::lock_guard<std::mutex> lock(fix_mutex_); | ||
| parser_.parse(line); | ||
| fix_copy = parser_.fix(); | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 71 out of 71 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
components/t-deck/example/main/t_deck_example.cpp:1
std::transformis used later in this file (inprintable()), but<algorithm>is not included in the shown includes. This is a compile error on standard toolchains; add#include <algorithm>.
components/sx126x/src/sx126x.cpp:1receiving_is set tofalseinstart_transmit(), so this TX_DONE path will never restart RX even if the radio was in continuous receive before TX (for non-blockingstart_transmit()usage). If the intended behavior is “return to RX if we were receiving before TX”, store that prior state (e.g.,return_to_rx_after_tx_) instart_transmit()and consult it here; otherwise, update/remove the misleading comment.
components/meshtastic/src/meshtastic_protobuf.cpp:1- The decode paths parse fields without validating that
wirematches the expected protobuf wire type for that field (e.g.,portnumshould be VARINT,payloadshould be LENGTH). Because this processes untrusted over-the-air frames, add wire-type checks per field andskip(wire)(or returnnullopt) on mismatch to avoid mis-decoding random/corrupted bytes into plausible-looking messages.
components/meshtastic/src/meshtastic.cpp:1 - On invalid PSK length,
expand_psk()returns an empty key and the node continues operating unencrypted (only logging an error). That’s a dangerous failure mode because it can silently downgrade confidentiality if logs are missed. Consider making this a hard failure (e.g., set an internalpsk_valid_flag and havesend_*()/handle_frame()refuse to operate when invalid), or provide an explicitallow_unencrypted_fallbackconfig to require a conscious opt-in.
Description
Adds LoRa + GPS support to espp, along with a radio-agnostic Meshtastic
node, and wires all three into the T-Deck and M5Stack Cardputer BSPs.
New components
sx126x—espp::Sx126xdriver for Semtech SX1261 / SX1262 / LLCC68LoRa radios. Built on
espp::BasePeripheral<uint8_t, false>; the callersupplies a
write_then_readthat holds chip-select across the write andread phases (one full-duplex SPI transfer), since SX126x commands return
their status/data in the same CS assertion. LoRa modulation with explicit
header, configurable frequency / SF / BW / CR / preamble / CRC / sync word,
TCXO and DC-DC/LDO options, and DIO1 IRQ servicing.
gps—espp::Gps(UART NMEA reader task) plus a platform-independentespp::NmeaParser(RMC/GGA) and anespp::GpsFixvalue type with auser-supplied on-fix callback.
meshtastic—espp::MeshtasticNode, radio-agnostic (you provide atransmitfunction and feed it received frames). Implements over-the-airinterop on the public default channel: 16-byte little-endian packet header,
AES-CTR payload encryption with the default PSK, djb2 frequency-slot + XOR
channel hashing, a small hand-written protobuf codec for Text / NodeInfo /
Position, packet de-duplication, and optional managed-flood rebroadcast.
The README carries a clean-room / licensing note (Meshtastic firmware and
protobufs are GPL-3; this is an independent MIT implementation of the
wire format).
BSP integration — both boards gain
initialize_lora(radio_config)/lora()andinitialize_gps(...)/gps():the shared LCD/SD SPI bus. GPS (T-Deck Plus, u-blox MIA-M10Q) over UART.
module, 3.0 V TCXO on DIO3, LDO regulator) on the shared microSD SPI bus,
with the Cap's PI4IOE5V6408 IO expander driving the RF switch / GPS LNA;
ATGM336H GPS over UART.
Examples
sx126x,gps, andmeshtasticexamples (the meshtasticexample has a Kconfig board + region selector and runs a full node).
scrolling RX/TX log with RSSI/SNR).
(Text / LoRa / IMU / GPS / Sys / Help) with keyboard navigation, and now
brings up GPS when the Cap is present.
Docs / CI — per-component READMEs, a new
doc/en/wireless/docs section(index + sx126x + gps + meshtastic, each with an example page), Doxyfile
inputs, and
build.yml/upload_components.ymlmatrix entries for the threenew examples.
Motivation and Context
espp had no LoRa or GPS support and no path to interoperate with the
Meshtastic ecosystem. This adds reusable, radio-/board-agnostic building
blocks (a general SX126x driver, an NMEA GPS reader, and a Meshtastic wire
codec) and demonstrates them end-to-end on two popular ESP32-S3 dev boards,
so espp users can build LoRa messaging / mesh / tracker applications.
How has this been tested?
so espp users can build LoRa messaging / mesh / tracker applications.
How has this been tested?
a raw private LoRa link (US LongFast modulation, private sync word
0x12),confirmed bidirectional on real devices using the GUI examples' LoRa tabs.
GPS fixes displayed on both boards. TCXO voltage / regulator settings for
each module were validated against the vendors' RadioLib configs after an
initial dead-oscillator symptom on the Cardputer module.
esp32s3withESP-IDF v5.5.2 —
sx126x,gps, andmeshtasticexamples (the latter forboth the T-Deck and Cardputer-Adv Kconfig targets), plus the updated T-Deck
and Cardputer GUI examples.
--enable=all, the repo's CI config) cleanon the changed files.
over-the-air against a stock Meshtastic device/phone — all hardware testing
so far used the raw-LoRa path, which shares the SX126x driver but not the
Meshtastic framing/crypto. This is the main follow-up before relying on
mesh interop.
Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action.