use Teensy 3.1 DMA to send sine wave to DAC, timed by PDB
Example of using Teensy 3.1 DMA to send sine wave value to DAC timed by PDB, based on https://forum.pjrc.com/threads/28101-Using-the-DAC-with-DMA-on-Teensy-3-1
you can jumper DAC to A0 and sample the output or view with scope.
main.cpp
- Committer:
- manitou
- Date:
- 2015-10-05
- Revision:
- 0:a57be408001f
File content as of revision 0:a57be408001f:
// DMA output to DAC controlled by PDB // https://forum.pjrc.com/threads/28101-Using-the-DAC-with-DMA-on-Teensy-3-1 #include "mbed.h" #include "USBSerial.h" #define PRREG(x) pc.printf(#x" 0x%0x\n",x) USBSerial pc; // Virtual serial port over USB #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN_MASK | PDB_SC_CONT_MASK | PDB_SC_PDBIE_MASK | PDB_SC_DMAEN_MASK) // 48mhz bus 128 khz #define PDB_PERIOD (375-1) #define CHNL 0 #define DMAMUX_SOURCE_PDB 48 AnalogIn adc(A0); static volatile uint16_t sinetable[] = { 2047, 2147, 2248, 2348, 2447, 2545, 2642, 2737, 2831, 2923, 3012, 3100, 3185, 3267, 3346, 3422, 3495, 3564, 3630, 3692, 3750, 3804, 3853, 3898, 3939, 3975, 4007, 4034, 4056, 4073, 4085, 4093, 4095, 4093, 4085, 4073, 4056, 4034, 4007, 3975, 3939, 3898, 3853, 3804, 3750, 3692, 3630, 3564, 3495, 3422, 3346, 3267, 3185, 3100, 3012, 2923, 2831, 2737, 2642, 2545, 2447, 2348, 2248, 2147, 2047, 1948, 1847, 1747, 1648, 1550, 1453, 1358, 1264, 1172, 1083, 995, 910, 828, 749, 673, 600, 531, 465, 403, 345, 291, 242, 197, 156, 120, 88, 61, 39, 22, 10, 2, 0, 2, 10, 22, 39, 61, 88, 120, 156, 197, 242, 291, 345, 403, 465, 531, 600, 673, 749, 828, 910, 995, 1083, 1172, 1264, 1358, 1453, 1550, 1648, 1747, 1847, 1948, }; int main() { wait(2.0); pc.printf("SystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__); // DAC init SIM->SCGC2 |= SIM_SCGC2_DAC0_MASK; // enable DAC clock DAC0->C0 = DAC_C0_DACEN_MASK | DAC_C0_DACRFS_MASK; // enable the DAC module, 3.3V reference // slowly ramp up to DC voltage, approx 1/4 second for (int16_t i=0; i<2048; i+=8) { *(int16_t *)&(DAC0->DAT[0]) = i; wait(0.001); } // PDB init set the programmable delay block to trigger DMA requests SIM->SCGC6 |= SIM_SCGC6_PDB_MASK; // enable PDB clock PDB0->IDLY = 0; // interrupt delay register PDB0->MOD = PDB_PERIOD; // modulus register, sets period PDB0->SC = PDB_CONFIG | PDB_SC_LDOK_MASK; // load registers from buffers PDB0->SC = PDB_CONFIG | PDB_SC_SWTRIG_MASK; // reset and restart PDB0->CH[0].C1 = 0x0101; // enable PDB // DMA init continuous loop SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; // DMA clock SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK; // Enable clock to DMA mux DMAMUX->CHCFG[CHNL] = DMAMUX_CHCFG_ENBL_MASK | /*DMAMUX_CHCFG_TRIG_MASK |*/ DMAMUX_CHCFG_SOURCE(DMAMUX_SOURCE_PDB); // associate DMA channel with PDB trigger int bytes = sizeof(sinetable); DMA0->CR = DMA_CR_EMLM_MASK | DMA_CR_EDBG_MASK; // ? needed for circular DMA0->CERQ = CHNL; //disable channel DMA0->CERR = CHNL; // clear errors on channel DMA0->TCD[CHNL].SADDR = (uint32_t)sinetable; DMA0->TCD[CHNL].SOFF = 2; DMA0->TCD[CHNL].ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1); //16-bit DMA0->TCD[CHNL].NBYTES_MLNO = 2; DMA0->TCD[CHNL].SLAST = -bytes; DMA0->TCD[CHNL].DADDR = (uint32_t)&(DAC0->DAT[0]); DMA0->TCD[CHNL].DOFF = 0; DMA0->TCD[CHNL].CITER_ELINKYES = bytes/2; DMA0->TCD[CHNL].DLAST_SGA = 0; DMA0->TCD[CHNL].BITER_ELINKYES = bytes/2; DMA0->SERQ = CHNL; // enable #if 0 PRREG(SIM->SCGC2); PRREG(SIM->SCGC6); PRREG(SIM->SCGC7); PRREG(PDB0->MOD); PRREG(DMAMUX->CHCFG[CHNL]); PRREG(DAC0->C0); PRREG(DMA0->CR); PRREG(DMA0->TCD[CHNL].CSR); PRREG(DMA0->TCD[CHNL].ATTR); PRREG(DMA0->TCD[CHNL].SOFF); PRREG(DMA0->TCD[CHNL].DOFF); PRREG(DMA0->TCD[CHNL].NBYTES_MLNO); PRREG(DMA0->TCD[CHNL].BITER_ELINKYES); PRREG(DMA0->TCD[CHNL].CITER_ELINKYES); PRREG(DMA0->TCD[CHNL].SLAST); PRREG(DMA0->TCD[CHNL].DLAST_SGA); PRREG(DMA0->TCD[CHNL].SADDR); PRREG(DMA0->TCD[CHNL].DADDR); //while(1); #endif while(1) { pc.printf("%d\n",adc.read_u16()); // sample DAC output, jumper DAC to A0 } }