diff options
author | danielgarcia@gmail.com <danielgarcia@gmail.com@4ad4ec5c-605d-bd5c-5796-512c9b60011b> | 2013-11-10 05:36:14 +0400 |
---|---|---|
committer | danielgarcia@gmail.com <danielgarcia@gmail.com@4ad4ec5c-605d-bd5c-5796-512c9b60011b> | 2013-11-10 05:36:14 +0400 |
commit | e9d4489e508a99dc9e949f7762c2d6f3529524bb (patch) | |
tree | db02d9fe781a3bdbc3b6ebd5af148f6ffe1c7f91 | |
parent | 7185b516211105fc9644063548240c0057d77012 (diff) | |
parent | adc78ce93b7b6b009aab35e9fce94074920b6bf5 (diff) |
Sync w/main FastSPI_LED2 branch
-rw-r--r-- | FastSPI_LED2.h | 3 | ||||
-rw-r--r-- | chipsets.h | 21 | ||||
-rw-r--r-- | clockless.h | 179 | ||||
-rw-r--r-- | delay.h | 3 | ||||
-rw-r--r-- | examples/FirstLight/FirstLight.ino | 13 | ||||
-rw-r--r-- | fastpin.h | 15 | ||||
-rw-r--r-- | hsv2rgb.cpp | 4 | ||||
-rw-r--r-- | lib8tion.h | 2 | ||||
-rw-r--r-- | preview_changes.txt | 7 |
9 files changed, 124 insertions, 123 deletions
diff --git a/FastSPI_LED2.h b/FastSPI_LED2.h index 8bcedc93..d83c2aa9 100644 --- a/FastSPI_LED2.h +++ b/FastSPI_LED2.h @@ -28,6 +28,7 @@ enum EClocklessChipsets { WS2812, WS2812B, UCS1903, + WS2811_400, NEOPIXEL, TM1829 }; @@ -111,6 +112,7 @@ public: case WS2812B: case NEOPIXEL: case WS2811: return addLeds(new WS2811Controller800Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset); + case WS2811_400: return addLeds(new WS2811Controller400Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset); } return NULL; } @@ -129,6 +131,7 @@ public: case WS2812B: case NEOPIXEL: case WS2811: return addLeds(new WS2811Controller800Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); + case WS2811_400: return addLeds(new WS2811Controller400Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset); } return NULL; } @@ -93,7 +93,7 @@ template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t S class WS2801Controller : public CLEDController { typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI; SPI mSPI; - CMinWait<24> mWaitDelay; + CMinWait<500> mWaitDelay; public: WS2801Controller() {} @@ -300,19 +300,22 @@ class UCS1903Controller400Khz : public ClocklessController<DATA_PIN, NS(500), NS // TM1809 - 312.5ns, 312.5ns, 325ns template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB> class TM1809Controller800Khz : public ClocklessController<DATA_PIN, NS(350), NS(350), NS(550), RGB_ORDER> {}; -#if NO_TIME(320, 320, 550) +#if NO_TIME(350, 350, 550) #warning "Not enough clock cycles available for the TM1809" #endif -// WS2811 - 350n, 350ns, 550ns +// WS2811 - 400ns, 400ns, 450ns template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB> -class WS2811Controller800Khz : public ClocklessController<DATA_PIN, NS(320), NS(320), NS(550), RGB_ORDER> {}; - -template <uint8_t DATA_PIN, uint8_t DATA_PIN2, EOrder RGB_ORDER = RGB> -class WS2811Controller2800Khz : public ClocklessController2<DATA_PIN, DATA_PIN2, NS(320), NS(320), NS(550), RGB_ORDER> {}; +class WS2811Controller800Khz : public ClocklessController<DATA_PIN, NS(400), NS(400), NS(450), RGB_ORDER> {}; +#if NO_TIME(400, 400, 450) +#warning "No enough clock cycles available for the WS2811 (800khz)" +#endif -#if NO_TIME(320, 320, 550) -#warning "Not enough clock cycles available for the WS2811" +// WS2811@400khz - 800ns, 800ns, 900ns +template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB> +class WS2811Controller400Khz : public ClocklessController<DATA_PIN, NS(800), NS(800), NS(900), RGB_ORDER> {}; +#if NO_TIME(800, 800, 900) +#warning "No enough clock cycles available for the WS2811 (400Khz)" #endif // 750NS, 750NS, 750NS diff --git a/clockless.h b/clockless.h index 270fcfc5..9bffb9fc 100644 --- a/clockless.h +++ b/clockless.h @@ -9,10 +9,10 @@ // #define NS(_NS) (_NS / (1000 / (F_CPU / 1000000L))) #if F_CPU < 96000000 #define NS(_NS) ( (_NS * (F_CPU / 1000000L))) / 1000 -#define CLKS_TO_MICROS(_CLKS) _CLKS / (F_CPU / 1000000L) +#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 1000000L) #else #define NS(_NS) ( (_NS * (F_CPU / 2000000L))) / 1000 -#define CLKS_TO_MICROS(_CLKS) _CLKS / (F_CPU / 2000000L) +#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 2000000L) #endif // Macro for making sure there's enough time available @@ -34,6 +34,14 @@ # endif #endif +// Scaling macro choice +#if defined(LIB8_ATTINY) +# define INLINE_SCALE(B, SCALE) delaycycles<3>() +# warning "No hardware multiply, inline brightness scaling disabled" +#else +# define INLINE_SCALE(B, SCALE) B = scale8_LEAVING_R1_DIRTY(B, SCALE) +#endif + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Base template for clockless controllers. These controllers have 3 control points in their cycle for each bit. The first point @@ -62,23 +70,6 @@ public: mPort = FastPin<DATA_PIN>::port(); } - template <int N>inline static void bitSetFast(register data_ptr_t port, register data_t hi, register data_t lo, register uint8_t b) { - // First cycle - SET_HI; // 1/2 clock cycle if using out - delaycycles<T1 - (_CYCLES(DATA_PIN) + 1)>(); // 1st cycle length minus 1/2 clock for out, 1 clock for sbrs - __asm__ __volatile__ ("sbrs %0, %1" :: "r" (b), "M" (N) :); // 1 clock for check (+1 if skipping, next op is also 1 clock) - - // Second cycle - SET_LO; // 1/2 clock cycle if using out - delaycycles<T2 - _CYCLES(DATA_PIN)>(); // 2nd cycle length minus 1/2 clock for out - - // Third cycle - SET_LO; // 1 clock cycle if using out - delaycycles<T3 - _CYCLES(DATA_PIN)>(); // 3rd cycle length minus 1 clock for out - } - - #define END_OF_BYTE - #define END_OF_LOOP 6 // loop compare, jump, next uint8_t load template <int N, int ADJ>inline static void bitSetLast(register data_ptr_t port, register data_t hi, register data_t lo, register uint8_t b) { // First cycle SET_HI; // 1 clock cycle if using out, 2 otherwise @@ -106,7 +97,7 @@ public: showRGBInternal<0, false>(nLeds, scale, (const byte*)&data); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); @@ -119,7 +110,7 @@ public: showRGBInternal<0, true>(nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); @@ -130,10 +121,10 @@ public: mWait.wait(); cli(); - showRGBInternal<1, true>(nLeds, scale, (const byte*)rgbdata); + showRGBInternal<1, true>((long)nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); @@ -154,7 +145,7 @@ public: register uint8_t b; b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)]; - b = scale8_LEAVING_R1_DIRTY(b, scale); + b = INLINE_SCALE(b, scale); register uint8_t c; register uint8_t d; @@ -165,11 +156,13 @@ public: } delaycycles<1>(); // Leave an extra 2 clocks for the next byte load - bitSetLast<7, 0>(port, hi, lo, b); + bitSetLast<7, 1>(port, hi, lo, b); + delaycycles<1>(); + // Leave an extra 4 clocks for the scale - bitSetLast<6, 5>(port, hi, lo, b); + bitSetLast<6, 6>(port, hi, lo, b); c = ADVANCE ? data[SKIP + RGB_BYTE1(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE1(RGB_ORDER)]; - c = scale8_LEAVING_R1_DIRTY(c, scale); + INLINE_SCALE(c, scale); bitSetLast<5, 1>(port, hi, lo, b); for(register byte x=5; x; x--) { @@ -178,11 +171,13 @@ public: } delaycycles<1>(); // Leave an extra 2 clocks for the next byte load - bitSetLast<7, 0>(port, hi, lo, c); + bitSetLast<7, 1>(port, hi, lo, c); + delaycycles<1>(); + // Leave an extra 4 clocks for the scale - bitSetLast<6, 5>(port, hi, lo, c); + bitSetLast<6, 6>(port, hi, lo, c); d = ADVANCE ? data[SKIP + RGB_BYTE2(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE2(RGB_ORDER)]; - d = scale8_LEAVING_R1_DIRTY(d, scale); + INLINE_SCALE(d, scale); bitSetLast<5, 1>(port, hi, lo, c); for(register byte x=5; x; x--) { @@ -194,9 +189,9 @@ public: bitSetLast<7, 2>(port, hi, lo, d); data += (SKIP + 3); // Leave an extra 4 clocks for the scale - bitSetLast<6, 5>(port, hi, lo, d); + bitSetLast<6, 6>(port, hi, lo, d); b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)]; - b = scale8_LEAVING_R1_DIRTY(b, scale); + INLINE_SCALE(b, scale); bitSetLast<5, 6>(port, hi, lo, d); } cleanup_R1(); @@ -231,7 +226,7 @@ public: showRGBInternal<0, false>(nLeds, scale, (const byte*)&data); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); @@ -244,7 +239,7 @@ public: showRGBInternal<0, true>(nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); @@ -258,73 +253,63 @@ public: showRGBInternal<1, true>(nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); sei(); mWait.mark(); } #endif + inline static void write8Bits(register data_ptr_t port, register data_t hi, register data_t lo, register uint32_t & b) __attribute__ ((always_inline)) { + // TODO: hand rig asm version of this method. The timings are based on adjusting/studying GCC compiler ouptut. This + // will bite me in the ass at some point, I know it. + for(register uint32_t i = 7; i > 0; i--) { + FastPin<DATA_PIN>::fastset(port, hi); + delaycycles<T1 - 5>(); // 5 cycles - 2 store, 1 and, 1 test, 1 if + if(b & 0x80) { FastPin<DATA_PIN>::fastset(port, hi); } else { FastPin<DATA_PIN>::fastset(port, lo); } + b <<= 1; + delaycycles<T2 - 2>(); // 2 cycles, 1 store/skip, 1 shift + FastPin<DATA_PIN>::fastset(port, lo); + delaycycles<T3 - 5>(); // 3 cycles, 2 store, 1 sub, 1 branch backwards + } + // delay an extra cycle because falling out of the loop takes on less cycle than looping around + delaycycles<1>(); + + FastPin<DATA_PIN>::fastset(port, hi); + delaycycles<T1 - 6>(); + if(b & 0x80) { FastPin<DATA_PIN>::fastset(port, hi); } else { FastPin<DATA_PIN>::fastset(port, lo); } + delaycycles<T2 - 2>(); // 4 cycles, 2 store, store/skip + FastPin<DATA_PIN>::fastset(port, lo); + } + + // 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. template<int SKIP, bool ADVANCE> static void showRGBInternal(register int nLeds, register uint8_t scale, register const byte *rgbdata) { register byte *data = (byte*)rgbdata; + register data_t mask = FastPin<DATA_PIN>::mask(); register data_ptr_t port = FastPin<DATA_PIN>::port(); nLeds *= (3 + SKIP); register uint8_t *end = data + nLeds; - register data_t hi = FastPin<DATA_PIN>::hival(); - register data_t lo = FastPin<DATA_PIN>::loval();; + register data_t hi = *port | mask; + register data_t lo = *port & ~mask; *port = lo; register uint32_t b; - b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)]; + b = ((ADVANCE)?data:rgbdata)[SKIP + RGB_BYTE0(RGB_ORDER)]; b = scale8(b, scale); while(data < end) { - // TODO: hand rig asm version of this method. The timings are based on adjusting/studying GCC compiler ouptut. This - // will bite me in the ass at some point, I know it. - for(register uint32_t i = 7; i > 0; i--) { - SET_HI; - delaycycles<T1 - 3>(); // 3 cycles - 1 store, 1 test, 1 if - if(b & 0x80) { SET_HI; } else { SET_LO; } - b <<= 1; - delaycycles<T2 - 3>(); // 3 cycles, 1 store, 1 store/skip, 1 shift - SET_LO; - delaycycles<T3 - 3>(); // 3 cycles, 1 store, 1 sub, 1 branch backwards - } - // extra delay because branch is faster falling through - delaycycles<1>(); - - // 8th bit, interleave loading rest of data - SET_HI; - delaycycles<T1 - 3>(); - if(b & 0x80) { SET_HI; } else { SET_LO; } - delaycycles<T2 - 2>(); // 4 cycles, 2 store, store/skip - SET_LO; - - b = ADVANCE ? data[SKIP + RGB_BYTE1(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE1(RGB_ORDER)]; - b = scale8(b, scale); + // Write first byte, read next byte + write8Bits(port, hi, lo, b); + b = ((ADVANCE)?data:rgbdata)[SKIP + RGB_BYTE1(RGB_ORDER)]; + INLINE_SCALE(b, scale); delaycycles<T3 - 5>(); // 1 store, 2 load, 1 mul, 1 shift, - for(register uint32_t i = 7; i > 0; i--) { - SET_HI; - delaycycles<T1 - 3>(); // 3 cycles - 1 store, 1 test, 1 if - if(b & 0x80) { SET_HI; } else { SET_LO; } - b <<= 1; - delaycycles<T2 - 3>(); // 3 cycles, 1 store, 1 store/skip, 1 shift - SET_LO; - delaycycles<T3 - 3>(); // 3 cycles, 1 store, 1 sub, 1 branch backwards - } - // extra delay because branch is faster falling through - delaycycles<1>(); - - // 8th bit, interleave loading rest of data - SET_HI; - delaycycles<T1 - 3>(); - if(b & 0x80) { SET_HI; } else { SET_LO; } - delaycycles<T2 - 2>(); // 4 cycles, 2 store, store/skip - SET_LO; + // Write second byte + write8Bits(port, hi, lo, b); - b = ADVANCE ? data[SKIP + RGB_BYTE2(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE2(RGB_ORDER)]; - b = scale8(b, scale); + b = ((ADVANCE)?data:rgbdata)[SKIP + RGB_BYTE2(RGB_ORDER)]; + INLINE_SCALE(b, scale); data += 3 + SKIP; if((RGB_ORDER & 0070) == 0) { @@ -333,29 +318,13 @@ public: delaycycles<T3 - 5>(); // 1 store, 2 load, 1 mul, 1 shift, } - for(register uint32_t i = 7; i > 0; i--) { - SET_HI; - delaycycles<T1 - 3>(); // 3 cycles - 1 store, 1 test, 1 if - if(b & 0x80) { SET_HI; } else { SET_LO; } - b <<= 1; - delaycycles<T2 - 3>(); // 3 cycles, 1 store, 1 store/skip, 1 shift - SET_LO; - delaycycles<T3 - 3>(); // 3 cycles, 1 store, 1 sub, 1 branch backwards - } - // extra delay because branch is faster falling through - delaycycles<1>(); - - // 8th bit, interleave loading rest of data - SET_HI; - delaycycles<T1 - 3>(); - if(b & 0x80) { SET_HI; } else { SET_LO; } - delaycycles<T2 - 2>(); // 4 cycles, 2 store, store/skip - SET_LO; + // Write third byte + write8Bits(port, hi, lo, b); - b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)]; - b = scale8(b, scale); + b = ((ADVANCE)?data:rgbdata)[SKIP + RGB_BYTE0(RGB_ORDER)]; + INLINE_SCALE(b, scale); - delaycycles<T3 - 8>(); // 1 store, 2 load (with increment), 1 mul, 1 shift, 1 cmp, 1 branch backwards, 1 movim + delaycycles<T3 - 11>(); // 1 store, 2 load (with increment), 1 mul, 1 shift, 1 cmp, 1 branch backwards, 1 movim }; } }; @@ -389,7 +358,7 @@ public: showRGBInternal<0, false>(nLeds, scale, (const byte*)&data); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); savedClock.restore(); sei(); @@ -405,7 +374,7 @@ public: showRGBInternal<0, true>(nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); savedClock.restore(); sei(); @@ -421,7 +390,7 @@ public: showRGBInternal<1, true>(nLeds, scale, (const byte*)rgbdata); // Adjust the timer - long microsTaken = CLKS_TO_MICROS(nLeds * 8 * (T1 + T2 + T3)); + long microsTaken = CLKS_TO_MICROS((long)nLeds * 8 * (T1 + T2 + T3)); MS_COUNTER += (microsTaken / 1000); savedClock.restore(); sei(); @@ -64,6 +64,9 @@ template<int CYCLES> __attribute__((always_inline)) inline void delaycycles() { // pre-instantiations for values small enough to not need the loop, as well as sanity holders // for some negative values. +template<> __attribute__((always_inline)) inline void delaycycles<-6>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-5>() {} +template<> __attribute__((always_inline)) inline void delaycycles<-4>() {} template<> __attribute__((always_inline)) inline void delaycycles<-3>() {} template<> __attribute__((always_inline)) inline void delaycycles<-2>() {} template<> __attribute__((always_inline)) inline void delaycycles<-1>() {} diff --git a/examples/FirstLight/FirstLight.ino b/examples/FirstLight/FirstLight.ino index 25de2673..13340ebd 100644 --- a/examples/FirstLight/FirstLight.ino +++ b/examples/FirstLight/FirstLight.ino @@ -1,3 +1,5 @@ +#define FORCE_SOFTWARE_SPI +#define FORCE_SOFTWARE_PINS #include "FastSPI_LED2.h" /////////////////////////////////////////////////////////////////////////////////////////// @@ -7,7 +9,7 @@ // // How many leds are in the strip? -#define NUM_LEDS 40 +#define NUM_LEDS 60 // Data pin that led data will be written out over #define DATA_PIN 23 @@ -27,14 +29,17 @@ void setup() { // FastLED.addLeds<TM1803, DATA_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<TM1804, DATA_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<TM1809, DATA_PIN, RGB>(leds, NUM_LEDS); - FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS); + // FastSPI_LED2.addLeds<WS2811, DATA_PIN, GRB>(leds+18, NUM_LEDS/3); + // FastLED.addLeds<WS2811, 8, RGB>(leds + 225, NUM_LEDS/4); // FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS); + // FastLED.addLeds<NEOPIXEL, DATA_PIN, RGB>(leds, NUM_LEDS); + // FastLED.addLeds<WS2811_400, DATA_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<UCS1903, DATA_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS); // FastLED.addLeds<SM16716, RGB>(leds, NUM_LEDS); - // FastLED.addLeds<LPD8806, RGB>(leds, NUM_LEDS); + FastLED.addLeds<LPD8806, RGB>(leds, NUM_LEDS); // FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); // FastLED.addLeds<SM16716, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS); @@ -58,4 +63,4 @@ void loop() { // Turn our current led back to black for the next loop around leds[whiteLed] = CRGB::Black; } -}
\ No newline at end of file +} @@ -28,7 +28,11 @@ public: // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define _CYCLES(_PIN) (((_PIN >= 62 ) || (_PIN>=42 && _PIN<=49) || (_PIN>=14 && _PIN <=17) || (_PIN>=6 && _PIN <=9)) ? 2 : 1) +#else #define _CYCLES(_PIN) ((_PIN >= 24) ? 2 : 1) +#endif class Selectable { public: @@ -326,8 +330,17 @@ typedef volatile uint32_t * ptr_reg32_t; // built on, then much higher speed access will be possible, namely with direct GPIO register accesses. // /////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(FORCE_SOFTWARE_PINS) +#warning "Softwrae pin support forced pin access will be slightly slower. See fastpin.h for info." +#define NO_HARDWARE_PIN_SUPPORT + +#elif defined(__AVR_ATtiny85__) +_IO(B); + +_DEFPIN_AVR(0, 0x01, B); _DEFPIN_AVR(1, 0x02, B); _DEFPIN_AVR(2, 0x04, B); _DEFPIN_AVR(3, 0x08, B); +_DEFPIN_AVR(4, 0x10, B); _DEFPIN_AVR(5, 0x20, B); -#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) +#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) // Accelerated port definitions for arduino avrs _IO(D); _IO(B); _IO(C); diff --git a/hsv2rgb.cpp b/hsv2rgb.cpp index 748144fb..b0abdab9 100644 --- a/hsv2rgb.cpp +++ b/hsv2rgb.cpp @@ -48,7 +48,7 @@ void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb); void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb); -#if defined(__AVR__) +#if defined(__AVR__) && !defined( LIB8_ATTINY ) void hsv2rgb_raw(const struct CHSV & hsv, struct CRGB & rgb) { hsv2rgb_raw_avr( hsv, rgb); @@ -154,7 +154,7 @@ void hsv2rgb_raw_C (const struct CHSV & hsv, struct CRGB & rgb) -#if defined(__AVR__) +#if defined(__AVR__) && !defined( LIB8_ATTINY ) void hsv2rgb_raw_avr(const struct CHSV & hsv, struct CRGB & rgb) { uint8_t hue, saturation, value; @@ -196,7 +196,7 @@ Lib8tion is pronounced like 'libation': lie-BAY-shun // On ATtiny, we just use C implementations #define SCALE8_C 1 #define SCALE16BY8_C 1 -#define SCALE16_C 0 +#define SCALE16_C 1 #define MUL8_C 1 #define QMUL8_C 1 #define EASE8_C 1 diff --git a/preview_changes.txt b/preview_changes.txt index ccf4bafc..9b1a8831 100644 --- a/preview_changes.txt +++ b/preview_changes.txt @@ -1,5 +1,10 @@ -(Post RC3) +Release Candidate 5 +* Gemma and Trinket: supported except for global "setBrightness" + +Release Candidate 4 * Added NEOPIXEL as a synonym for WS2811 +* Fix WS2811/WS2812B timings, bring it in line to exactly 1.25ns/bit. +* Fix handling of constant color definitions (damn you, gcc!) Release Candidate 3 * Fixed bug when Clock and Data were on the same port |