Files
roro9stack/docs/milestones/M3.md
T
twislaandClaude Opus 5.5 fed065a6f9 M3 step 1: RadioLib and lora probe
The probe finds the SX1262 (TCXO 1.8 V works) and measures the antenna
path: the Cap's PI4IOE5V6408 at 0x43 must drive P0 high, or the receiver
is deaf (-111.9 dBm flat vs -87 to -94 dBm with P0 high). DIO2 makes no
difference to reception. Receive only; the radio is left asleep.

RadioLib 7.8.1 + probe: +23.6 KB flash, +656 B static RAM (release).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-05 18:52:38 +02:00

7.0 KiB
Raw Blame History

M3 — Radio bring-up: the LoRa Scanner

Status: in progress (branch m3): step 1 done.

Goal: the LoRa radio on the Cap works, receive only: a Radio Service owns it and shares the SPI bus with the SD card safely, and a LoRa Scanner App shows what's on the air, either packets (Sniffer) or energy across the band (Sweep). Nothing in M3 can transmit. The mesh comes on top of this in M4 (receive) and M5 (transmit).

Hardware: the Cap LoRa-1262 carries an SX1262 (868–923 MHz, +22 dBm) with an RP-SMA antenna. Pins, as in Meshtastic's board file for the Cardputer ADV: NSS 5, RST 3, DIO1 (IRQ) 4, BUSY 6, on the SPI bus shared with the microSD card (SCK 40, MISO 39, MOSI 14; card CS 12). Meshtastic uses DIO2 as the RF switch and DIO3 for a 1.8 V TCXO, marked optional. M5Stack's page adds an FM8625H antenna switch enabled by P0 of a PI4IOE5V6408 I/O expander on the internal I2C bus, address not given; Meshtastic doesn't mention it. Step 1 measures which is true.

No other LoRa device yet. meshmap.net (2026-10-05) lists two Meshtastic nodes within 10 km of the desk and six within 30 km, with positions blurred by a few km; none is known to be in range. M3 needs none: it only receives.

Measured (step 1, lora probe)

  • Internal I2C bus (8/9): 0x18 (ES8311 codec), 0x34 (TCA8418 keyboard), 0x43 (PI4IOE5V6408, ID register 0xA2), 0x69 (BMI270 IMU).
  • The SX1262 answers on NSS 5, RST 3, DIO1 4, BUSY 6. Its version string reads SX1261 V2D 2D02, which SX1262 chips report too. The 1.8 V TCXO works on the first try; the radio is ready 38 ms after begin.
  • The expander's P0 connects the antenna; it's required. At power-on P0 is an input (direction 0x00, high-impedance 0xFF), and the receiver reads a flat -111.9 dBm at 869.525 MHz, BW 250 kHz: the chip's own floor, deaf. With P0 driven high, the noise floor is -87 to -94 dBm: the antenna hearing the room. So the Radio Service drives P0 high at boot (Q91).
  • DIO2 doesn't change reception (within ±2 dB over three runs, P0 high). It likely selects TX versus RX in the FM8625H; it stays the RF switch, as in Meshtastic.
  • The noise floor at the desk is high (-87 to -94 dBm, varying run to run), about 25 dB above thermal noise for 250 kHz. Something nearby is loud, possibly the Cardputer itself or the PC; Sweep (step 5) should show where it sits.
  • Cost: RadioLib 7.8.1 and the probe add 23.6 KB of flash and 656 bytes of static RAM to the release firmware (1,679,843 bytes of 3,342,336).

Decisions (design round 2026-10-05)

# Decision
Q89 M3 is the radio only: Radio Service, Sniffer, Sweep. Notes and the File Browser (Q30) move out to issue #3 and a Notes issue, as a later side milestone.
Q90 RadioLib, pinned (ADR 0001). SX1262 on NSS 5, RST 3, DIO1 4, BUSY 6; DIO2 as RF switch; TCXO at 1.8 V tried first, falling back to the crystal (Meshtastic's TCXO_OPTIONAL).
Q91 Step 1 is lora probe: chip status and version, which oscillator setting worked, and an I2C scan of the internal bus for the PI4IOE5V6408. If present, its P0 is set high at boot (harmless) and DIO2 stays the switch. A wrong switch receives deaf, so compare noise floors.
Q92 A Radio Service owns the SX1262: driver, bus lock, IRQ task. The LoRa Scanner uses it in M3; the Mesh Service sits on top of it in M4.
Q93 Every radio transfer takes the shared bus lock (SPI.beginTransaction, as the card does). DIO1's interrupt only wakes the task; no SPI in the ISR. Done when a Gemini page streams to the card while the Sniffer receives, with no lost packets and no card errors (lora status counters).
Q94 Receive only: the Radio Service has no transmit function in M3. It doesn't exist, rather than being unused.
Q95 Sniffer defaults: EU868 LongFast, 869.525 MHz, BW 250 kHz, SF 11, CR 4/5, sync word 0x2B, preamble 16 (Q19). The other Meshtastic presets are offered, plus custom settings.
Q96 The Sniffer lists packets (time, RSSI, SNR, frequency error, length; hex dump on Enter) and decodes the Meshtastic header: the first 16 bytes are never encrypted (destination, sender, packet ID, hop limit and hop start, channel hash, next hop, relay node). Host-tested. Payload decryption is M4.
Q97 A Sniffer Capture is pcap with LoRaTap headers (link type 270), for Wireshark. Started by hand, Status Bar mark, its own Clean-up category, the 90% rule.
Q98 Sweep steps across the Region's band (863–870 MHz) in 100 kHz steps by default, reading instant RSSI: bars with peak hold, and a waterfall, Wi-Fi Tools style. Optionally CAD on the preset's frequency to tell LoRa traffic from noise.
Q99 Sweep takes the radio and pauses the Sniffer, visibly (Q18). From M4 it pauses the Mesh Service the same way.
Q100 The Sniffer runs while the App is open or a Capture is recording; otherwise the radio sleeps. From M4 the Mesh Service keeps it on.
Q101 Status Bar: a radio mark while receiving, flashing on each packet; muted during a Sweep.
Q102 Debug aids: lora status (settings, counters, last RSSI/SNR, noise floor), lora probe, lora rx on/off (packets on the consoles). Raw packets are never written to the card outside a Capture.
Q103 A ring of the last 32 packets in RAM (about 9 KB at full length); older ones are dropped unless capturing. IRQ task stack trimmed by measurement; RadioLib's flash and RAM measured in step 1 against the floors.
Q104 Done when (below) includes an hour of listening on LongFast by a window. Real packets heard become M4 test fixtures. If none are heard, M3 still closes, and a reference Meshtastic node (Q21) becomes a requirement for M4.

Done when

  • lora probe reports the SX1262, its oscillator setting and the RF switch arrangement, and the result is written here.
  • The Sniffer receives on LongFast with the App open or a Capture running, and the radio sleeps otherwise.
  • Sweep shows the noise floor across 863–870 MHz, and a known signal (a remote key fob, a 868 MHz sensor, anything) stands out.
  • The shared-bus test passes (Q93): a Gemini page to the card while the Sniffer receives, no lost packets, no card errors.
  • A Capture opens in Wireshark with LoRaTap fields.
  • The Status Bar mark follows Q101.
  • One hour of LongFast listening by a window has been run and its result recorded here.
  • Free heap stays above the floors (Q86) with the Sniffer, Wi-Fi, IRC on TLS and the UI running.
  • Nothing in the firmware can transmit.

Work breakdown

  1. Hardware check: RadioLib in the build, lora probe (Q91), flash and RAM cost measured.
  2. Meshtastic header and LoRaTap (host-tested): header parsing, presets and their radio settings, pcap/LoRaTap writing.
  3. Radio Service: receive on its own task behind the bus lock, the packet ring, lora status and lora rx, the shared-bus test.
  4. LoRa Scanner App, Sniffer: the packet list, details, preset choice, Captures, Status Bar mark.
  5. Sweep: the RSSI sweep, bars and waterfall, pausing the Sniffer.
  6. Listening hour and the measurements above, recorded here.