A comprehensive, type-safe Nim wrapper for the libDaisy hardware abstraction library, enabling elegant Nim development for the Electro-Smith Daisy Seed embedded audio platform.
This wrapper allows you to write firmware for the Daisy Seed embedded audio board using the Nim programming language instead of C++. It provides a clean, type-safe API that wraps libDaisy's hardware abstraction layer.
Key Features:
- Zero overhead - Direct C++ interop with no runtime cost
- Type safety - Nim's strong type system catches errors at compile time
- Clean API - Idiomatic Nim interfaces to libDaisy functionality
- Comprehensive - 90% coverage of libDaisy (user-facing features: 95%)
- Feature complete - 44 examples demonstrating all major functionality (requires testing)
- Well documented - Complete API reference and technical documentation
- 85 modules - Core peripherals, device drivers, UI framework, storage, sensors
- Daisy Seed - STM32H750-based embedded audio board
- USB cable - For programming and power
- Audio I/O (optional) - For audio applications
- Nim - 2.0 or later
- ARM Toolchain -
arm-none-eabi-gccand related tools - libDaisy - The C++ library this wraps (sibling directory)
- dfu-util or st-flash - For uploading firmware
- Clone this wrapper with submodules:
cd /path/to/your/projects
git clone --recursive https://github.com/Brokezawa/nimphea
cd nimphea- One-time setup (clones submodules and builds libDaisy):
nimble init_libdaisyYour directory structure will be:
nimphea/
├── libDaisy/ # C++ library (submodule)
├── src/ # Nim wrapper
├── examples/ # Example programs
└── docs/ # Documentation
- Try an example:
nimble make blink # Build example for ARM Cortex-M7
nimble flash blink # Flash to Daisy via USB (DFU)Note: If you plan to use the ICM20948 9-axis IMU sensor, you must apply a patch to libDaisy first:
cd nimphea
./apply_patches.shThis fixes an upstream bug in libDaisy's ICM20948 magnetometer initialization. See patches/README.md for details. The patch is safe and only affects ICM20948 functionality.
Why is this needed?
- The ICM20948 module in libDaisy has a bug preventing magnetometer initialization
- We've created a minimal 1-line patch that fixes the issue
- This patch has been prepared for upstream submission to libDaisy
- Other sensors (APDS9960, DPS310, TLV493D, MPR121, NeoTrellis) work without patches
See QUICKSTART.md for detailed setup instructions.
The Daisy Seed is a powerful embedded audio platform perfect for:
- Audio Effects - Delays, reverbs, distortion, filters, modulation
- Synthesizers - Wavetable, FM, subtractive, granular synthesis
- Instruments - Samplers, sequencers, drum machines, loopers
- Controllers - MIDI devices, CV interfaces, sensor systems
- Data Systems - Audio recorders, analyzers, data loggers
- Audio I/O - Stereo input/output, 8-96kHz sample rates, DMA-based
- GPIO - 32 configurable pins, all standard modes
- System - Initialization, timing, utilities
- I2C - 4 buses, master/slave modes, up to 1MHz
- SPI - 6 buses, master/slave, full-duplex
- Multi-Slave SPI - Share SPI bus between up to 4 devices
- UART - 6 ports, configurable baud rates
- ADC - Analog inputs, multi-channel, multiplexed
- PWM - Hardware PWM output, 4 channels per timer
- DAC - Analog voltage outputs
- USB Device CDC - Virtual serial port over USB
- USB MIDI - MIDI device and host modes
- USB Host - Mass storage, MIDI devices
- SD Card - SDMMC interface, FatFS filesystem, FAT32 support
- WAV Files - WAV parser, streaming player, real-time recorder
- Wavetable Loading - Multi-bank wavetable loader from SD
- QSPI Flash - 8MB QSPI flash read/write/erase operations
- Persistent Storage - Type-safe settings storage with dirty detection
- External SDRAM - 64MB for large audio buffers
- MIDI - Hardware UART and USB MIDI I/O
- Switches - Debounced switch handling, multiple types
- Encoders - Rotary encoder support with button
- Controls - Analog knobs, CV inputs (uses ADC)
- OLED Displays - SSD1306 driver with I2C/SPI support
- FIFO Queue - Lock-free queue for audio/event buffering
- Stack - Fixed-capacity LIFO stack
- RingBuffer - Circular buffer for delay effects
- FixedStr - Stack-allocated string for displays
- Parameter Mapping - Curve-based control mapping (exp/log/cubic)
- MappedValue - Value scaling and quantization utilities
- UniqueId - STM32 device unique identifier
- CpuLoad - Real-time CPU usage monitoring
- ICM20948 - 9-axis IMU (gyro, accel, magnetometer, temp) - I2C/SPI
- APDS9960 - Gesture/proximity/RGB/light sensor - I2C
- DPS310 - Barometric pressure and altitude sensor - I2C/SPI
- TLV493D - 3D magnetic field sensor - I2C
- MPR121 - 12-channel capacitive touch controller - I2C
- NeoTrellis - 4x4 RGB LED button matrix (Adafruit seesaw) - I2C
- AK4556 - Audio codec for Daisy Seed Rev 4
- WM8731 - I2C audio codec for Daisy Seed Rev 5
- PCM3060 - High-performance codec for Daisy Seed Rev 7
- LCD HD44780 - Character LCD driver (16x2, 20x4)
- OLED Fonts - 8 bitmap fonts for OLED displays
- PCA9685 - 16-channel 12-bit PWM LED driver - I2C
- DotStar - High-speed RGB LED strips (APA102/SK9822) - SPI
- NeoPixel - WS2812B RGB LEDs via I2C bridge (Adafruit Seesaw) - I2C
- 74HC595 - 8-bit shift register (output) - SPI
- 74HC4021 - 8-bit shift register (input) - SPI
- MCP23017 - 16-channel GPIO expander - I2C
- MAX11300 PIXI - 20-channel programmable mixed-signal I/O (ADC/DAC/GPIO) - SPI
- EXPERIMENTAL: Full implementation available but NOT tested on hardware
- Wraps libDaisy C++ driver with complete API coverage
- Should be considered experimental until community validation
- Daisy Seed - Base platform (STM32H750, 480MHz ARM Cortex-M7)
- Daisy Pod - Desktop synthesizer format (encoder, 2 knobs, 2 buttons, RGB LEDs, MIDI)
- Daisy Patch - Eurorack module format (OLED, encoder, 4 CV/knobs, gate I/O, MIDI)
- Daisy Field - Keyboard/CV interface (16-key keyboard, 8 knobs, 26 RGB LEDs, 4 CV I/O)
- Daisy Patch SM - Compact Eurorack (12 CV in, 3 CV out, 4 gate in, PCM3060 codec)
- Daisy Petal - Guitar pedal (7 footswitches, 6 knobs, encoder, 12 RGB LEDs)
- Daisy Versio - Eurorack effect (7 knobs/CV, gate in, 2 switches, 4 RGB LEDs)
- Daisy Legio - Compact utility (encoder, 3 CV in, gate in, 2 switches, 2 RGB LEDs)
- System Control - Clock configuration, timing functions (ms/microseconds), bootloader access
- DMA Cache Coherency - Cache management for STM32H750 DMA operations
- V/Oct Calibration - Eurorack pitch CV calibration (1V/octave tracking)
- Scoped IRQ Blocking - RAII-pattern interrupt control for critical sections
- Logger - USB/UART debug logging with string-based API
- File Table - FAT filesystem indexing for fast file access
The examples/ directory contains 43 feature-complete examples covering:
- Basic - GPIO, LEDs, buttons (blink, button_led, gpio_input)
- Audio - Passthrough, synthesis, effects (sine_wave, distortion_effect)
- File I/O - WAV playback/recording, samplers, loopers, QSPI flash
- Peripherals - ADC, PWM, I2C, SPI, UART, USB, MIDI
- Displays - OLED (I2C/SPI), LCD HD44780 character displays
- Sensors - IMU, gesture, pressure, magnetic, touch controllers
- LED Drivers - PCA9685, DotStar, NeoPixel, shift registers
- I/O Expansion - MCP23017 GPIO expander, MAX11300 PIXI
- Data Structures - FIFO, Stack, RingBuffer, fixed strings
- Board-Specific - Pod, Patch, Field, Patch SM, Petal, Versio, Legio examples
- System - Clock config, logging, timing, CPU monitoring
See EXAMPLES.md for complete testing matrix with expected behavior, hardware requirements, and troubleshooting for all 43 examples.
- QUICKSTART.md - Get started in 5 minutes
- BUILD_SYSTEM.md - Complete build system guide
- API_REFERENCE.md - Complete API documentation
- NIM_FEATURES.md - Why Nim? Language advantages
- EXAMPLES.md - Example testing matrix with expected behavior and hardware requirements
- TESTING_GUIDE.md - Comprehensive hardware testing procedures and checklist
- FLASH_GUIDE.md - QSPI flash memory usage guide
- CONTRIBUTING.md - How to contribute to the project
nimphea/
├── AGENTS.md # AI agent guide
├── README.md # This file
├── LICENSE # License file
├── nimphea.nimble # Nimble package file
│
├── docs/ # Documentation
│ ├── QUICKSTART.md # Quick start guide
│ ├── API_REFERENCE.md # Complete API documentation
│ ├── NIM_FEATURES.md # Nim language advantages
│ ├── BUILD_SYSTEM.md # Build system guide
│ ├── FLASH_GUIDE.md # QSPI flash memory guide
│ ├── EXAMPLES.md # Example testing matrix
│ ├── TESTING_GUIDE.md # Hardware testing procedures
│ └── CONTRIBUTING.md # Contribution guide
│
├── src/ # Wrapper source code (85 modules)
│ ├── nimphea.nim # Core API (GPIO, audio, system)
│ ├── nimphea_macros.nim # Compile-time macro system
│ ├── nimphea_adc.nim # ADC (analog input)
│ ├── nimphea_dac.nim # DAC (analog output)
│ ├── nimphea_pwm.nim # PWM (pulse width modulation)
│ ├── nimphea_gatein.nim # Gate input detection
│ ├── nimphea_timer.nim # Hardware timers
│ ├── nimphea_rng.nim # Random number generator
│ ├── nimphea_oled.nim # OLED displays (SSD1306)
│ ├── nimphea_i2c.nim # I2C communication
│ ├── nimphea_spi.nim # SPI communication
│ ├── nimphea_spi_multislave.nim # Multi-device SPI
│ ├── nimphea_sai.nim # SAI audio peripheral
│ ├── nimphea_serial.nim # UART serial
│ ├── nimphea_midi.nim # MIDI I/O
│ ├── nimphea_usb.nim # USB device/host/MIDI
│ ├── nimphea_sdmmc.nim # SD card interface
│ ├── nimphea_fatfs.nim # FatFS filesystem
│ ├── nimphea_qspi.nim # QSPI flash memory
│ ├── nimphea_persistent_storage.nim # Settings storage
│ ├── nimphea_sdram.nim # External SDRAM
│ ├── nimphea_controls.nim # Switches & encoders
│ ├── nimphea_switch.nim # Debounced button/switch
│ ├── nimphea_switch3.nim # 3-position switch
│ ├── nimphea_led.nim # Single LED control
│ ├── nimphea_rgbled.nim # RGB LED control
│ ├── nimphea_color.nim # Color utilities
│ ├── nimphea_shift_register.nim # Shift register helper
│ ├── nimphea_wavformat.nim # WAV file format constants
│ ├── nimphea_wavparser.nim # WAV file parser
│ ├── nimphea_wavplayer.nim # WAV streaming player
│ ├── nimphea_wavwriter.nim # WAV recorder
│ ├── nimphea_wavetable_loader.nim # Wavetable loader
│ ├── nimphea_fifo.nim # Lock-free FIFO queue
│ ├── nimphea_stack.nim # Fixed-capacity stack
│ ├── nimphea_ringbuffer.nim # Circular buffer
│ ├── nimphea_fixedstr.nim # Stack-allocated string
│ ├── nimphea_parameter.nim # Parameter mapping
│ ├── nimphea_mapped_value.nim # Value utilities
│ ├── nimphea_uniqueid.nim # Device unique ID
│ ├── nimphea_cpuload.nim # CPU load monitoring
│ ├── nimphea_system.nim # System control & timing
│ ├── nimphea_dma.nim # DMA cache coherency
│ ├── nimphea_voct_calibration.nim # V/Oct CV calibration
│ ├── nimphea_scoped_irq.nim # RAII interrupt blocking
│ ├── nimphea_logger.nim # Debug logging
│ ├── nimphea_file_table.nim # FAT filesystem indexing
│ ├── nimphea_pod.nim # Daisy Pod board
│ ├── nimphea_patch.nim # Daisy Patch board
│ ├── nimphea_field.nim # Daisy Field board
│ ├── nimphea_patch_sm.nim # Daisy Patch SM board
│ ├── nimphea_petal.nim # Daisy Petal board
│ ├── nimphea_versio.nim # Daisy Versio board
│ ├── nimphea_legio.nim # Daisy Legio board
│ ├── panicoverride.nim # Embedded panic handler
│ │
│ ├── dev/ # Device drivers (17 modules)
│ │ ├── codec_ak4556.nim # AK4556 audio codec
│ │ ├── codec_wm8731.nim # WM8731 audio codec
│ │ ├── codec_pcm3060.nim # PCM3060 audio codec
│ │ ├── lcd_hd44780.nim # HD44780 character LCD
│ │ ├── icm20948.nim # 9-axis IMU sensor
│ │ ├── apds9960.nim # Gesture/light sensor
│ │ ├── dps310.nim # Pressure sensor
│ │ ├── tlv493d.nim # 3D magnetic sensor
│ │ ├── mpr121.nim # Touch controller
│ │ ├── neotrellis.nim # RGB button matrix
│ │ ├── leddriver.nim # PCA9685 LED driver
│ │ ├── dotstar.nim # APA102 LED strips
│ │ ├── neopixel.nim # WS2812B via seesaw
│ │ ├── mcp23x17.nim # GPIO expander
│ │ ├── sr595.nim # 74HC595 shift register
│ │ ├── sr4021.nim # 74HC4021 shift register
│ │ └── max11300.nim # MAX11300 PIXI
│ │
│ └── ui/ # UI Framework (4 modules)
│ ├── core.nim # UI core types and state
│ ├── events.nim # Event system
│ ├── controls.nim # UI controls (monitors)
│ └── menu_builder.nim # Menu DSL
│
└── examples/ # Example programs (43)
└── *.nim # Example programs
The wrapper uses a compile-time macro system to automatically emit required C++ includes based on which modules you import. No manual include management needed!
import src/nimphea # Automatically includes daisy_seed.h
import src/nimphea_i2c # Automatically includes hid/i2c.hDefine symbols to include only what you need:
# In your code or nimble configuration
{.define: useI2C.}
{.define: useUSB.}All wrapper functions compile to direct C++ calls with no overhead:
hw.setLed(true) # Compiles to: hw.SetLed(true);Nim's type system prevents common embedded errors:
var pin: DaisyPin = DPin0 # Type-safe pin selection
var rate: I2CSpeed = I2C_400KHZ # Enumerated constantsDaisy Seed Features:
- MCU: STM32H750IBK6 (ARM Cortex-M7, 480MHz)
- RAM: 512KB internal + 64MB external SDRAM
- Flash: 128KB internal (bootloader) + 8MB QSPI
- Audio: 24-bit stereo ADC/DAC, up to 96kHz
- GPIO: 32 pins, 3.3V logic
- Interfaces: 4×I2C, 6×SPI, 6×UART, USB, SDMMC
- Storage: MicroSD card slot
- Power: USB or external 3.3-5V
- Compile time: ~0.6s per example (Nim → C++)
- Binary size: ~64KB typical (minimal example)
- Audio latency: <3ms typical (depends on buffer size)
- Memory overhead: Zero - direct C++ interop
Development Machine:
- Linux, macOS, or Windows
- Nim 2.0 or later
- ARM embedded toolchain (
arm-none-eabi-gcc) - dfu-util (for USB flashing) or ST-Link tools
Target Hardware:
- Daisy Seed board
- USB cable for programming
- Power supply (USB or external)
Pure nimble-based build system:
nimble init_libdaisy # One-time: clone submodules, build libDaisy
nimble make <name> # Build example for ARM Cortex-M7
nimble flash <name> # Flash to Daisy via DFU (USB bootloader)
nimble stlink <name> # Flash to Daisy via ST-Link (debug probe)
nimble test # Quick syntax check (fast: ~7 seconds)
nimble test_build # Full build test (slow: ~45 minutes, validates linking)
nimble test_unit # Unit tests on host machine (no hardware needed)
nimble clear # Remove build artifacts
nimble docs # Generate HTML API documentationCommon workflows:
# Build and flash via USB (DFU bootloader)
nimble make blink
nimble flash blink
# Build and flash via ST-Link (faster, no bootloader mode)
nimble make blink
nimble stlink blink
# Quick syntax check (development workflow)
nimble test
# Full build validation (before releases)
nimble test_build
# Build with specific board (e.g., Daisy Patch)
nimble make patch_demoFlashing Methods:
| Method | Command | Requirements | Speed |
|---|---|---|---|
| DFU | nimble flash <name> |
USB cable, bootloader mode | Normal |
| ST-Link | nimble stlink <name> |
ST-Link probe, JTAG connection | Fast |
See BUILD_SYSTEM.md for detailed build system documentation, troubleshooting, and advanced usage.
All build artifacts go into build/ directory for clean organization.
This wrapper follows the same MIT license as libDaisy. See LICENSE file for details.
Contributions are welcome! See CONTRIBUTING.md for:
- Development setup
- Code style guidelines
- Testing requirements
- Areas needing work
- How to submit PRs
- libDaisy GitHub - The C++ library
- Daisy Wiki - Hardware documentation
- Electro-Smith Forum - Community support
- Nim Language - Nim programming language
- STM32H750 Datasheet - MCU details
Current Version: 1.0.0
Stability:
- Feature Complete - All major functionality implemented and documented
- API Stable - No breaking changes planned
- Use at Your Own Risk - Requires community testing before production use
- 85/85 Modules - All modules implemented and API verified
- Memory Safe - Zero heap allocation in audio paths
- Well Tested - 100% example compilation pass rate
- Issues: Use GitHub issues for bug reports
- Discussions: GitHub discussions for questions
- Forum: Electro-Smith forum for hardware questions
- Electro-Smith for creating Daisy and libDaisy
- Nim Community for the excellent language and tools
- Contributors who helped test and improve this wrapper
Ready to build something amazing? Start with QUICKSTART.md!