Wio Terminal and SAMD 51 DAC

I notice there are 2 DAC pins on my Wio Terminal 40 pin header, DAC0 and DAC1, on pins 11 and 26, respectively. I presume these can be coded for audio playout but I can’t find any howTwos or tutorials? According to stuff I’ve seen about the SAMD 51, these can also function as ADCs, as well. (??)

Has anybody got any example code or successfully got audio out of their Wio using these pins? Anybody know of an ArduinoIDE-friendly way of programming this or of any tutorials?

OK, gotta laugh, in my impatience to wait for an answer, I solved the riddle :grinning:

The following code puts a 1kHz square wave tone on DAC0, and in inverted phase on DAC1.

uint32_t sqrWave = 0;  //  Create a 32 bit unsigned integer
void setup() {
  dacConfigure();  //  Zero the DACs to prevent noise

void loop() {                  //  main loop
  if(sqrWave == 0){
    sqrWave = 65535;  //  take the square wave to maximum
  } else {
    sqrWave = 0;  //  take the square wave to minimum
  dacWrite(sqrWave, 65535 - sqrWave);  //  Reverse phase between left and right channels

  delay(1);  //  1 millisecond delay makes the tone approx. 1kHz 

void dacConfigure(){            //  Zero the DAC
  analogWriteResolution(16);  //  Set the resolution to 16 bits (CD quality)
  analogWrite(DAC0, 0);  //  Zero the left channel
  analogWrite(DAC1, 0);  //  Zero the right channel

void dacWrite(uint32_t lSample, uint32_t rSample){  //  Write samples to DACs
  analogWrite(DAC0, lSample);  //  Write left sample to left channel
  analogWrite(DAC1, rSample);  //  Write right sample to right channel

And I thought it was going to be hard! :rofl:

Posted before I got a speaker on it. :confused: Might be the impedance, but I suspect I have more reading to do.

Any help still appreciated. The DAC library for the Maker and Zero doesn’t work, either BTW. “Unable to build for board Wio Terminal” from memory.

Doing all my own work on this, here, but others might find it useful…

If we analogWrite to the DAC at greater than its bitrate (at least I think that’s what was causing silence, despite having a clear set of numbers being fed to it, as reported by the serial monitor), I didn’t get any output until I bitcrushed the 16 bit numbers down to 12 bit using…

#include <Chrono.h>    //  uses the Chrono library, just cheating to get tighter timing
#include <math.h>    //  math library for sinf (floating point sin)

Chrono sampleTimer(Chrono::MICROS);         //  instantiate class of Chrono to time sample output

float smplRate = 44100.0;                   //  deault playback sample rate (44.1kHz)
float smplWvLn = 1000000 / smplRate;        //  sample rate wavelength in uS
float otPtFreq = 824.1;                     //  sets output frequency in Hz
float otPtWvLn = 1000000 / otPtFreq;        //  output wavelength in uS
float inc = 2 * PI * smplWvLn / otPtWvLn;   //  radians increment per sample
float i = 0.0;                              //  increment counter

void setup() {
  analogWriteResolution(12);                //  set output bitrate for inbuilt DACs
  sampleTimer.start();                      //  start sampleTimer

void loop(){
  if(sampleTimer.hasPassed(smplWvLn)){      //  the sampleTimer returns true
    sampleTimer.restart();                    //  restart the timer
    unsigned long out = sinusoid();    //  call for next sample from the wavetable
    analogWrite(DAC0,out >> 4);             //  write sample to DAC0
    analogWrite(DAC1,out >> 4);             //  write sample to DAC1

float sinusoid(){
  if(i < 2 * PI){
    float r = 2046.5 + 2048.0 * sinf(i); scales sample to 12 bit amplitude (0 to 4095)
    i += inc;
    return r;
  } else if (i >= 2 * PI){
    i = 0;

I’ve actually managed to give it ultra-low frequencies and I’ve had some awesome sinewaves on my 'scope!