BERGSONNE

Analog (ADC / DAC)

The ADC turns a pad voltage into a number; the DAC does the reverse. core_adc reads pads as raw counts or calibrated millivolts (and the die temperature and supply rail); core_dac drives a voltage out. Both sit on hal_* / ll_* — use the Core / HAL / LL toggle at the top of the sidebar to switch.

Overview

The ADC is a 12-bit SAR converter (counts 0–4095). You can read a pad as raw counts, or as millivolts — the latter uses the factory VREFINT calibration so the reading is supply-independent. The Tier 2 pad calls own ADC1 and read by tile pad number; the Tier 1 handle API gives you resolution, sampling speed, and DMA.

DAC is Core.ST.H5 only
Only the H5 Core exposes a DAC. The ADC is on every Core (M0+ through M33).

Reading inputs

The shortest path is the Tier 2 pad read — coregen has already set the pad to analog. For full control (resolution, sampling speed) use the Tier 1 handle:

#include "core.h"

  // Tier 2 — pad declared analog in config.json:
  uint16_t raw = core_adc_read_pad(8);
  uint32_t mv  = core_adc_read_mv_pad(8);

  // Tier 1 — explicit handle:
  core_adc_t adc;
  core_adc_init(&adc, ADC_12BIT);
  core_adc_add(&adc, 8, SAMP_MED);
  uint16_t r = core_adc_read(&adc, 8);
  uint32_t v = core_adc_read_mv(&adc, 8);

Temperature & supply

Two internal channels need no pad: the die temperature sensor and the supply rail (via VREFINT). The Tier 2 calls return tenths of a degree and millivolts:

int32_t  decidegc = core_adc_temp_decidegc();   // e.g. 234 = 23.4 °C
  uint32_t vdd_mv   = core_adc_vdd_mv();          // measured supply

DAC output

On the H5 Core, the DAC drives a fixed voltage out. Init once, then write a raw 12-bit value or a millivolt level:

#include "core.h"   // Core.ST.H5 only

  core_dac_init();
  core_dac_write(2048);       // mid-scale (raw 12-bit)
  core_dac_write_mv(1650);    // 1.65 V

Cross-architecture support

Raw and millivolt reads are verified broadly; oversampling, continuous/scan, and DMA vary by Core, and the temperature sensor’s accuracy depends on whether the factory cal is bus-accessible. The DAC is H5-only:

●L0M0+9/10●L4M49/10●W5M339/10●H5M339/10WCH (RISC-V) · Nordic (nRF54) — in development
·L0M0+·L4M4·W5M33●H5M33WCH (RISC-V) · Nordic (nRF54) — in development

See the implementation status for the full matrix.

Known gaps

What the SDK itself lists as missing here, straight from the headers:

ADC
lowDSLTwin VDD / die-temp are constants

read_pad / read_mv_pad use the per-pad slider on the chip view, but temp_decidegc and vdd_mv return fixed values (25.0 °C / 3300 mV). No UI affordance to vary them yet — DSL programs that branch on under-/over-temp or low-VDD logic always see nominal in the IDE.

mediumDSLNo DSL access to sampling speed / resolution

Tier 2 calls the default instance at its compile-time resolution (12-bit) and per-pad sampling speed set during init. SAMP_FAST / MED / SLOW / VERY_SLOW and ADC_6/8/10/12BIT aliases are reachable only via the explicit-handle Tier 1 API.

mediumDSLNo multi-instance ADC dispatch

Tier 2 wrappers always hit core_adc1. Cores with multiple ADCs (Core.ST.H5 has ADC1 + ADC2) need per-pad peripheral tagging in tile JSON before coregen can emit the dispatch. Until then DSL programs are limited to whichever pads coregen routed to ADC1.

mediumC APINo oversampling / averaging helper

STM32 ADCs can hardware-oversample 2×–256× for extra effective resolution. The HAL exposes the registers but core_adc has no convenience wrapper — callers reach into tal_adc / hal_adc to set OVSR/OVSS bits manually.

lowC APINo injected channels

Regular-group external triggers ARE supported: core_adc_set_trigger() paces DMA conversions from a TIMx TRGO or EXTI line. Injected groups (a second, higher-priority conversion sequence that preempts the regular one) are not surfaced. Bring-your-own register writes if you need a preempting sample inside a control loop.

DAC
mediumC APINo waveform / DMA generation

Single-sample writes only. STM32H5's DAC supports DMA-fed sample buffers + the internal noise / triangle wave generators — none of which are wrapped. Audio + arbitrary-waveform tiles need this.

lowC APINo dual-channel synchronization

The DAC peripheral has two channels that can be triggered together for stereo / I-Q output. Only single-channel writes are exposed.

From the @studio unsupported notes in core_adc.h, core_dac.h — tiles@6af026f.

API reference

ADC

Default-instance · Tier 2
int core_adc_read_pad(uint8_t pad);
Read a pad as raw ADC counts (0–4095 at 12-bit resolution).
int core_adc_read_mv_pad(uint8_t pad);
Read a pad as calibrated millivolts (uses VREFINT for per-chip accuracy).
int core_adc_temp_decidegc(void);
Die temperature in tenths of deg C (e.g. 253 = 25.3 C). Dispatches to the default ADC instance.
int core_adc_vdd_mv(void);
VDD supply voltage in millivolts (via VREFINT). Dispatches to the default ADC instance.
Lower-level · Tier 1
hal_status_t core_adc_init(core_adc_t * adc, uint32_t resolution);
Initialise the ADC at the given resolution.
hal_status_t core_adc_add(core_adc_t * adc, uint8_t pad, uint32_t samp);
Register a pad as an ADC input with the given sampling speed.
uint16_t core_adc_read(core_adc_t * adc, uint8_t pad);
Single-shot read — returns raw ADC count.
uint32_t core_adc_read_mv(core_adc_t * adc, uint8_t pad);
Single-shot read — returns calibrated millivolts.
int32_t core_adc_temp(core_adc_t * adc);
Die temperature in tenths of deg C (e.g. 253 = 25.3 C).
uint32_t core_adc_vdd(core_adc_t * adc);
Actual VDD supply voltage in millivolts via VREFINT.
hal_status_t core_adc_start_dma(core_adc_t * adc, uint16_t * buf, uint16_t len, hal_callback_t cb, void * ctx);
Start continuous conversion with DMA circular buffer.
void core_adc_stop_dma(core_adc_t * adc);
Stop continuous DMA conversion.
uint16_t core_adc_dma_read(core_adc_t * adc, uint8_t pad);
Read most recent DMA result for a pad.
uint32_t core_adc_dma_read_mv(core_adc_t * adc, uint8_t pad);
Read most recent DMA result for a pad, in calibrated millivolts. Prime VDDA before starting DMA (call core_adc_vdd(adc) once), since measuring VREFINT needs the regular sequence that DMA owns.
uint32_t core_adc_raw_to_mv(core_adc_t * adc, uint16_t raw);
Convert a raw count from a DMA buffer to millivolts.
hal_status_t core_adc_set_trigger(core_adc_t * adc, uint8_t extsel, uint32_t edge);
Pace DMA conversions from a hardware trigger instead of free-running. Call before core_adc_start_dma. See hal_adc_set_trigger for why this matters to any slow output rate: it is what makes a DMA ring span the whole output period, turning the average into a real anti-alias filter instead of a burst average. core_timer_init_freq(&t, TIM2, 800); core_timer_set_trgo(&t, LL_TIM_MMS_UPDATE); core_adc_set_trigger(adc, LL_ADC_L0_TRG_TIM2_TRGO, ADC_TRIG_RISING); core_adc_start_dma(adc, buf, len, 0, 0); core_timer_start(&t);
int core_adc_dma_slot(core_adc_t * adc, uint8_t pad);
Buffer slot a pad occupies in one DMA scan (-1 if not registered). Use the stride when the buffer holds several scans for averaging.

Generated from core_adc.h — tiles@6f27e78.

DAC

Default-instance · Tier 2
void core_dac_init(void);
Initialize the DAC (clock, GPIO, peripheral). Call once from `on start` before any writes.
void core_dac_write(uint16_t val);
Write a raw 12-bit value. Output = val / 4095 × VREF+.
void core_dac_write_mv(uint16_t mv);
Write a voltage in millivolts.
uint16_t core_dac_read(void);
Read back the current DAC output register value (12-bit).

Generated from core_dac.h — tiles@2a1a847.