First Phase 1 increment toward the single-device 3-in-1: one Heltec V3 (ESP32-S3 + single SX1262) rotating the radio through the Meshtastic / MeshCore / Reticulum PHY presets, logging every raw packet it demodulates per dwell window. No framing/crypto/bridge yet — proves the RX loop first. Validated on hardware: radio.begin() clean, all three presets cycle, and the Meshtastic window received live broadcast packets (-36..-41 dBm). The single-radio time-multiplex premise (ARCHITECTURE.md §2) holds. MeshCore sync word and Reticulum PHY are flagged placeholders in CONFIGS[]. Deps pinned (espressif32 7.0.1, RadioLib 7.7.1). Adds venv/pycache/storage to .gitignore. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 lines
2.7 KiB
Markdown
56 lines
2.7 KiB
Markdown
# firmware (Phase 1)
|
||
|
||
Embedded firmware for the single-device **3-in-1**: one Heltec WiFi LoRa 32 V3
|
||
(ESP32-S3 + one SX1262) time-multiplexing its single radio across the
|
||
Meshtastic / MeshCore / Reticulum PHY configs. See `../docs/ARCHITECTURE.md`
|
||
§2-§3 for why Phase 1 is a time-multiplexed single radio (Option A).
|
||
|
||
## Current increment: tri-protocol RX scanner
|
||
|
||
`src/main.cpp` is the **first** Phase 1 step. It does not bridge, decode, or
|
||
transmit yet — it rotates the SX1262 through each network's PHY preset, listens
|
||
for a fixed dwell window, and logs every raw LoRa packet it demodulates
|
||
(length, RSSI, SNR, hex). The point is to answer the project's central open
|
||
question before building any protocol stacks: *can one re-tuned radio actually
|
||
hear all three networks?*
|
||
|
||
**Validated on hardware (2026-07-01):** flashed to a Heltec V3, the scanner
|
||
`radio.begin()`'d cleanly, cycled all three presets, and received **live
|
||
Meshtastic broadcast packets** (payloads prefixed `ffffffff`) at −36 to
|
||
−41 dBm during the Meshtastic dwell. The single-radio time-multiplex premise
|
||
holds. MeshCore/Reticulum windows were silent — expected, see open items below.
|
||
|
||
## Open items baked into the config table
|
||
|
||
- **MeshCore sync word** (`src/main.cpp`, `CONFIGS[]`) is a guess (`0x12`,
|
||
RadioLib's private default). Confirm against MeshCore `src/` — this is the
|
||
same open item as `../docs/ARCHITECTURE.md` §1/§5.
|
||
- **Reticulum PHY** has no protocol-mandated preset; it's operator-configured.
|
||
The entry is a placeholder — set it to your actual RNS RNode interface
|
||
config or that window hears nothing.
|
||
- **Meshtastic frequency** is set to the documented 869.525 MHz, but Meshtastic
|
||
hashes the channel name to a slot within the region plan, so real
|
||
deployments may sit on a different slot.
|
||
|
||
## Build / flash / monitor
|
||
|
||
Requires PlatformIO (`pip install platformio`). Versions are pinned in
|
||
`platformio.ini` (espressif32 7.0.1, RadioLib 7.7.1) — do not float them.
|
||
|
||
```bash
|
||
pio run # compile
|
||
pio run -t upload --upload-port /dev/cu.usbserial-0001 # flash (adjust port)
|
||
pio device monitor -b 115200 # watch the scan
|
||
```
|
||
|
||
## Roadmap from here
|
||
|
||
1. **RX decode per protocol** — turn logged raw packets into `{sender, text}`
|
||
(Meshtastic 16-byte header + AES-CTR; MeshCore framing; Reticulum via
|
||
microReticulum). Start with Meshtastic since we already receive it.
|
||
2. **On-device bridge/dedup** — port the Phase 0 `bridge_core` relay+dedup
|
||
logic to C++.
|
||
3. **TX** — re-originate a decoded message onto the other two networks within
|
||
their dwell windows (queue between windows).
|
||
4. Revisit dwell timing / RAM budget with real per-protocol state (§3).
|