Embedded firmware projects and shared libraries for MinimapPR nodes.
Two runtime families live here. Which one a node uses follows from its MCU and build system:
| Library | Build system | Purpose |
|---|---|---|
lib/minimap_node_runtime |
CMake (Pico SDK) | node runtime for the RP2350 Sirith nodes — clock discipline, GPS/PPS capture, transport QoS, sensor interfaces |
lib/minimap_node_core |
PlatformIO | original Arduino/ESP32 runtime — protocol builder, HTTP publisher, WiFi helpers |
lib/minimap_audio_pico |
CMake + PlatformIO | RP2040/RP2350 PIO audio sources (TDM-4, PDM, mono I2S) and the PDM CIC/halfband decimator |
lib/minimap_audio_esp32 |
PlatformIO | ESP32 I2S audio source drivers |
lib/minimap_transport_cyw43 |
CMake | Pico W / Pico 2 W CYW43 WiFi uplink |
lib/minimap_transport_espc5 |
CMake | ESP32-C5 companion-radio uplink (for non-W Pico boards) |
lib/cmake/mmpr_nodecfg.cmake |
CMake | forwards a node's node_config.h settings into the shared libraries |
| Node target | Board | Audio | Uplink |
|---|---|---|---|
nodes/sirith_tetrahedral |
pico2_w (RP2350) |
4-mic TDM via ADAU7112, 32 kHz | CYW43 WiFi |
nodes/sirith_planar |
pico2 (RP2350) |
5-mic PDM planar array, 48 kHz | ESP32-C5 companion |
nodes/point_single_mic |
esp32dev |
single I2S mic | ESP32 WiFi |
Used by every Pico-SDK node:
- node protocol payload builder (
POST /api/v1/ingest/frame) and base64 PCM encoding NodeClockframe timestamping,GpsPpsTimerCapturePPS discipline, andClockHoldoverModelfor drift estimation across PPS gapsNmeaGpsSourceUART time/position ingestAudioTransportQos— backpressure and drop policy on the uplinkIUplinkTransportabstraction (CYW43 or ESP32-C5 behind the same interface)IAudioSource+NodeRunnerpublisher loop- optional sensors: SHT4x environmental, LSM6 temperature, LIS2MDL magnetometer with
MagAutoOrientationsmoothing, piezo buzzer
minimap_node_core is the older PlatformIO-only equivalent, still used by the ESP32 point node.
Four-channel TDM capture from an ADAU7112 on a Pico 2 W (RP2350). The Pico drives BCLK/FSYNC
in master mode, samples SDATA, and reconstructs four slots per frame via PIO.
Also supports optional BLE scanning (MMPR_ENABLE_BLE_SCAN), posting observations to
/api/v1/ingest/ble.
Edit nodes/sirith_tetrahedral/include/node_config.h:
MMPR_NODECFG_AUDIO_INPUT_MODE—0TDM 4-mic,1I2S mono,3synthetic (no hardware)- WiFi credentials and
MMPR_NODECFG_SERVER_BASE_URL - audio rate/channels/frame size (
32000Hz,4,512by default) - TDM sample edge, capture bit offset, and data-pin bias
MMPR_NODECFG_GPS_PPS_PINand GPS UART settings- BLE scan intervals and audio-queue watermarks
- optional LSM6 IMU temperature telemetry (
metadata.temperature_c,metadata.temperature_source)
This target uses the Raspberry Pi Pico SDK via CMake, not PlatformIO. The easiest path is the
Raspberry Pi Pico VS Code extension, which provisions the toolchain under ~/.pico-sdk/ and wires
up the Compile Project / Run Project tasks in .vscode/tasks.json.
From the command line, using that same toolchain:
cd firmware/nodes/sirith_tetrahedral
~/.pico-sdk/cmake/v3.31.5/bin/cmake -S . -B build -G Ninja \
-DCMAKE_MAKE_PROGRAM=~/.pico-sdk/ninja/v1.12.1/ninja
~/.pico-sdk/ninja/v1.12.1/ninja -C build
~/.pico-sdk/picotool/2.2.0-a4/picotool/picotool load build/sirith_tetrahedral.uf2 -fxAdjust the version directories to match what your ~/.pico-sdk/ actually contains — the extension
pins them per install.
Five-mic coplanar PDM array on a plain Pico 2 (RP2350): four corner mics at a 25 mm radius plus one
center mic, all at z = 0. PDM is captured over three data lines (2+2+1 sharing) and decimated on
core 1 by PdmCicDecimator — see lib/minimap_audio_pico/PDM_DESIGN.md.
The board is deliberately pico2 rather than pico2_w so no CYW43/lwIP/btstack is linked in; WiFi
is offloaded to an ESP32-C5 companion over minimap_transport_espc5.
Coplanar arrays have a mirror ambiguity about their plane, so the server applies a half_space
constraint (upper by default for sirith_planar nodes) to fold mirror-symmetric solutions.
Configure via nodes/sirith_planar/include/node_config.h; build exactly as for the tetrahedral node,
substituting the target name. Hardware notes are in
nodes/sirith_planar/HARDWARE_REVIEW.md.
A single-mic ESP32 target on the PlatformIO/Arduino runtime — the simplest node that speaks the protocol, and the reference for adding new ESP32-class hardware.
cd firmware/nodes/point_single_mic
pio run
pio run -t upload
pio device monitorThe pico-free model code (clock holdover, transport QoS, PDM decimation) builds and runs off-target with a plain host toolchain:
cd firmware/nodes/sirith_tetrahedral/tests/host # or nodes/sirith_planar/tests/host
cmake -S . -B build && cmake --build build && ctest --test-dir buildmacOS note: if the Command Line Tools libc++ headers are broken in your environment, the host build fails at
#include <vector>and similar. Point the compiler at the SDK's copy explicitly:-DCMAKE_CXX_FLAGS="-isystem $(xcrun --show-sdk-path)/usr/include/c++/v1".
lib/minimap_transport_espc5/tests/host follows the same pattern.
Nodes timestamp frames from NodeClock, disciplined in order of preference:
- GPS PPS —
GpsPpsTimerCapturelatches the RP2350 timer on each PPS edge;NmeaGpsSourcesupplies absolute time from the UART sentences. Reportstime_quality: gps_locked. - Holdover — when PPS drops out,
ClockHoldoverModelextrapolates from the measured drift rate rather than falling straight back to free-running. - NTP sync at startup (ESP32 targets), then monotonic frame stepping. Reports
ntp_syncorfree_running.
Time quality is sent per frame and used by the server to weight fusion.
Pico SDK (CMake) family — copy nodes/sirith_planar as the template:
- Create
nodes/<new_node>/withCMakeLists.txt,pico_sdk_import.cmake,include/node_config.h, and a<new_node>.cppmain. add_subdirectorythe runtime, an audio lib, and a transport lib from../../lib, and includelib/cmake/mmpr_nodecfg.cmaketo forward yournode_config.hsettings.- Implement an
IAudioSourcefor the hardware inlib/minimap_audio_picoor a new hardware lib. - Reuse
NodeRunner,NodeClock, and theIUplinkTransportimplementations.
PlatformIO family — copy nodes/point_single_mic:
- Create
nodes/<new_node>/withplatformio.ini,src/main.cpp,include/node_config.h. - Set
lib_extra_dirs = ../../libsominimap_node_coreand the audio libs resolve. - Implement an
IAudioSourceinlib/minimap_audio_esp32or a new hardware lib.
Either way, fill the NodeDescriptor with real geometry and capabilities — the server derives
sensor_offsets_m, half-space constraints, and localization strategy from it. That keeps protocol
and transport behavior consistent across all node types.