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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers example2.h Source File

example2.h

00001 /*
00002  * This example was provided to support Mbed forum thread:-
00003  * http://mbed.org/forum/mbed/topic/1798
00004  */
00005  
00006 #include "mbed.h"
00007 #include "MODDMA.h"
00008 
00009 #define SAMPLE_BUFFER_LENGTH 32
00010 
00011 DigitalOut led1(LED1);
00012 DigitalOut led2(LED2);
00013 
00014 MODDMA dma;
00015 Serial pc(USBTX, USBRX);
00016 
00017 // ISR set's this when transfer complete.
00018 bool dmaTransferComplete = false;
00019 
00020 // Function prototypes for IRQ callbacks.
00021 // See definitions following main() below.
00022 void TC0_callback(void);
00023 void ERR0_callback(void);
00024 
00025 int main() {
00026 
00027     // Create a buffer to hold the ADC samples and clear it.
00028     // Note, we are going to sample two ADC inputs so they
00029     // end up in this buffer "interleaved". So you will want
00030     // a buffer twice this size to a real life given sample
00031     // frequency. See the printf() output for details.
00032     uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH];    
00033     memset(adcInputBuffer, 0, sizeof(adcInputBuffer));
00034     
00035     // We use the ADC irq to trigger DMA and the manual says
00036     // that in this case the NVIC for ADC must be disabled.
00037     NVIC_DisableIRQ(ADC_IRQn);
00038     
00039     // Power up the ADC and set PCLK
00040     LPC_SC->PCONP    |=  (1UL << 12);
00041     LPC_SC->PCLKSEL0 &= ~(3UL << 24); // PCLK = CCLK/4 96M/4 = 24MHz
00042     
00043     // Enable the ADC, 12MHz,  ADC0.0 & .1
00044     LPC_ADC->ADCR  = (1UL << 21) | (1UL << 8) | (3UL << 0); 
00045     
00046     // Set the pin functions to ADC
00047     LPC_PINCON->PINSEL1 &= ~(3UL << 14);  /* P0.23, Mbed p15. */
00048     LPC_PINCON->PINSEL1 |=  (1UL << 14);
00049     LPC_PINCON->PINSEL1 &= ~(3UL << 16);  /* P0.24, Mbed p16. */
00050     LPC_PINCON->PINSEL1 |=  (1UL << 16);
00051     
00052     // Setup the serial port to print out results.
00053     pc.baud(115200);
00054     pc.printf("ADC with DMA example\n");
00055     pc.printf("====================\n");
00056     
00057     // Prepare an ADC configuration.
00058     MODDMA_Config *conf = new MODDMA_Config;
00059     conf
00060      ->channelNum    ( MODDMA::Channel_0 )
00061      ->srcMemAddr    ( 0 )
00062      ->dstMemAddr    ( (uint32_t)adcInputBuffer )
00063      ->transferSize  ( SAMPLE_BUFFER_LENGTH )
00064      ->transferType  ( MODDMA::p2m )
00065      ->transferWidth ( MODDMA::word )
00066      ->srcConn       ( MODDMA::ADC )
00067      ->dstConn       ( 0 )
00068      ->dmaLLI        ( 0 )
00069      ->attach_tc     ( &TC0_callback )
00070      ->attach_err    ( &ERR0_callback )
00071     ; // end conf.
00072     
00073     // Prepare configuration.
00074     dma.Setup( conf );
00075     
00076     // Enable configuration.
00077     dma.Enable( conf );
00078     
00079     // Enable ADC irq flag (to DMA).
00080     // Note, don't set the individual flags,
00081     // just set the global flag.
00082     LPC_ADC->ADINTEN = 0x100;
00083 
00084     // Enable burst mode on inputs 0 and 1.
00085     LPC_ADC->ADCR |= (1UL << 16); 
00086     
00087     while (1) {
00088         // When transfer complete do this block.
00089         if (dmaTransferComplete) {
00090             delete conf; // No memory leaks, delete the configuration.
00091             dmaTransferComplete = false;
00092             for (int i = 0; i < SAMPLE_BUFFER_LENGTH; i++) {
00093                 int channel = (adcInputBuffer[i] >> 24) & 0x7;
00094                 int iVal = (adcInputBuffer[i] >> 4) & 0xFFF;
00095                 double fVal = 3.3 * (double)((double)iVal) / ((double)0x1000); // scale to 0v to 3.3v
00096                 pc.printf("Array index %02d : ADC input channel %d = 0x%03x %01.3f volts\n", i, channel, iVal, fVal);                  
00097             }
00098         }
00099         
00100         // Just flash LED1 for something to do.
00101         led1 = !led1;
00102         wait(0.25);        
00103     }
00104 }
00105 
00106 // Configuration callback on TC
00107 void TC0_callback(void) {
00108     
00109     MODDMA_Config *config = dma.getConfig();
00110     
00111     // Disbale burst mode and switch off the IRQ flag.
00112     LPC_ADC->ADCR &= ~(1UL << 16);
00113     LPC_ADC->ADINTEN = 0;    
00114     
00115     // Finish the DMA cycle by shutting down the channel.
00116     dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
00117     dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
00118     
00119     // Tell main() while(1) loop to print the results.
00120     dmaTransferComplete = true;            
00121     
00122     // Switch on LED2 to show transfer complete.
00123     led2 = 1;        
00124     
00125     // Clear DMA IRQ flags.
00126     if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
00127     if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
00128 }
00129 
00130 // Configuration callback on Error
00131 void ERR0_callback(void) {
00132     // Switch off burst conversions.
00133     LPC_ADC->ADCR |= ~(1UL << 16);
00134     LPC_ADC->ADINTEN = 0;
00135     error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
00136 }
00137