Skip to content

chronick/duopulse

Repository files navigation

DaisySP Patch.Init Eurorack Firmware

Custom firmware for the Patch.Init Eurorack module using DaisySP DSP library.

Overview

This project provides a custom firmware implementation for the Electro-Smith Patch.Init Eurorack module. The Patch.Init is a versatile eurorack module featuring:

  • 2x CV inputs (±5V)
  • 2x CV outputs (±5V)
  • 2x audio inputs
  • 2x audio outputs
  • Multiple GPIO pins for buttons, LEDs, and encoders
  • STM32H7 microcontroller with floating-point unit

DuoPulse v5: 2-Voice Algorithmic Drum Sequencer

DuoPulse v5 is an opinionated 2-voice percussion sequencer designed for electronic music from club-ready techno to experimental IDM. Version 5 features zero shift layers - every parameter is directly accessible through 8 knobs across two modes.

Core Design Philosophy

  1. Zero shift layers: Every parameter directly accessible
  2. CV law: CV1-4 always modulate performance parameters regardless of mode
  3. Knob pairing: Related functions across Performance/Config modes
  4. Deterministic variation: Same settings + seed = identical output

Control Layout

Performance Mode (Switch UP)

Knob Parameter 0% 100%
K1 ENERGY Sparse Busy
K2 SHAPE Stable (euclidean) Wild (weighted random)
K3 AXIS X Grounded (downbeats) Floating (offbeats)
K4 AXIS Y Simple Complex

Config Mode (Switch DOWN)

Knob Parameter 0% 100%
K1 CLOCK DIV ÷4 (slow) ×4 (fast)
K2 SWING Straight Heavy swing
K3 DRIFT Locked (same each phrase) Evolving
K4 ACCENT Flat (all hits equal) Dynamic (ghosts to accents)

Key Features

SHAPE Zones: Three-way pattern character blending

  • 0-30% STABLE: Humanized euclidean, techno, four-on-floor
  • 30-70% SYNCOPATED: Funk, displaced, tension
  • 70-100% WILD: IDM, chaos, weighted random

Voice Relationship (COMPLEMENT): Voice 2 (shimmer) fills gaps in Voice 1 (anchor) pattern. DRIFT controls placement variation.

ACCENT Velocity: Position-aware dynamics from ghost notes to accents based on metric weight.

AUX Output: Fill Gate (default) or secret Hat Burst mode via Hold+Switch gesture.

CV Inputs (Always Modulate Performance Params)

CV Modulates Range
CV 1 ENERGY ±50%
CV 2 SHAPE ±50%
CV 3 AXIS X ±50%
CV 4 AXIS Y ±50%

Power-On Behavior

Fresh-start boot: All settings reset to musical defaults

  • Performance knobs read from hardware immediately
  • ENERGY=50%, SHAPE=30%, AXIS X/Y=50%
  • CLOCK DIV=×1, SWING=50%, DRIFT=0%, ACCENT=50%
  • Nothing persists across power cycles

See docs/specs/ for the complete specification.

Prerequisites

  • Hardware: Electro-Smith Patch.Init Eurorack module
  • Software:
    • ARM GCC toolchain (for STM32)
    • arm-none-eabi-gcc compiler
    • make build system
    • dfu-util for firmware deployment (or STM32CubeProgrammer)
    • For testing: Catch2 testing framework (optional)
  • DaisySP: Included as a git submodule

Installing Dependencies

macOS (using Homebrew):

brew install arm-none-eabi-gcc dfu-util

Linux (Debian/Ubuntu):

sudo apt-get update
sudo apt-get install gcc-arm-none-eabi dfu-util make

Catch2 (for unit testing):

# Option 1: Install system-wide (recommended)
git clone https://github.com/catchorg/Catch2.git
cd Catch2
cmake -Bbuild -H. -DBUILD_TESTING=OFF
sudo cmake --build build/ --target install

# Option 2: Use package manager
# macOS: brew install catch2
# Linux: sudo apt-get install catch2 (if available)

Project Structure

.
├── DaisySP/              # DaisySP library (git submodule)
├── src/                  # Source files
│   ├── main.cpp         # Main firmware entry point
│   └── ...
├── inc/                  # Header files
│   └── ...
├── tests/                # Unit tests
│   ├── test_main.cpp    # Test runner
│   └── ...
├── Makefile             # Build configuration
├── setup.sh             # Setup script for initial configuration
├── .cursor/             # Cursor IDE rules
│   └── rules
└── README.md            # This file

Build Instructions

Initial Setup

Quick Setup (recommended):

# Clone the repository
git clone --recursive https://github.com/yourusername/duopulse.git
cd duopulse

# Run setup script (initializes submodules and builds DaisySP)
./setup.sh

# Build the firmware
make

Manual Setup:

  1. Clone the repository (including submodules):

    git clone --recursive https://github.com/yourusername/duopulse.git
    cd duopulse

    If you've already cloned without submodules:

    git submodule update --init --recursive
  2. Build DaisySP library:

    cd DaisySP
    make
    cd ..
  3. Build the firmware:

    make

Build Targets

  • make or make all - Build the firmware
  • make clean - Remove build artifacts
  • make rebuild - Clean and rebuild
  • make test - Build and run unit tests
  • make program - Flash firmware to Patch.Init module (requires DFU mode)
  • make daisy-update - Update DaisySP submodule to latest version

Build Configuration

The Makefile supports the following variables:

  • DAISYSP_PATH - Path to DaisySP (default: ./DaisySP)
  • BUILD_DIR - Build output directory (default: build)
  • TARGET - Target board (default: patch)
  • DEBUG - Enable debug symbols (set DEBUG=1)

Example:

make DEBUG=1 BUILD_DIR=debug_build

Test Instructions

Running Unit Tests

The project includes a unit test framework using Catch2:

  1. Run all tests:

    make test
  2. Run specific test:

    ./build/test_runner [test_name]
  3. Run tests with verbose output:

    ./build/test_runner --success

Writing Tests

Tests are located in the tests/ directory. Each test file should:

  • Include the Catch2 header: #include <catch2/catch.hpp>
  • Use TEST_CASE() macro for test cases
  • Use REQUIRE() or CHECK() for assertions

Example:

#include <catch2/catch.hpp>
#include "../src/my_module.h"

TEST_CASE("MyModule processes audio correctly")
{
    MyModule module;
    module.Init(48000.0f);
    
    float input = 0.5f;
    float output = module.Process(input);
    
    REQUIRE(output >= -1.0f);
    REQUIRE(output <= 1.0f);
}

Test Coverage

To generate test coverage reports:

make test-coverage

This requires gcov and lcov to be installed.

Deploy Instructions

Preparing the Module

  1. Enter DFU (Device Firmware Update) mode:

    • Power off the module
    • Hold the BOOT button (if available) or use the DFU jumper
    • Power on the module while holding BOOT
    • Release BOOT button
    • The module should now be in DFU mode
  2. Verify DFU mode:

    dfu-util --list

    You should see the STM32 device listed.

Flashing Firmware

Method 1: Using Makefile (recommended)

make program

Method 2: Using dfu-util directly

dfu-util -a 0 -s 0x08000000:leave -D build/patch-init-firmware.bin

Method 3: Using STM32CubeProgrammer

  1. Open STM32CubeProgrammer
  2. Select "USB" connection
  3. Connect to the device
  4. Load the .bin or .hex file from build/
  5. Click "Download"

Post-Flash

After flashing:

  1. Power cycle the module (or use :leave flag with dfu-util)
  2. The module should boot with the new firmware
  3. Test audio and CV I/O to verify functionality

Troubleshooting

  • Device not found: Ensure module is in DFU mode and USB cable is connected
  • Permission denied: Add udev rules for STM32 DFU devices (Linux) or run with sudo
  • Flash fails: Verify module is in DFU mode and try resetting the module

Upgrading DaisySP

Update to Latest Version

  1. Navigate to DaisySP directory:

    cd DaisySP
  2. Fetch and checkout latest version:

    git fetch origin
    git checkout master  # or specific tag/commit
    git pull origin master
  3. Rebuild DaisySP:

    make clean
    make
  4. Return to project root and rebuild:

    cd ..
    make clean
    make

Update to Specific Version/Tag

cd DaisySP
git fetch --tags
git checkout v1.0.0  # Replace with desired version
make clean
make
cd ..
make clean
make

Update Submodule Reference

After updating DaisySP, commit the submodule reference:

git add DaisySP
git commit -m "Update DaisySP to version X.X.X"

Checking Current Version

cd DaisySP
git describe --tags
cd ..

Development Workflow

  1. Create a feature branch:

    git checkout -b feature/my-feature
  2. Make changes and test:

    make clean
    make
    make test
  3. Flash and test on hardware:

    make program
  4. Commit changes:

    git add .
    git commit -m "Description of changes"
  5. Push and create pull request

Hardware Configuration

Patch.Init Pin Assignments

Refer to the Patch.Init documentation for specific pin assignments. Common configurations:

  • CV Inputs: ADC channels 0-1
  • CV Outputs: DAC channels 0-1
  • Audio Inputs: I2S/SAI interface
  • Audio Outputs: I2S/SAI interface
  • GPIO: Configurable via daisy::GPIO

Sample Rate

Default sample rate: 48kHz

To change:

patch.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_96KHZ);

Block Size

Default block size: 4 samples

To change:

patch.SetAudioBlockSize(8);

Contributing

  1. Follow the coding standards in .cursor/rules
  2. Write unit tests for new features
  3. Update documentation as needed
  4. Test on hardware before submitting PR

License

[Specify your license here]

Resources

Troubleshooting

Build Issues

  • Missing toolchain: Install ARM GCC toolchain
  • DaisySP not found: Run git submodule update --init --recursive
  • Linker errors: Ensure DaisySP is built (cd DaisySP && make)

Runtime Issues

  • No audio output: Check audio callback registration and hardware connections
  • CV not working: Verify ADC/DAC configuration and pin assignments
  • Module crashes: Check for stack overflow, uninitialized variables, or division by zero

Debugging

Enable debug output:

make DEBUG=1

Use a debugger (OpenOCD + GDB) for hardware debugging:

make debug

Runtime Logging

The firmware includes a USB serial logging system for debugging without a hardware debugger.

Viewing Log Output:

# macOS/Linux - using screen
screen /dev/tty.usbmodem* 115200

# Alternative - using make target (saves to /tmp)
make listen

# Exit screen: Ctrl-A then \ then y

Log Levels:

  • TRACE: Verbose debugging
  • DEBUG: Development info (mode changes, events)
  • INFO: Normal operation (boot, config)
  • WARN: Warnings
  • ERROR: Critical issues

Configuration:

Adjust log levels in Makefile:

# Development: DEBUG+ logs, default INFO
CXXFLAGS += -DLOG_COMPILETIME_LEVEL=1
CXXFLAGS += -DLOG_DEFAULT_LEVEL=2

# Release: WARN/ERROR only
CXXFLAGS += -DLOG_COMPILETIME_LEVEL=3
CXXFLAGS += -DLOG_DEFAULT_LEVEL=3

See CLAUDE.md for complete logging documentation.

Support

For issues and questions:

  • Open an issue on GitHub
  • Check the DaisySP documentation
  • Visit the Daisy Forum

About

A two-channel eurorack sequencer for Daisy SP and Patch.init()

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors