i am to generate a sine wave with the maximum possible frequency on the mkr1010. About the resolution of the DAc and the number of samples I could thus already generate a sine of 25kHz, see the following code:
#define DAC_RESOLUTION 12
#define MAX_SAMPLES 10
int i = 0;
// Frequency 25kHz
static int sineTable[MAX_SAMPLES] =
{
0x800,0xcb3,0xf9b,0xf9b,0xcb3,
0x800,0x34c,0x64,0x64,0x34c,
};
void setup() {
analogWriteResolution(DAC_RESOLUTION);
analogReadResolution(DAC_RESOLUTION);
}
void loop() {
// Iteration of Datapoints
i = (i+1) % MAX_SAMPLES;
// write wave data to DAC0
analogWrite(A0, sineTable[i]); // write the selected waveform on DAC0
}
The sine is quite badly resolved but through a filter it looks better again. However, I was told to generate an even higher frequency via DMA. However, I find nothing on the Internet to control the registers for the MKR1010 and since I use Arduino for the first time, I am also a little overwhelmed. Does anyone have tips or tutorials available?
Here's some example code generating a 25kHz sine wave on A0, using the DAC, DMAC and a timebase triggered by timer TCC0:
// Output sine wave with a frequency of 25kHz on analog pin A0 using the DAC, DMAC and a timebase triggered by TCC0
volatile uint16_t sintable1[64];
volatile DmacDescriptor wrb[DMAC_CH_NUM] __attribute__ ((aligned (16))); // Write-back DMAC descriptors
volatile DmacDescriptor descriptor_section[DMAC_CH_NUM] __attribute__ ((aligned (16))); // DMAC channel descriptors
DmacDescriptor descriptor __attribute__ ((aligned (16))); // Place holder descriptor
void setup()
{
for (uint16_t i = 0; i < 64; i++) // Calculate the first sine table with 64 entries
{
sintable1[i] = (uint16_t)((sinf(2 * PI * (float)i / 64) * 511) + 512);
}
analogWriteResolution(10); // Set the DAC's resolution to 10-bits
analogWrite(A0, 0); // Initialise the DAC
DMAC->BASEADDR.reg = (uint32_t)descriptor_section; // Set the descriptor section base address
DMAC->WRBADDR.reg = (uint32_t)wrb; // Set the write-back descriptor base adddress
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf); // Enable the DMAC and priority levels
DMAC->CHID.reg = DMAC_CHID_ID(0); // Select DMAC channel 0
DMAC->CHCTRLB.reg = DMAC_CHCTRLB_LVL(0) | // Set DMAC priority to level 0 (lowest)
DMAC_CHCTRLB_TRIGSRC(TCC0_DMAC_ID_OVF) | // Trigger on timer TCC0 overflow
DMAC_CHCTRLB_TRIGACT_BEAT; // Trigger every beat
descriptor.DESCADDR.reg = (uint32_t)&descriptor_section[0]; // Set up a circular descriptor
descriptor.SRCADDR.reg = (uint32_t)&sintable1[0] + 64 * sizeof(uint16_t); // Read the current value in the sine table
descriptor.DSTADDR.reg = (uint32_t)&DAC->DATA.reg; // Copy it into the DAC data register
descriptor.BTCNT.reg = 64; // This takes the number of sine table entries = 64 beats
descriptor.BTCTRL.reg = DMAC_BTCTRL_BEATSIZE_HWORD | // Set the beat size to 16-bits (Half Word)
DMAC_BTCTRL_SRCINC | // Increment the source address every beat
DMAC_BTCTRL_VALID; // Flag the descriptor as valid
memcpy((void*)&descriptor_section[0], &descriptor, sizeof(DmacDescriptor)); // Copy to the channel 0 descriptor
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK
GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0
GCLK_CLKCTRL_ID_TCC0_TCC1; // Select GCLK0 as the clock source for timers: TCC0 and TCC1
TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ; // Setup TCC0 in Normal Frequency (NFRQ) mode
while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
TCC0->PER.reg = 29; // 25kHz sine wave, 64 samples: 48MHz / (25000 * 64) - 1
while(TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
TCC0->CTRLA.bit.ENABLE = 1; // Enable the TCC0 output
while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
DMAC->CHID.reg = DMAC_CHID_ID(0); // Select DMAC channel
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; // Enable DMAC channel
}
void loop() {}