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

Dependencies:   MODDMA mbed

Committer:
tohu
Date:
Wed Dec 10 21:35:57 2014 +0000
Revision:
5:6981fbf08586
Parent:
4:f2ef03b37a66
Halvst?dad variant

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tohu 0:26e4dc5b5a7d 1 #include "mbed.h"
tohu 1:b6ae9e61d764 2 #include "MODDMA.h"
tohu 0:26e4dc5b5a7d 3
tohu 0:26e4dc5b5a7d 4 Serial pc(USBTX, USBRX);
tohu 0:26e4dc5b5a7d 5
tohu 1:b6ae9e61d764 6 DigitalOut led1(LED1);
tohu 1:b6ae9e61d764 7 DigitalOut led2(LED2);
tohu 1:b6ae9e61d764 8 DigitalOut led3(LED3);
tohu 1:b6ae9e61d764 9 DigitalOut led4(LED4);
tohu 1:b6ae9e61d764 10
tohu 3:96f4cc4c5984 11 #define IMAGE_SIZE 123
tohu 0:26e4dc5b5a7d 12
tohu 1:b6ae9e61d764 13 //
tohu 1:b6ae9e61d764 14 // IMAGE AND RENDER BUFFER
tohu 1:b6ae9e61d764 15 //
tohu 1:b6ae9e61d764 16
tohu 4:f2ef03b37a66 17 #if 1
tohu 5:6981fbf08586 18 // OK
tohu 4:f2ef03b37a66 19 uint8_t smiley [IMAGE_SIZE] = {
tohu 5:6981fbf08586 20 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0xFF, 0x0, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF, 0x0, 0xFF, 0x0, 0xFF, 0xFF, 0xFF,
tohu 5:6981fbf08586 21 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0, 0x3F, 0xBE, 0x0, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0, 0xFF, 0xFF, 0xFF, 0x3F, 0xBE, 0x0, 0xFF, 0xFF, 0xFF,
tohu 5:6981fbf08586 22 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0, 0x7F, 0x7F, 0x0, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x0,
tohu 5:6981fbf08586 23 0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0, 0xBE, 0x3F, 0x0, 0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0, 0xFF, 0xFF, 0xFF, 0xBE, 0x3F, 0x0, 0xFF, 0xFF, 0xFF,
tohu 5:6981fbf08586 24 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0xFF, 0xFF, 0xFF,
tohu 5:6981fbf08586 25 0x0, 0x0, 0x0
tohu 5:6981fbf08586 26 };
tohu 3:96f4cc4c5984 27 #endif
tohu 2:1f2f547a9991 28
tohu 2:1f2f547a9991 29 uint8_t *renderBuffer;
tohu 2:1f2f547a9991 30 #if 0
tohu 2:1f2f547a9991 31 [IMAGE_SIZE*4];
tohu 2:1f2f547a9991 32 #endif
tohu 1:b6ae9e61d764 33
tohu 1:b6ae9e61d764 34 void copyImageToRender(uint8_t *image, uint8_t *buffer, size_t len);
tohu 1:b6ae9e61d764 35
tohu 1:b6ae9e61d764 36 //
tohu 1:b6ae9e61d764 37 // DMA STUFF
tohu 1:b6ae9e61d764 38 //
tohu 0:26e4dc5b5a7d 39
tohu 1:b6ae9e61d764 40 MODDMA dma;
tohu 1:b6ae9e61d764 41 MODDMA_Config *dmaConfig;
tohu 1:b6ae9e61d764 42
tohu 1:b6ae9e61d764 43 void TC_callback(void);
tohu 1:b6ae9e61d764 44 void ERR_callback(void);
tohu 1:b6ae9e61d764 45
tohu 1:b6ae9e61d764 46 bool flgCompleted = false;
tohu 1:b6ae9e61d764 47 bool flgFailed = false;
tohu 0:26e4dc5b5a7d 48
tohu 2:1f2f547a9991 49 SPI spi(p11, NC, p13);
tohu 2:1f2f547a9991 50
tohu 3:96f4cc4c5984 51 Timer dmaTimer;
tohu 3:96f4cc4c5984 52
tohu 0:26e4dc5b5a7d 53 int main()
tohu 0:26e4dc5b5a7d 54 {
tohu 0:26e4dc5b5a7d 55 // Setup the serial port to print out results.
tohu 0:26e4dc5b5a7d 56 pc.baud(115200);
tohu 0:26e4dc5b5a7d 57
tohu 1:b6ae9e61d764 58 led1 = false;
tohu 1:b6ae9e61d764 59 led2 = false;
tohu 1:b6ae9e61d764 60 led3 = false;
tohu 1:b6ae9e61d764 61 led4 = false;
tohu 1:b6ae9e61d764 62
tohu 2:1f2f547a9991 63 renderBuffer = (uint8_t *) malloc(IMAGE_SIZE*4);
tohu 2:1f2f547a9991 64
tohu 1:b6ae9e61d764 65 // Set up the image to render
tohu 1:b6ae9e61d764 66 copyImageToRender(smiley, renderBuffer, IMAGE_SIZE);
tohu 1:b6ae9e61d764 67
tohu 4:f2ef03b37a66 68 spi.format(8,3); // spi.format(8,0) har fungerat!!
tohu 4:f2ef03b37a66 69 spi.frequency(3000000); // 3200000 har fungerat!!!
tohu 2:1f2f547a9991 70
tohu 2:1f2f547a9991 71 // TODO: THIS COULD POSSIBLY FUCK UP THE AMOUNT OF DATA MOVED TO THE SSP IN EACH BURST
tohu 1:b6ae9e61d764 72 // Configure the DMA
tohu 1:b6ae9e61d764 73 dmaConfig = new MODDMA_Config;
tohu 1:b6ae9e61d764 74 dmaConfig
tohu 1:b6ae9e61d764 75 ->channelNum ( MODDMA::Channel_0 )
tohu 1:b6ae9e61d764 76 ->srcMemAddr ( (uint32_t) renderBuffer )
tohu 1:b6ae9e61d764 77 ->dstMemAddr ( MODDMA::SSP0_Tx )
tohu 2:1f2f547a9991 78 ->transferSize ( IMAGE_SIZE*4 )
tohu 1:b6ae9e61d764 79 ->transferType ( MODDMA::m2p )
tohu 1:b6ae9e61d764 80 ->dstConn ( MODDMA::SSP0_Tx )
tohu 1:b6ae9e61d764 81 ->attach_tc ( &TC_callback )
tohu 1:b6ae9e61d764 82 ->attach_err ( &ERR_callback )
tohu 1:b6ae9e61d764 83 ;
tohu 2:1f2f547a9991 84 LPC_SSP0->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
tohu 3:96f4cc4c5984 85
tohu 2:1f2f547a9991 86 if(!dma.Prepare(dmaConfig)) {
tohu 2:1f2f547a9991 87 error("Failed to prepare dma configuration!");
tohu 2:1f2f547a9991 88 }
tohu 3:96f4cc4c5984 89
tohu 3:96f4cc4c5984 90 dmaTimer.start();
tohu 3:96f4cc4c5984 91
tohu 1:b6ae9e61d764 92 dma.Enable(dmaConfig);
tohu 3:96f4cc4c5984 93
tohu 1:b6ae9e61d764 94 while(1) {
tohu 1:b6ae9e61d764 95
tohu 3:96f4cc4c5984 96 if(!flgCompleted) {
tohu 1:b6ae9e61d764 97 led1 = !led1;
tohu 3:96f4cc4c5984 98 } else {
tohu 3:96f4cc4c5984 99 pc.printf("Time spend in dma: %d us\n", dmaTimer.read_us());
tohu 3:96f4cc4c5984 100
tohu 3:96f4cc4c5984 101
tohu 1:b6ae9e61d764 102 led2 = !led2;
tohu 1:b6ae9e61d764 103 }
tohu 3:96f4cc4c5984 104 if(flgFailed) {
tohu 3:96f4cc4c5984 105 wait(0.1);
tohu 1:b6ae9e61d764 106 led2 = !led2;
tohu 1:b6ae9e61d764 107 }
tohu 1:b6ae9e61d764 108
tohu 3:96f4cc4c5984 109 uint8_t in[2] = { 0x99, 0x33 };
tohu 3:96f4cc4c5984 110 uint8_t out[8];
tohu 3:96f4cc4c5984 111
tohu 3:96f4cc4c5984 112 copyImageToRender(in, out, 2);
tohu 3:96f4cc4c5984 113
tohu 3:96f4cc4c5984 114 pc.printf("RENDER white: %02x %02x %02x %02x\n", out[0],out[1],out[2],out[3]);
tohu 3:96f4cc4c5984 115 pc.printf("RENDER black: %02x %02x %02x %02x\n", out[4],out[5],out[6],out[7]);
tohu 3:96f4cc4c5984 116
tohu 1:b6ae9e61d764 117 wait(1);
tohu 3:96f4cc4c5984 118 led4 = !led4;
tohu 0:26e4dc5b5a7d 119 }
tohu 0:26e4dc5b5a7d 120 }
tohu 1:b6ae9e61d764 121
tohu 1:b6ae9e61d764 122 void TC_callback(void)
tohu 1:b6ae9e61d764 123 {
tohu 1:b6ae9e61d764 124 LPC_SSP0->CR1 = 0; // Diable the SSP0 ?
tohu 3:96f4cc4c5984 125
tohu 1:b6ae9e61d764 126 // Just show sending buffer0 complete.
tohu 3:96f4cc4c5984 127 led3 = !led3;
tohu 3:96f4cc4c5984 128
tohu 1:b6ae9e61d764 129 // Get configuration pointer.
tohu 1:b6ae9e61d764 130 MODDMA_Config *config = dma.getConfig();
tohu 3:96f4cc4c5984 131
tohu 1:b6ae9e61d764 132 // Finish the DMA cycle by shutting down the channel.
tohu 1:b6ae9e61d764 133 dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
tohu 1:b6ae9e61d764 134 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
tohu 3:96f4cc4c5984 135
tohu 3:96f4cc4c5984 136 dmaTimer.stop();
tohu 3:96f4cc4c5984 137
tohu 1:b6ae9e61d764 138 flgCompleted = true;
tohu 3:96f4cc4c5984 139
tohu 1:b6ae9e61d764 140 // Clear DMA IRQ flags.
tohu 1:b6ae9e61d764 141 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
tohu 1:b6ae9e61d764 142 if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
tohu 1:b6ae9e61d764 143 }
tohu 1:b6ae9e61d764 144
tohu 1:b6ae9e61d764 145 void ERR_callback(void)
tohu 1:b6ae9e61d764 146 {
tohu 1:b6ae9e61d764 147 error("Something failed!!!!");
tohu 3:96f4cc4c5984 148
tohu 1:b6ae9e61d764 149 flgFailed = true;
tohu 1:b6ae9e61d764 150 }
tohu 1:b6ae9e61d764 151
tohu 1:b6ae9e61d764 152 void copyImageToRender(uint8_t *image, uint8_t *buffer, size_t len)
tohu 1:b6ae9e61d764 153 {
tohu 1:b6ae9e61d764 154 Timer timer;
tohu 1:b6ae9e61d764 155
tohu 1:b6ae9e61d764 156 timer.start();
tohu 1:b6ae9e61d764 157
tohu 1:b6ae9e61d764 158 int outIndex;
tohu 1:b6ae9e61d764 159
tohu 1:b6ae9e61d764 160 for(int i = 0; i < len; i++) {
tohu 1:b6ae9e61d764 161
tohu 2:1f2f547a9991 162 outIndex = i*4;
tohu 1:b6ae9e61d764 163
tohu 4:f2ef03b37a66 164 #if 0
tohu 3:96f4cc4c5984 165 // 11001100
tohu 3:96f4cc4c5984 166 buffer[outIndex] = 0xCC | image[i]&128>>2 | image[i]&64>>5;
tohu 3:96f4cc4c5984 167
tohu 3:96f4cc4c5984 168 // 11001100
tohu 3:96f4cc4c5984 169 buffer[outIndex+1] = 0xCC | image[i]&32 | image[i]&16>>3;
tohu 3:96f4cc4c5984 170
tohu 3:96f4cc4c5984 171 // 11001100
tohu 3:96f4cc4c5984 172 buffer[outIndex+2] = 0xCC |image[i]&8<<2 | image[i]&4>>1;
tohu 3:96f4cc4c5984 173
tohu 3:96f4cc4c5984 174 // 11001100
tohu 3:96f4cc4c5984 175 buffer[outIndex+3] = 0xCC |image[i]&2<<4 | image[i]&1<<1;
tohu 4:f2ef03b37a66 176 #else
tohu 2:1f2f547a9991 177 // 10001000
tohu 4:f2ef03b37a66 178 buffer[outIndex++] = 0x88 | (image[i]&128)>>1 | (image[i]&64)>>4;
tohu 1:b6ae9e61d764 179
tohu 2:1f2f547a9991 180 // 10001000
tohu 4:f2ef03b37a66 181 buffer[outIndex++] = 0x88 | (image[i]&32)<<1 | (image[i]&16)>>2;
tohu 1:b6ae9e61d764 182
tohu 2:1f2f547a9991 183 // 10001000
tohu 4:f2ef03b37a66 184 buffer[outIndex++] = 0x88 |(image[i]&8)<<3 | (image[i]&4);
tohu 2:1f2f547a9991 185
tohu 2:1f2f547a9991 186 // 10001000
tohu 4:f2ef03b37a66 187 buffer[outIndex] = 0x88 | (image[i]&2)<<5 | (image[i]&1)<<2;
tohu 3:96f4cc4c5984 188 #endif
tohu 1:b6ae9e61d764 189 }
tohu 1:b6ae9e61d764 190
tohu 1:b6ae9e61d764 191 timer.stop();
tohu 1:b6ae9e61d764 192
tohu 1:b6ae9e61d764 193 pc.printf("Time spend copying image: %d us\n", timer.read_us());
tohu 1:b6ae9e61d764 194 }
tohu 1:b6ae9e61d764 195