Tomas Hübner
/
DMANeoPixel
Programming an array of NeoPixels using the GPDMA for maximum performance.
main.cpp@5:6981fbf08586, 2014-12-10 (annotated)
- 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?
User | Revision | Line number | New 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 |