Tomas Hübner
/
DMANeoPixel
Programming an array of NeoPixels using the GPDMA for maximum performance.
Revision 5:6981fbf08586, committed 2014-12-10
- 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.