diff options
Diffstat (limited to 'chipsets.h')
-rw-r--r-- | chipsets.h | 371 |
1 files changed, 275 insertions, 96 deletions
@@ -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 |