use Teensy 3.1 DMA to send sine wave to DAC, timed by PDB

Dependencies:   USBDevice mbed

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.

Committer:
manitou
Date:
Mon Oct 05 14:23:37 2015 +0000
Revision:
0:a57be408001f
use DMA to output sine wave to DAC, timed by PDB

Who changed what in which revision?

UserRevisionLine numberNew contents of line
manitou 0:a57be408001f 1 // DMA output to DAC controlled by PDB
manitou 0:a57be408001f 2 // https://forum.pjrc.com/threads/28101-Using-the-DAC-with-DMA-on-Teensy-3-1
manitou 0:a57be408001f 3
manitou 0:a57be408001f 4 #include "mbed.h"
manitou 0:a57be408001f 5 #include "USBSerial.h"
manitou 0:a57be408001f 6
manitou 0:a57be408001f 7 #define PRREG(x) pc.printf(#x" 0x%0x\n",x)
manitou 0:a57be408001f 8
manitou 0:a57be408001f 9 USBSerial pc; // Virtual serial port over USB
manitou 0:a57be408001f 10
manitou 0:a57be408001f 11 #define PDB_CONFIG (PDB_SC_TRGSEL(15) | PDB_SC_PDBEN_MASK | PDB_SC_CONT_MASK | PDB_SC_PDBIE_MASK | PDB_SC_DMAEN_MASK)
manitou 0:a57be408001f 12 // 48mhz bus 128 khz
manitou 0:a57be408001f 13 #define PDB_PERIOD (375-1)
manitou 0:a57be408001f 14
manitou 0:a57be408001f 15 #define CHNL 0
manitou 0:a57be408001f 16 #define DMAMUX_SOURCE_PDB 48
manitou 0:a57be408001f 17
manitou 0:a57be408001f 18 AnalogIn adc(A0);
manitou 0:a57be408001f 19
manitou 0:a57be408001f 20
manitou 0:a57be408001f 21 static volatile uint16_t sinetable[] = {
manitou 0:a57be408001f 22 2047, 2147, 2248, 2348, 2447, 2545, 2642, 2737,
manitou 0:a57be408001f 23 2831, 2923, 3012, 3100, 3185, 3267, 3346, 3422,
manitou 0:a57be408001f 24 3495, 3564, 3630, 3692, 3750, 3804, 3853, 3898,
manitou 0:a57be408001f 25 3939, 3975, 4007, 4034, 4056, 4073, 4085, 4093,
manitou 0:a57be408001f 26 4095, 4093, 4085, 4073, 4056, 4034, 4007, 3975,
manitou 0:a57be408001f 27 3939, 3898, 3853, 3804, 3750, 3692, 3630, 3564,
manitou 0:a57be408001f 28 3495, 3422, 3346, 3267, 3185, 3100, 3012, 2923,
manitou 0:a57be408001f 29 2831, 2737, 2642, 2545, 2447, 2348, 2248, 2147,
manitou 0:a57be408001f 30 2047, 1948, 1847, 1747, 1648, 1550, 1453, 1358,
manitou 0:a57be408001f 31 1264, 1172, 1083, 995, 910, 828, 749, 673,
manitou 0:a57be408001f 32 600, 531, 465, 403, 345, 291, 242, 197,
manitou 0:a57be408001f 33 156, 120, 88, 61, 39, 22, 10, 2,
manitou 0:a57be408001f 34 0, 2, 10, 22, 39, 61, 88, 120,
manitou 0:a57be408001f 35 156, 197, 242, 291, 345, 403, 465, 531,
manitou 0:a57be408001f 36 600, 673, 749, 828, 910, 995, 1083, 1172,
manitou 0:a57be408001f 37 1264, 1358, 1453, 1550, 1648, 1747, 1847, 1948,
manitou 0:a57be408001f 38 };
manitou 0:a57be408001f 39
manitou 0:a57be408001f 40 int main() {
manitou 0:a57be408001f 41 wait(2.0);
manitou 0:a57be408001f 42 pc.printf("SystemCoreClock %d %s %s\n",SystemCoreClock,__TIME__,__DATE__);
manitou 0:a57be408001f 43 // DAC init
manitou 0:a57be408001f 44 SIM->SCGC2 |= SIM_SCGC2_DAC0_MASK; // enable DAC clock
manitou 0:a57be408001f 45 DAC0->C0 = DAC_C0_DACEN_MASK | DAC_C0_DACRFS_MASK; // enable the DAC module, 3.3V reference
manitou 0:a57be408001f 46 // slowly ramp up to DC voltage, approx 1/4 second
manitou 0:a57be408001f 47 for (int16_t i=0; i<2048; i+=8) {
manitou 0:a57be408001f 48 *(int16_t *)&(DAC0->DAT[0]) = i;
manitou 0:a57be408001f 49 wait(0.001);
manitou 0:a57be408001f 50 }
manitou 0:a57be408001f 51
manitou 0:a57be408001f 52 // PDB init set the programmable delay block to trigger DMA requests
manitou 0:a57be408001f 53 SIM->SCGC6 |= SIM_SCGC6_PDB_MASK; // enable PDB clock
manitou 0:a57be408001f 54 PDB0->IDLY = 0; // interrupt delay register
manitou 0:a57be408001f 55 PDB0->MOD = PDB_PERIOD; // modulus register, sets period
manitou 0:a57be408001f 56 PDB0->SC = PDB_CONFIG | PDB_SC_LDOK_MASK; // load registers from buffers
manitou 0:a57be408001f 57 PDB0->SC = PDB_CONFIG | PDB_SC_SWTRIG_MASK; // reset and restart
manitou 0:a57be408001f 58 PDB0->CH[0].C1 = 0x0101; // enable PDB
manitou 0:a57be408001f 59
manitou 0:a57be408001f 60 // DMA init continuous loop
manitou 0:a57be408001f 61 SIM->SCGC7 |= SIM_SCGC7_DMA_MASK; // DMA clock
manitou 0:a57be408001f 62 SIM->SCGC6 |= SIM_SCGC6_DMAMUX_MASK; // Enable clock to DMA mux
manitou 0:a57be408001f 63 DMAMUX->CHCFG[CHNL] = DMAMUX_CHCFG_ENBL_MASK | /*DMAMUX_CHCFG_TRIG_MASK |*/
manitou 0:a57be408001f 64 DMAMUX_CHCFG_SOURCE(DMAMUX_SOURCE_PDB); // associate DMA channel with PDB trigger
manitou 0:a57be408001f 65 int bytes = sizeof(sinetable);
manitou 0:a57be408001f 66 DMA0->CR = DMA_CR_EMLM_MASK | DMA_CR_EDBG_MASK; // ? needed for circular
manitou 0:a57be408001f 67 DMA0->CERQ = CHNL; //disable channel
manitou 0:a57be408001f 68 DMA0->CERR = CHNL; // clear errors on channel
manitou 0:a57be408001f 69 DMA0->TCD[CHNL].SADDR = (uint32_t)sinetable;
manitou 0:a57be408001f 70 DMA0->TCD[CHNL].SOFF = 2;
manitou 0:a57be408001f 71 DMA0->TCD[CHNL].ATTR = DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1); //16-bit
manitou 0:a57be408001f 72 DMA0->TCD[CHNL].NBYTES_MLNO = 2;
manitou 0:a57be408001f 73 DMA0->TCD[CHNL].SLAST = -bytes;
manitou 0:a57be408001f 74 DMA0->TCD[CHNL].DADDR = (uint32_t)&(DAC0->DAT[0]);
manitou 0:a57be408001f 75 DMA0->TCD[CHNL].DOFF = 0;
manitou 0:a57be408001f 76 DMA0->TCD[CHNL].CITER_ELINKYES = bytes/2;
manitou 0:a57be408001f 77 DMA0->TCD[CHNL].DLAST_SGA = 0;
manitou 0:a57be408001f 78 DMA0->TCD[CHNL].BITER_ELINKYES = bytes/2;
manitou 0:a57be408001f 79
manitou 0:a57be408001f 80 DMA0->SERQ = CHNL; // enable
manitou 0:a57be408001f 81 #if 0
manitou 0:a57be408001f 82 PRREG(SIM->SCGC2);
manitou 0:a57be408001f 83 PRREG(SIM->SCGC6);
manitou 0:a57be408001f 84 PRREG(SIM->SCGC7);
manitou 0:a57be408001f 85 PRREG(PDB0->MOD);
manitou 0:a57be408001f 86 PRREG(DMAMUX->CHCFG[CHNL]);
manitou 0:a57be408001f 87 PRREG(DAC0->C0);
manitou 0:a57be408001f 88 PRREG(DMA0->CR);
manitou 0:a57be408001f 89 PRREG(DMA0->TCD[CHNL].CSR);
manitou 0:a57be408001f 90 PRREG(DMA0->TCD[CHNL].ATTR);
manitou 0:a57be408001f 91 PRREG(DMA0->TCD[CHNL].SOFF);
manitou 0:a57be408001f 92 PRREG(DMA0->TCD[CHNL].DOFF);
manitou 0:a57be408001f 93 PRREG(DMA0->TCD[CHNL].NBYTES_MLNO);
manitou 0:a57be408001f 94 PRREG(DMA0->TCD[CHNL].BITER_ELINKYES);
manitou 0:a57be408001f 95 PRREG(DMA0->TCD[CHNL].CITER_ELINKYES);
manitou 0:a57be408001f 96 PRREG(DMA0->TCD[CHNL].SLAST);
manitou 0:a57be408001f 97 PRREG(DMA0->TCD[CHNL].DLAST_SGA);
manitou 0:a57be408001f 98 PRREG(DMA0->TCD[CHNL].SADDR);
manitou 0:a57be408001f 99 PRREG(DMA0->TCD[CHNL].DADDR);
manitou 0:a57be408001f 100 //while(1);
manitou 0:a57be408001f 101 #endif
manitou 0:a57be408001f 102
manitou 0:a57be408001f 103 while(1) {
manitou 0:a57be408001f 104 pc.printf("%d\n",adc.read_u16()); // sample DAC output, jumper DAC to A0
manitou 0:a57be408001f 105 }
manitou 0:a57be408001f 106 }
manitou 0:a57be408001f 107