SPI RAM 23LC1024 (Microchip) with DMA and FIFO

Dependencies:   SerRAM mbed

Fork of SPIRAM_23LC1024_DMA by Suga koubou

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 // 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 }