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
example4.h
00001 /* 00002 * Demonstrates sending a buffer repeatedly to the DAC using DMA. 00003 * Connect an oscilloscope to Mbed pin 18. This example doesn't 00004 * output anything else (nothing on any serial ports). 00005 */ 00006 #include "mbed.h" 00007 #include "MODDMA.h" 00008 00009 // Make the buffer size match the number of degrees 00010 // in a circle since we are going to output a sinewave. 00011 #define BUFFER_SIZE 360 00012 00013 // Set DAC output power mode. 00014 #define DAC_POWER_MODE (1 << 16) 00015 00016 DigitalOut led1(LED1); 00017 DigitalOut led3(LED3); 00018 DigitalOut led4(LED4); 00019 00020 int buffer[2][BUFFER_SIZE]; 00021 00022 AnalogOut signal(p18); 00023 00024 MODDMA dma; 00025 MODDMA_Config *conf0, *conf1; 00026 00027 void TC0_callback(void); 00028 void ERR0_callback(void); 00029 00030 void TC1_callback(void); 00031 void ERR1_callback(void); 00032 00033 int main() { 00034 volatile int life_counter = 0; 00035 00036 // Create a sinewave buffer for testing. 00037 for (int i = 0; i <= 90; i++) buffer[0][i] = (512 * sin(3.14159/180.0 * i)) + 512; 00038 for (int i = 91; i <= 180; i++) buffer[0][i] = buffer[0][180 - i]; 00039 for (int i = 181; i <= 270; i++) buffer[0][i] = 512 - (buffer[0][i - 180] - 512); 00040 for (int i = 271; i < 360; i++) buffer[0][i] = 512 - (buffer[0][360 - i] - 512); 00041 00042 // Adjust the sinewave buffer for use with DAC hardware. 00043 for (int i = 0; i < 360; i++) { 00044 buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0); 00045 buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave. 00046 } 00047 00048 // Prepare the GPDMA system for buffer0. 00049 conf0 = new MODDMA_Config; 00050 conf0 00051 ->channelNum ( MODDMA::Channel_0 ) 00052 ->srcMemAddr ( (uint32_t) &buffer[0] ) 00053 ->dstMemAddr ( MODDMA::DAC ) 00054 ->transferSize ( 360 ) 00055 ->transferType ( MODDMA::m2p ) 00056 ->dstConn ( MODDMA::DAC ) 00057 ->attach_tc ( &TC0_callback ) 00058 ->attach_err ( &ERR0_callback ) 00059 ; // config end 00060 00061 00062 // Prepare the GPDMA system for buffer1. 00063 conf1 = new MODDMA_Config; 00064 conf1 00065 ->channelNum ( MODDMA::Channel_1 ) 00066 ->srcMemAddr ( (uint32_t) &buffer[1] ) 00067 ->dstMemAddr ( MODDMA::DAC ) 00068 ->transferSize ( 360 ) 00069 ->transferType ( MODDMA::m2p ) 00070 ->dstConn ( MODDMA::DAC ) 00071 ->attach_tc ( &TC1_callback ) 00072 ->attach_err ( &ERR1_callback ) 00073 ; // config end 00074 00075 00076 // Calculating the transfer frequency: 00077 // By default, the Mbed library sets the PCLK_DAC clock value 00078 // to 24MHz. One complete sinewave cycle in each buffer is 360 00079 // points long. So, for a 1Hz wave we would need to transfer 360 00080 // values per second. That would be 24000000/360 which is approx 00081 // 66,666. But that's no good! The count val is only 16bits in size 00082 // so bare this in mind. If you need to go slower you will need to 00083 // alter PCLK_DAC from CCLK/4 to CCLK/8. 00084 // For our demo we are going to have the sinewave run at 1kHz. 00085 // That's 24000000/360000 which is approx 66. Experimentation 00086 // however showed 65 to get closer to 1kHz (on my Mbed and scope 00087 // at least). 00088 LPC_DAC->DACCNTVAL = 65; // 6500 for 10Hz 00089 00090 // Prepare first configuration. 00091 if (!dma.Prepare( conf0 )) { 00092 error("Doh!"); 00093 } 00094 00095 // Begin (enable DMA and counter). Note, don't enable 00096 // DBLBUF_ENA as we are using DMA double buffering. 00097 LPC_DAC->DACCTRL |= (3UL << 2); 00098 00099 while (1) { 00100 // There's not a lot to do as DMA and interrupts are 00101 // now handling the buffer transfers. So we'll just 00102 // flash led1 to show the Mbed is alive and kicking. 00103 if (life_counter++ > 1000000) { 00104 led1 = !led1; // Show some sort of life. 00105 life_counter = 0; 00106 } 00107 } 00108 } 00109 00110 // Configuration callback on TC 00111 void TC0_callback(void) { 00112 00113 // Just show sending buffer0 complete. 00114 led3 = !led3; 00115 00116 // Get configuration pointer. 00117 MODDMA_Config *config = dma.getConfig(); 00118 00119 // Finish the DMA cycle by shutting down the channel. 00120 dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); 00121 00122 // Swap to buffer1 00123 dma.Prepare( conf1 ); 00124 00125 // Clear DMA IRQ flags. 00126 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 00127 } 00128 00129 // Configuration callback on Error 00130 void ERR0_callback(void) { 00131 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); 00132 } 00133 00134 // Configuration callback on TC 00135 void TC1_callback(void) { 00136 00137 // Just show sending buffer1 complete. 00138 led4 = !led4; 00139 00140 // Get configuration pointer. 00141 MODDMA_Config *config = dma.getConfig(); 00142 00143 // Finish the DMA cycle by shutting down the channel. 00144 dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); 00145 00146 // Swap to buffer0 00147 dma.Prepare( conf0 ); 00148 00149 // Clear DMA IRQ flags. 00150 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 00151 } 00152 00153 // Configuration callback on Error 00154 void ERR1_callback(void) { 00155 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); 00156 }
Generated on Tue Jul 12 2022 12:57:52 by 1.7.2