xprs-dev/firmware

Firmware for XPRS stations

XPRS is an open packet format for radio and mesh networks, a successor to APRS: short text packets of at most 250 bytes carrying messages, observations, files and commands, each signed by the station that wrote it. It is not tied to one radio. This firmware turns inexpensive ESP32 and nRF52 boards into stations that carry the same packets over Bluetooth 5, ESP-NOW, WiFi, LoRa and VHF, with a callsign derived from the station's own key so a receiver can check who said what. One board usually does several of these jobs at once.

  • Digipeater (repeater)Re-airs what it hears so a packet reaches stations beyond the sender's range, within a hop budget, and holds back when a neighbour has already repeated it.
  • BridgeJoins the radios it has into one network: what it hears on Bluetooth, LoRa or ESP-NOW it passes to the others and to the LAN.
  • iGate (internet gateway)Passes what the radios hear onto the network over WiFi, and what arrives from there back onto the air, so a message is not limited to radio range.
  • Hotspot (portable chat)Opens its own WiFi access point: a phone joins, the chat page opens by itself, and nobody needs an app or an account. The T-Deck's keyboard lets it chat on its own.
A T-Deck screen: a green radar sweeps over the stations in reach, then the chat, stats, reachable, traffic, this-device and settings panels.
A T-Deck running this firmware: the radar of who is in reach, then chat, stats, reachable stations, traffic, this device and settings. Every frame is a capture of the board's own screen; the radar is a time-lapse, so its clock runs fast.

Supported boards

Each card is one folder under models/: what the board is, which XPRS bearers it carries, what the station on it does, how to build and flash it. Filter by bearer or by hardware.

9shown
8shipping
4chip families
BearerHardware

T-Deck

LilyGO

ESP32-S3 shipping v0.4.0

LilyGO T-Deck: ESP32-S3 (dual-core 240 MHz, 512 KB RAM, 8 MB PSRAM, 16 MB flash), 2.8" 320x240 ST7789 LCD with GT911 touch, QWERTY keyboard on its own ESP32-C3, trackball, microSD, speaker, microphone, USB-C, LiPo connector. Radios: WiFi 2.4 GHz, Bluetooth 5 with extended advertising, and an SX1262 LoRa module (868 MHz on this unit). The only board with all four bearers, and the only one you can type on, so it gets the interactive chat panel. Also serves the BLE GATT mesh session that the P1-Pro connects to.

Install XPRS 0.4.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32-S3 / C3 over native USB.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX7 dual @ 240 MHz
Memory
512 KB RAM · 8 MB PSRAM · 16 MB flash
Storage
microSD (shares the panel's SPI bus)
Screen
ST7789 320×240
Power
usb+battery
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
Front and back: 320x240 screen, trackball, QWERTY keyboard, SD slot, LoRa module.
Front and back: 320x240 screen, trackball, QWERTY keyboard, SD slot, LoRa module.LilyGO product photography, lilygo.cc
Second view.
Second view.LilyGO product photography, lilygo.cc
Third view.
Third view.LilyGO product photography, lilygo.cc
Fourth view.
Fourth view.LilyGO product photography, lilygo.cc
Build from source
cd models/tdeck/firmware
~/.platformio/penv/bin/pio run -e tdeck
~/.platformio/penv/bin/pio run -e tdeck -t upload

ESP32-S3-ePaper-1.54

Waveshare

ESP32-S3 shipping v0.1.0

Waveshare ESP32-S3-ePaper-1.54: ESP32-S3 (dual-core 240 MHz, 512 KB RAM; V1 with 4 MB flash and 2 MB PSRAM, V2 with 8 MB and 8 MB) behind a 1.54" 200x200 black-and-white e-paper panel in a white case, with an SHTC3 temperature and humidity sensor, a PCF85063 RTC, microSD, an ES8311 audio codec with microphone and speaker, and a battery. Radios: WiFi 2.4 GHz, Bluetooth 5. Runs the shared station on BLE5, the LAN and ESP-NOW, keeps its archive on the card, and shows one page that refreshes only when it changes: the room's temperature and humidity, who is in reach, the newest messages and the network.

Install XPRS 0.1.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32-S3 / C3 over native USB.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX7 dual @ 240 MHz
Memory
512 KB RAM · 2 MB PSRAM · 4 MB flash
Storage
microSD (SDMMC 1-bit; holds the archive)
Screen
1.54in e-paper (SSD1681 class) 200×200
Power
usb+battery
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
ESP32-S3-ePaper-1.54 in its white case, the 200x200 panel showing a picture.
ESP32-S3-ePaper-1.54 in its white case, the 200x200 panel showing a picture.Waveshare product photography, waveshare.com
Second view.
Second view.Waveshare product photography, waveshare.com
Third view.
Third view.Waveshare product photography, waveshare.com
Build from source
cd models/epaper-1in54/firmware
~/.platformio/penv/bin/pio run -e epaper
~/.platformio/penv/bin/pio run -e epaper -t upload

ESP32-C3 Mini

Espressif (and SuperMini clones)

ESP32-C3 shipping v0.1.0

ESP32-C3 mini board: single-core RISC-V at 160 MHz, 400 KB RAM, no PSRAM, 4 MB flash, native USB, one LED, BOOT button, no screen. Radios: WiFi 2.4 GHz and Bluetooth 5 with extended advertising. Runs the shared station on BLE5, ESP-NOW and the LAN, with the HTTP API and the walk-up hotspot whose chat page is how a person uses a board with no screen. No archive: 4 MB of flash leaves less room than one index segment. The WiFi and BLE share one radio, so the board is tuned for it (short BLE scan, 536-byte TCP segments).

Install XPRS 0.1.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32-S3 / C3 over native USB.

BLE5
LoRa
LAN
ESP-NOW
Core
RISC-V single @ 160 MHz
Memory
400 KB RAM · 4 MB flash
Storage
none
Screen
none
Power
usb
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
ESP32-C3-DevKitM-1, isometric.
ESP32-C3-DevKitM-1, isometric.Espressif, ESP32-C3-DevKitM-1 user guide
Annotated photo: the module, the two buttons, the RGB LED on GPIO8.
Annotated photo: the module, the two buttons, the RGB LED on GPIO8.Espressif, ESP32-C3-DevKitM-1 user guide
Pinout.
Pinout.Espressif, ESP32-C3-DevKitM-1 user guide
Build from source
cd models/esp32c3-mini/firmware
~/.platformio/penv/bin/pio run -e c3mini
~/.platformio/penv/bin/pio run -e c3mini -t upload

WiFi LoRa 32 (V3)

Heltec Automation

ESP32-S3 shipping v0.1.0

Heltec WiFi LoRa 32 V3: ESP32-S3 (dual-core 240 MHz, 512 KB RAM, 8 MB flash), 0.96" 128x64 SSD1306 OLED, SX1262 LoRa (868/915 or 433 MHz by variant), USB-C, LiPo connector, U.FL antenna. Radios: WiFi 2.4 GHz, Bluetooth 5 with extended advertising, LoRa. Same MCU and LoRa chip as the T-Deck, so an xprs_app port is a pin table away; today it is a multiboard target that does not compile.

Install XPRS 0.1.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32 over USB-serial.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX7 dual @ 240 MHz
Memory
512 KB RAM · 8 MB flash
Storage
none
Screen
SSD1306 128×64
Power
usb+battery
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
V3: USB-C, SX1262 under the OLED, the version on the silk.
V3: USB-C, SX1262 under the OLED, the version on the silk.Heltec Automation product photography, heltec.org
In its packaging: the red LoRa 32 label with the band printed on it.
In its packaging: the red LoRa 32 label with the band printed on it.Heltec Automation product photography, heltec.org
Build from source
cd models/heltec-v3/firmware
~/.platformio/penv/bin/pio run -e heltec_v3
~/.platformio/penv/bin/pio run -e heltec_v3 -t upload

T-Dongle-S3

LilyGO

ESP32-S3 shipping v0.4.0

LilyGO USB-A stick: ESP32-S3 (dual-core 240 MHz, 512 KB RAM, no PSRAM, 16 MB flash), 160x80 ST7735 colour LCD, microSD slot, one BOOT button, USB-JTAG serial. Radios: WiFi 2.4 GHz and Bluetooth 5 with extended advertising. Runs the full xprs_app station: BLE5, LAN and ESP-NOW bearers, digipeater, cross- bearer bridge, APRS-IS iGate, HTTP API, indexer, signed OTA. Meant to be plugged in next to a router as the BLE-to-LAN bridge; the screen cycles three status views on its own since the button is usually under the case.

Install XPRS 0.4.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32-S3 / C3 over native USB.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX7 dual @ 240 MHz
Memory
512 KB RAM · 16 MB flash
Storage
microSD (present, but the archive lives in internal flash since 0.4.0)
Screen
ST7735 160×80
Power
usb
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
The stick, cap on and cap off: 160x80 screen on the face, ESP32-S3 under the clear shell.
The stick, cap on and cap off: 160x80 screen on the face, ESP32-S3 under the clear shell.LilyGO product photography, lilygo.cc
Second view.
Second view.LilyGO product photography, lilygo.cc
Third view.
Third view.LilyGO product photography, lilygo.cc
Fourth view.
Fourth view.LilyGO product photography, lilygo.cc
Build from source
cd models/tdongle-s3/firmware
~/.platformio/penv/bin/pio run -e tdongle
~/.platformio/penv/bin/pio run -e tdongle -t upload

M5Stack Core

M5Stack

ESP32 shipping v0.2.0

M5Stack Core Basic: original ESP32 (dual-core 240 MHz, 520 KB RAM, 16 MB flash) in a 54 mm stackable case with a 320x240 ILI9342C LCD, three front buttons, speaker, microSD, Grove port, USB-C and a 110 mAh battery. Radios: WiFi 2.4 GHz and Bluetooth 4.2 (legacy advertising only, so no BLE5 bearer). Runs xprs_app over LAN and ESP-NOW with the seven-panel dashboard, hotspot AP with the chat page, digipeater, iGate, indexer and signed OTA. Used as the second station on the bench: anything the T-Dongle or T-Deck sends has something to hear it.

Install XPRS 0.2.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32 over USB-serial.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX6 dual @ 240 MHz
Memory
520 KB RAM · 16 MB flash
Storage
microSD
Screen
ILI9342C 320×240
Power
usb+battery
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
Core Basic: 320x240 in the black stackable case, three buttons under the screen.
Core Basic: 320x240 in the black stackable case, three buttons under the screen.M5Stack product photography, docs.m5stack.com
Second view.
Second view.M5Stack product photography, docs.m5stack.com
Third view.
Third view.M5Stack product photography, docs.m5stack.com
Module dimensions, from the vendor page.
Module dimensions, from the vendor page.M5Stack product photography, docs.m5stack.com
Build from source
cd models/m5stack-core/firmware
~/.platformio/penv/bin/pio run -e m5stack
~/.platformio/penv/bin/pio run -e m5stack -t upload

SenseCAP Solar Node P1-Pro

Seeed Studio · SKU 114993633

nRF52840 shipping v0.1.0

Seeed SenseCAP Solar Node P1-Pro: nRF52840 (Cortex-M4F 64 MHz, 256 KB RAM, 1 MB flash + 2 MB QSPI) on a XIAO module, SX1262 LoRa (862-930 MHz), L76K GNSS, Bluetooth 5, four 18650 cells, 5 W solar panel, weatherproof case with pole bracket, RP-SMA antenna, USB-C, Grove port. No WiFi, no screen. Runs a port of the XPRS codec and bearer on the Adafruit nRF52 core: beacons, digipeats on LoRa and BLE5, bridges between the two, and dials a T-Deck's GATT channel. Built to sit outdoors unattended.

Install XPRS 0.1.0

No flasher needed. Tap the board's reset button twice; it shows up as a USB drive. Copy firmware.uf2 onto that drive and the board reboots into it. Works from any computer, including a phone with a USB-C cable.

Details: nRF52 by UF2 drag-and-drop.

BLE5
LoRa
LAN
ESP-NOW
Core
ARM Cortex-M4F single @ 64 MHz
Memory
256 KB RAM · 1 MB flash
Storage
2 MB QSPI flash
Screen
none
GNSS
Seeed XIAO L76K (GPS / GLONASS / Galileo / BeiDou)
Power
solar+battery
Size
191.2 x 201.2 x 42.1 mm
Toolchain
arduino-nrf52
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
The node, panel side.
The node, panel side.Seeed Studio product photography
Block diagram with the full GPIO map: LoRa, GNSS, LEDs, buttons, Grove, and the solar charging path.
Block diagram with the full GPIO map: LoRa, GNSS, LEDs, buttons, Grove, and the solar charging path.Seeed Studio, industrial datasheet for SKU 114993633
Three-quarter view with the antenna fitted.
Three-quarter view with the antenna fitted.Seeed Studio product photography
Pole-mounted on its bracket.
Pole-mounted on its bracket.Seeed Studio product photography
Inside: the four 18650 cells and the carrier board.
Inside: the four 18650 cells and the carrier board.Seeed Studio product photography
The port and button row on the underside.
The port and button row on the underside.Seeed Studio product photography
Exterior callouts, mounted and from below. The datasheet numbers these 1-15 and prints no legend.
Exterior callouts, mounted and from below. The datasheet numbers these 1-15 and prints no legend.Seeed Studio, industrial datasheet for SKU 114993633
Build from source
cd models/sensecap-p1-pro/firmware
~/.platformio/penv/bin/pio run -e p1pro
~/.platformio/penv/bin/pio run -e p1pro -t upload

Any ESP32 board

Espressif DevKitC and its clones

ESP32 shipping v0.1.0

For any board built on an original ESP32 with 4 MB of flash or more: the Espressif ESP32-DevKitC, the DOIT DevKit V1, and the many WROOM-32 boards sold under other names (dual-core 240 MHz, 520 KB RAM, WiFi 2.4 GHz, Bluetooth 4.2, USB through a CP210x or CH340). Runs the shared station on ESP-NOW and the LAN, with the HTTP API and the walk-up hotspot whose chat page is how a person uses a board with no screen. It drives no pin, so the one image is safe whatever a board has wired up. No BLE bearer (Bluetooth 4.2 adverts are too short for an XPRS beacon) and no archive (4 MB leaves less room than one index segment).

Install XPRS 0.1.0

Flash it from this page. Plug the board into this computer over USB, press the button, and pick its serial port in the dialog. The browser writes the whole image (bootloader, partition table, application). Needs Chrome or Edge on a desktop; phones and Firefox cannot do this.

This browser has no Web Serial: use Chrome or Edge on a desktop, or download the files below.Web flashing only works when the page is served over HTTPS.

Or download the files and flash them with esptool: ESP32 over USB-serial.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX6 dual @ 240 MHz
Memory
520 KB RAM · 4 MB flash
Storage
none
Screen
none
Power
usb
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
ESP32-DevKitC V4 functional overview: WROOM-32 module, EN and Boot buttons, USB-UART.
ESP32-DevKitC V4 functional overview: WROOM-32 module, EN and Boot buttons, USB-UART.Espressif, ESP32-DevKitC V4 user guide
Pin layout.
Pin layout.Espressif, ESP32-DevKitC V4 user guide
Build from source
cd models/generic/firmware
~/.platformio/penv/bin/pio run -e generic
~/.platformio/penv/bin/pio run -e generic -t upload

kv4p HT

kv4p (Vance Vagell)

ESP32 legacy

kv4p HT: an open-hardware VHF handheld interface. ESP32 (dual-core 240 MHz, 520 KB RAM, 4 MB flash) driving an SA818 FM transceiver module (134-174 MHz, 1 W), with PTT, squelch and audio in/out on GPIO, an SMA antenna and a USB-C link to a phone. No screen. Radios: WiFi 2.4 GHz, Bluetooth 4.2, VHF FM. The only board that transmits on an amateur voice band; here it carries packet through xprs_sa818 in the multiboard build.

Install XPRS

No prebuilt image: build it from source (below), then flash over a USB-serial bridge (CP210x/CH340), esptool; hold BOOT if it will not connect. Details.

BLE5
LoRa
LAN
ESP-NOW
Core
Xtensa LX6 dual @ 240 MHz
Memory
520 KB RAM · 4 MB flash
Storage
none
Screen
none
Power
usb
Toolchain
esp-idf
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
The kv4p HT in its printed case, SMA antenna fitted, on a phone.
The kv4p HT in its printed case, SMA antenna fitted, on a phone.Vance Vagell, kv4p-ht repository (website-src/img), CC-licensed project
PCB v1.8: the ESP32 module and the SA818 under the shield.
PCB v1.8: the ESP32 module and the SA818 under the shield.Vance Vagell, kv4p-ht repository (website-src/img), CC-licensed project
Build from source
cd multiboard
~/.platformio/penv/bin/pio run -e kv4p
~/.platformio/penv/bin/pio run -e kv4p -t upload

Flashing

Each card links to the one of these that applies. The prebuilt images are whatever tools/scripts/collect_prebuilt.py last copied out of a pio run; the version is printed beside them.

From this page (ESP32 boards)

The Install button on a card uses ESP Web Tools: the browser talks to the board over Web Serial and writes bootloader, partition table and application at the offsets in the board's manifest.json. It needs Chrome or Edge, and this page served over HTTPS (it does not work from a file:// URL, and Firefox and Safari have no Web Serial). Tick "erase" on a board that ran something else before; it clears NVS and the OTA selector. On Linux the user must be in the dialout group.

ESP32 over USB-serial

Original ESP32 boards (M5Stack Core, Heltec V1/V2, kv4p, DevKitC) have a CP210x or CH340 USB-serial bridge; so does the Heltec V3, an S3 behind a CP2102, whose bootloader goes at 0x0 like every S3. The port shows up as /dev/ttyUSB0 on Linux, COMx on Windows. Most auto-reset into the bootloader; if esptool reports "Failed to connect", hold BOOT, tap EN/RST, release BOOT. The bootloader goes at 0x1000 on this chip.

pip install esptool
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash \
  0x1000  bootloader.bin \
  0x8000  partitions.bin \
  0x20000 firmware.bin

Add --erase-all the first time, or after a different firmware.

ESP32-S3 / ESP32-C3 over native USB

The S3 and C3 boards here (T-Dongle, T-Deck, DevKitM-1, the e-paper board) use the chip's own USB-JTAG-serial port: no bridge chip, and it appears as /dev/ttyACM0 or under /dev/serial/by-id/usb-Espressif_USB_JTAG_serial_debug_unit_*. Bootloader at 0x0. If the port does not appear, hold BOOT while plugging in. The T-Dongle's cable and hub combination loses the link with the flasher stub, so its project pins --no-stub and 115200 baud; the T-Deck does not need that.

esptool.py --chip esp32s3 --port /dev/ttyACM0 write_flash \
  0x0     bootloader.bin \
  0x8000  partitions.bin \
  0x20000 firmware.bin

Use --chip esp32c3 for the C3. With two S3 boards on one machine, use the by-id path; the projects do, so pio run -t upload cannot hit the wrong one.

nRF52 by UF2 drag-and-drop

The SenseCAP P1-Pro's XIAO nRF52840 has an Adafruit-style UF2 bootloader. Tap reset twice, quickly; a USB drive named XIAO-SENSE (or similar) mounts. Copy firmware.uf2 onto it; the board reboots into the new image when the copy finishes. No driver, no tool, any OS. If the drive does not appear, the second tap was too slow or the board is not in reach of the reset button through the case: the button row is on the underside (see the photos).

From source

Every card's "Build from source" block is the exact command pair. The projects pin their upload port by USB serial number in platformio.ini; on a different machine change upload_port or pass --upload-port. Multiboard targets marked legacy may not compile today; multiboard/README.md keeps the table.

yes, tested on hardware untested, or hardware supports it but firmware does not yet not possible on this hardware

Generated from models/*/board.yml by tools/scripts/build_catalog.py. Do not edit this file; edit the board's board.yml and rebuild. Hover a bearer or a role for the note behind it. Photo credits are on each card; the same data is in docs/boards.json.