Stepping artifact on SAM L21 DAC transitions

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm seeing this stepping artifact coming from the DAC of an ATSAML21J18B on a SAM L21 Xplained Pro board at the start of conversions:

 

 

 

 

 

Sorry for the retro photos; all I've got is an old analog 60MHz scope.  For now, my code (below) is simply flipping the DAC value between 0 (0V) and 0xFFF (3.3V) at a rate of 16kHz (well within the 100uS period the DAC can hold its output within one LSB).  Dropping down is clean, but ramping up exhibits the stepping (switching delays on the underlying resistor network?)

 

Is this normal / expected?

 

I'm converting a PWM audio project from an ATtiny861a.  I'm still in the midst of things, but so far the sound coming out of my SAM DAC is worse.  I recognize the audio and can get it to play at roughly the correct speed, but it's coming out pretty choppy and noisy.  Even the doorbell on the ASF3 demo, which admittedly is just 8kHz, isn't great (I can't use START/ASF4 as it doesn't support FATFS on the SAML21, which i need for other portions of the project).  I'm trying to strip everything down to basics so I can tweak the pieces individually then build them back up.  I was kind of hoping for cleaner transitions from the built-in DAC.  I don't suppose there's any sort of "double buffering" available on the analog output side (to delay the new value from being applied until it's stabilized)?  I know the DAC value itself is buffered, but that's just on the digital input side.

 

CODE

 

Here's the loop generating those waveforms:

uint8_t flipper = 0;
while(1) {
  dac_chan_write(&dac_module, DAC_CHANNEL_1, flipper ? 0xFFF : 0);
  flipper = !flipper;
  while (!dac_chan_is_end_of_conversion(&dac_module, DAC_CHANNEL_1)) {} // wait for data buffer to be empty
}

Here's how I configured the DAC (I grabbed the salient bits; let me know if I missed anything important):

struct dac_config config;
struct dac_chan_config channel_config;

config.clock_source      = GCLK_GENERATOR_0;     // 4 MHz from OSC16M
config.reference         = DAC_REFERENCE_VDDANA; // Analog VCC as reference
config.differential_mode = false;
dac_init(dac_module, DAC, &config);

config.left_adjust       = false;
config.current           = DAC_CURRENT_12M;      // also tried 100K
config.run_in_standby    = false;
config.dither_mode       = false;
config->refresh_period   = 0;
dac_chan_set_config(dac_module, DAC_CHANNEL_1, &channel_config);
dac_chan_enable(dac_module, DAC_CHANNEL_1);

Here's some bits from the events stuff:

const uint32_t sample_rate = 16000;

struct tc_config config;
tc_get_config_defaults(&config);

config.clock_source      = GCLK_GENERATOR_0;
config.wave_generation   = TC_WAVE_GENERATION_MATCH_FREQ;

tc_init(tc_module, TC3, &config);

// Enable periodic event output generation
struct tc_events events = { .generate_event_on_overflow = true };
tc_enable_events(tc_module, &events);

// Set the timer top value to alter the overflow frequency
tc_set_top_value(tc_module, system_gclk_gen_get_hz(GCLK_GENERATOR_0) / sample_rate);

tc_enable(tc_module);

...

struct events_config config;
events_get_config_defaults(&config);
config.generator    = EVSYS_ID_GEN_TC3_OVF;
config.path         = EVENTS_PATH_ASYNCHRONOUS;
events_allocate(event, &config);
events_attach_user(event, EVSYS_ID_USER_DAC_START_1);

//Enable event triggered conversions
struct dac_events events = { .on_event_chan1_start_conversion = true };

dac_enable_events(dac_module, &events);
dac_enable(dac_module);

 

Last Edited: Fri. Jan 24, 2020 - 09:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I notice the datasheet gives the conversion time 12 x 2 x TGCLK, so if TGCLK is 4MHz that should yield a 6us settling time, right?  Looks more like 15us above.

 

For fun, here's one of those steps with GCLK_MAIN showing beneath it.

 

Last Edited: Fri. Jan 24, 2020 - 10:08 AM