diff options
-rw-r--r-- | clockless_arm_sam.h | 130 | ||||
-rw-r--r-- | clockless_block_arm_sam.h | 62 | ||||
-rw-r--r-- | examples/Cylon/Cylon.ino | 13 | ||||
-rw-r--r-- | led_sysdefs.h | 20 |
4 files changed, 67 insertions, 158 deletions
diff --git a/clockless_arm_sam.h b/clockless_arm_sam.h index 68617af2..0c38b611 100644 --- a/clockless_arm_sam.h +++ b/clockless_arm_sam.h @@ -40,39 +40,14 @@ protected: virtual void showColor(const struct CRGB & rgbdata, int nLeds, CRGB scale) { PixelController<RGB_ORDER> pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); - cli(); - SysClockSaver savedClock(TOTAL); - - uint32_t clocks = showRGBInternal(pixels); - - // Adjust the timer - long microsTaken = CLKS_TO_MICROS(clocks); - long millisTaken = (microsTaken / 1000); - savedClock.restore(); - do { TimeTick_Increment(); } while(--millisTaken > 0); - sei(); + showRGBInternal(pixels); mWait.mark(); } virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { PixelController<RGB_ORDER> pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); - cli(); - SysClockSaver savedClock(TOTAL); - - // Serial.print("Scale is "); - // Serial.print(scale.raw[0]); Serial.print(" "); - // Serial.print(scale.raw[1]); Serial.print(" "); - // Serial.print(scale.raw[2]); Serial.println(" "); - // FastPinBB<DATA_PIN>::hi(); delay(1); FastPinBB<DATA_PIN>::lo(); - uint32_t clocks = showRGBInternal(pixels); - - // Adjust the timer - long microsTaken = CLKS_TO_MICROS(clocks); - long millisTaken = (microsTaken / 1000); - savedClock.restore(); - do { TimeTick_Increment(); } while(--millisTaken > 0); - sei(); + showRGBInternal(pixels); mWait.mark(); } @@ -80,97 +55,32 @@ protected: virtual void show(const struct CARGB *rgbdata, int nLeds, CRGB scale) { PixelController<RGB_ORDER> pixels(rgbdata, nLeds, scale, getDither()); mWait.wait(); - cli(); - SysClockSaver savedClock(TOTAL); - - uint32_t clocks = showRGBInternal(pixels); - - // Adjust the timer - long microsTaken = CLKS_TO_MICROS(clocks); - long millisTaken = (microsTaken / 1000); - savedClock.restore(); - do { TimeTick_Increment(); } while(--millisTaken > 0); + showRGBInternal(pixels); sei(); mWait.mark(); } #endif -#if 0 -// Get the arm defs, register/macro defs from the k20 -#define ARM_DEMCR *(volatile uint32_t *)0xE000EDFC // Debug Exception and Monitor Control -#define ARM_DEMCR_TRCENA (1 << 24) // Enable debugging & monitoring blocks -#define ARM_DWT_CTRL *(volatile uint32_t *)0xE0001000 // DWT control register -#define ARM_DWT_CTRL_CYCCNTENA (1 << 0) // Enable cycle count -#define ARM_DWT_CYCCNT *(volatile uint32_t *)0xE0001004 // Cycle count register - - template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register data_ptr_t port, register uint8_t & b) { - for(register uint32_t i = BITS; i > 0; i--) { - while(ARM_DWT_CYCCNT < next_mark); - next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); - *port = 1; - uint32_t flip_mark = next_mark - ((b&0x80) ? (T3) : (T2+T3)); - b <<= 1; - while(ARM_DWT_CYCCNT < flip_mark); - *port = 0; - } - } - - // 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 void showRGBInternal(PixelController<RGB_ORDER> pixels) { - register data_ptr_t port = FastPinBB<DATA_PIN>::port(); - *port = 0; - - // Setup the pixel controller and load/scale the first byte - pixels.preStepFirstByteDithering(); - register uint8_t b = pixels.loadAndScale0(); - - // Get access to the clock - ARM_DEMCR |= ARM_DEMCR_TRCENA; - ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; - ARM_DWT_CYCCNT = 0; - uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); - - while(pixels.has(1)) { - pixels.stepDithering(); - - // Write first byte, read next byte - writeBits<8+XTRA0>(next_mark, port, b); - b = pixels.loadAndScale1(); - - // Write second byte, read 3rd byte - writeBits<8+XTRA0>(next_mark, port, b); - b = pixels.loadAndScale2(); - - // Write third byte - writeBits<8+XTRA0>(next_mark, port, b); - b = pixels.advanceAndLoadAndScale0(); - }; - } -#else -// I hate using defines for these, should find a better representation at some point -#define _CTRL CTPTR[0] -#define _LOAD CTPTR[1] -#define _VAL CTPTR[2] -#define VAL (volatile uint32_t)(*((uint32_t*)(SysTick_BASE + 8))) template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register data_ptr_t port, register uint8_t & b) { // Make sure we don't slot into a wrapping spot, this will delay up to 12.5µs for WS2812 - // while(VAL < (TOTAL*10)); + // bool bShift=0; + // while(VAL < (TOTAL*10)) { bShift=true; } + // if(bShift) { next_mark = (VAL-TOTAL); }; for(register uint32_t i = BITS; i > 0; i--) { // wait to start the bit, then set the pin high - while(VAL > next_mark); - next_mark = (VAL-TOTAL); + while(DUE_TIMER_VAL < next_mark); + next_mark = (DUE_TIMER_VAL+TOTAL); *port = 1; // how long we want to wait next depends on whether or not our bit is set to 1 or 0 if(b&0x80) { // we're a 1, wait until there's less than T3 clocks left - while((VAL - next_mark) > (T3)); + while((next_mark - DUE_TIMER_VAL) > (T3)); } else { // we're a 0, wait until there's less than (T2+T3+slop) clocks left in this bit - while((VAL-next_mark) > (T2+T3+6+TADJUST+TADJUST)); + while((next_mark - DUE_TIMER_VAL) > (T2+T3+6+TADJUST+TADJUST)); } *port=0; b <<= 1; @@ -182,11 +92,9 @@ protected: // gcc will use register Y for the this pointer. static uint32_t showRGBInternal(PixelController<RGB_ORDER> & pixels) { // Setup and start the clock - register volatile uint32_t *CTPTR asm("r6")= &SysTick->CTRL; FORCE_REFERENCE(CTPTR); - _LOAD = 0x00FFFFFF; - _VAL = 0; - _CTRL |= SysTick_CTRL_CLKSOURCE_Msk; - _CTRL |= SysTick_CTRL_ENABLE_Msk; + TC_Configure(DUE_TIMER,DUE_TIMER_CHANNEL,TC_CMR_TCCLKS_TIMER_CLOCK1); + pmc_enable_periph_clk(DUE_TIMER_ID); + TC_Start(DUE_TIMER,DUE_TIMER_CHANNEL); register data_ptr_t port asm("r7") = FastPinBB<DATA_PIN>::port(); FORCE_REFERENCE(port); *port = 0; @@ -195,11 +103,15 @@ protected: pixels.preStepFirstByteDithering(); register uint8_t b = pixels.loadAndScale0(); - // while(VAL < (TOTAL*10)); - uint32_t next_mark = (VAL - (TOTAL)); + uint32_t next_mark = (VAL + (TOTAL)); while(pixels.has(1)) { pixels.stepDithering(); + cli(); + if(DUE_TIMER_VAL > next_mark) { + if((DUE_TIMER_VAL - next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); return DUE_TIMER_VAL; } + } + writeBits<8+XTRA0>(next_mark, port, b); b = pixels.loadAndScale1(); @@ -209,9 +121,11 @@ protected: writeBits<8+XTRA0>(next_mark, port,b); b = pixels.advanceAndLoadAndScale0(); + sei(); }; - return 0x00FFFFFF - _VAL; + TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); + return DUE_TIMER_VAL; } #endif }; diff --git a/clockless_block_arm_sam.h b/clockless_block_arm_sam.h index f98afb16..6f9fc797 100644 --- a/clockless_block_arm_sam.h +++ b/clockless_block_arm_sam.h @@ -88,15 +88,7 @@ public: virtual void showColor(const struct CRGB & rgbdata, int nLeds, CRGB scale) { MultiPixelController<LANES,PORT_MASK,RGB_ORDER> pixels(rgbdata,nLeds, scale, getDither() ); mWait.wait(); - cli(); - SysClockSaver savedClock(TOTAL); - - uint32_t clocks = showRGBInternal(pixels, nLeds); - - long microsTaken = CLKS_TO_MICROS(clocks); - long millisTaken = (microsTaken / 1000); - savedClock.restore(); - while(millisTaken-- > 0) { TimeTick_Increment(); } + showRGBInternal(pixels, nLeds); sei(); mWait.mark(); } @@ -107,38 +99,18 @@ public: virtual void show(const struct CRGB *rgbdata, int nLeds, CRGB scale) { MultiPixelController<LANES,PORT_MASK,RGB_ORDER> pixels(rgbdata,nLeds, scale, getDither() ); mWait.wait(); - cli(); - SysClockSaver savedClock(TOTAL); - - uint32_t clocks = showRGBInternal(pixels, nLeds); - - - long microsTaken = CLKS_TO_MICROS(clocks); - long millisTaken = (microsTaken / 1000); - savedClock.restore(); - while(millisTaken-- > 0) { TimeTick_Increment(); } - sei(); + showRGBInternal(pixels, nLeds); mWait.mark(); } #ifdef SUPPORT_ARGB virtual void show(const struct CARGB *rgbdata, int nLeds, CRGB scale) { mWait.wait(); - cli(); - showRGBInternal(PixelController<RGB_ORDER>(rgbdata, nLeds, scale, getDither())); - - - // Adjust the timer - long microsTaken = nLeds * CLKS_TO_MICROS(24 * (T1 + T2 + T3)); - MS_COUNTER += (microsTaken / 1000); - sei(); mWait.mark(); } #endif -#define VAL *((uint32_t*)(SysTick_BASE + 8)) - template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, Lines & b3, MultiPixelController<LANES, PORT_MASK, RGB_ORDER> &pixels) { // , register uint32_t & b2) { register Lines b2; transpose8x1(b.bytes,b2.bytes); @@ -147,15 +119,15 @@ public: register uint8_t scale = pixels.template getscale<PX>(pixels); for(uint32_t i = 0; (i < LANES) && (i<8); i++) { - while(VAL > next_mark); + while(DUE_TIMER_VAL < next_mark); + next_mark = (DUE_TIMER_VAL+TOTAL); - next_mark = VAL - (TOTAL-12); *FastPin<FIRST_PIN>::sport() = PORT_MASK; - while((VAL-next_mark) > (T2+T3+6)); + while(next_mark - DUE_TIMER_VAL) > (T2+T3+6)); *FastPin<FIRST_PIN>::cport() = (~b2.bytes[7-i]) & PORT_MASK; - while((VAL - next_mark) > T3); + while((next_mark - DUE_TIMER_VAL) > T3); *FastPin<FIRST_PIN>::cport() = PORT_MASK; b3.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale); @@ -167,10 +139,10 @@ public: next_mark = VAL - (TOTAL-3); *FastPin<FIRST_PIN>::sport() = PORT_MASK; - while((VAL-next_mark) > (T2+T3+6)); + while(next_mark - DUE_TIMER_VAL) > (T2+T3+6)); *FastPin<FIRST_PIN>::cport() = (~b2.bytes[7-i]) & PORT_MASK; - while((VAL - next_mark) > T3); + while((next_mark - DUE_TIMER_VAL) > T3); *FastPin<FIRST_PIN>::cport() = PORT_MASK; } } @@ -188,20 +160,20 @@ public: } // Setup and start the clock - register volatile uint32_t *CTPTR asm("r6")= &SysTick->CTRL; FORCE_REFERENCE(CTPTR); - _LOAD = 0x00FFFFFF; - _VAL = 0; - _CTRL |= SysTick_CTRL_CLKSOURCE_Msk; - _CTRL |= SysTick_CTRL_ENABLE_Msk; + TC_Configure(DUE_TIMER,DUE_TIMER_CHANNEL,TC_CMR_TCCLKS_TIMER_CLOCK1); + pmc_enable_periph_clk(DUE_TIMER_ID); + TC_Start(DUE_TIMER,DUE_TIMER_CHANNEL); VAL = 0; cli(); - uint32_t next_mark = (VAL - (TOTAL)); + uint32_t next_mark = (DUE_TIMER_VAL + (TOTAL)); while(nLeds--) { allpixels.stepDithering(); cli(); - if(VAL < next_mark) { - if((next_mark - VAL) > ((WAIT_TIME*5)*CLKS_PER_US)) { sei(); return 0x00FFFFF - _VAL; } + if(DUE_TIMER_VAL > next_mark) { + if((DUE_TIMER_VAL - next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { + sei(); TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); return DUE_TIMER_VAL; + } } // Write first byte, read next byte @@ -216,7 +188,7 @@ public: sei(); } - return 0x00FFFFFF - _VAL; + return DUE_TIMER_VAL; } diff --git a/examples/Cylon/Cylon.ino b/examples/Cylon/Cylon.ino index 56e2d1d5..76046b41 100644 --- a/examples/Cylon/Cylon.ino +++ b/examples/Cylon/Cylon.ino @@ -10,9 +10,11 @@ #define CLOCK_PIN 13 // Define the array of leds -CRGB leds[40]; +CRGB leds[NUM_LEDS]; void setup() { + Serial.begin(57600); + Serial.println("resetting"); LEDS.addLeds<NEOPIXEL,DATA_PIN>(leds,NUM_LEDS); LEDS.setBrightness(84); } @@ -20,8 +22,8 @@ void setup() { void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } } void loop() { - uint8_t hue = 0; - // Serial.print("x"); + static uint8_t hue = 0; + Serial.print("x"); // First slide the led in one direction for(int i = 0; i < NUM_LEDS; i++) { // Set the i'th led to red @@ -32,8 +34,9 @@ void loop() { // leds[i] = CRGB::Black; fadeall(); // Wait a little bit before we loop around and do it again - delay(100); + delay(10); } + Serial.print("x"); // Now go in the other direction. for(int i = (NUM_LEDS)-1; i >= 0; i--) { @@ -45,6 +48,6 @@ void loop() { // leds[i] = CRGB::Black; fadeall(); // Wait a little bit before we loop around and do it again - delay(100); + delay(10); } } diff --git a/led_sysdefs.h b/led_sysdefs.h index 894055f1..3ec49ad6 100644 --- a/led_sysdefs.h +++ b/led_sysdefs.h @@ -2,6 +2,7 @@ #define __INC_LED_SYSDEFS_H #if defined(__MK20DX128__) || defined(__MK20DX256__) + #define FASTLED_TEENSY3 #define FASTLED_ARM #define FASTLED_ACCURATE_CLOCK @@ -11,14 +12,33 @@ #if (F_CPU == 96000000) #define CLK_DBL 1 #endif + #elif defined(__SAM3X8E__) + #define FASTLED_ARM + +// Setup DUE timer defines/channels/etc... +#ifndef DUE_TIMER_CHANNEL +#define DUE_TIMER_GROUP 0 +#endif + +#ifndef DUE_TIMER_CHANNEL +#define DUE_TIMER_CHANNEL 0 +#endif + +#define DUE_TIMER ((DUE_TIMER_GROUP==0) ? TC0 : ((DUE_TIMER_GROUP==1) ? TC1 : TC2)) +#define DUE_TIMER_ID (ID_TC0 + (DUE_TIMER_GROUP*3) + DUE_TIMER_CHANNEL) +#define DUE_TIMER_VAL (DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_CV << 1) +#define DUE_TIMER_RUNNING ((DUE_TIMER->TC_CHANNEL[DUE_TIMER_CHANNEL].TC_SR & TC_SR_CLKSTA) != 0) + #else + #define FASTLED_AVR #define FASTLED_ACCURATE_CLOCK #ifndef INTERRUPT_THRESHOLD #define INTERRUPT_THRESHOLD 10 #endif + #endif #ifndef CLK_DBL |