Hello Everyone,
I'm working on implementing some code using the SAMD51 on the Adafruit Metro M4 express.
I create a single period sinusoid (4000 samples long) and block-write it using DMA to the DAC at what I thought was 1M Sample/second.
Problem is: the sinusoid when looked at on the scope has a period of 200uS - which would make it a whopping 20M Samples/second - seems incorrect....
the DMA is triggered every 800uS - which looks good on the scope (time between pulses).
Can anyone tell me what I'm missing here - I'm sure that I'll be kicking myself...
thank you in advance for any help!
Code using arduino IDE follows........
#define HWORDS 4000
uint16_t data[HWORDS];
float phase = 3.14159 * 2./HWORDS;
int i;
static DmacDescriptor descriptor1 attribute((aligned(16)));
void dma_init() {
static DmacDescriptor descriptor attribute((aligned(16)));
static DmacDescriptor descriptor1 attribute((aligned(16)));
static DmacDescriptor wrb attribute((aligned(16)));
static uint32_t chnl0 = 0; // DMA channel
DMAC->BASEADDR.reg = (uint32_t)&descriptor1;
DMAC->WRBADDR.reg = (uint32_t)&wrb;
DMAC->CTRL.bit.LVLEN0 =1 ;
DMAC->CTRL.bit.LVLEN1 =1 ;
DMAC->CTRL.bit.LVLEN2 =1 ;
DMAC->CTRL.bit.LVLEN3 =1 ;
DMAC->CTRL.bit.DMAENABLE = 1;
DMAC->Channel[0].CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(0x0) | // Set DMAC t0 software trigger
DMAC_CHCTRLA_TRIGACT_BLOCK; // DMAC block transfer
descriptor1.DESCADDR.reg = (uint32_t) &descriptor1;
descriptor1.BTCTRL.bit.VALID = 0x1; //Its a valid channel
descriptor1.BTCTRL.bit.BEATSIZE = 0x1; // HWORD.
descriptor1.BTCTRL.bit.SRCINC = 0x1; //Source increment is enabled
descriptor1.BTCTRL.bit.DSTINC = 0x0; //Destination increment disabled
descriptor1.BTCNT.reg = HWORDS; //HWORDS points to send
descriptor1.SRCADDR.reg = (uint32_t)&data + 2*HWORDS; //send from the data vevtor
descriptor1.DSTADDR.reg = (uint32_t)&DAC->DATA[1].reg; //to the DAC output
// start channel
DMAC ->Channel[0].CHCTRLA.bit.ENABLE = 0x1; //OK
DMAC->CTRL.bit.DMAENABLE = 1;
}
void dac_init(){
GCLK->GENCTRL[7].reg = GCLK_GENCTRL_DIV(4) | // Divide the 48MHz clock source by divisor 4: 48MHz/4 = 12MHz (max for DAC)
GCLK_GENCTRL_GENEN | // Enable GCLK7
GCLK_GENCTRL_SRC_DFLL; // Select 48MHz DFLL clock source
while (GCLK->SYNCBUSY.bit.GENCTRL7);
GCLK->PCHCTRL[42].reg = GCLK_PCHCTRL_CHEN | // Enable the DAC peripheral channel
GCLK_PCHCTRL_GEN_GCLK7; // Connect generic clock 7 to DAC
MCLK->APBDMASK.bit.DAC_ = 1;
DAC->CTRLA.bit.SWRST = 1;
while(DAC->CTRLA.bit.SWRST);
DAC->DACCTRL[1].reg = DAC_DACCTRL_REFRESH(2) |
DAC_DACCTRL_CCTRL_CC12M |
DAC_DACCTRL_ENABLE;// |
DAC_DACCTRL_LEFTADJ;
DAC->CTRLA.reg = DAC_CTRLA_ENABLE;
while(DAC->SYNCBUSY.bit.ENABLE);
while(!DAC->STATUS.bit.READY1);
PORT->Group[0].DIRSET.reg = (1 << 2);
PORT->Group[0].PINCFG[5].bit.PMUXEN = 1;
PORT->Group[0].PMUX[1].bit.PMUXE = 1;
}
void setup() {
for (i=0;i<HWORDS;i++) data_= 4*(sinf(i*phase) * 510.0f + 512.0f); //Make a single-period sine wave._
- dac_init();*
- dma_init(); *
}
void loop() { - DMAC->SWTRIGCTRL.reg |= (1 << 0); //Software trigger to set off the DAC*
- delayMicroseconds(800);*
}
DAC_ONLY.ino (2.9 KB)


