RAK4631 board: - SX126X_POWER_EN on P1.05 driven HIGH at init (radio is power-gated; without this the chip has no power and SPI hangs) - HFXO + LFXO external crystals in embassy_nrf::Config (USB CDC-ACM needs +/- 500 ppm which the internal RC oscillator can't provide) - SoftwareVbusDetect(true, true) so USB enumerates without needing a CLOCK_POWER interrupt handler - Green LED on P1.03 via SimpleLed (RAK19007 Base LED1, active HIGH) - driver/mod.rs: open simple_led feature gate for rak_wisblock_4631 - Spim::new pin-order comment on SPI setup (arg order is sck/miso/mosi, not sck/mosi/miso — easy to get wrong) debug-checkpoint instrumentation (feature-gated, zero cost in release): - radio.rs: debug_blink::set(N) at each TX-phase boundary, filling in the long-aspirational blink-map doc - debug_blink.rs: checkpoint 19 between prepare_for_cad and cad(), so future bring-ups can distinguish modem-setup hang from DIO1-wait hang justfile + mise.toml: - set shell := ["mise", "exec", "--", "sh", "-c"] so recipes always resolve tools through mise, not whatever happens to be on PATH - replace per-board := vars + long if/elif _info chain with a single case statement — one place per board, two lists (names + metadata) - new flash-dfu recipe using adafruit-nrfutil via uvx, with VID:PID (239a:0029) port autodetect for the Adafruit nRF52 bootloader - mise.toml: rust pins now carry ARM targets + clippy, so 'mise install' is sufficient bootstrapping (no extra rustup target add steps) Verified TX on real hardware (RAK19007 Base + RAK4631 Core + RAK1921 OLED, US915 band): ADVERT round-trip with an external receiver.
DongLoRa Firmware
Embedded Rust firmware for DongLoRa boards. Exposes the LoRa radio over USB CDC-ACM using a COBS-framed binary protocol.
Building
just setup # one-time toolchain install
just build heltec_v4 # build for a specific board
just flash heltec_v4 # build + flash
just check-all # compile-check all boards
just clippy heltec_v4 # lint
just test # host-side protocol unit tests
All commands are run from the firmware/ directory.
Supported Boards
| Board | Feature | MCU | Radio | USB | Target |
|---|---|---|---|---|---|
| Heltec V3 | heltec_v3 |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| Heltec V3 (UART) | heltec_v3_uart |
ESP32-S3 | SX1262 | CP2102 bridge | xtensa-esp32s3-none-elf |
| Heltec V4 | heltec_v4 |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| ELECROW ThinkNode-M2 | elecrow_thinknode_m2 |
ESP32-S3 | SX1262 | CP2102 bridge | xtensa-esp32s3-none-elf |
| LilyGo T-Beam | lilygo_tbeam |
ESP32 | SX1276 | CP2102 bridge | xtensa-esp32-none-elf |
| LilyGo T-Beam S3 Supreme | lilygo_tbeam_supreme |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| RAK WisBlock 4631 | rak_wisblock_4631 |
nRF52840 | SX1262 | Native CDC-ACM | thumbv7em-none-eabihf |
| Waveshare RP2040-LoRa | waveshare_rp2040_lora |
RP2040 | SX1262 | Native CDC-ACM | thumbv6m-none-eabi |
| Wio Tracker L1 | wio_tracker_l1 |
nRF52840 | SX1262 | Native CDC-ACM | thumbv7em-none-eabihf |
Heltec V3 USB Note
The default heltec_v3 build uses native USB CDC-ACM, which requires a
hardware modification to your board. Stock Heltec V3 boards route USB through a
CP2102 bridge chip to UART — the ESP32-S3's native USB pins (GPIO19/GPIO20) are
routed to header pins but not connected to the USB connector.
To enable native USB on a Heltec V3:
- Solder 0-ohm (or 22-ohm) resistors at pads R29 (D+) and R3 (D-)
- Disconnect the CP2102 from the USB connector's D+/D- lines (cut traces or remove the CP2102 bridge resistors)
After this mod, the board appears as /dev/ttyACM0 with the DongLoRa VID:PID
(1209:5741), just like the V4 and nRF boards.
If you have a stock (unmodified) V3, use heltec_v3_uart instead:
just build heltec_v3_uart
just flash heltec_v3_uart
This builds firmware that communicates via the CP2102 bridge (appears as
/dev/ttyUSB0).
Adding a Board
See src/board/PORTING.md.
Protocol
See PROTOCOL.md for the complete wire format specification.