diff options
author | Daniel Garcia <danielgarcia@gmail.com> | 2016-01-24 01:10:13 +0300 |
---|---|---|
committer | Daniel Garcia <danielgarcia@gmail.com> | 2016-01-24 01:10:13 +0300 |
commit | dbf4292184110d1a5e36818c437a44004786c92f (patch) | |
tree | a0761df2ce1ff676ff0e0ee98e852f072674428f | |
parent | 1e21888813ddd280e59d3d2711569a14dee16771 (diff) |
Switch Teensy parallel output to use CPixelLEDController objects
-rw-r--r-- | FastLED.h | 4 | ||||
-rw-r--r-- | platforms/arm/k20/clockless_block_arm_k20.h | 181 |
2 files changed, 71 insertions, 114 deletions
@@ -388,8 +388,8 @@ public: case WS2811_400_PORTD: return addLeds(new InlineBlockClocklessController<NUM_LANES, PORTD_FIRST_PIN, NS(800), NS(800), NS(900), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); #endif #ifdef HAS_PORTDC - case WS2811_PORTDC: return addLeds(new SixteenWayInlineBlockClocklessController<16,NS(320), NS(320), NS(640), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); - case WS2811_400_PORTDC: return addLeds(new SixteenWayInlineBlockClocklessController<16,NS(800), NS(800), NS(900), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); + case WS2811_PORTDC: return addLeds(new SixteenWayInlineBlockClocklessController<NUM_LANES,NS(320), NS(320), NS(640), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); + case WS2811_400_PORTDC: return addLeds(new SixteenWayInlineBlockClocklessController<NUM_LANES,NS(800), NS(800), NS(900), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); #endif } } diff --git a/platforms/arm/k20/clockless_block_arm_k20.h b/platforms/arm/k20/clockless_block_arm_k20.h index b5e4007a..f2b76468 100644 --- a/platforms/arm/k20/clockless_block_arm_k20.h +++ b/platforms/arm/k20/clockless_block_arm_k20.h @@ -13,14 +13,14 @@ #define PORT_MASK (((1<<LANES)-1) & ((FIRST_PIN==2) ? 0xFF : 0xFFF)) #define MIN(X,Y) (((X)<(Y)) ? (X):(Y)) -#define LANES ((FIRST_PIN==2) ? MIN(__LANES,8) : MIN(__LANES,12)) +#define USED_LANES ((FIRST_PIN==2) ? MIN(LANES,8) : MIN(LANES,12)) #include "kinetis.h" FASTLED_NAMESPACE_BEGIN -template <uint8_t __LANES, int FIRST_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 40> -class InlineBlockClocklessController : public CLEDController { +template <uint8_t LANES, int FIRST_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 40> +class InlineBlockClocklessController : public CPixelLEDController<RGB_ORDER, LANES, PORT_MASK> { typedef typename FastPin<FIRST_PIN>::port_ptr_t data_ptr_t; typedef typename FastPin<FIRST_PIN>::port_t data_t; @@ -28,11 +28,23 @@ class InlineBlockClocklessController : public CLEDController { data_ptr_t mPort; CMinWait<WAIT_TIME> mWait; public: - virtual int size() { return m_nLeds * __LANES; } + virtual int size() { return CLEDController::size() * LANES; } + + virtual void showPixels(PixelController<RGB_ORDER, LANES, PORT_MASK> & pixels) { + mWait.wait(); + uint32_t clocks = showRGBInternal(pixels); + #if FASTLED_ALLOW_INTTERUPTS == 0 + // Adjust the timer + long microsTaken = CLKS_TO_MICROS(clocks); + MS_COUNTER += (1 + (microsTaken / 1000)); + #endif + + mWait.mark(); + } virtual void init() { if(FIRST_PIN == PORTC_FIRST_PIN) { // PORTC - switch(LANES) { + switch(USED_LANES) { case 12: FastPin<30>::setOutput(); case 11: FastPin<29>::setOutput(); case 10: FastPin<27>::setOutput(); @@ -47,7 +59,7 @@ public: case 1: FastPin<15>::setOutput(); } } else if(FIRST_PIN == PORTD_FIRST_PIN) { // PORTD - switch(LANES) { + switch(USED_LANES) { case 8: FastPin<5>::setOutput(); case 7: FastPin<21>::setOutput(); case 6: FastPin<20>::setOutput(); @@ -64,39 +76,6 @@ public: virtual uint16_t getMaxRefreshRate() const { return 400; } - virtual void clearLeds(int nLeds) { - showColor(CRGB(0, 0, 0), nLeds, 0); - } - - // set all the leds on the controller to a given color - virtual void showColor(const struct CRGB & rgbdata, int nLeds, CRGB scale) { - PixelController<RGB_ORDER,LANES,PORT_MASK> pixels(rgbdata,nLeds, scale, getDither() ); - mWait.wait(); - uint32_t clocks = showRGBInternal(pixels,nLeds); - #if FASTLED_ALLOW_INTTERUPTS == 0 - // Adjust the timer - long microsTaken = CLKS_TO_MICROS(clocks); - MS_COUNTER += (1 + (microsTaken / 1000)); - #endif - - mWait.mark(); - } - - virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { - PixelController<RGB_ORDER,LANES,PORT_MASK> pixels(rgbdata,nLeds, scale, getDither() ); - mWait.wait(); - uint32_t clocks = showRGBInternal(pixels,nLeds); - #if FASTLED_ALLOW_INTTERUPTS == 0 - // Adjust the timer - long microsTaken = CLKS_TO_MICROS(clocks); - MS_COUNTER += (1 + (microsTaken / 1000)); - #endif - - mWait.mark(); - } - - - typedef union { uint8_t bytes[12]; uint16_t shorts[6]; @@ -105,7 +84,7 @@ public: template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, PixelController<RGB_ORDER, LANES, PORT_MASK> &pixels) { // , register uint32_t & b2) { register Lines b2; - if(LANES>8) { + if(USED_LANES>8) { transpose8<1,2>(b.bytes,b2.bytes); transpose8<1,2>(b.bytes+8,b2.bytes+1); } else { @@ -114,13 +93,13 @@ public: register uint8_t d = pixels.template getd<PX>(pixels); register uint8_t scale = pixels.template getscale<PX>(pixels); - for(register uint32_t i = 0; i < (LANES/2); i++) { + for(register uint32_t i = 0; i < (USED_LANES/2); i++) { while(ARM_DWT_CYCCNT < next_mark); next_mark = ARM_DWT_CYCCNT + (T1+T2+T3)-3; *FastPin<FIRST_PIN>::sport() = PORT_MASK; while((next_mark - ARM_DWT_CYCCNT) > (T2+T3+(2*(F_CPU/24000000)))); - if(LANES>8) { + if(USED_LANES>8) { *FastPin<FIRST_PIN>::cport() = ((~b2.shorts[i]) & PORT_MASK); } else { *FastPin<FIRST_PIN>::cport() = ((~b2.bytes[7-i]) & PORT_MASK); @@ -130,20 +109,20 @@ public: *FastPin<FIRST_PIN>::cport() = PORT_MASK; b.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale); - b.bytes[i+(LANES/2)] = pixels.template loadAndScale<PX>(pixels,i+(LANES/2),d,scale); + b.bytes[i+(USED_LANES/2)] = pixels.template loadAndScale<PX>(pixels,i+(USED_LANES/2),d,scale); } // if folks use an odd numnber of lanes, get the last byte's value here - if(LANES & 0x01) { - b.bytes[LANES-1] = pixels.template loadAndScale<PX>(pixels,LANES-1,d,scale); + if(USED_LANES & 0x01) { + b.bytes[USED_LANES-1] = pixels.template loadAndScale<PX>(pixels,USED_LANES-1,d,scale); } - for(register uint32_t i = LANES/2; i < 8; i++) { + for(register uint32_t i = USED_LANES/2; i < 8; i++) { while(ARM_DWT_CYCCNT < next_mark); next_mark = ARM_DWT_CYCCNT + (T1+T2+T3)-3; *FastPin<FIRST_PIN>::sport() = PORT_MASK; while((next_mark - ARM_DWT_CYCCNT) > (T2+T3+(2*(F_CPU/24000000)))); - if(LANES>8) { + if(USED_LANES>8) { *FastPin<FIRST_PIN>::cport() = ((~b2.shorts[i]) & PORT_MASK); } else { // b2.bytes[0] = 0; @@ -154,28 +133,13 @@ public: *FastPin<FIRST_PIN>::cport() = PORT_MASK; } - - - // while(ARM_DWT_CYCCNT < next_mark); - // next_mark = ARM_DWT_CYCCNT + (T1+T2+T3)-3; - // *FastPin<FIRST_PIN>::sport() = PORT_MASK; - // - // while((next_mark - ARM_DWT_CYCCNT) > (T2+T3+6)); - // if(LANES>8) { - // *FastPin<FIRST_PIN>::cport() = ((~b2.shorts[7]) & PORT_MASK); - // } else { - // *FastPin<FIRST_PIN>::cport() = PORT_MASK; // ((~b2.bytes[7-i]) & PORT_MASK); - // } - // - // while((next_mark - ARM_DWT_CYCCNT) > (T3)); - // *FastPin<FIRST_PIN>::cport() = PORT_MASK; } // This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then // gcc will use register Y for the this pointer. - static uint32_t showRGBInternal(PixelController<RGB_ORDER, LANES, PORT_MASK> &allpixels, int nLeds) { + static uint32_t showRGBInternal(PixelController<RGB_ORDER, LANES, PORT_MASK> &allpixels) { // Get access to the clock ARM_DEMCR |= ARM_DEMCR_TRCENA; ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; @@ -186,14 +150,14 @@ public: register Lines b0; allpixels.preStepFirstByteDithering(); - for(int i = 0; i < LANES; i++) { + for(int i = 0; i < USED_LANES; i++) { b0.bytes[i] = allpixels.loadAndScale0(i); } cli(); uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); - while(nLeds--) { + while(allpixels.has(1)) { #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); // if interrupts took longer than 45µs, punt on the current frame @@ -221,13 +185,12 @@ public: } }; -#define DLANES (MIN(__LANES,16)) -#define PMASK ((1<<(DLANES))-1) +#define PMASK ((1<<(LANES))-1) #define PMASK_HI (PMASK>>8 & 0xFF) #define PMASK_LO (PMASK & 0xFF) -template <uint8_t __LANES, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50> -class SixteenWayInlineBlockClocklessController : public CLEDController { +template <uint8_t LANES, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50> +class SixteenWayInlineBlockClocklessController : public CPixelLEDController<RGB_ORDER, LANES, PMASK> { typedef typename FastPin<PORTC_FIRST_PIN>::port_ptr_t data_ptr_t; typedef typename FastPin<PORTC_FIRST_PIN>::port_t data_t; @@ -236,47 +199,41 @@ class SixteenWayInlineBlockClocklessController : public CLEDController { CMinWait<WAIT_TIME> mWait; public: virtual void init() { - // FastPin<30>::setOutput(); - // FastPin<29>::setOutput(); - // FastPin<27>::setOutput(); - // FastPin<28>::setOutput(); - switch(DLANES) { - case 16: FastPin<12>::setOutput(); - case 15: FastPin<11>::setOutput(); - case 14: FastPin<13>::setOutput(); - case 13: FastPin<10>::setOutput(); - case 12: FastPin<9>::setOutput(); - case 11: FastPin<23>::setOutput(); - case 10: FastPin<22>::setOutput(); - case 9: FastPin<15>::setOutput(); - - case 8: FastPin<5>::setOutput(); - case 7: FastPin<21>::setOutput(); - case 6: FastPin<20>::setOutput(); - case 5: FastPin<6>::setOutput(); - case 4: FastPin<8>::setOutput(); - case 3: FastPin<7>::setOutput(); - case 2: FastPin<14>::setOutput(); - case 1: FastPin<2>::setOutput(); - } - } - - virtual void clearLeds(int nLeds) { - showColor(CRGB(0, 0, 0), nLeds, 0); + static_assert(LANES <= 16, "Maximum of 16 lanes for Teensy parallel controllers!"); + // FastPin<30>::setOutput(); + // FastPin<29>::setOutput(); + // FastPin<27>::setOutput(); + // FastPin<28>::setOutput(); + switch(LANES) { + case 16: FastPin<12>::setOutput(); + case 15: FastPin<11>::setOutput(); + case 14: FastPin<13>::setOutput(); + case 13: FastPin<10>::setOutput(); + case 12: FastPin<9>::setOutput(); + case 11: FastPin<23>::setOutput(); + case 10: FastPin<22>::setOutput(); + case 9: FastPin<15>::setOutput(); + + case 8: FastPin<5>::setOutput(); + case 7: FastPin<21>::setOutput(); + case 6: FastPin<20>::setOutput(); + case 5: FastPin<6>::setOutput(); + case 4: FastPin<8>::setOutput(); + case 3: FastPin<7>::setOutput(); + case 2: FastPin<14>::setOutput(); + case 1: FastPin<2>::setOutput(); + } } - // set all the leds on the controller to a given color - virtual void showColor(const struct CRGB & rgbdata, int nLeds, CRGB scale) { - PixelController<RGB_ORDER,DLANES,PMASK> pixels(rgbdata,nLeds, scale, getDither() ); + virtual void showPixels(PixelController<RGB_ORDER, LANES, PMASK> & pixels) { mWait.wait(); - showRGBInternal(pixels,nLeds); - mWait.mark(); - } + uint32_t clocks = showRGBInternal(pixels); + #if FASTLED_ALLOW_INTTERUPTS == 0 + // Adjust the timer + long microsTaken = CLKS_TO_MICROS(clocks); + MS_COUNTER += (1 + (microsTaken / 1000)); + #endif - virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { - PixelController<RGB_ORDER,DLANES,PMASK> pixels(rgbdata,nLeds, scale, getDither() ); - mWait.wait(); - showRGBInternal(pixels,nLeds); mWait.mark(); } @@ -286,14 +243,14 @@ public: uint32_t raw[4]; } Lines; - template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, PixelController<RGB_ORDER,DLANES, PMASK> &pixels) { // , register uint32_t & b2) { + template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, PixelController<RGB_ORDER,LANES, PMASK> &pixels) { // , register uint32_t & b2) { register Lines b2; transpose8x1(b.bytes,b2.bytes); transpose8x1(b.bytes+8,b2.bytes+8); register uint8_t d = pixels.template getd<PX>(pixels); register uint8_t scale = pixels.template getscale<PX>(pixels); - for(register uint32_t i = 0; (i < DLANES) && (i < 8); i++) { + for(register uint32_t i = 0; (i < LANES) && (i < 8); i++) { while(ARM_DWT_CYCCNT < next_mark); next_mark = ARM_DWT_CYCCNT + (T1+T2+T3)-3; *FastPin<PORTD_FIRST_PIN>::sport() = PMASK_LO; @@ -308,7 +265,7 @@ public: *FastPin<PORTC_FIRST_PIN>::cport() = PMASK_HI; b.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale); - if(DLANES==16 || (DLANES>8 && ((i+8) < DLANES))) { + if(LANES==16 || (LANES>8 && ((i+8) < LANES))) { b.bytes[i+8] = pixels.template loadAndScale<PX>(pixels,i+8,d,scale); } } @@ -318,7 +275,7 @@ public: // This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then // gcc will use register Y for the this pointer. - static uint32_t showRGBInternal(PixelController<RGB_ORDER,DLANES, PMASK> &allpixels, int nLeds) { + static uint32_t showRGBInternal(PixelController<RGB_ORDER,LANES, PMASK> &allpixels) { // Get access to the clock ARM_DEMCR |= ARM_DEMCR_TRCENA; ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; @@ -329,14 +286,14 @@ public: register Lines b0; allpixels.preStepFirstByteDithering(); - for(int i = 0; i < DLANES; i++) { + for(int i = 0; i < LANES; i++) { b0.bytes[i] = allpixels.loadAndScale0(i); } cli(); uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); - while(nLeds--) { + while(allpixels.has(1)) { allpixels.stepDithering(); #if 0 && (FASTLED_ALLOW_INTERRUPTS == 1) cli(); |