Skip to content

A comprehensive, type-safe Nim wrapper for the libDaisy hardware abstraction library

License

Notifications You must be signed in to change notification settings

Brokezawa/Nimphea

Repository files navigation

Nimphea

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.

Version Platform Nim License

What is this?

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

Quick Start

Hardware Requirements

  • Daisy Seed - STM32H750-based embedded audio board
  • USB cable - For programming and power
  • Audio I/O (optional) - For audio applications

Software Requirements

  • Nim - 2.0 or later
  • ARM Toolchain - arm-none-eabi-gcc and related tools
  • libDaisy - The C++ library this wraps (sibling directory)
  • dfu-util or st-flash - For uploading firmware

Installation

  1. Clone this wrapper with submodules:
cd /path/to/your/projects
git clone --recursive https://github.com/Brokezawa/nimphea
cd nimphea
  1. One-time setup (clones submodules and builds libDaisy):
nimble init_libdaisy

Your directory structure will be:

nimphea/
├── libDaisy/          # C++ library (submodule)
├── src/               # Nim wrapper
├── examples/          # Example programs
└── docs/              # Documentation
  1. Try an example:
nimble make blink      # Build example for ARM Cortex-M7
nimble flash blink      # Flash to Daisy via USB (DFU)

Applying Patches (Required for ICM20948 Sensor)

Note: If you plan to use the ICM20948 9-axis IMU sensor, you must apply a patch to libDaisy first:

cd nimphea
./apply_patches.sh

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

What Can You Build?

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

Features

Core Hardware

  • Audio I/O - Stereo input/output, 8-96kHz sample rates, DMA-based
  • GPIO - 32 configurable pins, all standard modes
  • System - Initialization, timing, utilities

Peripherals

  • 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

  • USB Device CDC - Virtual serial port over USB
  • USB MIDI - MIDI device and host modes
  • USB Host - Mass storage, MIDI devices

Storage & Memory

  • 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

User Interface

  • 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

Data Structures & Utilities

  • 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

Sensor Modules

  • 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

Audio Codecs & Displays

  • 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

Device Drivers & Expansion

  • 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

Board Support

  • 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 Features

  • 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

Examples

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.

Documentation

Project Structure

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

Technical Highlights

Automatic Include Management

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

Selective Compilation

Define symbols to include only what you need:

# In your code or nimble configuration
{.define: useI2C.}
{.define: useUSB.}

Zero-Cost Abstractions

All wrapper functions compile to direct C++ calls with no overhead:

hw.setLed(true)  # Compiles to: hw.SetLed(true);

Type Safety

Nim's type system prevents common embedded errors:

var pin: DaisyPin = DPin0       # Type-safe pin selection
var rate: I2CSpeed = I2C_400KHZ # Enumerated constants

Hardware Specifications

Daisy 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

Performance

  • 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

Requirements

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)

Building

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 documentation

Common 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_demo

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

License

This wrapper follows the same MIT license as libDaisy. See LICENSE file for details.

Contributing

Contributions are welcome! See CONTRIBUTING.md for:

  • Development setup
  • Code style guidelines
  • Testing requirements
  • Areas needing work
  • How to submit PRs

Resources

Status

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

Support

  • Issues: Use GitHub issues for bug reports
  • Discussions: GitHub discussions for questions
  • Forum: Electro-Smith forum for hardware questions

Acknowledgments

  • 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!

About

A comprehensive, type-safe Nim wrapper for the libDaisy hardware abstraction library

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors