Compile supported Pure Data (Pd) patches into standalone audio firmware for the Raspberry Pi RP2350, using Heavy/hvcc and the Pico SDK. Create patches in Pure Data or plugdata, then build your own synthesizer with I2S audio output and configurable hardware controls.
Patches are compiled ahead of time into C/C++ and included in the firmware. Changing a patch requires rebuilding and flashing the device. Only the objects supported by hvcc can be compiled; this project does not provide a libpd runtime.
- Audio: 48 kHz, stereo, 16-bit PCM over I2S.
- Hardware controls: optional potentiometers, MPR121 capacitive touch, OLED display, buttons, and WS2812 LEDs.
- MIDI: optional USB MIDI input from a host; TRS MIDI support is in progress.
- Build: one Python entrypoint with pinned Python tooling and vendored SDK submodules.
Quick start · Write your own patch · Configuration · Documentation
The maintainer's setup uses a Waveshare RP2350-Zero and a PCM5102/PCM5102A I2S DAC. These are sufficient for the first example; the display, buttons, potentiometers, and touch controller are optional.
Default I2S signal connections:
- DAC DIN → GPIO 5
- DAC LCK / LRCLK / WS → GPIO 6
- DAC BCK / BCLK → GPIO 7
Connect the board and DAC to a common ground and follow your DAC module's power and mode requirements. See configuration for pin overrides.
The build targets waveshare_rp2350_zero by default. Other RP2350 boards, including Raspberry Pi Pico 2, require their own board configuration and hardware validation. RP2040 is outside the current target.
Host support: Windows is actively used and tested by the maintainer; Linux and macOS are best effort. Reports of working configurations are welcome.
- Python 3.9+ and Git.
- ARM GCC toolchain, with
arm-none-eabi-gccandarm-none-eabi-g++onPATH, orPICO_TOOLCHAIN_PATHset to the toolchain root containingbin/. - Host C/C++ compiler for Pico SDK tools such as
pioasm: GCC, LLVM/Clang, or Visual Studio Build Tools with the C++ workload. On Windows, use a developer shell when relying on MSVC.
On Linux, the usual packages are gcc-arm-none-eabi and build-essential. On macOS, install an ARM GCC toolchain and Xcode Command Line Tools.
The next step installs pinned hvcc, CMake, and Ninja from requirements.txt; separate system installations of CMake and Ninja are unnecessary. The Pico SDK and pico-extras are included as submodules.
git clone --recurse-submodules https://github.com/berkut0/Pureberry.git
cd PureberryFor an existing checkout, run git submodule update --init --recursive from its root.
Windows PowerShell:
python -m venv venv
& .\venv\Scripts\Activate.ps1
python -m pip install -r requirements.txtLinux / macOS shell:
python3 -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txtKeep the environment active for all build commands. The build script uses hvcc from PATH; third_party/hvcc is a source/tests reference, not the compiler executable used for builds. Keep dependency versions aligned with requirements.txt when reproducing a build.
Run from the repository root:
python scripts/build_firmware.py pd-patches/hv_sine_simple_test.pd --no-ws2812This patch generates a continuous 440 Hz sine wave on both channels. The command disables WS2812 output; OLED, MPR121, and USB MIDI are already disabled by default.
The UF2 file is normally written to:
build/hv_sine_simple_test/firmware-build/rp2350_puredata_firmware.elf.uf2
If a build directory is locked on Windows, the script can select a timestamped directory instead; use the artifact path printed in the build output.
Put the board into BOOTSEL mode and copy the .uf2 file to its mounted mass-storage drive. After reboot, the example should produce the tone through the DAC's analog outputs.
Alternatively, with picotool installed and the board in BOOTSEL mode:
picotool load build/hv_sine_simple_test/firmware-build/rp2350_puredata_firmware.elf.uf2
picotool reboot- Start with an included patch in Pure Data or plugdata.
- In plugdata, enable Compile Mode to identify objects unsupported by its compiler. Check compatibility with the project's pinned hvcc version as well; the tool versions may differ.
- Connect your audio signals to
[dac~]and save the.pdfile. - Build it with
python scripts/build_firmware.py path/to/your_patch.pd, adding the feature flags your hardware needs, then flash the resulting UF2.
Examples to explore:
- Basic oscillator sequence
- USB MIDI synthesizer — build with
--usb-midi; see the MIDI guide. - Potentiometer controls — enable the ADC backend described below.
- WS2812 LED control
- MPR121 touch input — build with
--mpr121.
For object compatibility, see the hvcc documentation and its supported/unsupported object lists for the compiler version you use. The build script automatically adds the vendored heavylib abstraction search path; additional paths can be supplied through HVCC_SEARCH_PATHS.
Defaults are in core/src/config.h. For local overrides, copy core/src/config_local.h.example to core/src/config_local.h and adjust the relevant settings.
- I2S:
PICO_AUDIO_I2S_DATA_PIN,PICO_AUDIO_I2S_CLOCK_PIN_BASE, andPICO_AUDIO_I2S_CLOCK_PINS_SWAPPED. The clock pins must be consecutive. - I2C: define buses with
I2C_BUS0_*/I2C_BUS1_*, then select them withOLED_I2C_BUS_ID/MPR121_I2C_BUS_ID. Default bus 0 uses GPIO 2/3; WS2812 uses GPIO 16. - Potentiometers: disabled by default. Set
POTS_BACKENDtoPOTS_BACKEND_ADC; choosePOTS_ADC_FIRST_CHANNELandPOTS_COUNT. ADC channels map to GPIO 26–29 on RP2350A and GPIO 40–47 on RP2350B.
WS2812 is enabled by default. OLED, MPR121, USB MIDI, and I2C DMA are disabled by default.
# Enable selected peripherals for a MIDI patch
python scripts/build_firmware.py pd-patches/midi_synth_example.pd --usb-midi --oled --mpr121 --i2c-dma
# Disable WS2812 for a minimal audio build
python scripts/build_firmware.py pd-patches/hv_sine_simple_test.pd --no-ws2812
# Override individual CMake options
python scripts/build_firmware.py pd-patches/hv_sine_simple_test.pd -D ENABLE_OLED=ON -D ENABLE_WS2812=OFF
# Use the optional 240 MHz overclock profile
python scripts/build_firmware.py pd-patches/hv_sine_simple_test.pd --overclockedWithout --overclocked, the clock profile follows config.h / config_local.h. The flag forces FW_SYS_CLOCK_PROFILE_OC_240MHZ and defaults PICO_FLASH_SPI_CLKDIV=4, unless explicitly overridden with -D.
- MIDI input: use standard Pd objects such as
[notein]and[ctlin]; see docs/MIDI.md. - Potentiometers: receive normalized values with
[r knob1 @hv_param 0 1 0]throughknob4for the default four-channel configuration. Values arrive only when they change and the ADC backend is enabled. Polling, deadband, and smoothing are configurable. - Other inputs: use
@hv_paramfor scalar state; use ordinary receivers/messages for events. Match names to the routes implemented in patch_api.c. - LED output: the supported command is
set_led_colorwith three floats(r g b)in the range 0–1 or 0–255; it sets all LEDs. It requires WS2812 support.
Use -v for live build output or -d for full commands and paths. -q limits console output to errors. These options affect the console only; full output is always saved to:
build/<patch>/build_firmware.log— latest run, overwritten on each build.build/<patch>/logs/build_firmware_<timestamp>.log— archive for each run.
For build failures, check submodules, the active venv, and both toolchains first. For missing audio, check DAC power, common ground, and I2S wiring. See technical troubleshooting for more detail.
When reporting a problem, include your OS, board and DAC, exact build command, first error block, and the log from that run.
- TECH.md — build internals, audio pipeline, multicore contracts, and troubleshooting.
- MIDI guide — USB MIDI setup and patch-side usage.
- Patch API implementation — hardware input routes and output commands.
- Example patches — starting points for your own patches.
Audio processing runs on core1; USB and peripheral servicing run on core0. Core0 publishes control events to ctrl_queue, which core1 drains before processing each audio block. Patch LED commands publish mailbox state; core0 applies the hardware update. Driver and send-hook rules are documented in TECH.md.
Repository layout: pd-patches/ contains patches, core/ contains firmware, scripts/ contains build tooling, sdk/ and third_party/ contain dependencies, and build/ contains generated output.
Useful contributions include reproducing builds on Linux/macOS, testing another RP2350 board, adding hvcc-compatible example patches, and improving setup instructions. Include the commit, tool versions, hardware configuration, and build command when reporting a working setup or a bug.
I started experimenting with Pure Data firmware on RP2040 in late 2023. The RP2350's FPU encouraged me to revisit the project and publish the build system for others interested in making their own audio hardware.
Pureberry is intended for people who enjoy working with both patches and embedded hardware. The goal is to make that path easier to reproduce and improve together.
Pureberry is licensed under the MIT License. Third-party dependencies retain their own licenses.