example of variable frequency DAQ output using DMA Controller

Dependencies:   mbed MODDMA

Committer:
jtarasidis
Date:
Thu Mar 26 20:11:31 2020 +0000
Revision:
0:6f5952a298e2
sin example MODDMA

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jtarasidis 0:6f5952a298e2 1 /*
jtarasidis 0:6f5952a298e2 2 * Demonstrates sending a buffer repeatedly to the DAC using DMA.
jtarasidis 0:6f5952a298e2 3 * Connect an oscilloscope to Mbed pin 18. This example doesn't
jtarasidis 0:6f5952a298e2 4 * output anything else (nothing on any serial ports).
jtarasidis 0:6f5952a298e2 5 */
jtarasidis 0:6f5952a298e2 6 #include "mbed.h"
jtarasidis 0:6f5952a298e2 7 #include "MODDMA.h"
jtarasidis 0:6f5952a298e2 8
jtarasidis 0:6f5952a298e2 9 // Make the buffer size match the number of degrees
jtarasidis 0:6f5952a298e2 10 // in a circle since we are going to output a sinewave.
jtarasidis 0:6f5952a298e2 11 #define BUFFER_SIZE 360
jtarasidis 0:6f5952a298e2 12
jtarasidis 0:6f5952a298e2 13 // Set DAC output power mode.
jtarasidis 0:6f5952a298e2 14 #define DAC_POWER_MODE (1 << 16)
jtarasidis 0:6f5952a298e2 15
jtarasidis 0:6f5952a298e2 16 DigitalOut led1(LED1);
jtarasidis 0:6f5952a298e2 17 DigitalOut led3(LED3);
jtarasidis 0:6f5952a298e2 18 DigitalOut led4(LED4);
jtarasidis 0:6f5952a298e2 19
jtarasidis 0:6f5952a298e2 20 int buffer[2][BUFFER_SIZE];
jtarasidis 0:6f5952a298e2 21
jtarasidis 0:6f5952a298e2 22 AnalogOut signal(p18);
jtarasidis 0:6f5952a298e2 23
jtarasidis 0:6f5952a298e2 24 MODDMA dma;
jtarasidis 0:6f5952a298e2 25 MODDMA_Config *conf0, *conf1;
jtarasidis 0:6f5952a298e2 26
jtarasidis 0:6f5952a298e2 27 void TC0_callback(void);
jtarasidis 0:6f5952a298e2 28 void ERR0_callback(void);
jtarasidis 0:6f5952a298e2 29
jtarasidis 0:6f5952a298e2 30 void TC1_callback(void);
jtarasidis 0:6f5952a298e2 31 void ERR1_callback(void);
jtarasidis 0:6f5952a298e2 32
jtarasidis 0:6f5952a298e2 33 int main() {
jtarasidis 0:6f5952a298e2 34 volatile int life_counter = 0;
jtarasidis 0:6f5952a298e2 35
jtarasidis 0:6f5952a298e2 36 // Create a sinewave buffer for testing.
jtarasidis 0:6f5952a298e2 37 for (int i = 0; i <= 90; i++) buffer[0][i] = (512 * sin(3.14159/180.0 * i)) + 512;
jtarasidis 0:6f5952a298e2 38 for (int i = 91; i <= 180; i++) buffer[0][i] = buffer[0][180 - i];
jtarasidis 0:6f5952a298e2 39 for (int i = 181; i <= 270; i++) buffer[0][i] = 512 - (buffer[0][i - 180] - 512);
jtarasidis 0:6f5952a298e2 40 for (int i = 271; i < 360; i++) buffer[0][i] = 512 - (buffer[0][360 - i] - 512);
jtarasidis 0:6f5952a298e2 41
jtarasidis 0:6f5952a298e2 42 // Adjust the sinewave buffer for use with DAC hardware.
jtarasidis 0:6f5952a298e2 43 for (int i = 0; i < 360; i++) {
jtarasidis 0:6f5952a298e2 44 buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0);
jtarasidis 0:6f5952a298e2 45 buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave.
jtarasidis 0:6f5952a298e2 46 }
jtarasidis 0:6f5952a298e2 47
jtarasidis 0:6f5952a298e2 48 // Prepare the GPDMA system for buffer0.
jtarasidis 0:6f5952a298e2 49 conf0 = new MODDMA_Config;
jtarasidis 0:6f5952a298e2 50 conf0
jtarasidis 0:6f5952a298e2 51 ->channelNum ( MODDMA::Channel_0 )
jtarasidis 0:6f5952a298e2 52 ->srcMemAddr ( (uint32_t) &buffer[0] )
jtarasidis 0:6f5952a298e2 53 ->dstMemAddr ( MODDMA::DAC )
jtarasidis 0:6f5952a298e2 54 ->transferSize ( 360 )
jtarasidis 0:6f5952a298e2 55 ->transferType ( MODDMA::m2p )
jtarasidis 0:6f5952a298e2 56 ->dstConn ( MODDMA::DAC )
jtarasidis 0:6f5952a298e2 57 ->attach_tc ( &TC0_callback )
jtarasidis 0:6f5952a298e2 58 ->attach_err ( &ERR0_callback )
jtarasidis 0:6f5952a298e2 59 ; // config end
jtarasidis 0:6f5952a298e2 60
jtarasidis 0:6f5952a298e2 61
jtarasidis 0:6f5952a298e2 62 // Prepare the GPDMA system for buffer1.
jtarasidis 0:6f5952a298e2 63 conf1 = new MODDMA_Config;
jtarasidis 0:6f5952a298e2 64 conf1
jtarasidis 0:6f5952a298e2 65 ->channelNum ( MODDMA::Channel_1 )
jtarasidis 0:6f5952a298e2 66 ->srcMemAddr ( (uint32_t) &buffer[1] )
jtarasidis 0:6f5952a298e2 67 ->dstMemAddr ( MODDMA::DAC )
jtarasidis 0:6f5952a298e2 68 ->transferSize ( 360 )
jtarasidis 0:6f5952a298e2 69 ->transferType ( MODDMA::m2p )
jtarasidis 0:6f5952a298e2 70 ->dstConn ( MODDMA::DAC )
jtarasidis 0:6f5952a298e2 71 ->attach_tc ( &TC1_callback )
jtarasidis 0:6f5952a298e2 72 ->attach_err ( &ERR1_callback )
jtarasidis 0:6f5952a298e2 73 ; // config end
jtarasidis 0:6f5952a298e2 74
jtarasidis 0:6f5952a298e2 75
jtarasidis 0:6f5952a298e2 76 // Calculating the transfer frequency:
jtarasidis 0:6f5952a298e2 77 // By default, the Mbed library sets the PCLK_DAC clock value
jtarasidis 0:6f5952a298e2 78 // to 24MHz. One complete sinewave cycle in each buffer is 360
jtarasidis 0:6f5952a298e2 79 // points long. So, for a 1Hz wave we would need to transfer 360
jtarasidis 0:6f5952a298e2 80 // values per second. That would be 24000000/360 which is approx
jtarasidis 0:6f5952a298e2 81 // 66,666. But that's no good! The count val is only 16bits in size
jtarasidis 0:6f5952a298e2 82 // so bare this in mind. If you need to go slower you will need to
jtarasidis 0:6f5952a298e2 83 // alter PCLK_DAC from CCLK/4 to CCLK/8.
jtarasidis 0:6f5952a298e2 84 // For our demo we are going to have the sinewave run at 1kHz.
jtarasidis 0:6f5952a298e2 85 // That's 24000000/360000 which is approx 66. Experimentation
jtarasidis 0:6f5952a298e2 86 // however showed 65 to get closer to 1kHz (on my Mbed and scope
jtarasidis 0:6f5952a298e2 87 // at least).
jtarasidis 0:6f5952a298e2 88 LPC_DAC->DACCNTVAL = 65; // 6500 for 10Hz
jtarasidis 0:6f5952a298e2 89
jtarasidis 0:6f5952a298e2 90 // Prepare first configuration.
jtarasidis 0:6f5952a298e2 91 if (!dma.Prepare( conf0 )) {
jtarasidis 0:6f5952a298e2 92 error("Doh!");
jtarasidis 0:6f5952a298e2 93 }
jtarasidis 0:6f5952a298e2 94
jtarasidis 0:6f5952a298e2 95 // Begin (enable DMA and counter). Note, don't enable
jtarasidis 0:6f5952a298e2 96 // DBLBUF_ENA as we are using DMA double buffering.
jtarasidis 0:6f5952a298e2 97 LPC_DAC->DACCTRL |= (3UL << 2);
jtarasidis 0:6f5952a298e2 98
jtarasidis 0:6f5952a298e2 99 while (1) {
jtarasidis 0:6f5952a298e2 100 // There's not a lot to do as DMA and interrupts are
jtarasidis 0:6f5952a298e2 101 // now handling the buffer transfers. So we'll just
jtarasidis 0:6f5952a298e2 102 // flash led1 to show the Mbed is alive and kicking.
jtarasidis 0:6f5952a298e2 103 if (life_counter++ > 1000000) {
jtarasidis 0:6f5952a298e2 104 led1 = !led1; // Show some sort of life.
jtarasidis 0:6f5952a298e2 105 life_counter = 0;
jtarasidis 0:6f5952a298e2 106 }
jtarasidis 0:6f5952a298e2 107 }
jtarasidis 0:6f5952a298e2 108 }
jtarasidis 0:6f5952a298e2 109
jtarasidis 0:6f5952a298e2 110 // Configuration callback on TC
jtarasidis 0:6f5952a298e2 111 void TC0_callback(void) {
jtarasidis 0:6f5952a298e2 112
jtarasidis 0:6f5952a298e2 113 // Just show sending buffer0 complete.
jtarasidis 0:6f5952a298e2 114 led3 = !led3;
jtarasidis 0:6f5952a298e2 115
jtarasidis 0:6f5952a298e2 116 // Get configuration pointer.
jtarasidis 0:6f5952a298e2 117 MODDMA_Config *config = dma.getConfig();
jtarasidis 0:6f5952a298e2 118
jtarasidis 0:6f5952a298e2 119 // Finish the DMA cycle by shutting down the channel.
jtarasidis 0:6f5952a298e2 120 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
jtarasidis 0:6f5952a298e2 121
jtarasidis 0:6f5952a298e2 122 // Swap to buffer1
jtarasidis 0:6f5952a298e2 123 dma.Prepare( conf1 );
jtarasidis 0:6f5952a298e2 124
jtarasidis 0:6f5952a298e2 125 // Clear DMA IRQ flags.
jtarasidis 0:6f5952a298e2 126 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
jtarasidis 0:6f5952a298e2 127 }
jtarasidis 0:6f5952a298e2 128
jtarasidis 0:6f5952a298e2 129 // Configuration callback on Error
jtarasidis 0:6f5952a298e2 130 void ERR0_callback(void) {
jtarasidis 0:6f5952a298e2 131 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
jtarasidis 0:6f5952a298e2 132 }
jtarasidis 0:6f5952a298e2 133
jtarasidis 0:6f5952a298e2 134 // Configuration callback on TC
jtarasidis 0:6f5952a298e2 135 void TC1_callback(void) {
jtarasidis 0:6f5952a298e2 136
jtarasidis 0:6f5952a298e2 137 // Just show sending buffer1 complete.
jtarasidis 0:6f5952a298e2 138 led4 = !led4;
jtarasidis 0:6f5952a298e2 139
jtarasidis 0:6f5952a298e2 140 // Get configuration pointer.
jtarasidis 0:6f5952a298e2 141 MODDMA_Config *config = dma.getConfig();
jtarasidis 0:6f5952a298e2 142
jtarasidis 0:6f5952a298e2 143 // Finish the DMA cycle by shutting down the channel.
jtarasidis 0:6f5952a298e2 144 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
jtarasidis 0:6f5952a298e2 145
jtarasidis 0:6f5952a298e2 146 // Swap to buffer0
jtarasidis 0:6f5952a298e2 147 dma.Prepare( conf0 );
jtarasidis 0:6f5952a298e2 148
jtarasidis 0:6f5952a298e2 149 // Clear DMA IRQ flags.
jtarasidis 0:6f5952a298e2 150 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
jtarasidis 0:6f5952a298e2 151 }
jtarasidis 0:6f5952a298e2 152
jtarasidis 0:6f5952a298e2 153 // Configuration callback on Error
jtarasidis 0:6f5952a298e2 154 void ERR1_callback(void) {
jtarasidis 0:6f5952a298e2 155 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
jtarasidis 0:6f5952a298e2 156 }