Zoltan Hudak / MODDMA
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers example4.h Source File

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