Skip to content
berkut0Public

About

Compile Pure Data (Pd) patches into standalone RP2350 audio firmware with Heavy/hvcc and the Pico SDK. I2S output and configurable hardware controls.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Repository files navigation

Pureberry — Pure Data to RP2350 firmware

Pureberry — Pure Data to RP2350 firmware

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

Hardware and support

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.

Quick start

1. Install prerequisites

  • Python 3.9+ and Git.
  • ARM GCC toolchain, with arm-none-eabi-gcc and arm-none-eabi-g++ on PATH, or PICO_TOOLCHAIN_PATH set to the toolchain root containing bin/.
  • 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.

2. Get the sources and prepare the environment

git clone --recurse-submodules https://github.com/berkut0/Pureberry.git
cd Pureberry

For 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.txt

Linux / macOS shell:

python3 -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txt

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

3. Build the included example

Run from the repository root:

python scripts/build_firmware.py pd-patches/hv_sine_simple_test.pd --no-ws2812

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

4. Flash the firmware

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

Write your own patch

  1. Start with an included patch in Pure Data or plugdata.
  2. 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.
  3. Connect your audio signals to [dac~] and save the .pd file.
  4. 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:

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.

Configuration

Board and peripherals

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, and PICO_AUDIO_I2S_CLOCK_PINS_SWAPPED. The clock pins must be consecutive.
  • I2C: define buses with I2C_BUS0_* / I2C_BUS1_*, then select them with OLED_I2C_BUS_ID / MPR121_I2C_BUS_ID. Default bus 0 uses GPIO 2/3; WS2812 uses GPIO 16.
  • Potentiometers: disabled by default. Set POTS_BACKEND to POTS_BACKEND_ADC; choose POTS_ADC_FIRST_CHANNEL and POTS_COUNT. ADC channels map to GPIO 26–29 on RP2350A and GPIO 40–47 on RP2350B.

Build options

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 --overclocked

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

Patch controls

  • 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] through knob4 for 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_param for 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_color with three floats (r g b) in the range 0–1 or 0–255; it sets all LEDs. It requires WS2812 support.

Troubleshooting

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.

Documentation

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.

Contributing

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.

Project background

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.

License

Pureberry is licensed under the MIT License. Third-party dependencies retain their own licenses.

About

Compile Pure Data (Pd) patches into standalone RP2350 audio firmware with Heavy/hvcc and the Pico SDK. I2S output and configurable hardware controls.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages