Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Garcia <danielgarcia@gmail.com>2014-01-21 09:12:56 +0400
committerDaniel Garcia <danielgarcia@gmail.com>2014-01-21 09:12:56 +0400
commit0757fd59034ca7f8fdc8fa779923426c447e9206 (patch)
tree28a268a0a47e1a2e8f47008613d9fe8bfa2745fb
parent4db5cba81454e2c66aeeab72e29a419ccae47ecb (diff)
parented8c33d914b707e4b1c8d43c8f21a2936110ad85 (diff)
merge from mainline release
-rw-r--r--FastLED.cpp2
-rw-r--r--FastLED.h54
-rw-r--r--README.md16
-rw-r--r--chipsets.h66
-rw-r--r--clockless.h31
-rw-r--r--clockless_trinket.h279
-rw-r--r--controller.h3
-rw-r--r--delay.h38
-rw-r--r--dmx.h2
-rw-r--r--examples/Blink/Blink.ino4
-rw-r--r--examples/Cylon/Cylon.ino2
-rw-r--r--examples/FirstLight/FirstLight.ino7
-rw-r--r--examples/testleds/testleds.pde95
-rw-r--r--lib8tion.cpp6
14 files changed, 435 insertions, 170 deletions
diff --git a/FastLED.cpp b/FastLED.cpp
index a7cf3c5f..7d78a8b4 100644
--- a/FastLED.cpp
+++ b/FastLED.cpp
@@ -1,4 +1,4 @@
-#include "FastSPI_LED2.h"
+#include "FastLED.h"
#if defined(__SAM3X8E__)
volatile uint32_t fuckit;
diff --git a/FastLED.h b/FastLED.h
index 221931c9..19df7ace 100644
--- a/FastLED.h
+++ b/FastLED.h
@@ -7,6 +7,7 @@
#include "clockless.h"
#include "block_clockless.h"
#include "clockless2.h"
+#include "clockless_trinket.h"
#include "lib8tion.h"
#include "hsv2rgb.h"
#include "chipsets.h"
@@ -58,27 +59,27 @@ public:
template<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN > CLEDController *addLeds(const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset = 0) {
switch(CHIPSET) {
- case LPD8806: return addLeds(new LPD8806Controller<DATA_PIN, CLOCK_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
- case WS2801: return addLeds(new WS2801Controller<DATA_PIN, CLOCK_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
- case SM16716: return addLeds(new SM16716Controller<DATA_PIN, CLOCK_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
+ case LPD8806: { static LPD8806Controller<DATA_PIN, CLOCK_PIN> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case WS2801: { static WS2801Controller<DATA_PIN, CLOCK_PIN> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case SM16716: { static SM16716Controller<DATA_PIN, CLOCK_PIN> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
}
}
template<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER > CLEDController *addLeds(const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset = 0) {
switch(CHIPSET) {
- case LPD8806: return addLeds(new LPD8806Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case WS2801: return addLeds(new WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case SM16716: return addLeds(new SM16716Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case P9813: return addLeds(new P9813Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
+ case LPD8806: { static LPD8806Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case WS2801: { static WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case SM16716: { static SM16716Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case P9813: { static P9813Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
}
}
template<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER, uint8_t SPI_DATA_RATE > CLEDController *addLeds(const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset = 0) {
switch(CHIPSET) {
- case LPD8806: return addLeds(new LPD8806Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE>(), data, nLedsOrOffset, nLedsIfOffset);
- case WS2801: return addLeds(new WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE>(), data, nLedsOrOffset, nLedsIfOffset);
- case SM16716: return addLeds(new SM16716Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE>(), data, nLedsOrOffset, nLedsIfOffset);
- case P9813: return addLeds(new P9813Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE>(), data, nLedsOrOffset, nLedsIfOffset);
+ case LPD8806: { static LPD8806Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case WS2801: { static WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case SM16716: { static SM16716Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
+ case P9813: { static P9813Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_DATA_RATE> c; return addLeds(&c, data, nLedsOrOffset, nLedsIfOffset); }
}
}
@@ -101,18 +102,18 @@ public:
CLEDController *addLeds(const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset = 0) {
switch(CHIPSET) {
#ifdef FASTSPI_USE_DMX_SIMPLE
- case DMX: return addLeds(new DMXController<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
+ case DMX: { static DMXController<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
#endif
- case TM1829: return addLeds(new TM1829Controller800Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
+ case TM1829: { static TM1829Controller800Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
case TM1804:
- case TM1809: return addLeds(new TM1809Controller800Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
- case TM1803: return addLeds(new TM1803Controller400Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
- case UCS1903: return addLeds(new UCS1903Controller400Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
+ case TM1809: { static TM1809Controller800Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case TM1803: { static TM1803Controller400Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case UCS1903: { static UCS1903Controller400Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
case WS2812:
case WS2812B:
- case WS2811: return addLeds(new WS2811Controller800Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
- case NEOPIXEL: return addLeds(new WS2811Controller800Khz<DATA_PIN, GRB>(), data, nLedsOrOffset, nLedsIfOffset);
- case WS2811_400: return addLeds(new WS2811Controller400Khz<DATA_PIN>(), data, nLedsOrOffset, nLedsIfOffset);
+ case WS2811: { static WS2811Controller800Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case NEOPIXEL: { static WS2811Controller800Khz<DATA_PIN, GRB> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case WS2811_400: { static WS2811Controller400Khz<DATA_PIN> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
}
return NULL;
}
@@ -121,17 +122,18 @@ public:
CLEDController *addLeds(const struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset = 0) {
switch(CHIPSET) {
#ifdef FASTSPI_USE_DMX_SIMPLE
- case DMX: return addLeds(new DMXController<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
+ case DMX: {static DMXController<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
#endif
- case TM1829: return addLeds(new TM1829Controller800Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case TM1809: return addLeds(new TM1809Controller800Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case TM1803: return addLeds(new TM1803Controller400Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
- case UCS1903: return addLeds(new UCS1903Controller400Khz<DATA_PIN, RGB_ORDER>(), data, nLedsOrOffset, nLedsIfOffset);
+ case TM1829: { static TM1829Controller800Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case TM1804:
+ case TM1809: { static TM1809Controller800Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case TM1803: { static TM1803Controller400Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case UCS1903: { static UCS1903Controller400Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
case WS2812:
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);
+ case WS2811: { static WS2811Controller800Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
+ case WS2811_400: { static WS2811Controller400Khz<DATA_PIN, RGB_ORDER> controller; return addLeds(&controller, data, nLedsOrOffset, nLedsIfOffset); }
}
return NULL;
}
diff --git a/README.md b/README.md
index fbe59a69..bc31e9ae 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ How quickly can you get up and running with the library? Here's a simple blink
void setup() { FastLED.addLeds<NEOPIXEL, 6>(leds, NUM_LEDS); }
void loop() {
leds[0] = CRGB::White; FastLED.show(); delay(30);
- leds[0] = CRGB::Black; FastLED.show(); delay30);
+ leds[0] = CRGB::Black; FastLED.show(); delay(30);
}
## Supported LED chipsets
@@ -39,6 +39,9 @@ Here's a list of all the LED chipsets are supported. More details on the led ch
* SM16716 - SPI based chipset
* DMX - send rgb data out over DMX using arduino DMX libraries
+LPD6803, HL1606, and "595"-style shift registers are no longer supported by the library. The older Version 1 of the library ("FastSPI_LED") has support for these, but is missing many of the advanced features of current versions and is no longer being maintained.
+
+
## Supported platforms
Right now the library is supported on a variety of arduino compatable platforms. If it's ARM or AVR and uses the arduino software (or a modified version of it to build) then it is likely supported. Note that we have a long list of upcoming platforms to support, so if you don't see what you're looking for here, ask, it may be on the roadmap (or may already be supported). N.B. at the moment we are only supporting the stock compilers that ship with the arduino software. Support for upgraded compilers, as well as using AVR studio and skipping the arduino entirely, should be coming in a near future release.
@@ -46,9 +49,16 @@ Right now the library is supported on a variety of arduino compatable platforms.
* Arduino & compatibles - straight up arduino devices, uno, duo, leonardo, mega, nano, etc...
* Teensy 2, Teensy++ 2, Teensy 3 - arduino compataible from pjrc.com with some extra goodies (note the teensy 3 is ARM, not AVR!)
-What types of platforms are we thinking about supporting in the future? Here's a short list: MSP430, ChipKit32, Maple, Beagleboard
+What types of platforms are we thinking about supporting in the future? Here's a short list: Arduino Due, MSP430, ChipKit32, Maple, Beagleboard
+
+## What about that name?
+
+Wait, what happend to FastSPI_LED and FastSPI_LED2? The library was initially named FastSPI_LED because it was focused on very fast and efficient SPI access. However, since then, the library has expanded to support a number of LED chipsets that don't use SPI, as well as a number of math and utility functions for LED processing across the board. We decided that the name FastLED more accurately represents the totality of what the library provides, everything fast, for LEDs.
+
+## For more information
+
+Check out the official site http://fastled.io for links to documentation, issues, and news
-*TODO* - provide link to full documentation in readme.
*TODO* - get candy
diff --git a/chipsets.h b/chipsets.h
index 64adc837..00cedf0d 100644
--- a/chipsets.h
+++ b/chipsets.h
@@ -286,10 +286,46 @@ public:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
-// Clockless template instantiations
+// Clockless template instantiations - see clockless.h for how the timing values are used
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if defined(LIB8_ATTINY) && (F_CPU == 8000000)
+// WS2811@8Mhz 2 clocks, 5 clocks, 3 clocks
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class WS2811Controller800Khz : public ClocklessController_Trinket<DATA_PIN, 2, 5, 3, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class WS2811Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 4, 10, 6, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class UCS1903Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 4, 12, 4, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class TM1809Controller800Khz : public ClocklessController<DATA_PIN, 2, 5, 3, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class TM1803Controller400Khz : public ClocklessController<DATA_PIN, 6, 6, 6, RGB_ORDER> {};
+
+#elif defined(LIB8_ATTINY) && (F_CPU == 16000000)
+
+// WS2811@16Mhz 4 clocks, 10 clocks, 6 clocks
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class WS2811Controller800Khz : public ClocklessController_Trinket<DATA_PIN, 4, 10, 6, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class WS2811Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 8, 20, 12, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class UCS1903Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 8, 24, 8, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class TM1809Controller800Khz : public ClocklessController<DATA_PIN, 4, 10, 6, RGB_ORDER> {};
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class TM1803Controller400Khz : public ClocklessController<DATA_PIN, 12, 12, 12, RGB_ORDER> {};
+
+#else
// UCS1903 - 500ns, 1500ns, 500ns
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
class UCS1903Controller400Khz : public ClocklessController<DATA_PIN, NS(500), NS(1500), NS(500), RGB_ORDER> {};
@@ -297,7 +333,7 @@ class UCS1903Controller400Khz : public ClocklessController<DATA_PIN, NS(500), NS
#warning "Not enough clock cycles available for the UCS103"
#endif
-// TM1809 - 312.5ns, 312.5ns, 325ns
+// TM1809 - 350ns, 350ns, 550ns
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(350, 350, 550)
@@ -308,14 +344,14 @@ class TM1809Controller800Khz : public ClocklessController<DATA_PIN, NS(350), NS(
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
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)"
+#warning "Not enough clock cycles available for the WS2811 (800khz)"
#endif
// 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)"
+#warning "Not enough clock cycles available for the WS2811 (400Khz)"
#endif
// 750NS, 750NS, 750NS
@@ -326,28 +362,10 @@ class TM1803Controller400Khz : public ClocklessController<DATA_PIN, NS(750), NS(
#endif
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1829Controller800Khz : public ClocklessController<DATA_PIN, NS(340), NS(340), NS(550), RGB_ORDER, true, 500> {
-public:
- // virtual void show(const struct CRGB *data, int nLeds, uint8_t scale = 255) {
- // ClocklessController<DATA_PIN, NS(340), NS(340), NS(550), RGB_ORDER, false, 500>::show(data, nLeds, scale8(scale, 254));
- // }
-
- // virtual void showColor(const struct CRGB &data, int nLeds, uint8_t scale = 255) {
- // ClocklessController<DATA_PIN, NS(340), NS(340), NS(550), RGB_ORDER, false, 500>::showColor(data, nLeds, scale8(scale, 254));
- // }
-};
+class TM1829Controller800Khz : public ClocklessController<DATA_PIN, NS(340), NS(340), NS(550), RGB_ORDER, true, 500> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1829Controller1600Khz : public ClocklessController<DATA_PIN, NS(100), NS(300), NS(200), RGB_ORDER, true, 500> {
-public:
- virtual void show(const struct CRGB *data, int nLeds, uint8_t scale = 255) {
- ClocklessController<DATA_PIN, NS(100), NS(300), NS(200), RGB_ORDER, true, 500>::show(data, nLeds, scale8(scale, 254));
- }
-
- virtual void showColor(const struct CRGB &data, int nLeds, uint8_t scale = 255) {
- ClocklessController<DATA_PIN, NS(100), NS(300), NS(200), RGB_ORDER, true, 500>::showColor(data, nLeds, scale8(scale, 254));
- }
-};
+class TM1829Controller1600Khz : public ClocklessController<DATA_PIN, NS(100), NS(300), NS(200), RGB_ORDER, true, 500> {};
#if NO_TIME(100, 300, 200)
#warning "Not enough clock cycles available for TM1829@1.6Mhz"
#endif
diff --git a/clockless.h b/clockless.h
index 9bffb9fc..0147fb53 100644
--- a/clockless.h
+++ b/clockless.h
@@ -144,8 +144,12 @@ public:
register uint8_t b;
- b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
- b = INLINE_SCALE(b, scale);
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE0(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
+ }
+ b = scale8_LEAVING_R1_DIRTY(b, scale);
register uint8_t c;
register uint8_t d;
@@ -161,7 +165,12 @@ public:
// Leave an extra 4 clocks for the scale
bitSetLast<6, 6>(port, hi, lo, b);
- c = ADVANCE ? data[SKIP + RGB_BYTE1(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE1(RGB_ORDER)];
+ if(ADVANCE) {
+ c = data[SKIP + RGB_BYTE1(RGB_ORDER)];
+ } else {
+ c = rgbdata[SKIP + RGB_BYTE1(RGB_ORDER)];
+ delaycycles<1>();
+ }
INLINE_SCALE(c, scale);
bitSetLast<5, 1>(port, hi, lo, b);
@@ -176,7 +185,12 @@ public:
// Leave an extra 4 clocks for the scale
bitSetLast<6, 6>(port, hi, lo, c);
- d = ADVANCE ? data[SKIP + RGB_BYTE2(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE2(RGB_ORDER)];
+ if(ADVANCE) {
+ d = data[SKIP + RGB_BYTE2(RGB_ORDER)];
+ } else {
+ d = rgbdata[SKIP + RGB_BYTE2(RGB_ORDER)];
+ delaycycles<1>();
+ }
INLINE_SCALE(d, scale);
bitSetLast<5, 1>(port, hi, lo, c);
@@ -190,7 +204,12 @@ public:
data += (SKIP + 3);
// Leave an extra 4 clocks for the scale
bitSetLast<6, 6>(port, hi, lo, d);
- b = ADVANCE ? data[SKIP + RGB_BYTE0(RGB_ORDER)] :rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
+ if(ADVANCE) {
+ b = data[SKIP + RGB_BYTE0(RGB_ORDER)];
+ } else {
+ b = rgbdata[SKIP + RGB_BYTE0(RGB_ORDER)];
+ delaycycles<1>();
+ }
INLINE_SCALE(b, scale);
bitSetLast<5, 6>(port, hi, lo, d);
}
@@ -534,4 +553,4 @@ public:
#endif
-#endif \ No newline at end of file
+#endif
diff --git a/clockless_trinket.h b/clockless_trinket.h
new file mode 100644
index 00000000..168ba670
--- /dev/null
+++ b/clockless_trinket.h
@@ -0,0 +1,279 @@
+#ifndef __INC_CLOCKLESS_TRINKET_H
+#define __INC_CLOCKLESS_TRINKET_H
+
+#include "controller.h"
+#include "lib8tion.h"
+#include "delay.h"
+#include <avr/interrupt.h> // for cli/se definitions
+
+
+// Scaling macro choice
+#ifndef TRINKET_SCALE
+#define TRINKET_SCALE 1
+#endif
+
+// Variations on the functions in delay.h - w/a loop var passed in to preserve registers across calls by the optimizer/compiler
+template<int CYCLES> inline void _dc(register uint8_t & loopvar);
+
+template<int _LOOP, int PAD> inline void _dc_AVR(register uint8_t & loopvar) {
+ _dc<PAD>(loopvar);
+ asm __volatile__ ( "LDI %[loopvar], %[_LOOP]\n\tL_%=: DEC %[loopvar]\n\t BRNE L_%=\n\t" :
+ [loopvar] "+a" (loopvar) : [_LOOP] "M" (_LOOP) : );
+}
+
+template<int CYCLES> __attribute__((always_inline)) inline void _dc(register uint8_t & loopvar) {
+ _dc_AVR<CYCLES/3,CYCLES%3>(loopvar);
+}
+template<> __attribute__((always_inline)) inline void _dc<0>(register uint8_t & loopvar) {}
+template<> __attribute__((always_inline)) inline void _dc<1>(register uint8_t & loopvar) {asm __volatile__("cp r0,r0":::);}
+template<> __attribute__((always_inline)) inline void _dc<2>(register uint8_t & loopvar) {asm __volatile__("rjmp .+0":::);}
+
+#define D1(ADJ) _dc<T1-(2+ADJ)>(loopvar);
+#define D2(ADJ) _dc<T2-(1+ADJ)>(loopvar);
+#define D3(ADJ) _dc<T3-(1+ADJ)>(loopvar);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Base template for clockless controllers. These controllers have 3 control points in their cycle for each bit. The first point
+// is where the line is raised hi. The second point is where the line is dropped low for a zero. The third point is where the
+// line is dropped low for a one. T1, T2, and T3 correspond to the timings for those three in clock cycles.
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <uint8_t DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int WAIT_TIME = 50>
+class ClocklessController_Trinket : public CLEDController {
+ typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
+ typedef typename FastPin<DATA_PIN>::port_t data_t;
+
+ CMinWait<WAIT_TIME> mWait;
+public:
+ virtual void init() {
+ FastPin<DATA_PIN>::setOutput();
+ }
+
+ virtual void clearLeds(int nLeds) {
+ static byte zeros[3] = {0,0,0};
+ showRGBInternal_AdjTime(0, false, nLeds, 0, zeros);
+ }
+
+ // set all the leds on the controller to a given color
+ virtual void showColor(const struct CRGB & data, int nLeds, uint8_t scale = 255) {
+ showRGBInternal_AdjTime(0, false, nLeds, scale, (const byte*)&data);
+ }
+
+ virtual void show(const struct CRGB *rgbdata, int nLeds, uint8_t scale = 255) {
+ showRGBInternal_AdjTime(0, true, nLeds, scale, (const byte*)rgbdata);
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void show(const struct CARGB *rgbdata, int nLeds, uint8_t scale = 255) {
+ showRGBInternal_AdjTime(1, true, nLeds, scale, (const byte*)rgbdata);
+ }
+#endif
+
+ void __attribute__ ((noinline)) showRGBInternal_AdjTime(int skip, bool advance, int nLeds, uint8_t scale, const byte *rgbdata) {
+ mWait.wait();
+ cli();
+
+ showRGBInternal(skip, advance, nLeds, scale, rgbdata);
+
+
+ // Adjust the timer
+ long microsTaken = CLKS_TO_MICROS((long)nLeds * 24 * (T1 + T2 + T3));
+ MS_COUNTER += (microsTaken / 1000);
+ sei();
+ mWait.mark();
+ }
+
+#define USE_ASM_MACROS
+
+#define ASM_VARS : /* write variables */ \
+ [b0] "+r" (b0), \
+ [b1] "+r" (b1), \
+ [b2] "+r" (b2), \
+ [count] "+x" (count), \
+ [scale_base] "+r" (scale_base), \
+ [data] "+z" (data), \
+ [loopvar] "+a" (loopvar) \
+ : /* use variables */ \
+ [hi] "r" (hi), \
+ [lo] "r" (lo), \
+ [scale] "r" (scale), \
+ [ADV] "r" (advanceBy), \
+ [zero] "r" (zero), \
+ [O0] "M" (RGB_BYTE0(RGB_ORDER)), \
+ [O1] "M" (RGB_BYTE1(RGB_ORDER)), \
+ [O2] "M" (RGB_BYTE2(RGB_ORDER)), \
+ [PORT] "M" (FastPin<DATA_PIN>::port()-0x20) \
+ : /* clobber registers */
+
+
+// 1 cycle, write hi to the port
+#define HI1 asm __volatile__("out %[PORT], %[hi]" ASM_VARS );
+// 1 cycle, write lo to the port
+#define LO1 asm __volatile__("out %[PORT], %[lo]" ASM_VARS );
+// 2 cycles, sbrs on flipping the lne to lo if we're pushing out a 0
+#define QLO2(B, N) asm __volatile__("sbrs %[" #B "], " #N ASM_VARS ); LO1;
+// load a byte from ram into the given var with the given offset
+#define LD2(B,O) asm __volatile__("ldd %[" #B "], Z + %[" #O "]" ASM_VARS );
+// 3 cycles - load a byte from ram into the scaling scratch space with the given offset, clear the target var
+#define LDSCL3(B,O) asm __volatile__("ldd %[scale_base], Z + %[" #O "]\n\tclr %[" #B "]" ASM_VARS );
+// 2 cycles - increment the data pointer
+#define IDATA2 asm __volatile__("add %A[data], %A[ADV]\n\tadc %B[data], %B[ADV]" ASM_VARS );
+// 2 cycles - decrement the counter
+#define DCOUNT2 asm __volatile__("sbiw %[count], 1" ASM_VARS );
+// 2 cycles - jump to the beginning of the loop
+#define JMPLOOP2 asm __volatile__("rjmp 1b" ASM_VARS );
+// 2 cycles - jump out of the loop
+#define BRLOOP1 asm __volatile__("breq 2f" ASM_VARS );
+// 2 cycles - perform one step of the scaling (if a given bit is set in scale, add scale-base to the scratch space)
+#define SCALE2(B, N) asm __volatile__("sbrc %[scale], " #N "\n\tadd %[" #B "], %[scale_base]" ASM_VARS );
+// 1 cycle - rotate right, pulling in from carry
+#define ROR1(B) asm __volatile__("ror %[" #B "]" ASM_VARS );
+// 1 cycle, clear the carry bit
+#define CLC1 asm __volatile__("clc" ASM_VARS );
+// 1 cycle, move one register to another
+#define MOV1(B1, B2) asm __volatile__("mov %[" #B1 "], %[" #B2 "]" ASM_VARS );
+// 4 cycles, rotate, clear carry, scale next bit
+#define RORSC4(B, N) ROR1(B) CLC1 SCALE2(B, N)
+// 4 cycles, scale bit, rotate, clear carry
+#define SCROR4(B, N) SCALE2(B,N) ROR1(B) CLC1
+// define the beginning of the loop
+#define LOOP asm __volatile__("1:" ASM_VARS );
+#define DONE asm __volatile__("2:" ASM_VARS );
+// delay time
+
+
+ // 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 __attribute__ ((noinline)) showRGBInternal(int skip, bool advance, int nLeds, uint8_t scale, const byte *rgbdata) {
+ byte *data = (byte*)rgbdata;
+ data_t mask = FastPin<DATA_PIN>::mask();
+ data_ptr_t port = FastPin<DATA_PIN>::port();
+ // register uint8_t *end = data + nLeds;
+ data_t hi = *port | mask;
+ data_t lo = *port & ~mask;
+ *port = lo;
+
+ uint8_t b0, b1, b2;
+ uint16_t count = nLeds;
+ uint8_t scale_base = 0;
+ uint16_t advanceBy = advance ? (skip+3) : 0;
+ const uint8_t zero = 0;
+ b0 = data[RGB_BYTE0(RGB_ORDER)];
+ b0 = scale8(b0, scale);
+ b1 = data[RGB_BYTE1(RGB_ORDER)];
+ b2 = 0;
+ register uint8_t loopvar;
+
+ if(RGB_ORDER == RGB) {
+ // If the rgb order is RGB, we can cut back on program space usage by making a much more compact
+ // representation.
+
+ // multiply count by 3, don't use * because there's no hardware multiply
+ count = count+(count<<1);
+ advanceBy = advance ? 1 : 0;
+ {
+ /* asm */
+ LOOP
+ // Sum of the clock counts across each row should be 10 for 8Mhz, WS2811
+#if TRINKET_SCALE
+ // Inline scaling, RGB ordering matches byte ordering
+ HI1 D1(0) QLO2(b0, 7) LDSCL3(b1,O1) D2(3) LO1 SCALE2(b1,0) D3(2)
+ HI1 D1(0) QLO2(b0, 6) RORSC4(b1,1) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 5) SCROR4(b1,2) D2(4) LO1 SCALE2(b1,3) D3(2)
+ HI1 D1(0) QLO2(b0, 4) RORSC4(b1,4) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 3) SCROR4(b1,5) D2(4) LO1 SCALE2(b1,6) D3(2)
+ HI1 D1(0) QLO2(b0, 2) RORSC4(b1,7) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 1) IDATA2 D2(2) LO1 D3(0)
+ // In the last bit's first block, we decrement and branch to done if we decremented to 0
+ HI1 D1(0) QLO2(b0, 0) DCOUNT2 BRLOOP1 MOV1(b0, b1) D2(4) LO1 D3(2) JMPLOOP2
+#else
+ // no inline scaling, RGB ordering matches byte ordering
+ HI1 D1(0) QLO2(b0, 7) LD2(b1,O1) D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 6) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 5) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 4) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 3) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 2) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 1) IDATA2 D2(2) LO1 D3(0)
+ // In the last bit's first block, we decrement and branch to done if we decremented to 0
+ HI1 D1(0) QLO2(b2, 0) DCOUNT2 BRLOOP1 MOV1(b0,b1) D2(4) LO1 D3(2) JMPLOOP2
+#endif
+ DONE
+ D2(4) LO1 D3(0)
+ }
+ }
+ else
+ {
+ {
+ /* asm */
+ LOOP
+ // Sum of the clock counts across each row should be 10 for 8Mhz, WS2811
+#if TRINKET_SCALE
+ // Inline scaling - RGB ordering
+ HI1 D1(0) QLO2(b0, 7) LDSCL3(b1,O1) D2(3) LO1 SCALE2(b1,0) D3(2)
+ HI1 D1(0) QLO2(b0, 6) RORSC4(b1,1) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 5) SCROR4(b1,2) D2(4) LO1 SCALE2(b1,3) D3(2)
+ HI1 D1(0) QLO2(b0, 4) RORSC4(b1,4) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 3) SCROR4(b1,5) D2(4) LO1 SCALE2(b1,6) D3(2)
+ HI1 D1(0) QLO2(b0, 2) RORSC4(b1,7) D2(4) LO1 ROR1(b1) CLC1 D3(2)
+ HI1 D1(0) QLO2(b0, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 0) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 7) LDSCL3(b2,O2) D2(3) LO1 SCALE2(b2,0) D3(2)
+ HI1 D1(0) QLO2(b1, 6) RORSC4(b2,1) D2(4) LO1 ROR1(b2) CLC1 D3(2)
+ HI1 D1(0) QLO2(b1, 5) SCROR4(b2,2) D2(4) LO1 SCALE2(b2,3) D3(2)
+ HI1 D1(0) QLO2(b1, 4) RORSC4(b2,4) D2(4) LO1 ROR1(b2) CLC1 D3(2)
+ HI1 D1(0) QLO2(b1, 3) SCROR4(b2,5) D2(4) LO1 SCALE2(b2,6) D3(2)
+ HI1 D1(0) QLO2(b1, 2) RORSC4(b2,7) D2(4) LO1 ROR1(b2) CLC1 D3(2)
+ HI1 D1(0) QLO2(b1, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 0) IDATA2 D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 7) LDSCL3(b0,O0) D2(3) LO1 SCALE2(b0,0) D3(2)
+ HI1 D1(0) QLO2(b2, 6) RORSC4(b0,1) D2(4) LO1 ROR1(b0) CLC1 D3(2)
+ HI1 D1(0) QLO2(b2, 5) SCROR4(b0,2) D2(4) LO1 SCALE2(b0,3) D3(2)
+ HI1 D1(0) QLO2(b2, 4) RORSC4(b0,4) D2(4) LO1 ROR1(b0) CLC1 D3(2)
+ HI1 D1(0) QLO2(b2, 3) SCROR4(b0,5) D2(4) LO1 SCALE2(b0,6) D3(2)
+ HI1 D1(0) QLO2(b2, 2) RORSC4(b0,7) D2(4) LO1 ROR1(b0) CLC1 D3(2)
+ HI1 D1(0) QLO2(b2, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 0) DCOUNT2 BRLOOP1 D2(3) LO1 D3(2) JMPLOOP2
+#else
+ // no inline scaling - non-straight RGB ordering
+ HI1 D1(0) QLO2(b0, 7) LD2(b1,O1) D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 6) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 5) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 4) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 3) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 2) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b0, 0) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 7) LD2(b2,O2) D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 6) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 5) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 4) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 3) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 2) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b1, 0) IDATA2 D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 7) LD2(b0,O0) D2(2) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 6) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 5) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 4) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 3) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 2) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 1) D2(0) LO1 D3(0)
+ HI1 D1(0) QLO2(b2, 0) DCOUNT2 BRLOOP1 D2(3) LO1 D3(2) JMPLOOP2
+#endif
+ DONE
+ D2(4) LO1 D3(0)
+ }
+ }
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void showARGB(struct CARGB *data, int nLeds) {
+ // TODO: IMPLEMENTME
+ }
+#endif
+};
+
+#endif
diff --git a/controller.h b/controller.h
index dd07130a..e745459d 100644
--- a/controller.h
+++ b/controller.h
@@ -21,7 +21,8 @@
/// Base definition for an LED controller. Pretty much the methods that every LED controller object will make available.
/// Note that the showARGB method is not impelemented for all controllers yet. Note also the methods for eventual checking
/// of background writing of data (I'm looking at you, teensy 3.0 DMA controller!). If you want to pass LED controllers around
-/// to methods, make them references to this type, keeps your code saner.
+/// to methods, make them references to this type, keeps your code saner. However, most people won't be seeing/using these objects
+/// directly at all
class CLEDController {
public:
// initialize the LED controller
diff --git a/delay.h b/delay.h
index 3797e487..1f5ffa77 100644
--- a/delay.h
+++ b/delay.h
@@ -9,8 +9,10 @@
#if defined(__arm__)
# define NOP __asm__ __volatile__ ("nop\n");
+# define NOP2 __asm__ __volatile__ ("nop\n\tnop");
#else
# define NOP __asm__ __volatile__ ("cp r0,r0\n");
+# define NOP2 __asm__ __volatile__ ("rjmp .+0");
#endif
// predeclaration to not upset the compiler
@@ -72,10 +74,38 @@ template<> __attribute__((always_inline)) inline void delaycycles<-2>() {}
template<> __attribute__((always_inline)) inline void delaycycles<-1>() {}
template<> __attribute__((always_inline)) inline void delaycycles<0>() {}
template<> __attribute__((always_inline)) inline void delaycycles<1>() {NOP;}
-template<> __attribute__((always_inline)) inline void delaycycles<2>() {NOP;NOP;}
-template<> __attribute__((always_inline)) inline void delaycycles<3>() {NOP;NOP;NOP;}
-template<> __attribute__((always_inline)) inline void delaycycles<4>() {NOP;NOP;NOP;NOP;}
-template<> __attribute__((always_inline)) inline void delaycycles<5>() {NOP;NOP;NOP;NOP;NOP;}
+template<> __attribute__((always_inline)) inline void delaycycles<2>() {NOP2;}
+template<> __attribute__((always_inline)) inline void delaycycles<3>() {NOP;NOP2;}
+template<> __attribute__((always_inline)) inline void delaycycles<4>() {NOP2;NOP2;}
+template<> __attribute__((always_inline)) inline void delaycycles<5>() {NOP2;NOP2;NOP;}
+
+// Some timing related macros/definitions
+
+// Macro to convert from nano-seconds to clocks and clocks to nano-seconds
+// #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) ((long)(_CLKS)) / (F_CPU / 1000000L)
+#else
+#define NS(_NS) ( (_NS * (F_CPU / 2000000L))) / 1000
+#define CLKS_TO_MICROS(_CLKS) ((long)(_CLKS)) / (F_CPU / 2000000L)
+#endif
+
+// Macro for making sure there's enough time available
+#define NO_TIME(A, B, C) (NS(A) < 3 || NS(B) < 3 || NS(C) < 6)
+
+#if defined(__MK20DX128__)
+ extern volatile uint32_t systick_millis_count;
+# define MS_COUNTER systick_millis_count
+#else
+# 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
#ifdef __SAM3X8E__
class SysClockSaver {
diff --git a/dmx.h b/dmx.h
index a7c1c1f0..03329d0e 100644
--- a/dmx.h
+++ b/dmx.h
@@ -57,7 +57,7 @@ public:
};
-#elif defined(DmxSerial_h)
+#elif defined(FASTSPI_USE_DMX_SERIAL)
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB> class DMXController : public CLEDController {
public:
diff --git a/examples/Blink/Blink.ino b/examples/Blink/Blink.ino
index 6e5c6173..bc5c84d2 100644
--- a/examples/Blink/Blink.ino
+++ b/examples/Blink/Blink.ino
@@ -6,7 +6,7 @@
// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
-#define DATA_PIN 11
+#define DATA_PIN 3
#define CLOCK_PIN 13
// Define the array of leds
@@ -20,7 +20,7 @@ void setup() {
// FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
- FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
+ FastLED.addLeds<NEOPIXEL, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<UCS1903, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);
diff --git a/examples/Cylon/Cylon.ino b/examples/Cylon/Cylon.ino
index 96b6ac59..bec878c5 100644
--- a/examples/Cylon/Cylon.ino
+++ b/examples/Cylon/Cylon.ino
@@ -5,7 +5,7 @@
// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
-// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
+// ground, and power), like the LPD8806, define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 11
#define CLOCK_PIN 13
diff --git a/examples/FirstLight/FirstLight.ino b/examples/FirstLight/FirstLight.ino
index 8f82c370..dff123b9 100644
--- a/examples/FirstLight/FirstLight.ino
+++ b/examples/FirstLight/FirstLight.ino
@@ -1,6 +1,7 @@
// Use if you want to force the software SPI subsystem to be used for some reason (generally, you don't)
// #define FORCE_SOFTWARE_SPI
// Use if you want to force non-accelerated pin access (hint: you really don't, it breaks lots of things)
+// #define FORCE_SOFTWARE_SPI
// #define FORCE_SOFTWARE_PINS
#include "FastLED.h"
@@ -31,16 +32,16 @@ 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, GRB>(leds, NUM_LEDS);
+ // FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
- // FastLED.addLeds<WS2812B, 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);
diff --git a/examples/testleds/testleds.pde b/examples/testleds/testleds.pde
deleted file mode 100644
index 7a0e088b..00000000
--- a/examples/testleds/testleds.pde
+++ /dev/null
@@ -1,95 +0,0 @@
-#include <FastSPI_LED.h>
-
-#define NUM_LEDS 150
-
-// Sometimes chipsets wire in a backwards sort of way
-struct CRGB { unsigned char b; unsigned char r; unsigned char g; };
-// struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
-struct CRGB *leds;
-
-#define PIN 4
-
-void setup()
-{
- FastSPI_LED.setLeds(NUM_LEDS);
- FastSPI_LED.setChipset(CFastSPI_LED::SPI_SM16716);
- //FastSPI_LED.setChipset(CFastSPI_LED::SPI_TM1809);
- //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
- //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
- //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
- //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
-
- FastSPI_LED.setPin(PIN);
-
- FastSPI_LED.init();
- FastSPI_LED.start();
-
- leds = (struct CRGB*)FastSPI_LED.getRGBData();
-}
-
-void loop() {
- // one at a time
- for(int j = 0; j < 3; j++) {
- for(int i = 0 ; i < NUM_LEDS; i++ ) {
- memset(leds, 0, NUM_LEDS * 3);
- switch(j) {
- case 0: leds[i].r = 255; break;
- case 1: leds[i].g = 255; break;
- case 2: leds[i].b = 255; break;
- }
- FastSPI_LED.show();
- delay(10);
- }
- }
-
- // growing/receeding bars
- for(int j = 0; j < 3; j++) {
- memset(leds, 0, NUM_LEDS * 3);
- for(int i = 0 ; i < NUM_LEDS; i++ ) {
- switch(j) {
- case 0: leds[i].r = 255; break;
- case 1: leds[i].g = 255; break;
- case 2: leds[i].b = 255; break;
- }
- FastSPI_LED.show();
- delay(10);
- }
- for(int i = NUM_LEDS-1 ; i >= 0; i-- ) {
- switch(j) {
- case 0: leds[i].r = 0; break;
- case 1: leds[i].g = 0; break;
- case 2: leds[i].b = 0; break;
- }
- FastSPI_LED.show();
- delay(1);
- }
- }
-
- // Fade in/fade out
- for(int j = 0; j < 3; j++ ) {
- memset(leds, 0, NUM_LEDS * 3);
- for(int k = 0; k < 256; k++) {
- for(int i = 0; i < NUM_LEDS; i++ ) {
- switch(j) {
- case 0: leds[i].r = k; break;
- case 1: leds[i].g = k; break;
- case 2: leds[i].b = k; break;
- }
- }
- FastSPI_LED.show();
- delay(3);
- }
- for(int k = 255; k >= 0; k--) {
- for(int i = 0; i < NUM_LEDS; i++ ) {
- switch(j) {
- case 0: leds[i].r = k; break;
- case 1: leds[i].g = k; break;
- case 2: leds[i].b = k; break;
- }
- }
- FastSPI_LED.show();
- delay(3);
- }
- }
-}
-
diff --git a/lib8tion.cpp b/lib8tion.cpp
index 224d44f2..d7d6b13e 100644
--- a/lib8tion.cpp
+++ b/lib8tion.cpp
@@ -82,11 +82,11 @@ void * memcpy8 ( void * dst, void* src, uint16_t num )
//__attribute__ ((noinline))
void * memmove8 ( void * dst, void* src, uint16_t num )
{
- if( src < dst) {
- // if src < dst then we can use the forward-stepping memcpy8
+ if( src > dst) {
+ // if src > dst then we can use the forward-stepping memcpy8
return memcpy8( dst, src, num);
} else {
- // if src > dst then we have to step backward:
+ // if src < dst then we have to step backward:
dst = (char*)dst + num;
src = (char*)src + num;
asm volatile(