diff options
-rw-r--r-- | FastLED.h | 11 | ||||
-rw-r--r-- | clockless_block_arm_k20.h | 163 | ||||
-rw-r--r-- | examples/Multiple/ParallelOutputDemo/ParallelOutputDemo.ino | 6 |
3 files changed, 174 insertions, 6 deletions
@@ -7,8 +7,8 @@ #define xstr(s) str(s) #define str(s) #s -#define FASTLED_VERSION 3000000 -#warning FastLED version 3000000 (Not really a warning, just telling you here.) +#define FASTLED_VERSION 3001000 +#warning FastLED version 3001000 (Not really a warning, just telling you here.) #define __PROG_TYPES_COMPAT__ @@ -92,6 +92,9 @@ enum EBlockChipsets { #ifdef PORTD_FIRST_PIN WS2811_PORTD, #endif +#ifdef HAS_PORTDC + WS2811_PORTDC, +#endif }; #if defined(LIB8_ATTINY) @@ -240,7 +243,11 @@ static CLEDController &addLeds(struct CRGB *data, int nLedsOrOffset, int nLedsIf #ifdef PORTD_FIRST_PIN case WS2811_PORTD: return addLeds(new InlineBlockClocklessController<NUM_LANES, PORTD_FIRST_PIN, NS(250), NS(510), NS(490), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); #endif +#ifdef HAS_PORTDC + case WS2811_PORTDC: return addLeds(new SixteenWayInlineBlockClocklessController<16,NS(250), NS(510), NS(490), RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); +#endif } + } template<EBlockChipsets CHIPSET, int NUM_LANES> diff --git a/clockless_block_arm_k20.h b/clockless_block_arm_k20.h index 4bbdb027..d9ab69ff 100644 --- a/clockless_block_arm_k20.h +++ b/clockless_block_arm_k20.h @@ -8,9 +8,12 @@ #define PORTC_FIRST_PIN 15 #define PORTD_FIRST_PIN 2 +#define HAS_PORTDC 1 #define PORT_MASK (((1<<LANES)-1) & ((FIRST_PIN==2) ? 0xFF : 0xFFF)) - +#define PMASK ((1<<LANES)-1) +#define PMASK_HI (PMASK>>8 & 0xFF) +#define PMASK_LO (PMASK & 0xFF) #include "kinetis.h" 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 = 50> @@ -194,6 +197,164 @@ public: return ARM_DWT_CYCCNT; } }; + +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 { + typedef typename FastPin<PORTC_FIRST_PIN>::port_ptr_t data_ptr_t; + typedef typename FastPin<PORTC_FIRST_PIN>::port_t data_t; + + data_t mPinMask; + data_ptr_t mPort; + CMinWait<WAIT_TIME> mWait; +public: + virtual void init() { + // 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(); + } + } + + 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) { + MultiPixelController<LANES,PMASK,RGB_ORDER> pixels(rgbdata,nLeds, scale, getDither() ); + mWait.wait(); + cli(); + + uint32_t clocks = showRGBInternal(pixels,nLeds); + + // Adjust the timer + long microsTaken = CLKS_TO_MICROS(clocks); + MS_COUNTER += (microsTaken / 1000); + sei(); + mWait.mark(); + } + + virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { + MultiPixelController<LANES,PMASK,RGB_ORDER> pixels(rgbdata,nLeds, scale, getDither() ); + mWait.wait(); + cli(); + + uint32_t clocks = showRGBInternal(pixels,nLeds); + + // Adjust the timer + long microsTaken = CLKS_TO_MICROS(clocks); + MS_COUNTER += (microsTaken / 1000); + sei(); + mWait.mark(); + } + +#ifdef SUPPORT_ARGB + virtual void show(const struct CARGB *rgbdata, int nLeds, CRGB scale) { + mWait.wait(); + cli(); + + uint32_t clocks = showRGBInternal(PixelController<RGB_ORDER>(rgbdata, nLeds, scale, getDither())); + + + // Adjust the timer + long microsTaken = CLKS_TO_MICROS(clocks); + MS_COUNTER += (microsTaken / 1000); + sei(); + mWait.mark(); + } +#endif + + + typedef union { + uint8_t bytes[16]; + uint16_t shorts[8]; + 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, MultiPixelController<LANES, PMASK, RGB_ORDER> &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 < 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; + *FastPin<PORTC_FIRST_PIN>::sport() = PMASK_HI; + + while((next_mark - ARM_DWT_CYCCNT) > (T2+T3+6)); + *FastPin<PORTD_FIRST_PIN>::cport() = ((~b2.bytes[7-i]) & PMASK_LO); + *FastPin<PORTC_FIRST_PIN>::cport() = ((~b2.bytes[15-i]) & PMASK_HI); + + while((next_mark - ARM_DWT_CYCCNT) > (T3)); + *FastPin<PORTD_FIRST_PIN>::cport() = PMASK_LO; + *FastPin<PORTC_FIRST_PIN>::cport() = PMASK_HI; + + b.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale); + if(LANES>8 && ((i+8) < LANES)) { + b.bytes[i+8] = pixels.template loadAndScale<PX>(pixels,i+8,d,scale); + } + } + } + + + + // 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(MultiPixelController<LANES, PMASK, RGB_ORDER> &allpixels, int nLeds) { + // Get access to the clock + ARM_DEMCR |= ARM_DEMCR_TRCENA; + ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; + ARM_DWT_CYCCNT = 0; + + // Setup the pixel controller and load/scale the first byte + allpixels.preStepFirstByteDithering(); + register Lines b0; + + allpixels.preStepFirstByteDithering(); + for(int i = 0; i < LANES; i++) { + b0.bytes[i] = allpixels.loadAndScale0(i); + } + + uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); + + while(nLeds--) { + allpixels.stepDithering(); + + // Write first byte, read next byte + writeBits<8+XTRA0,1>(next_mark, b0, allpixels); + + // Write second byte, read 3rd byte + writeBits<8+XTRA0,2>(next_mark, b0, allpixels); + allpixels.advanceData(); + + // Write third byte + writeBits<8+XTRA0,0>(next_mark, b0, allpixels); + }; + + return ARM_DWT_CYCCNT; + } +}; #endif #endif diff --git a/examples/Multiple/ParallelOutputDemo/ParallelOutputDemo.ino b/examples/Multiple/ParallelOutputDemo/ParallelOutputDemo.ino index d1f7fc4a..d646cdec 100644 --- a/examples/Multiple/ParallelOutputDemo/ParallelOutputDemo.ino +++ b/examples/Multiple/ParallelOutputDemo/ParallelOutputDemo.ino @@ -2,13 +2,14 @@ #define NUM_LEDS_PER_STRIP 64 // Note: this can be 12 if you're using a teensy 3 and don't mind soldering the pads on the back -#define NUM_STRIPS 8 +#define NUM_STRIPS 16 CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP]; // Pin layouts on the teensy 3/3.1: // WS2811_PORTD: 2,14,7,8,6,20,21,5 // WS2811_PORTC: 15,22,23,9,10,13,11,12,28,27,29,30 (these last 4 are pads on the bottom of the teensy) +// WS2811_PORTDC: 2,14,7,8,6,20,21,5,15,22,23,9,10,13,11,12 - 16 way parallel // // Pin layouts on the due // WS2811_PORTA: 69,68,61,60,59,100,58,31 (note: pin 100 only available on the digix) @@ -19,9 +20,8 @@ CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP]; void setup() { // LEDS.addLeds<WS2811_PORTA,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP); // LEDS.addLeds<WS2811_PORTB,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP); - LEDS.addLeds<WS2811_PORTC,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP); // LEDS.addLeds<WS2811_PORTD,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP).setCorrection(TypicalLEDStrip); - + LEDS.addLeds<WS2811_PORTDC,NUM_STRIPS>(leds, NUM_LEDS_PER_STRIP); LEDS.setBrightness(32); } |