diff options
author | Daniel Garcia <danielgarcia@gmail.com> | 2014-11-24 23:11:38 +0300 |
---|---|---|
committer | Daniel Garcia <danielgarcia@gmail.com> | 2014-11-24 23:11:38 +0300 |
commit | c2f9d3159ae858e6ca2af118cb3666f9a05d560f (patch) | |
tree | 63c7a89884a589763b86ba34d477fbfc3ff87c97 | |
parent | d51d5c7ce1ffeba8739cd0faaaaf5e8379a9176d (diff) |
Add configuration option for allowing/disallowing interrupts. Disable by default for AVR, block out AVR implementation of wiring functions.
-rw-r--r-- | fastled_config.h | 7 | ||||
-rw-r--r-- | led_sysdefs.h | 2 | ||||
-rw-r--r-- | platforms.h | 2 | ||||
-rw-r--r-- | platforms/arm/k20/clockless_arm_k20.h | 7 | ||||
-rw-r--r-- | platforms/arm/k20/clockless_block_arm_k20.h | 37 | ||||
-rw-r--r-- | platforms/arm/k20/led_sysdefs_arm_k20.h | 5 | ||||
-rw-r--r-- | platforms/arm/sam/clockless_arm_sam.h | 4 | ||||
-rw-r--r-- | platforms/arm/sam/clockless_block_arm_sam.h | 7 | ||||
-rw-r--r-- | platforms/arm/sam/led_sysdefs_arm_sam.h | 5 | ||||
-rw-r--r-- | platforms/avr/clockless_trinket.h | 20 | ||||
-rw-r--r-- | platforms/avr/led_sysdefs_avr.h | 14 | ||||
-rw-r--r-- | wiring.cpp | 4 |
12 files changed, 108 insertions, 6 deletions
diff --git a/fastled_config.h b/fastled_config.h index 3e5a8c4e..e085f61a 100644 --- a/fastled_config.h +++ b/fastled_config.h @@ -9,4 +9,11 @@ // Use this option only for debugging bitbang'd spi access or to work around bugs in hardware // spi access. Forces use of bit-banged spi, even on pins that has hardware SPI available. // #define FORCE_SOFTWARE_SPI + +// Use this to force FastLED to allow interrupts in the clockless chipsets (or to force it to +// disallow), overriding the default on platforms that support this. Set the value to 1 to +// allow interrupts or 0 to disallow them. +// #define FASTLED_ALLOW_INTERRUPTS 1 +// #define FASTLED_ALLOW_INTERRUPTS 0 + #endif diff --git a/led_sysdefs.h b/led_sysdefs.h index 29bced42..3e7ebaa2 100644 --- a/led_sysdefs.h +++ b/led_sysdefs.h @@ -1,6 +1,8 @@ #ifndef __INC_LED_SYSDEFS_H #define __INC_LED_SYSDEFS_H +#include "fastled_config.h" + #if defined(__MK20DX128__) || defined(__MK20DX256__) // Include k20/T3 headers #include "platforms/arm/k20/led_sysdefs_arm_k20.h" diff --git a/platforms.h b/platforms.h index 9f1c7579..5b34ddc0 100644 --- a/platforms.h +++ b/platforms.h @@ -1,6 +1,8 @@ #ifndef __INC_PLATFORMS_H #define __INC_PLATFORMS_H +#include "fastled_config.h" + #if defined(__MK20DX128__) || defined(__MK20DX256__) // Include k20/T3 headers #include "platforms/arm/k20/fastled_arm_k20.h" diff --git a/platforms/arm/k20/clockless_arm_k20.h b/platforms/arm/k20/clockless_arm_k20.h index d96c9bb2..53b6f85b 100644 --- a/platforms/arm/k20/clockless_arm_k20.h +++ b/platforms/arm/k20/clockless_arm_k20.h @@ -97,17 +97,20 @@ protected: pixels.preStepFirstByteDithering(); register uint8_t b = pixels.loadAndScale0(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); + #endif while(pixels.has(1)) { pixels.stepDithering(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); // if interrupts took longer than 45µs, punt on the current frame if(ARM_DWT_CYCCNT > next_mark) { if((ARM_DWT_CYCCNT-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return ARM_DWT_CYCCNT; } } - + #endif // Write first byte, read next byte writeBits<8+XTRA0>(next_mark, port, hi, lo, b); b = pixels.loadAndScale1(); @@ -119,7 +122,9 @@ protected: // Write third byte, read 1st byte of next pixel writeBits<8+XTRA0>(next_mark, port, hi, lo, b); b = pixels.advanceAndLoadAndScale0(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); + #endif }; return ARM_DWT_CYCCNT; diff --git a/platforms/arm/k20/clockless_block_arm_k20.h b/platforms/arm/k20/clockless_block_arm_k20.h index 63dc5030..bebbf0d7 100644 --- a/platforms/arm/k20/clockless_block_arm_k20.h +++ b/platforms/arm/k20/clockless_block_arm_k20.h @@ -88,9 +88,9 @@ public: typedef union { - uint8_t bytes[16]; - uint16_t shorts[8]; - uint32_t raw[4]; + uint8_t bytes[12]; + uint16_t shorts[6]; + uint32_t raw[3]; } Lines; template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register Lines & b, MultiPixelController<LANES, PORT_MASK, RGB_ORDER> &pixels) { // , register uint32_t & b2) { @@ -132,11 +132,11 @@ public: 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[i]) & PORT_MASK); } else { + // b2.bytes[0] = 0; *FastPin<FIRST_PIN>::cport() = ((~b2.bytes[7-i]) & PORT_MASK); } @@ -144,6 +144,21 @@ 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; } @@ -165,15 +180,19 @@ public: b0.bytes[i] = allpixels.loadAndScale0(i); } + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); + #endif while(nLeds--) { + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); // if interrupts took longer than 45µs, punt on the current frame if(ARM_DWT_CYCCNT > next_mark) { if((ARM_DWT_CYCCNT-next_mark) > ((WAIT_TIME-5)*CLKS_PER_US)) { sei(); return ARM_DWT_CYCCNT; } } + #endif allpixels.stepDithering(); // Write first byte, read next byte @@ -185,7 +204,9 @@ public: // Write third byte writeBits<8+XTRA0,0>(next_mark, b0, allpixels); + #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); + #endif }; return ARM_DWT_CYCCNT; @@ -314,16 +335,21 @@ public: b0.bytes[i] = allpixels.loadAndScale0(i); } + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); uint32_t next_mark = ARM_DWT_CYCCNT + (T1+T2+T3); + #endif while(nLeds--) { allpixels.stepDithering(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); // if interrupts took longer than 45µs, punt on the current frame if(ARM_DWT_CYCCNT > next_mark) { if((ARM_DWT_CYCCNT-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return ARM_DWT_CYCCNT; } } + #endif + // Write first byte, read next byte writeBits<8+XTRA0,1>(next_mark, b0, allpixels); @@ -333,7 +359,10 @@ public: // Write third byte writeBits<8+XTRA0,0>(next_mark, b0, allpixels); + + #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); + #endif }; return ARM_DWT_CYCCNT; diff --git a/platforms/arm/k20/led_sysdefs_arm_k20.h b/platforms/arm/k20/led_sysdefs_arm_k20.h index abed80f9..e0a8a979 100644 --- a/platforms/arm/k20/led_sysdefs_arm_k20.h +++ b/platforms/arm/k20/led_sysdefs_arm_k20.h @@ -9,6 +9,11 @@ #define INTERRUPT_THRESHOLD 1 #endif +// Default to allowing interrupts +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 1 +#endif + #if (F_CPU == 96000000) #define CLK_DBL 1 #endif diff --git a/platforms/arm/sam/clockless_arm_sam.h b/platforms/arm/sam/clockless_arm_sam.h index 6924cc9d..ebc8c0ad 100644 --- a/platforms/arm/sam/clockless_arm_sam.h +++ b/platforms/arm/sam/clockless_arm_sam.h @@ -107,10 +107,12 @@ protected: while(pixels.has(1)) { pixels.stepDithering(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) 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; } } + #endif writeBits<8+XTRA0>(next_mark, port, b); @@ -121,7 +123,9 @@ protected: writeBits<8+XTRA0>(next_mark, port,b); b = pixels.advanceAndLoadAndScale0(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); + #endif }; TC_Stop(DUE_TIMER,DUE_TIMER_CHANNEL); diff --git a/platforms/arm/sam/clockless_block_arm_sam.h b/platforms/arm/sam/clockless_block_arm_sam.h index 51eb1b92..128617a2 100644 --- a/platforms/arm/sam/clockless_block_arm_sam.h +++ b/platforms/arm/sam/clockless_block_arm_sam.h @@ -159,16 +159,20 @@ public: pmc_enable_periph_clk(DUE_TIMER_ID); TC_Start(DUE_TIMER,DUE_TIMER_CHANNEL); + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); + #endif uint32_t next_mark = (DUE_TIMER_VAL + (TOTAL)); while(nLeds--) { allpixels.stepDithering(); + #if (FASTLED_ALLOW_INTERRUPTS == 1) 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; } } + #endif // Write first byte, read next byte writeBits<8+XTRA0,1>(next_mark, b0, b1, allpixels); @@ -179,7 +183,10 @@ public: allpixels.advanceData(); // Write third byte writeBits<8+XTRA0,0>(next_mark, b2, b0, allpixels); + + #if (FASTLED_ALLOW_INTERRUPTS == 1) sei(); + #endif } return DUE_TIMER_VAL; diff --git a/platforms/arm/sam/led_sysdefs_arm_sam.h b/platforms/arm/sam/led_sysdefs_arm_sam.h index e45f9609..a6ef12bb 100644 --- a/platforms/arm/sam/led_sysdefs_arm_sam.h +++ b/platforms/arm/sam/led_sysdefs_arm_sam.h @@ -22,6 +22,11 @@ #define INTERRUPT_THRESHOLD 1 #endif +// Default to allowing interrupts +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 1 +#endif + // reuseing/abusing cli/sei defs for due #define cli() __disable_irq(); __disable_fault_irq(); #define sei() __enable_irq(); __enable_fault_irq(); diff --git a/platforms/avr/clockless_trinket.h b/platforms/avr/clockless_trinket.h index 4630719d..fd831319 100644 --- a/platforms/avr/clockless_trinket.h +++ b/platforms/avr/clockless_trinket.h @@ -104,6 +104,16 @@ protected: showRGBInternal(pixels); + // Adjust the timer + #if (!defined(NO_CORRECTION) || (NO_CORRECTION == 0)) && (FASTLED_ALLOW_INTERRUPTS == 0) + uint32_t microsTaken = (uint32_t)nLeds * (uint32_t)CLKS_TO_MICROS(24 * (T1 + T2 + T3)); + if(microsTaken > 1024) { + MS_COUNTER += (microsTaken >> 10); + } else { + MS_COUNTER++; + } + #endif + sei(); mWait.mark(); } @@ -243,9 +253,11 @@ protected: uint8_t loopvar=0; + #if (FASTLED_ALLOW_INTERRUPTS == 1) TCCR0A |= 0x30; OCR0B = (uint8_t)(TCNT0 + ((WAIT_TIME-INTERRUPT_THRESHOLD)/US_PER_TICK)); TIFR0 = 0x04; + #endif { while(count--) { @@ -256,8 +268,8 @@ protected: ADJDITHER2(d1,e1); ADJDITHER2(d2,e2); + #if (FASTLED_ALLOW_INTERRUPTS == 1) cli(); - if(TIFR0 & 0x04) { sei(); TCCR0A &= ~0x30; @@ -265,6 +277,7 @@ protected: } hi = *port | mask; lo = *port & ~mask; + #endif // Sum of the clock counts across each row should be 10 for 8Mhz, WS2811 // The values in the D1/D2/D3 indicate how many cycles the previous column takes @@ -347,15 +360,20 @@ protected: HI1 D1(1) QLO2(b2, 1) D2(0) LO1 D3(0) HI1 D1(1) QLO2(b2, 0) D2(0) LO1 D3(0) #endif + + #if (FASTLED_ALLOW_INTERRUPTS == 1) // set the counter mark OCR0B = (uint8_t)(TCNT0 + ((WAIT_TIME-INTERRUPT_THRESHOLD)/US_PER_TICK)); TIFR0 = 0x04; sei(); + #endif } } + #if (FASTLED_ALLOW_INTERRUPTS == 1) // stop using the clock juggler TCCR0A &= ~0x30; + #endif } #ifdef SUPPORT_ARGB diff --git a/platforms/avr/led_sysdefs_avr.h b/platforms/avr/led_sysdefs_avr.h index 19cfabee..e4972c7d 100644 --- a/platforms/avr/led_sysdefs_avr.h +++ b/platforms/avr/led_sysdefs_avr.h @@ -18,4 +18,18 @@ typedef volatile uint8_t RwReg; /**< Read-Write 8-bit register (volatile u #endif +// Default to disallowing interrupts (may want to gate this on teensy2 vs. other arm platforms, since the +// teensy2 has a good, fast millis interrupt implementation) +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 0 +#endif + +# if defined(CORE_TEENSY) +extern volatile unsigned long timer0_millis_count; +# define MS_COUNTER timer0_millis_count +# else +extern volatile unsigned long timer0_millis; +# define MS_COUNTER timer0_millis +# endif + #endif @@ -1,6 +1,7 @@ #define FASTLED_INTERNAL #include "FastLED.h" +#if 0 #if defined(FASTLED_AVR) && !defined(TEENSYDUINO) && !defined(LIB8_ATTINY) extern "C" { @@ -230,3 +231,6 @@ void init() } }; #endif + +#endif + |