<alp/dac.h> — Digital-to-Analog Conversion
Millivolt-domain DAC writes against studio-resolved channel indices. Split out of <alp/adc.h> in v0.7 — DAC now has its own registry and backend dispatch.
The channel-config side (reference voltage, output buffering) lives in devicetree on the Zephyr backend; this header only exposes the runtime knobs apps actually tune.
Header
#include <alp/dac.h>
#include <alp/e1m_pinout.h>
Write a voltage
alp_dac_t *out = alp_dac_open(&(alp_dac_config_t){
.channel_id = ALP_E1M_DAC0,
.initial_mv = 0u,
});
alp_dac_write_mv(out, 1650u); // mid-rail on a 3.3 V reference
alp_dac_close(out);
close() does not power-down the converter or alter the output — it stays at the last-programmed level until the next open() reprograms it. Passing NULL is a no-op.
Config struct
| Field | Type | Notes |
|---|---|---|
channel_id | uint32_t | Studio-resolved DAC channel (ALP_E1M_DAC0..ALP_E1M_DAC1). Must be < ALP_E1M_DAC_COUNT and resolvable on the active SoM. |
initial_mv | uint16_t | Initial output in millivolts; 0 = ground. |
Functions
| Call | Returns |
|---|---|
alp_dac_open(const alp_dac_config_t *cfg) | Open handle, or NULL (NULL cfg / channel out of range / converter not ready / pool exhausted). |
alp_dac_write_mv(dac, uint16_t mv) | ALP_OK / ALP_ERR_NOT_READY / ALP_ERR_IO. Saturates at the reference rail and rounds to the converter's hardware resolution (12-bit on the GD32 DAC). |
alp_dac_read_mv(dac, uint16_t *mv_out) | ALP_OK / ALP_ERR_NOT_READY / ALP_ERR_INVAL / ALP_ERR_IO. Reads back the programmed setpoint — useful where the rounded hardware value differs from the request. |
alp_dac_close(dac) | void. Releases the handle; output level persists. |
alp_dac_capabilities(const alp_dac_t *dac) | const alp_capabilities_t *. Backend-populated capability descriptor (e.g. for gating DMA-driven waveform paths on ALP_INSTANCE_CAP_DMA). NULL → NULL; the pointer is valid for the handle's lifetime. Mirrors alp_adc_capabilities. |
Backends
| Backend | Routing |
|---|---|
| Zephyr | dac_* driver class. On the V2N family (V2N + V2N-M1, both carrying the GD32G553 supervisor MCU) the SDK routes DAC writes through the GD32 IO MCU bridge (per the 2026-05-12 hardware decision). |
| Yocto | Industrial I/O sysfs (/sys/bus/iio/devices/). |
| Baremetal | Vendor HAL DAC channel registers. |
On the E1M-AEN801 (Alif E8) the native DAC reference is fixed at 0.750 V (DAC12_VREF_CONT=0x4) — bench-confirmed via a DAC0 → ADC loopback (the aen-analog-validate example).
Capability validation
alp_dac_open() rejects an out-of-range channel up front with ALP_ERR_INVAL — a portable capability gate against ALP_SOC_DAC_COUNT (a no-op under CONFIG_ALP_SOC_NONE), mirroring the ADC dispatch.
ABI status
[ABI-STABLE] since v0.2 — base surface stable. v0.9.0 adds alp_dac_capabilities (additive).
See also
<alp/adc.h>— the analog input counterpart- Examples: dac-waveform — portable sine generation (native DAC12 on E1M, GD32-bridged DAC0 on E1M-X)
- Examples: aen-analog-validate — DAC0 → ADC loopback on E8