MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC

Dependents:   FirstTest WaveSim IO-dma-memmem DACDMAfuncgenlib ... more

Committer:
AjK
Date:
Mon Mar 14 13:51:38 2011 +0000
Revision:
16:cb10aec6feb1
1.12 See ChangeLoc.c

Who changed what in which revision?

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