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.

11shown
10shipping
5chip families
BearerHardware

T-Deck

LilyGO

ESP32-S3 shipping v0.5.1

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.5.1

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.1

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.1

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.2.1

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.2.1

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.1

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.1

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.5.1

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.5.1

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.3.1

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.3.1

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

SenseCAP Card Tracker T1000-E

Seeed Studio · SKU 114993369

nRF52840 shipping v0.1.0

Seeed SenseCAP Card Tracker T1000-E: nRF52840 (Cortex-M4F 64 MHz, 256 KB RAM, 1 MB flash), Semtech LR1110 LoRa (863-928 MHz), Airoha AG3335 GNSS, NTC temperature and light sensors, QMA6100P accelerometer, buzzer, one LED and one button, Bluetooth 5, a built-in battery and a magnetic charging cable. No WiFi, no screen. The XPRS station on it is carried by a person: it finds whether Meshtastic or MeshCore is around and lives on that one, repeats the native mesh, carries XPRS between Bluetooth and LoRa, beacons its position (asked of its owner's phone, or its own receiver), temperature and battery, and holds mail for the people it meets.

What it does

The first minute
The LED blinks three times when the radio is up. For about half a minute the card then listens on Meshtastic's LongFast and on MeshCore's default channel, asking each with a small probe that their repeaters carry. It settles on the one that answers (a repeater that carried the probe beats an XPRS station heard, which beats any traffic), remembers it across a restart, and asks again every hour. It only moves to the other network after two hourly checks in a row agree, so one quiet hour does not flip it. With nothing heard anywhere it stays where it was.
What it carries
Everything XPRS it hears on LoRa is passed on over Bluetooth. From Bluetooth to LoRa it is choosy, because the channel is shared and every frame costs battery: messages, receipts, reactions, alerts, files, identities and mailbox declarations go out; presence chatter, anything marked scope:local, anything for a person already in Bluetooth range, replays older than half an hour and repeats within half an hour do not. It also repeats the native Meshtastic or MeshCore traffic of the network it is on, the way a stock repeater does, inside the same airtime budget (10% of each hour on the EU 869 MHz band, with a reserve for SOS).
Where it says it is
If its owner's phone is within Bluetooth range, the card asks the phone for its position (the XPRS app answers only cards it owns) and uses that, which costs the card almost nothing. Without the phone it switches on its own GPS for one fix, at most every 15 minutes, or every hour when two fixes in a row put it in the same place. It gives up after two minutes indoors. A position older than about 20 minutes is not sent at all.
What it sends, and how often
On Bluetooth, every five minutes: position, accuracy, its temperature, battery percentage and voltage, how much mail it holds, and the callsigns it heard directly. On LoRa, every fifteen minutes, a shorter version of the same. Its identity every 30 minutes on Bluetooth and every 3 hours on LoRa, and once an hour a short service line saying it is a portable relay on battery. Everything is signed.
Your position is public
The position in these beacons is meant to be heard: anyone on the mesh within range of the card, and anyone the network passes the beacon to, can read where the card is. When your phone answers the card, that is your position. Do not carry the card, or do not make it yours, if that is not what you want.
It holds mail for the people it meets
The card keeps up to 64 letters. It holds mail for anyone whose own mailbox declaration names the card, and for people it has met in the last 30 days. When it next hears the recipient directly it hands the letters over on that link, a few at a time, retrying a copy after 30 seconds, 2 minutes and 10 minutes, and forgets a letter once the recipient's signed receipt arrives. Held mail and receipts survive a restart. Because its signed beacons list the devices it heard over Bluetooth, the network learns on its own that this card is the place to route mail for them.
Making it yours
There is no claim over the air on this card yet. Connect it by USB and on its serial console (115200, DTR on) type `cfg set own1` followed by your npub, then `cfg set own1c` followed by your callsign; each line saves and restarts the card. From version 1.2.23 the XPRS app notices within a few minutes that the card is yours, starts answering its position questions, and names the card first in your mailbox declaration, so your mail can wait on it.
Battery
Built for at least three days on a charge: most of the time the processor sleeps, Bluetooth listens a tenth of the time (more while your phone is advertising), and the LoRa radio only wakes to look for a preamble. The design figure is about 5 mA, roughly five days; it has not been measured over a full discharge yet. A busy mesh to repeat, and using its own GPS instead of your phone, both shorten it.
Good to know
The temperature is the card's own, so in a pocket it reads close to body heat. The light sensor and the accelerometer are not used yet. The console prints only with DTR on, and answers one-letter commands (? for its state, S for sensors, w for position, m for mail). To go back to Meshtastic, send D on the console and copy Meshtastic's T1000-E UF2 onto the drive that appears.
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
none
Screen
none
GNSS
Airoha AG3335 (GPS / GLONASS / Galileo / BeiDou), UART at 115200
Power
battery
Size
85 x 55 x 6.5 mm
Toolchain
arduino-nrf52
BeaconDigipeaterBridgeiGateHotspotAPIIndexerShareReticulumOTAGossipDashboardChatMesh sessionVHF
The card, front, three-quarter view: the button with the LED beside it, and the boards under the clear case.
The card, front, three-quarter view: the button with the LED beside it, and the boards under the clear case.Seeed Studio product photography
Dimensions: 85 x 55 x 6.5 mm, a credit card with some thickness.
Dimensions: 85 x 55 x 6.5 mm, a credit card with some thickness.Seeed Studio product photography
The back: the magnetic pogo-pin connector for the charging and data cable, the shielded modules, and the label.
The back: the magnetic pogo-pin connector for the charging and data cable, the shielded modules, and the label.Seeed Studio product photography
Build from source
cd models/sensecap-t1000e/firmware
~/.platformio/penv/bin/pio run -e t1000e
~/.platformio/penv/bin/pio run -e t1000e -t upload

Any ESP32 board

Espressif DevKitC and its clones

ESP32 shipping v0.2.1

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.2.1

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).

A vendor device over its own web UI

The Reolink doorbell is not a microcontroller: it is a small Linux computer with a vendor updater, and the only way in is that updater. The build produces a .pak in the vendor's own format; it is renamed to the vendor's filename pattern with a version number higher than the one installed, then uploaded in the camera's web UI under System → Maintenance → Firmware Update. There is no cable, no bootloader and no signature check, so the two validators in the board's firmware/tool/ (a nandsim mount, and the camera's own flasher under qemu) are what stands between a build and a brick. Run both. The one non-obvious trap: the browser must be able to read the file, so a confined Chromium cannot take it from /tmp and silently uploads nothing.

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.