Programming an array of NeoPixels using the GPDMA for maximum performance.

Dependencies:   MODDMA mbed

Files at this revision

API Documentation at this revision

Comitter:
tohu
Date:
Wed Dec 10 21:35:57 2014 +0000
Parent:
4:f2ef03b37a66
Commit message:
Halvst?dad variant

Changed in this revision

example4.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/example4.h	Sat Dec 06 19:57:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Demonstrates sending a buffer repeatedly to the DAC using DMA.
- * Connect an oscilloscope to Mbed pin 18. This example doesn't
- * output anything else (nothing on any serial ports).
- */
-#include "mbed.h"
-#include "MODDMA.h"
-
-// Make the buffer size match the number of degrees
-// in a circle since we are going to output a sinewave.
-#define BUFFER_SIZE 360
-
-// Set DAC output power mode.
-#define DAC_POWER_MODE  (1 << 16)
-
-DigitalOut led1(LED1);
-DigitalOut led3(LED3);
-DigitalOut led4(LED4);
-
-int buffer[2][BUFFER_SIZE];
-
-AnalogOut signal(p18);
-
-MODDMA dma;
-MODDMA_Config *conf0, *conf1;
-
-void TC0_callback(void);
-void ERR0_callback(void);
-
-void TC1_callback(void);
-void ERR1_callback(void);
-
-int main() {
-    volatile int life_counter = 0;
-    
-    
-    // Prepare the GPDMA system for buffer0.
-    conf0 = new MODDMA_Config;
-    conf0
-     ->channelNum    ( MODDMA::Channel_0 )
-     ->srcMemAddr    ( (uint32_t) &buffer[0] )
-     ->dstMemAddr    ( MODDMA::DAC )
-     ->transferSize  ( 360 )
-     ->transferType  ( MODDMA::m2p )
-     ->dstConn       ( MODDMA::DAC )
-     ->attach_tc     ( &TC0_callback )
-     ->attach_err    ( &ERR0_callback )     
-    ; // config end
-    
-    
-    // Prepare the GPDMA system for buffer1.
-    conf1 = new MODDMA_Config;
-    conf1
-     ->channelNum    ( MODDMA::Channel_1 )
-     ->srcMemAddr    ( (uint32_t) &buffer[1] )
-     ->dstMemAddr    ( MODDMA::DAC )
-     ->transferSize  ( 360 )
-     ->transferType  ( MODDMA::m2p )
-     ->dstConn       ( MODDMA::DAC )
-     ->attach_tc     ( &TC1_callback )
-     ->attach_err    ( &ERR1_callback )     
-    ; // config end
-
-    
-    // Calculating the transfer frequency:
-    // By default, the Mbed library sets the PCLK_DAC clock value
-    // to 24MHz. One complete sinewave cycle in each buffer is 360
-    // points long. So, for a 1Hz wave we would need to transfer 360
-    // values per second. That would be 24000000/360 which is approx
-    // 66,666. But that's no good! The count val is only 16bits in size
-    // so bare this in mind. If you need to go slower you will need to
-    // alter PCLK_DAC from CCLK/4 to CCLK/8.
-    // For our demo we are going to have the sinewave run at 1kHz.
-    // That's 24000000/360000 which is approx 66. Experimentation
-    // however showed 65 to get closer to 1kHz (on my Mbed and scope 
-    // at least).
-    LPC_DAC->DACCNTVAL = 65; // 6500 for 10Hz
-
-    // Prepare first configuration.
-    if (!dma.Prepare( conf0 )) {
-        error("Doh!");
-    }
-    
-    // Begin (enable DMA and counter). Note, don't enable
-    // DBLBUF_ENA as we are using DMA double buffering.
-    LPC_DAC->DACCTRL |= (3UL << 2);
-    
-    while (1) { 
-        // There's not a lot to do as DMA and interrupts are
-        // now handling the buffer transfers. So we'll just
-        // flash led1 to show the Mbed is alive and kicking.
-        if (life_counter++ > 1000000) {
-            led1 = !led1; // Show some sort of life.
-            life_counter = 0;
-        }
-    } 
-}
-
-// Configuration callback on TC
-void TC0_callback(void) {
-    
-    // Just show sending buffer0 complete.
-    led3 = !led3; 
-        
-    // Get configuration pointer.
-    MODDMA_Config *config = dma.getConfig();
-    
-    // Finish the DMA cycle by shutting down the channel.
-    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
-   
-    // Swap to buffer1
-    dma.Prepare( conf1 );
-
-    // Clear DMA IRQ flags.
-    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-}
-
-// Configuration callback on Error
-void ERR0_callback(void) {
-    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
-}
-
-// Configuration callback on TC
-void TC1_callback(void) {
-    
-    // Just show sending buffer1 complete.
-    led4 = !led4; 
-        
-    // Get configuration pointer.
-    MODDMA_Config *config = dma.getConfig();
-    
-    // Finish the DMA cycle by shutting down the channel.
-    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
-    
-    // Swap to buffer0
-    dma.Prepare( conf0 );
-    
-    // Clear DMA IRQ flags.
-    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-}
-
-// Configuration callback on Error
-void ERR1_callback(void) {
-    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
-}
--- a/main.cpp	Sat Dec 06 19:57:16 2014 +0000
+++ b/main.cpp	Wed Dec 10 21:35:57 2014 +0000
@@ -8,73 +8,22 @@
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 
-
 #define IMAGE_SIZE 123
 
-// Set DAC output power mode.
-#define DAC_POWER_MODE  (1 << 16)
-
 //
 // IMAGE AND RENDER BUFFER
 //
 
-// TODO: WHY DOESN'T THE LAST BIT GET OK!?!?!?!?!?!
-
-// WHY DOES ALL 0,1,4,5,8,9,C,D GET DISPLACED??
-
-int foo = 0xcc;
-int bar = 0xee;
-
-#if 0
-uint8_t  smiley [IMAGE_SIZE] = {
-    0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 
-    0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 
-    0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 
-    0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 
-    0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF
-    };
-#endif
-
 #if 1
+// OK
 uint8_t  smiley [IMAGE_SIZE] = {
-    0x0, 0x0, 0xFF, 0x0, 0x0, 0xDC, 0x0, 0x0, 0xBA, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0,0x0, 0x0, 0x3E, 0x0, 0x0, 0x1F,
-    0x0, 0x0, 0xFF, 0x0, 0x0, 0xDC, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x1F,
-    0x0, 0x0, 0xFF, 0x0, 0x0, 0xDC, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x1F,
-    0x0, 0x0, 0xFF, 0x0, 0x0, 0xDC, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x1F,
-    0x0, 0x0, 0xFF, 0x0, 0x0, 0xDC, 0x0, 0x0, 0xBA, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x3E, 0x0, 0x0, 0x1F,
-    0x0, 0x0, 0x0
-};
-#endif
-
-#if 0
-uint8_t  smiley [IMAGE_SIZE] = {
-    0x00, 0x0, 0x0, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x5, 0x5, 0x5,0x6, 0x6, 0x6, 0x7, 0x7, 0x7,
-    0x8, 0x8, 0x8, 0x9, 0x9, 0x9, 0xa, 0xa, 0xa, 0xb, 0xb, 0xb, 0xc, 0xc, 0xc, 0xd, 0xd, 0xd,0xe, 0xe, 0xe, 0xf, 0xf, 0xf,
-    0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17,
-    0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f,
-    0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7,
-    0x0, 0x0, 0x0
-};
-#endif
-
-#if 0
-uint8_t  smiley [IMAGE_SIZE] = {
-    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-    0x0, 0x0, 0x0
-};
-
-uint8_t  smiley [IMAGE_SIZE] = {
-    0xFF,0x0,0x0,0xD9,0x0,0x0,0xBA,0x0,0x0,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x3E,0x0,0x0,0x1F,0x0,0x0,
-    0xFF,0x0,0x0,0xD9,0x0,0x0,0x0,0xFF,0xFF,0x0,0x0,0x0,0x0,0xFF,0xFF,0x0,0x0,0x0,0x0,0xFF,0xFF,0x1F,0x0,0x0,
-    0xFF,0x0,0x0,0xD9,0x0,0x0,0x0,0xFF,0xFF,0x0,0x0,0x0,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x1F,0x0,0x0,
-    0xFF,0x0,0x0,0xD9,0x0,0x0,0x0,0xFF,0xFF,0x0,0x0,0x0,0x0,0xFF,0xFF,0x0,0x0,0x0,0x0,0xFF,0xFF,0x1F,0x0,0x0,
-    0xFF,0x0,0x0,0xD9,0x0,0x0,0xBA,0x0,0x0,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x0,0xFF,0xFF,0x3E,0x0,0x0,0x1F,0x0,0x0,
-    0x0, 0x0, 0x0
-};
+    0x0,  0xFF, 0x0, 0xFF,  0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0x0,  0xFF, 0x0, 0x0,  0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0x0,  0xFF, 0x0,  0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0, 0x3F, 0xBE, 0x0, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0,  0xFF, 0xFF, 0xFF, 
+    0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0, 0x7F, 0x7F, 0x0, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0, 
+    0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0, 0xBE, 0x3F, 0x0, 0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0, 0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0,  0xFF, 0xFF, 0xFF, 
+    0xFF, 0x0,  0x0, 0xFF, 0xFF,  0xFF, 0xFF, 0xFF,  0xFF, 0xFF, 0x0,  0x0, 0xFF, 0x0,  0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0,  0x0,  0xFF, 0xFF, 0xFF,
+    0x0,  0x0, 0x0
+    };
 #endif
 
 uint8_t *renderBuffer;
@@ -119,13 +68,6 @@
     spi.format(8,3); // spi.format(8,0) har fungerat!!
     spi.frequency(3000000); // 3200000 har fungerat!!!
 
-#if 0
-    // SET SPI OUTPUT PINS
-    LPC_PINCON->PINSEL0 |= (3u<<30); // SCK0
-    // LPC_PINCON->PINSEL1 |= (3<<2); // MISO0
-    LPC_PINCON->PINSEL1 |= (3<<4); // MOSI0
-#endif
-
     // TODO: THIS COULD POSSIBLY FUCK UP THE AMOUNT OF DATA MOVED TO THE SSP IN EACH BURST
     // Configure the DMA
     dmaConfig = new MODDMA_Config;
@@ -141,27 +83,6 @@
     ;
     LPC_SSP0->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
 
-#if 0
-    // Set up SSP0 (SPI)
-    //LPC_GPDMA->DMACSoftSReq = 0xC;
-    //NVIC_EnableIRQ(DMA_IRQn);
-
-    // SET THE CLOCK AND POWER THE SSP0 UP
-    LPC_SC->PCLKSEL0 &= ~(2<<10); // PCLK_SSP0 = CCLK/2 (96MHz)
-    LPC_SSP0->CPSR = 10; // CPSDVSR = 10 (9600kHz)
-    // PCLK/(PSR*(SCR+1))
-    LPC_SSP0->CR0 =  (3<<8) | 7;  // SCR = 1 (2400kHz), CPOL = low, SPI frame format, 8 bits per frame
-    // Start the transfer
-    LPC_SSP0->DMACR |= 3; // TX/RXDMAE - enable transmit FIFO for DMA
-
-    if(!dma.Prepare(dmaConfig)) {
-        error("Failed to prepare dma configuration!");
-    }
-
-    LPC_SSP0->CR1 = 2; // Enable the SSP0
-
-#else
-
     if(!dma.Prepare(dmaConfig)) {
         error("Failed to prepare dma configuration!");
     }
@@ -170,8 +91,6 @@
 
     dma.Enable(dmaConfig);
 
-#endif
-
     while(1) {
 
         if(!flgCompleted) {
@@ -202,11 +121,6 @@
 
 void TC_callback(void)
 {
-    //
-    // TODO: FIX THIS UP!!!!
-    // DISMANTLE THE SSP0 (SPI)
-    //
-
     LPC_SSP0->CR1 = 0; // Diable the SSP0    ?
 
     // Just show sending buffer0 complete.