nimphea/dev/max11300

Search:
Group by:
Source   Edit  

MAX11300 20-Port Programmable Mixed-Signal I/O Module

Device driver for MAX11300 PIXI - 20-port ADC/DAC/GPIO device. Highly opinionated implementation optimized for Eurorack modular synthesis.

This is a full wrapper around libDaisy's MAX11300 C++ driver, supporting:

  • 20 configurable pins (ADC, DAC, GPIO input/output)
  • DMA-based continuous updates via Start() method
  • Multiple voltage ranges (-10V to +10V)
  • Up to 4 devices on shared SPI bus (multi-slave)

⚠️ IMPORTANT: This implementation wraps libDaisy's C++ driver but has NOT been tested on hardware. It follows libDaisy's proven code and compiles successfully, but should be considered experimental until hardware validation is complete.

Example:

var pixi: MAX11300[1]  # Single device
var config: MAX11300Config[1]
config.transport_config.pin_config.defaults()

if pixi.init(config) != MAX_OK:
  # Handle error

# Configure pins
discard pixi.configurePinAsAnalogRead(0, PIN_0, ADC_NEG5_TO_5)
discard pixi.configurePinAsAnalogWrite(0, PIN_1, DAC_NEG5_TO_5)

# Start DMA updates (optional)
discard pixi.start(nil, nil)

# Read/write
let cvIn = pixi.readAnalogPinVolts(0, PIN_0)
pixi.writeAnalogPinVolts(0, PIN_1, cvIn)

Types

AdcVoltageRange {.importcpp: "daisy::MAX11300Types::AdcVoltageRange", size: 4.} = enum
  ADC_0_TO_10 = "daisy::MAX11300Types::AdcVoltageRange::ZERO_TO_10",
  ADC_NEG5_TO_5 = "daisy::MAX11300Types::AdcVoltageRange::NEGATIVE_5_TO_5",
  ADC_NEG10_TO_0 = "daisy::MAX11300Types::AdcVoltageRange::NEGATIVE_10_TO_0",
  ADC_0_TO_2P5 = "daisy::MAX11300Types::AdcVoltageRange::ZERO_TO_2P5"
ADC voltage ranges (assumes proper power supply) WARNING: DigitalRead pins are 0-5V only and corrupted by negative voltages Source   Edit  
DacVoltageRange {.importcpp: "daisy::MAX11300Types::DacVoltageRange", size: 4.} = enum
  DAC_0_TO_10 = "daisy::MAX11300Types::DacVoltageRange::ZERO_TO_10",
  DAC_NEG5_TO_5 = "daisy::MAX11300Types::DacVoltageRange::NEGATIVE_5_TO_5",
  DAC_NEG10_TO_0 = "daisy::MAX11300Types::DacVoltageRange::NEGATIVE_10_TO_0"
DAC voltage ranges (assumes proper power supply) DigitalWrite pins are 0-5V only Source   Edit  
MAX11300[N] {.bycopy, nodecl.} = object

MAX11300 device wrapper (currently supports N=1 only)

Note: The libDaisy C++ template is complex to wrap with multiple devices. This wrapper is hard-coded for single device (N=1). Multi-device support would require additional Nim/C++ template instantiation work.

Source   Edit  
MAX11300Config {.importcpp: "daisy::MAX11300<1>::Config", bycopy.} = object
  transport_config* {.importc: "transport_config".}: MAX11300TransportConfig
MAX11300 device configuration (currently supports N=1 only) Source   Edit  
MAX11300Cpp {.importcpp: "daisy::MAX11300<1>".} = object
C++ MAX11300 driver object (opaque wrapper) Source   Edit  
MAX11300DmaBuffer {.importcpp: "daisy::MAX11300Types::DmaBuffer", bycopy.} = object
  rx_buffer* {.importc: "rx_buffer".}: array[41, uint8]
  tx_buffer* {.importc: "tx_buffer".}: array[41, uint8]
DMA buffer for SPI transfers - must be in non-cached memory Source   Edit  
MAX11300Pin {.importcpp: "daisy::MAX11300Types::Pin", size: 4.} = enum
  PIN_0 = "daisy::MAX11300Types::Pin::PIN_0",
  PIN_1 = "daisy::MAX11300Types::Pin::PIN_1",
  PIN_2 = "daisy::MAX11300Types::Pin::PIN_2",
  PIN_3 = "daisy::MAX11300Types::Pin::PIN_3",
  PIN_4 = "daisy::MAX11300Types::Pin::PIN_4",
  PIN_5 = "daisy::MAX11300Types::Pin::PIN_5",
  PIN_6 = "daisy::MAX11300Types::Pin::PIN_6",
  PIN_7 = "daisy::MAX11300Types::Pin::PIN_7",
  PIN_8 = "daisy::MAX11300Types::Pin::PIN_8",
  PIN_9 = "daisy::MAX11300Types::Pin::PIN_9",
  PIN_10 = "daisy::MAX11300Types::Pin::PIN_10",
  PIN_11 = "daisy::MAX11300Types::Pin::PIN_11",
  PIN_12 = "daisy::MAX11300Types::Pin::PIN_12",
  PIN_13 = "daisy::MAX11300Types::Pin::PIN_13",
  PIN_14 = "daisy::MAX11300Types::Pin::PIN_14",
  PIN_15 = "daisy::MAX11300Types::Pin::PIN_15",
  PIN_16 = "daisy::MAX11300Types::Pin::PIN_16",
  PIN_17 = "daisy::MAX11300Types::Pin::PIN_17",
  PIN_18 = "daisy::MAX11300Types::Pin::PIN_18",
  PIN_19 = "daisy::MAX11300Types::Pin::PIN_19"
Represents a pin/port on the MAX11300 (20 pins total) Source   Edit  
MAX11300Result {.importcpp: "daisy::MAX11300Types::Result", size: 4.} = enum
  MAX_OK = "daisy::MAX11300Types::Result::OK",
  MAX_ERR = "daisy::MAX11300Types::Result::ERR"
Operation result codes Source   Edit  
MAX11300TransportConfig {.importcpp: "daisy::MAX11300MultiSlaveSpiTransport::Config<1>",
                          bycopy.} = object
  pin_config* {.importc: "pin_config".}: MAX11300TransportPinConfig
  periph* {.importc: "periph".}: SpiPeripheral
  baud_prescaler* {.importc: "baud_prescaler".}: SpiBaudPrescaler
Transport layer configuration Source   Edit  
MAX11300TransportPinConfig {.importcpp: "daisy::MAX11300MultiSlaveSpiTransport::Config<1>::PinConfig",
                             bycopy.} = object
  nss* {.importc: "nss".}: array[1, Pin] ## Chip select pins (one per device)
  mosi* {.importc: "mosi".}: Pin ## SPI MOSI
  miso* {.importc: "miso".}: Pin ## SPI MISO
  sclk* {.importc: "sclk".}: Pin ## SPI clock
SPI pin configuration for transport layer Source   Edit  
UpdateCompleteCallback = proc (context: pointer) {.cdecl.}
Callback called after each successful DMA update cycle Source   Edit  

Procs

proc configurePinAsAnalogRead[N](max: var MAX11300[N]; device: csize_t;
                                 pin: MAX11300Pin; range: AdcVoltageRange): MAX11300Result

Configure pin as analog input (ADC)

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number (PIN_0 to PIN_19)
  • range - Voltage range (ADC_0_TO_10, ADC_NEG5_TO_5, etc.)

Returns: MAX_OK on success, MAX_ERR on failure

Note: Requires appropriate power supply for chosen range

Source   Edit  
proc configurePinAsAnalogWrite[N](max: var MAX11300[N]; device: csize_t;
                                  pin: MAX11300Pin; range: DacVoltageRange): MAX11300Result

Configure pin as analog output (DAC)

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number (PIN_0 to PIN_19)
  • range - Voltage range (DAC_0_TO_10, DAC_NEG5_TO_5, etc.)

Returns: MAX_OK on success, MAX_ERR on failure

Note: Requires appropriate power supply for chosen range

Source   Edit  
proc configurePinAsDigitalRead[N](max: var MAX11300[N]; device: csize_t;
                                  pin: MAX11300Pin; threshold: float32 = 2.5): MAX11300Result

Configure pin as digital input (GPI)

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number (PIN_0 to PIN_19)
  • threshold - Logic level threshold voltage (default 2.5V)

Returns: MAX_OK on success, MAX_ERR on failure

WARNING: Digital input pins are 0-5V only. Voltages below -250mV will corrupt ALL analog readings on the device!

Source   Edit  
proc configurePinAsDigitalWrite[N](max: var MAX11300[N]; device: csize_t;
                                   pin: MAX11300Pin; voltage: float32 = 5.0): MAX11300Result

Configure pin as digital output (GPO)

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number (PIN_0 to PIN_19)
  • voltage - Output voltage for logic HIGH (default 5.0V)

Returns: MAX_OK on success, MAX_ERR on failure

Note: Digital outputs are 0-5V only (no negative voltages)

Source   Edit  
proc defaults(config: var MAX11300TransportConfig) {....raises: [], tags: [],
    forbids: [].}
Set default transport configuration Source   Edit  
proc defaults(config: var MAX11300TransportPinConfig) {....raises: [], tags: [],
    forbids: [].}
Set default pin configuration for Daisy Seed Default pins match libDaisy defaults:
  • SPI1: PORTB.5 (MOSI), PORTB.4 (MISO), PORTG.11 (SCLK)
  • CS0: PORTG.10
Source   Edit  
proc disablePin[N](max: var MAX11300[N]; device: csize_t; pin: MAX11300Pin): MAX11300Result

Disable pin (set to High-Z mode)

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number (PIN_0 to PIN_19)

Returns: MAX_OK on success, MAX_ERR on failure

Source   Edit  
proc init[N](max: var MAX11300[N]; config: MAX11300Config): MAX11300Result

Initialize MAX11300 device(s)

This performs:

  • SPI initialization and connectivity verification
  • Device configuration (ADC/DAC modes, conversion rates, etc.)
  • All pins initialized to High-Z (disabled) mode

Parameters:

  • config - Configuration including SPI pins and settings

Returns: MAX_OK on success, MAX_ERR on failure

Note: Call this once at startup before configuring pins

Source   Edit  
proc readAnalogPinRaw[N](max: var MAX11300[N]; device: csize_t; pin: MAX11300Pin): uint16

Read raw 12-bit ADC value (0-4095)

Note: This reads from local buffer. Call start() to enable automatic DMA updates, or values will be stale.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as ADC

Returns: Raw 12-bit value (0-4095)

Source   Edit  
proc readAnalogPinVolts[N](max: var MAX11300[N]; device: csize_t;
                           pin: MAX11300Pin): float32

Read ADC value in volts

Note: This reads from local buffer. Call start() to enable automatic DMA updates, or values will be stale.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as ADC

Returns: Voltage value according to configured range

Source   Edit  
proc readDigitalPin[N](max: var MAX11300[N]; device: csize_t; pin: MAX11300Pin): bool

Read digital input state

Note: This reads from local buffer. Call start() to enable automatic DMA updates, or values will be stale.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as GPI

Returns: true if above threshold, false otherwise

Source   Edit  
proc start[N](max: var MAX11300[N]; callback: UpdateCompleteCallback = nil;
              context: pointer = nil): MAX11300Result

Start continuous DMA updates

This begins automatic background updates that:

  • Write all DAC values to hardware
  • Read all ADC values from hardware
  • Write all GPO states to hardware
  • Read all GPI states from hardware
  • Call callback when complete (from interrupt context)
  • Repeat continuously

Parameters:

  • callback - Optional callback after each update (keep it fast!)
  • context - Optional context pointer passed to callback

Returns: MAX_OK on success, MAX_ERR on failure

Note: Can work without calling this (polling mode), but DMA updates provide much better performance and timing.

Source   Edit  
proc stop[N](max: var MAX11300[N])

Stop continuous DMA updates

Completes the current update cycle then stops. After this, read/write operations access local buffers only (polling mode).

Source   Edit  
proc twelveBitUintToVolts(value: uint16; range: AdcVoltageRange): float32 {.
    ...raises: [], tags: [], forbids: [].}

Convert 12-bit ADC code to voltage

Parameters:

  • value - Raw 12-bit value (0-4095)
  • range - ADC voltage range

Returns: Voltage value

Source   Edit  
proc voltsTo12BitUint(volts: float32; range: DacVoltageRange): uint16 {.
    ...raises: [], tags: [], forbids: [].}

Convert voltage to 12-bit DAC code

Parameters:

  • volts - Voltage value
  • range - DAC voltage range

Returns: 12-bit value (0-4095), clamped to range

Source   Edit  
proc writeAnalogPinRaw[N](max: var MAX11300[N]; device: csize_t;
                          pin: MAX11300Pin; value: uint16)

Write raw 12-bit DAC value (0-4095)

Note: This writes to local buffer. Call start() to enable automatic DMA updates, or values won't reach hardware.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as DAC
  • value - Raw 12-bit value (0-4095)
Source   Edit  
proc writeAnalogPinVolts[N](max: var MAX11300[N]; device: csize_t;
                            pin: MAX11300Pin; voltage: float32)

Write DAC value in volts

Note: This writes to local buffer. Call start() to enable automatic DMA updates, or values won't reach hardware.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as DAC
  • voltage - Voltage value (clamped to configured range)
Source   Edit  
proc writeDigitalPin[N](max: var MAX11300[N]; device: csize_t; pin: MAX11300Pin;
                        value: bool)

Write digital output state

Note: This writes to local buffer. Call start() to enable automatic DMA updates, or values won't reach hardware.

Parameters:

  • device - Device index (0 to N-1)
  • pin - Pin number configured as GPO
  • value - true for HIGH, false for LOW
Source   Edit