nimphea/per/adc

Source   Edit  

ADC (Analog to Digital Converter) support for libDaisy Nim wrapper

This module provides comprehensive ADC functionality for the Daisy Audio Platform, including single-channel inputs, multiplexed inputs, and various conversion speeds.

Example - Simple single-channel ADC:

import nimphea, per/adc

var hw = initDaisy()

# Configure ADC channels
var channels: array[2, AdcChannelConfig]
channels[0].initSingle(A0())
channels[1].initSingle(A1())

# Initialize ADC
var adc = initAdcHandle(channels, OVS_32)
adc.start()

while true:
  let value1 = adc.getFloat(0)  # 0.0 to 1.0
  let value2 = adc.getFloat(1)
  hw.delay(10)

Example - Multiplexed ADC (up to 8 inputs on one pin):

# Configure mux: one ADC pin with 4 multiplexed inputs
var channels: array[1, AdcChannelConfig]
channels[0].initMux(
  adcPin = A0(),
  muxChannels = 4,  # Using a 4052 mux (2 select lines)
  mux0 = D0(),      # First select line
  mux1 = D1()       # Second select line
)

var adc = initAdcHandle(channels, OVS_32)
adc.start()

while true:
  for i in 0..<4:
    let value = adc.getMuxFloat(0, i)  # Channel 0, mux index i
  hw.delay(10)

Types

AdcChannelConfig {.importcpp: "daisy::AdcChannelConfig", bycopy.} = object
Source   Edit  
AdcHandle {.importcpp: "daisy::AdcHandle".} = object
Source   Edit  
ConversionSpeed {.importcpp: "daisy::AdcChannelConfig::ConversionSpeed", size: 4.} = enum
  SPEED_1CYCLES_5 = 0,      ## 1.5 cycles conversion time (fastest)
  SPEED_2CYCLES_5,          ## 2.5 cycles conversion time
  SPEED_8CYCLES_5,          ## 8.5 cycles conversion time (default)
  SPEED_16CYCLES_5,         ## 16.5 cycles conversion time
  SPEED_32CYCLES_5,         ## 32.5 cycles conversion time
  SPEED_64CYCLES_5,         ## 64.5 cycles conversion time
  SPEED_387CYCLES_5,        ## 387.5 cycles conversion time
  SPEED_810CYCLES_5          ## 810.5 cycles conversion time (slowest, most accurate)
Source   Edit  
MuxPin {.importcpp: "daisy::AdcChannelConfig::MuxPin", size: 4.} = enum
  MUX_SEL_0 = 0,            ## First multiplexer select pin
  MUX_SEL_1,                ## Second multiplexer select pin
  MUX_SEL_2,                ## Third multiplexer select pin
  MUX_SEL_LAST               ## Internal marker
Source   Edit  
OverSampling {.importcpp: "daisy::AdcHandle::OverSampling", size: 4.} = enum
  OVS_NONE = 0,             ## No oversampling
  OVS_4,                    ## 4x oversampling
  OVS_8,                    ## 8x oversampling
  OVS_16,                   ## 16x oversampling
  OVS_32,                   ## 32x oversampling (default, good balance)
  OVS_64,                   ## 64x oversampling
  OVS_128,                  ## 128x oversampling
  OVS_256,                  ## 256x oversampling
  OVS_512,                  ## 512x oversampling
  OVS_1024,                 ## 1024x oversampling (slowest, most accurate)
  OVS_LAST                   ## Internal marker
Source   Edit  

Consts

DSY_ADC_MAX_CHANNELS = 16
Maximum number of ADC channels Source   Edit  

Procs

proc get(adc: AdcHandle; channel: int): uint16 {....raises: [], tags: [],
    forbids: [].}

Get raw 16-bit ADC value from a channel

Parameters: channel: Channel index (0-based)

Returns: Raw ADC value (0-65535)

Example:

let rawValue = adc.get(0)

Source   Edit  
proc getFloat(adc: AdcHandle; channel: int): float {.inline, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc getMux(adc: AdcHandle; channel: int; muxIndex: int): uint16 {.inline,
    ...raises: [], tags: [], forbids: [].}

Get raw 16-bit value from a multiplexed input

Parameters: channel: ADC channel index (0-based) muxIndex: Multiplexer input index (0-7)

Returns: Raw ADC value (0-65535)

Example:

# Read all 4 inputs from a mux on channel 0
for i in 0..<4:
  let value = adc.getMux(0, i)

Source   Edit  
proc getMuxFloat(adc: AdcHandle; channel: int; muxIndex: int): float {.inline,
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc getMuxPtr(adc: AdcHandle; channel: int; muxIndex: int): ptr uint16 {.
    inline, ...raises: [], tags: [], forbids: [].}

Get pointer to raw multiplexed ADC value

Parameters: channel: ADC channel index (0-based) muxIndex: Multiplexer input index (0-7)

Returns: Pointer to raw ADC value

Source   Edit  
proc getPtr(adc: AdcHandle; channel: int): ptr uint16 {....raises: [], tags: [],
    forbids: [].}

Get pointer to raw ADC value for zero-copy access

Useful for performance-critical code that needs direct memory access.

Parameters: channel: Channel index (0-based)

Returns: Pointer to raw ADC value

Source   Edit  
proc initAdcHandle(configs: var openArray[AdcChannelConfig];
                   oversampling: OverSampling = OVS_32): AdcHandle {....raises: [],
    tags: [], forbids: [].}

Initialize an ADC handle with the given channel configurations

Parameters: configs: Array of channel configurations (up to 16 channels) oversampling: Oversampling rate for noise reduction Higher = slower but more accurate OVS_32 is a good default balance

Example:

var channels: array[3, AdcChannelConfig]
channels[0].initSingle(A0())
channels[1].initSingle(A1())
channels[2].initSingle(A2())

var adc = initAdcHandle(channels, OVS_32)
adc.start()

Source   Edit  
proc initMux(config: var AdcChannelConfig; adcPin: Pin; muxChannels: int;
             mux0: Pin; mux1: Pin = Pin(); mux2: Pin = Pin();
             speed: ConversionSpeed = SPEED_8CYCLES_5) {....raises: [], tags: [],
    forbids: [].}

Initialize an ADC channel configuration for a multiplexed input

Supports CD405X series multiplexers (4051, 4052, 4053) to read multiple analog inputs through a single ADC channel.

Parameters: config: The channel configuration object to initialize adcPin: The ADC input pin connected to the mux output muxChannels: Number of mux inputs (1-8) mux0: First select line (required for all muxes) mux1: Second select line (required for 4+ channels) mux2: Third select line (required for 8 channels) speed: Conversion speed

Example - 4-channel mux (4052):

var channels: array[1, AdcChannelConfig]
channels[0].initMux(A0(), 4, D0(), D1())

Example - 8-channel mux (4051):

var channels: array[1, AdcChannelConfig]
channels[0].initMux(A0(), 8, D0(), D1(), D2())

Source   Edit  
proc initSingle(config: var AdcChannelConfig; pin: Pin;
                speed: ConversionSpeed = SPEED_8CYCLES_5) {....raises: [],
    tags: [], forbids: [].}

Initialize an ADC channel configuration for a single analog input

Parameters: config: The channel configuration object to initialize pin: The analog input pin (e.g., A0(), A1(), etc.) speed: Conversion speed - faster = less accurate but quicker reads

Example:

var channels: array[2, AdcChannelConfig]
channels[0].initSingle(A0())
channels[1].initSingle(A1(), SPEED_16CYCLES_5)

Source   Edit  
proc newAdcChannelConfig(): AdcChannelConfig {....raises: [], tags: [], forbids: [].}

Create a new ADC channel configuration

Example:

var cfg = newAdcChannelConfig()
cfg.initSingle(A0())

Source   Edit  
proc start(adc: var AdcHandle) {....raises: [], tags: [], forbids: [].}

Start ADC conversions

Must be called before reading values.

Source   Edit  
proc stop(adc: var AdcHandle) {....raises: [], tags: [], forbids: [].}
Stop ADC conversions Source   Edit