Tomas Hübner
/
DMANeoPixel
Programming an array of NeoPixels using the GPDMA for maximum performance.
main.cpp
- Committer:
- tohu
- Date:
- 2014-12-10
- Revision:
- 5:6981fbf08586
- Parent:
- 4:f2ef03b37a66
File content as of revision 5:6981fbf08586:
#include "mbed.h" #include "MODDMA.h" Serial pc(USBTX, USBRX); DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); #define IMAGE_SIZE 123 // // IMAGE AND RENDER BUFFER // #if 1 // OK uint8_t smiley [IMAGE_SIZE] = { 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; #if 0 [IMAGE_SIZE*4]; #endif void copyImageToRender(uint8_t *image, uint8_t *buffer, size_t len); // // DMA STUFF // MODDMA dma; MODDMA_Config *dmaConfig; void TC_callback(void); void ERR_callback(void); bool flgCompleted = false; bool flgFailed = false; SPI spi(p11, NC, p13); Timer dmaTimer; int main() { // Setup the serial port to print out results. pc.baud(115200); led1 = false; led2 = false; led3 = false; led4 = false; renderBuffer = (uint8_t *) malloc(IMAGE_SIZE*4); // Set up the image to render copyImageToRender(smiley, renderBuffer, IMAGE_SIZE); spi.format(8,3); // spi.format(8,0) har fungerat!! spi.frequency(3000000); // 3200000 har fungerat!!! // TODO: THIS COULD POSSIBLY FUCK UP THE AMOUNT OF DATA MOVED TO THE SSP IN EACH BURST // Configure the DMA dmaConfig = new MODDMA_Config; dmaConfig ->channelNum ( MODDMA::Channel_0 ) ->srcMemAddr ( (uint32_t) renderBuffer ) ->dstMemAddr ( MODDMA::SSP0_Tx ) ->transferSize ( IMAGE_SIZE*4 ) ->transferType ( MODDMA::m2p ) ->dstConn ( MODDMA::SSP0_Tx ) ->attach_tc ( &TC_callback ) ->attach_err ( &ERR_callback ) ; LPC_SSP0->DMACR = (1<<1)|(1<<0); // TX,RXDMAE if(!dma.Prepare(dmaConfig)) { error("Failed to prepare dma configuration!"); } dmaTimer.start(); dma.Enable(dmaConfig); while(1) { if(!flgCompleted) { led1 = !led1; } else { pc.printf("Time spend in dma: %d us\n", dmaTimer.read_us()); led2 = !led2; } if(flgFailed) { wait(0.1); led2 = !led2; } uint8_t in[2] = { 0x99, 0x33 }; uint8_t out[8]; copyImageToRender(in, out, 2); pc.printf("RENDER white: %02x %02x %02x %02x\n", out[0],out[1],out[2],out[3]); pc.printf("RENDER black: %02x %02x %02x %02x\n", out[4],out[5],out[6],out[7]); wait(1); led4 = !led4; } } void TC_callback(void) { LPC_SSP0->CR1 = 0; // Diable the SSP0 ? // 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.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); dmaTimer.stop(); flgCompleted = true; // Clear DMA IRQ flags. if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); } void ERR_callback(void) { error("Something failed!!!!"); flgFailed = true; } void copyImageToRender(uint8_t *image, uint8_t *buffer, size_t len) { Timer timer; timer.start(); int outIndex; for(int i = 0; i < len; i++) { outIndex = i*4; #if 0 // 11001100 buffer[outIndex] = 0xCC | image[i]&128>>2 | image[i]&64>>5; // 11001100 buffer[outIndex+1] = 0xCC | image[i]&32 | image[i]&16>>3; // 11001100 buffer[outIndex+2] = 0xCC |image[i]&8<<2 | image[i]&4>>1; // 11001100 buffer[outIndex+3] = 0xCC |image[i]&2<<4 | image[i]&1<<1; #else // 10001000 buffer[outIndex++] = 0x88 | (image[i]&128)>>1 | (image[i]&64)>>4; // 10001000 buffer[outIndex++] = 0x88 | (image[i]&32)<<1 | (image[i]&16)>>2; // 10001000 buffer[outIndex++] = 0x88 |(image[i]&8)<<3 | (image[i]&4); // 10001000 buffer[outIndex] = 0x88 | (image[i]&2)<<5 | (image[i]&1)<<2; #endif } timer.stop(); pc.printf("Time spend copying image: %d us\n", timer.read_us()); }