A powerful, modular eurorack and MIDI synthesizer controller built on the RP2350B microcontroller. Faderpunk provides 16 channels of flexible, programmable control with faders, buttons, CV jacks, and full MIDI integration, all configured through an intuitive web interface.
Faderpunk is an embedded Rust project that uses an RP2350B to create a feature-rich eurorack and MIDI controller. Each of the 16 channels can run a different "app" - from LFOs and sequencers to MIDI converters and Turing machines - creating a highly versatile control surface for modular synthesis.
- 16 Independent Channels: Each channel features a fader, button, RGB LED, and configurable CV jack
- Modular App Architecture: Run different apps on different channels simultaneously
- Dual-Core Performance: Hardware tasks on Core 0, application logic on Core 1
- WebUSB Configuration: Browser-based configurator with drag-and-drop layout management
- FRAM Storage: Persistent scene storage with fast save/recall
- Full MIDI Support: USB MIDI device capabilities
- I2C Integration: Compatible with 16n faderbank protocol
- Real-time Control: Async architecture ensures responsive performance
- RP2350B (Raspberry Pi Pico 2)
- Dual Cortex-M33 cores @ 150 MHz (overclocked to 250MHz)
- 520 KB SRAM
- MAX11300: 20-port programmable mixed-signal I/O (ADC/DAC)
- FM24V10: 1 Mbit FRAM for persistent storage
- WS2812B: RGB LED chains for visual feedback
- 16 faders, 16 buttons, configurable CV jacks per channel
Faderpunk uses a sophisticated dual-core architecture to maximize performance:
Runs dedicated Embassy async tasks for hardware interfaces:
- MAX11300 ADC/DAC communication
- Button scanning and debouncing
- LED control (WS2812B)
- MIDI input/output
- FRAM storage operations
- I2C communication
- WebUSB protocol handling
Executes user-facing apps:
- Each app runs as an independent Embassy task
- Apps receive hardware events via PubSub channels
- Apps send commands to hardware via async channels
- Clean abstraction through the
App<N>API
- Event PubSub: Broadcasts input events (button presses, fader changes, MIDI) to all apps
- Command Channel: Apps send hardware commands (set LED color, configure CV, send MIDI)
- Watch Channels: Global configuration and clock synchronization
- Serialization: Postcard format for efficient no_std data exchange
- Raspberry Pi Pico 2 (RP2350B)
- Faderpunk PCB with supporting components
- USB cable for programming and power
- Rust toolchain (nightly recommended)
picotoolfor UF2 conversion- Chromium-based browser for WebUSB configurator
You will need:
rustup- Rust (1.89 or newer) with
thumbv8m.main-none-eabihftarget (rustup target add thumbv8m.main-none-eabihf) - picotool
cd faderpunk # important, not in root
cargo build --releaseUse the provided script to build and convert to UF2 format:
# this needs to be done in the repository root
./build-uf2.shThis creates target/thumbv8m.main-none-eabihf/release/faderpunk.uf2
- Hold the SHIFT button (the one on the very bottom right, the yellow one) while connecting Faderpunk to your computer via USB.
- Device appears as a mass storage device
- Copy
faderpunk.uf2to the device - Device automatically reboots with new firmware
For rapid development with debug output:
cd faderpunk
cargo build
# Use probe-rs or similar tool for flashing with RTT debug outputThe Faderpunk Configurator is a React/TypeScript web application that communicates with the device via WebUSB.
- Drag-and-drop layout management
- Real-time parameter configuration
- Global settings (MIDI, I2C, clock, quantizer)
- Scene management
- Live visual feedback
You will need:
Before building the configurator you'll need to run
# in the root
./gen-bindings.shThis will create the Postcard bindings for the configurator (from libfp).
cd configurator
pnpm install
pnpm devAccess at http://localhost:5173
NOTE: When changes to libfp happen, the bindings will need to be regenerated. Delete the node_modules folder in configurator and do the following steps in that case.
WebUSB requires:
- Chrome/Chromium
- Edge
- Opera
- Brave
- Vivaldi or any Chromium-based browser
Firefox and Safari do not support WebUSB.
For more details, see configurator/README.md
faderpunk/
├── faderpunk/ # Main firmware crate
│ ├── src/
│ │ ├── main.rs # System initialization, core orchestration
│ │ ├── app.rs # App API and abstractions
│ │ ├── apps/ # App implementations
│ │ ├── tasks/ # Hardware driver tasks
│ │ ├── events.rs # Event types
│ │ ├── storage.rs # FRAM persistence
│ │ └── layout.rs # Channel layout management
│ └── Cargo.toml
├── libfp/ # Shared library
│ ├── src/ # Common types and utilities
│ └── Cargo.toml
├── configurator/ # Web configurator
│ ├── src/
│ └── package.json
├── gen-bindings/ # TypeScript binding generator
└── Cargo.toml # Workspace configuration
- Create a new file in
faderpunk/src/apps/my_app.rs:
use embassy_futures::select::select;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal};
use libfp::{AppIcon, Brightness, Color, Config, Range};
use crate::app::{App, Led};
pub const CHANNELS: usize = 1;
// App configuration visible to the configurator
pub static CONFIG: Config<0> = Config::new(
"My App",
"Description of what this app does",
Color::Blue,
AppIcon::Fader,
);
// Wrapper task - required for all apps
#[embassy_executor::task(pool_size = 16/CHANNELS)]
pub async fn wrapper(app: App<CHANNELS>, exit_signal: &'static Signal<NoopRawMutex, bool>) {
// Exit handler allows clean shutdown when app is removed from layout
select(run(&app), app.exit_handler(exit_signal)).await;
}
// Main app logic
pub async fn run(app: &App<CHANNELS>) {
let output = app.make_out_jack(0, Range::_0_10V).await;
let fader = app.use_faders();
let buttons = app.use_buttons();
let leds = app.use_leds();
leds.set(0, Led::Button, Color::Blue, Brightness::Mid);
loop {
buttons.wait_for_down(0).await;
let value = fader.get_value();
output.set_value(value);
leds.set(0, Led::Top, Color::Blue, Brightness::Custom((value / 16) as u8));
}
}- Register in
faderpunk/src/apps/mod.rs
42 => my_app,- Build the firmware and see if you can find your app in the configurator
# Check compilation
cargo check
# Run Clippy linter
cargo clippy
# Format code
cargo fmtThe project uses defmt for structured logging:
defmt::info!("Button pressed on channel {}", channel);View logs using probe-rs or similar RTT-capable debugger.
Faderpunk uses a 1 Mbit FRAM (FM24V10) for persistent storage:
- Fast writes (no wear leveling needed)
- Scene-based storage system
- Apps can save/load state via serialization
- Global configuration persistence
Apps implement scene save/load by serializing their state with postcard.
- USB MIDI device (shows as MIDI interface to host)
- Configurable channel routing
- Full MIDI message support via
midlycrate
- 16n faderbank protocol support
- Eurorack module integration
- Configurable addressing
- COBS framing for reliable packet transmission
- Postcard serialization for compact binary protocol
- Type-safe message definitions shared between firmware and configurator
- Real-time bidirectional communication
The workspace Cargo.toml configures aggressive optimization:
[profile.release]
lto = true
incremental = false
codegen-units = 1
debug = 2This maximizes performance while retaining debug symbols for profiling.
Contributions are welcome! Please follow the Rust Code of Conduct.
- Use
cargo fmtandcargo clippybefore committing - Test on hardware when possible
- Document new apps and features
- Update TypeScript bindings when changing protocol types
- Fork the repository
- Create a feature branch
- Make your changes with clear commit messages
- Ensure code passes clippy and builds successfully (warnings are, for the most part ok and expected at this point)
- Test on hardware if applicable
- Submit a pull request with a clear description
Faderpunk uses knope for release management on a single main branch:
- Stable releases: Automated via release PR flow
- Beta releases: Triggered manually via GitHub Actions
workflow_dispatch
Stable releases are fully automated:
- Push commits to
mainusing conventional commits (e.g.,feat:,fix:) - Release PR auto-created: The
prepare-releaseworkflow creates/updates areleasebranch and PR with version bumps and changelogs - Review the release PR: Edit changelogs if needed, verify version bumps
- Merge the release PR: This triggers the
releaseworkflow which:- Builds firmware (ELF + UF2) if faderpunk version changed
- Builds configurator if configurator version changed
- Creates GitHub releases with assets via
knope release - Deploys configurator to GitHub Pages
- Publishes
libfpto crates.io if version changed
Beta releases are triggered manually:
- Go to Actions → Beta Release → Run workflow on GitHub
- The workflow:
- Runs
knope prepare-release --prerelease-label betato bump versions (e.g.,1.8.0-beta.0) - Commits and pushes the version bump to
main - Builds firmware and configurator
- Creates GitHub prereleases via
knope release - Deploys configurator to
/beta/on GitHub Pages
- Runs
- Subsequent dispatches increment the beta number (
beta.1,beta.2, etc.) - Merging a stable release PR resets to the next stable version
- Create a branch from
main, make the fix with afix:commit, open a PR tomain - After merging, the
prepare-releaseworkflow auto-updates the release PR with a patch bump - Merge the release PR to publish
Each release produces:
Firmware (faderpunk/):
faderpunk.elf- ELF binary for debuggingfaderpunk-vX.Y.Z.uf2- UF2 file for flashing to device
Configurator (configurator/):
configurator.zip- Downloadable web app bundle- GitHub Pages deployment (root for stable,
/betafor beta)
Library (libfp/ - stable only):
- Published to crates.io when version changes
This project is licensed under GNU General Public License v3.0 (GPL-3.0).
See LICENSE for full terms.
Faderpunk is developed by ATOV
- UI/UX by Leise St. Clair
- Icon design by papernoise
- Community: Discord Server
- Issues: GitHub Issues
- Website: atov.de
- Dual-core async execution
- Sub-millisecond event response
- 12-bit CV resolution
- USB 1.1 (device and host)
- I2C (configurable speed)
- MIDI (USB and Serial)
- USB-powered
- Eurorack power compatible
Built with embedded Rust, Embassy async runtime, and a passion for modular synthesis.