Jp3141
Well-known member
I am trying to build an arbitrary waveform generator by using DMA to drive the DAC diretly from a table in (flash) memory. I need at least 50,000 points. My code works with < 32767 points, but not more. I can't quite understand in the Kinetis docs if this is a limitation of the DMA engine, or just the DMA library in Teensy.
For reference, here's my code:
andf the waveform is defined like this:
For reference, here's my code:
Code:
#include <DMAChannel.h>
// DAC on pin A14
#define LED 13
#include "kinetis.h"
#include "wave.h"
// Multiple input & output objects use the Programmable Delay Block
// to set their sample rate. They must all configure the same
// period to avoid chaos.
#define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_CONT | PDB_SC_PDBIE | PDB_SC_DMAEN)
// 128 samples; PDB_Period = F_BUS/(128*1kHz)
#if F_BUS == 6*1000*10000
#define PDB_PERIOD (468-1)
#elif F_BUS == 56*1000*1000
#define PDB_PERIOD (437-1)
#elif F_BUS == 48*1000*1000
#define PDB_PERIOD (375-1)
#elif F_BUS == 36*1000*1000
#define PDB_PERIOD (281-1)
#elif F_BUS == 24*1000*1000
#define PDB_PERIOD (187-1)
#elif F_BUS == 16*1000*1000
#define PDB_PERIOD (125-1)
#else
#error "Unsupported F_BUS speed"
#endif
DMAChannel dma(false);
// not much point in updating the DAC faster than 1 us
#define FSTEP (1*1000*1000)
void setup() {
Serial.begin(0);
while (!Serial);
pinMode(0, OUTPUT);
Serial.println(__FILE__ " " __DATE__ " " __TIME__);
Serial.printf("Arbitrary Wave Generator, Step F = %i\n\n", FSTEP);
dma.begin(true); // allocate the DMA channel first
pinMode(LED, OUTPUT);
SIM_SCGC2 |= SIM_SCGC2_DAC0; // enable DAC clock
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // enable the DAC module, 3.3V reference
// set the programmable delay block to trigger DMA requests
SIM_SCGC6 |= SIM_SCGC6_PDB; // enable PDB clock
PDB0_IDLY = 0; // interrupt delay register
PDB0_MOD = F_BUS/FSTEP-1; // modulus register, sets period
Serial.printf("FBUS = %6i, PDB0_MOD = %6i (+1)\n", F_BUS, F_BUS/FSTEP-1);
PDB0_SC = PDB_CONFIG | PDB_SC_LDOK; // load registers from buffers
PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG; // reset and restart
PDB0_CH0C1 = 0x0101; // channel n control register?
[U]// dma.sourceBuffer(WiringWave, sizeof(WiringWave)); // Doesn't work if > 65534
dma.sourceBuffer(WiringWave, 65534);[/U]
Serial.printf("Waveform size = %i\n", sizeof(WiringWave));
dma.destination(*(volatile uint16_t *)&(DAC0_DAT0L));
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_PDB);
digitalWrite(LED, HIGH);
dma.enable();
}
void loop() {
}
andf the waveform is defined like this:
Code:
static const uint16_t WiringWave[] = {
1780,
1755,
1727,
1696,
1666,
.
. // for ~ 50,000 total samples
.
.
1635,
1608,
1582,
1030};