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:
Diffstat (limited to 'chipsets.h')
-rw-r--r--chipsets.h371
1 files changed, 275 insertions, 96 deletions
diff --git a/chipsets.h b/chipsets.h
index 7c8d4e1d..5e15baa6 100644
--- a/chipsets.h
+++ b/chipsets.h
@@ -2,6 +2,7 @@
#define __INC_CHIPSETS_H
#include "pixeltypes.h"
+#include "clockless.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
@@ -9,17 +10,16 @@
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(24) >
+template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(12) >
class LPD8806Controller : public CLEDController {
typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
class LPD8806_ADJUST {
public:
// LPD8806 spec wants the high bit of every rgb data byte sent out to be set.
- __attribute__((always_inline)) inline static uint8_t adjust(register uint8_t data) { return (data>>1) | 0x80; }
- __attribute__((always_inline)) inline static uint8_t adjust(register uint8_t data, register uint8_t scale) { return (scale8(data, scale)>>1) | 0x80; }
- __attribute__((always_inline)) inline static void postBlock(int len) {
- SPI::writeBytesValueRaw(0, ((len+63)>>6));
+ __attribute__((always_inline)) inline static uint8_t adjust(register uint8_t data) { return ((data>>1) | 0x80) + ((data && (data<254)) & 0x01); }
+ __attribute__((always_inline)) inline static void postBlock(int len) {
+ SPI::writeBytesValueRaw(0, ((len*3+63)>>6));
}
};
@@ -27,15 +27,15 @@ class LPD8806Controller : public CLEDController {
SPI mSPI;
int mClearedLeds;
- void checkClear(int nLeds) {
- if(nLeds > mClearedLeds) {
+ void checkClear(int nLeds) {
+ if(nLeds > mClearedLeds) {
clearLine(nLeds);
mClearedLeds = nLeds;
}
}
-
- void clearLine(int nLeds) {
- int n = ((nLeds + 63) >> 6);
+
+ void clearLine(int nLeds) {
+ int n = ((nLeds*3 + 63) >> 6);
mSPI.writeBytesValue(0, n);
}
public:
@@ -45,39 +45,28 @@ public:
mClearedLeds = 0;
}
- virtual void clearLeds(int nLeds) {
+ virtual void clearLeds(int nLeds) {
mSPI.select();
- mSPI.writeBytesValueRaw(0x80, nLeds * 3);
+ mSPI.writeBytesValueRaw(0x80, nLeds * 3);
mSPI.writeBytesValueRaw(0, ((nLeds*3+63)>>6));
mSPI.release();
}
- virtual void showColor(const struct CRGB & data, int nLeds, uint8_t scale = 255) {
- mSPI.select();
- uint8_t a = 0x80 | (scale8(data[RGB_BYTE0(RGB_ORDER)], scale) >> 1);
- uint8_t b = 0x80 | (scale8(data[RGB_BYTE1(RGB_ORDER)], scale) >> 1);
- uint8_t c = 0x80 | (scale8(data[RGB_BYTE2(RGB_ORDER)], scale) >> 1);
- int iLeds = 0;
-
- while(iLeds++ < nLeds) {
- mSPI.writeByte(a);
- mSPI.writeByte(b);
- mSPI.writeByte(c);
- }
+protected:
- // latch in the world
- mSPI.writeBytesValueRaw(0, ((nLeds*3+63)>>6));
- mSPI.release();
+ virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
+ mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
}
- virtual void show(const struct CRGB *data, int nLeds, uint8_t scale = 255) {
- mSPI.template writeBytes3<LPD8806_ADJUST, RGB_ORDER>((byte*)data, nLeds * 3, scale);
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
+ // TODO rgb-ize scale
+ mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
}
#ifdef SUPPORT_ARGB
virtual void show(const struct CARGB *data, int nLeds, uint8_t scale) {
checkClear(nLeds);
- mSPI.template writeBytes3<1, LPD8806_ADJUST, RGB_ORDER>((byte*)data, nLeds * 4, scale);
+ mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
}
#endif
};
@@ -97,49 +86,209 @@ class WS2801Controller : public CLEDController {
public:
WS2801Controller() {}
- virtual void init() {
+ virtual void init() {
mSPI.init();
mWaitDelay.mark();
}
- virtual void clearLeds(int nLeds) {
+ virtual void clearLeds(int nLeds) {
mWaitDelay.wait();
mSPI.writeBytesValue(0, nLeds*3);
mWaitDelay.mark();
}
-
- virtual void showColor(const struct CRGB & data, int nLeds, uint8_t scale = 255) {
+
+protected:
+
+ virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
mWaitDelay.wait();
- mSPI.select();
- uint8_t a = scale8(data[RGB_BYTE0(RGB_ORDER)], scale);
- uint8_t b = scale8(data[RGB_BYTE1(RGB_ORDER)], scale);
- uint8_t c = scale8(data[RGB_BYTE2(RGB_ORDER)], scale);
-
- while(nLeds--) {
- mSPI.writeByte(a);
- mSPI.writeByte(b);
- mSPI.writeByte(c);
- }
- mSPI.waitFully();
- mSPI.release();
+ mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
mWaitDelay.mark();
}
- virtual void show(const struct CRGB *data, int nLeds, uint8_t scale) {
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
mWaitDelay.wait();
- mSPI.template writeBytes3<0, RGB_ORDER>((byte*)data, nLeds * 3, scale);
+ mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
mWaitDelay.mark();
}
#ifdef SUPPORT_ARGB
- virtual void show(const struct CRGB *data, int nLeds, uint8_t scale) {
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
mWaitDelay.wait();
- mSPI.template writeBytes3<1, RGB_ORDER>((byte*)data, nLeds * 4, scale);
+ mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
mWaitDelay.mark();
}
#endif
};
+template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(25)>
+class WS2803Controller : public WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_SPEED> {};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// APA102 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = BGR, uint8_t SPI_SPEED = DATA_RATE_MHZ(12)>
+class APA102Controller : public CLEDController {
+ typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
+ SPI mSPI;
+
+ void startBoundary() { mSPI.writeWord(0); mSPI.writeWord(0); }
+ void endBoundary() { /*mSPI.writeWord(0xFFFF); mSPI.writeWord(0xFFFF); */}
+
+ inline void writeLed(uint8_t b0, uint8_t b1, uint8_t b2) __attribute__((always_inline)) {
+ mSPI.writeByte(0xFF); mSPI.writeByte(b0); mSPI.writeByte(b1); mSPI.writeByte(b2);
+ }
+
+public:
+ APA102Controller() {}
+
+ virtual void init() {
+ mSPI.init();
+ }
+
+ virtual void clearLeds(int nLeds) {
+ showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
+ }
+
+protected:
+
+ virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());
+
+ mSPI.select();
+
+ startBoundary();
+ while(nLeds--) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.stepDithering();
+ }
+ endBoundary();
+
+ mSPI.waitFully();
+ mSPI.release();
+ }
+
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());
+
+ mSPI.select();
+
+ startBoundary();
+ for(int i = 0; i < nLeds; i++) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.advanceData();
+ pixels.stepDithering();
+ }
+ endBoundary();
+
+ mSPI.release();
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds,, scale, getDither());
+
+ mSPI.select();
+
+ startBoundary();
+ for(int i = 0; i < nLeds; i++) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.advanceData();
+ pixels.stepDithering();
+ }
+ endBoundary();
+
+ mSPI.release();
+ }
+#endif
+};
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// P9813 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(10)>
+class P9813Controller : public CLEDController {
+ typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
+ SPI mSPI;
+
+ void writeBoundary() { mSPI.writeWord(0); mSPI.writeWord(0); }
+
+ inline void writeLed(uint8_t r, uint8_t g, uint8_t b) __attribute__((always_inline)) {
+ register uint8_t top = 0xC0 | ((~b & 0xC0) >> 2) | ((~g & 0xC0) >> 4) | ((~r & 0xC0) >> 6);
+ mSPI.writeByte(top); mSPI.writeByte(b); mSPI.writeByte(g); mSPI.writeByte(r);
+ }
+
+public:
+ P9813Controller() {}
+
+ virtual void init() {
+ mSPI.init();
+ }
+
+ virtual void clearLeds(int nLeds) {
+ showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
+ }
+
+protected:
+
+ virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());
+
+ mSPI.select();
+
+ writeBoundary();
+ while(nLeds--) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.stepDithering();
+ }
+ writeBoundary();
+
+ mSPI.waitFully();
+ mSPI.release();
+ }
+
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());
+
+ mSPI.select();
+
+ writeBoundary();
+ for(int i = 0; i < nLeds; i++) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.advanceData();
+ pixels.stepDithering();
+ }
+ writeBoundary();
+
+ mSPI.release();
+ }
+
+#ifdef SUPPORT_ARGB
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
+ PixelController<RGB_ORDER> pixels(data, nLeds,, scale, getDither());
+
+ mSPI.select();
+
+ writeBoundary();
+ for(int i = 0; i < nLeds; i++) {
+ writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
+ pixels.advanceData();
+ pixels.stepDithering();
+ }
+ writeBoundary();
+
+ mSPI.release();
+ }
+#endif
+};
+
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SM16716 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
@@ -151,7 +300,7 @@ class SM16716Controller : public CLEDController {
typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
SPI mSPI;
- void writeHeader() {
+ void writeHeader() {
// Write out 50 zeros to the spi line (6 blocks of 8 followed by two single bit writes)
mSPI.select();
mSPI.writeBytesValueRaw(0, 6);
@@ -164,13 +313,13 @@ class SM16716Controller : public CLEDController {
public:
SM16716Controller() {}
- virtual void init() {
+ virtual void init() {
mSPI.init();
}
- virtual void clearLeds(int nLeds) {
+ virtual void clearLeds(int nLeds) {
mSPI.select();
- while(nLeds--) {
+ while(nLeds--) {
mSPI.template writeBit<0>(1);
mSPI.writeByte(0);
mSPI.writeByte(0);
@@ -181,39 +330,30 @@ public:
writeHeader();
}
- virtual void showColor(const struct CRGB & data, int nLeds, uint8_t scale = 255) {
- mSPI.select();
- uint8_t a = scale8(data[RGB_BYTE0(RGB_ORDER)], scale);
- uint8_t b = scale8(data[RGB_BYTE1(RGB_ORDER)], scale);
- uint8_t c = scale8(data[RGB_BYTE2(RGB_ORDER)], scale);
+protected:
- while(nLeds--) {
- mSPI.template writeBit<0>(1);
- mSPI.writeByte(a);
- mSPI.writeByte(b);
- mSPI.writeByte(c);
- }
+ virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
+ mSPI.template writePixels<FLAG_START_BIT, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
writeHeader();
- mSPI.release();
}
- virtual void show(const struct CRGB *data, int nLeds, uint8_t scale = 255) {
+ virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
// Make sure the FLAG_START_BIT flag is set to ensure that an extra 1 bit is sent at the start
// of each triplet of bytes for rgb data
// writeHeader();
- mSPI.template writeBytes3<FLAG_START_BIT, RGB_ORDER>((byte*)data, nLeds * 3, scale);
+ mSPI.template writePixels<FLAG_START_BIT, DATA_NOP, RGB_ORDER>( PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
writeHeader();
}
#ifdef SUPPORT_ARGB
- virtual void show(const struct CARGB *data, int nLeds, uint8_t scale = 255) {
+ virtual void show(const struct CARGB *data, int nLeds, CRGB scale) {
mSPI.writeBytesValue(0, 6);
mSPI.template writeBit<0>(0);
mSPI.template writeBit<0>(0);
// Make sure the FLAG_START_BIT flag is set to ensure that an extra 1 bit is sent at the start
// of each triplet of bytes for rgb data
- mSPI.template writeBytes3<1 | FLAG_START_BIT, RGB_ORDER>((byte*)data, nLeds * 4, scale);
+ mSPI.template writePixels<FLAG_START_BIT, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
}
#endif
};
@@ -224,76 +364,115 @@ public:
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#if defined(LIB8_ATTINY) && (F_CPU == 8000000)
-// WS2811@8Mhz 2 clocks, 5 clocks, 3 clocks
+// We want to force all avr's to use the Trinket controller when running at 8Mhz, because even the 328's at 8Mhz
+// need the more tightly defined timeframes.
+#if (F_CPU == 8000000 || F_CPU == 16000000 || F_CPU == 24000000) // || F_CPU == 48000000 || F_CPU == 96000000) // 125ns/clock
+#define FMUL (F_CPU/8000000)
+// LPD1886
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class WS2811Controller800Khz : public ClocklessController_Trinket<DATA_PIN, 2, 5, 3, RGB_ORDER> {};
+class LPD1886Controller1250Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 3 * FMUL, 2 * FMUL, RGB_ORDER, 4> {};
+// WS2811@800khz 2 clocks, 5 clocks, 3 clocks
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class WS2811Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 4, 10, 6, RGB_ORDER> {};
+class WS2811Controller800Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 5 * FMUL, 3 * FMUL, RGB_ORDER> {};
+//class WS2811Controller800Khz : public ClocklessController<DATA_PIN, 3 * FMUL, 4 * FMUL, 3 * FMUL, RGB_ORDER> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class UCS1903Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 4, 12, 4, RGB_ORDER> {};
+class WS2811Controller400Khz : public ClocklessController<DATA_PIN, 4 * FMUL, 10 * FMUL, 6 * FMUL, RGB_ORDER> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1809Controller800Khz : public ClocklessController<DATA_PIN, 2, 5, 3, RGB_ORDER> {};
+class UCS1903Controller400Khz : public ClocklessController<DATA_PIN, 4 * FMUL, 12 * FMUL, 4 * FMUL, 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)
+class UCS1903BController800Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 4 * FMUL, 4 * FMUL, RGB_ORDER> {};
-// 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> {};
+class TM1809Controller800Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 5 * FMUL, 3 * FMUL, RGB_ORDER> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class WS2811Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 8, 20, 12, RGB_ORDER> {};
+class TM1803Controller400Khz : public ClocklessController<DATA_PIN, 6 * FMUL, 9 * FMUL, 6 * FMUL, RGB_ORDER> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class UCS1903Controller400Khz : public ClocklessController_Trinket<DATA_PIN, 8, 24, 8, RGB_ORDER> {};
+class TM1829Controller800Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 5 * FMUL, 3 * FMUL, RGB_ORDER> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1809Controller800Khz : public ClocklessController<DATA_PIN, 4, 10, 6, RGB_ORDER> {};
+class GW6205Controller400Khz : public ClocklessController<DATA_PIN, 6 * FMUL, 7 * FMUL, 6 * FMUL, RGB_ORDER, 4> {};
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1803Controller400Khz : public ClocklessController<DATA_PIN, 12, 12, 12, RGB_ORDER> {};
+class GW6205Controller800Khz : public ClocklessController<DATA_PIN, 2 * FMUL, 4 * FMUL, 4 * FMUL, RGB_ORDER, 4> {};
#else
+// GW6205@400khz - 800ns, 800ns, 800ns
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class GW6205Controller400Khz : public ClocklessController<DATA_PIN, NS(800), NS(800), NS(800), RGB_ORDER, 4> {};
+#if NO_TIME(800, 800, 800)
+#warning "Not enough clock cycles available for the GW6205@400khz"
+#endif
+
+// GW6205@400khz - 400ns, 400ns, 400ns
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class GW6205Controller800Khz : public ClocklessController<DATA_PIN, NS(400), NS(400), NS(400), RGB_ORDER, 4> {};
+#if NO_TIME(400, 400, 400)
+#warning "Not enough clock cycles available for the GW6205@400khz"
+#endif
+
// 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> {};
-#if NO_TIME(500, 1500, 500)
-#warning "Not enough clock cycles available for the UCS103"
+#if NO_TIME(500, 1500, 500)
+#warning "Not enough clock cycles available for the UCS103@400khz"
+#endif
+
+// UCS1903B - 400ns, 450ns, 450ns
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class UCS1903BController800Khz : public ClocklessController<DATA_PIN, NS(400), NS(450), NS(450), RGB_ORDER> {};
+#if NO_TIME(400, 450, 450)
+#warning "Not enough clock cycles available for the UCS103B@800khz"
#endif
// 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)
+#if NO_TIME(350, 350, 550)
#warning "Not enough clock cycles available for the TM1809"
#endif
-// WS2811 - 400ns, 400ns, 450ns
+// WS2811 - 320ns, 320ns, 640ns
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)
+class WS2811Controller800Khz : public ClocklessController<DATA_PIN, NS(320), NS(320), NS(640), RGB_ORDER> {};
+#if NO_TIME(320, 320, 640)
#warning "Not enough clock cycles available for the WS2811 (800khz)"
#endif
-// WS2811@400khz - 800ns, 800ns, 900ns
+// 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)
+#if NO_TIME(800, 800, 900)
#warning "Not enough clock cycles available for the WS2811 (400Khz)"
#endif
// 750NS, 750NS, 750NS
template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
-class TM1803Controller400Khz : public ClocklessController<DATA_PIN, NS(750), NS(750), NS(750), RGB_ORDER> {};
-#if NO_TIME(750, 750, 750)
-#warning "Not enough clock cycles available for the UCS103"
+class TM1803Controller400Khz : public ClocklessController<DATA_PIN, NS(700), NS(1100), NS(700), RGB_ORDER> {};
+#if NO_TIME(750, 750, 750)
+#warning "Not enough clock cycles available for the TM1803"
+#endif
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class TM1829Controller800Khz : public ClocklessController<DATA_PIN, NS(340), NS(340), NS(550), RGB_ORDER, 0, 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, 0, true, 500> {};
+#if NO_TIME(100, 300, 200)
+#warning "Not enough clock cycles available for TM1829@1.6Mhz"
#endif
+
+template <uint8_t DATA_PIN, EOrder RGB_ORDER = RGB>
+class LPD1886Controller1250Khz : public ClocklessController<DATA_PIN, NS(200), NS(400), NS(200), RGB_ORDER, 4> {};
+#if NO_TIME(200,400,200)
+#warning "Not enough clock cycles for LPD1886"
+#endif
+
#endif
#endif