diff --git a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp
new file mode 100644
index 000000000..637fef0c5
--- /dev/null
+++ b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.cpp
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+NeoPixel library helper functions for Esp8266 and Esp32
+
+Written by Michael C. Miller.
+
+I invest time and resources providing this open source code,
+please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
+
+-------------------------------------------------------------------------
+This file is part of the Makuna/NeoPixelBus library.
+
+NeoPixelBus is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of
+the License, or (at your option) any later version.
+
+NeoPixelBus is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with NeoPixel. If not, see
+.
+-------------------------------------------------------------------------*/
+
+#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
+
+#include
+#include "NeoEspBitBangMethod.h"
+
+static inline uint32_t getCycleCount(void)
+{
+ uint32_t ccount;
+ __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
+ return ccount;
+}
+
+void ICACHE_RAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period, uint8_t IdleLevel)
+{
+ const uint32_t pinRegister = _BV(pin);
+ uint8_t mask = 0x80;
+ uint8_t subpix = *pixels++;
+ uint32_t cyclesStart = 0; // trigger emediately
+ uint32_t cyclesNext = 0;
+
+ for (;;)
+ {
+ // do the checks here while we are waiting on time to pass
+ uint32_t cyclesBit = t0h;
+ if (subpix & mask)
+ {
+ cyclesBit = t1h;
+ }
+
+ // after we have done as much work as needed for this next bit
+ // now wait for the HIGH
+ while (((cyclesStart = getCycleCount()) - cyclesNext) < period);
+
+ // set pin state
+ if (IdleLevel == LOW) {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+ } else {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+ }
+ // T_PINSET::setPin(pinRegister);
+
+ // wait for the LOW
+ while ((getCycleCount() - cyclesStart) < cyclesBit);
+
+ // reset pin start
+ if (IdleLevel == LOW) {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+ } else {
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+ }
+ // T_PINSET::resetPin(pinRegister);
+
+ cyclesNext = cyclesStart;
+
+ // next bit
+ mask >>= 1;
+ if (mask == 0)
+ {
+ // no more bits to send in this byte
+ // check for another byte
+ if (pixels >= end)
+ {
+ // no more bytes to send so stop
+ break;
+ }
+ // reset mask to first bit and get the next byte
+ mask = 0x80;
+ subpix = *pixels++;
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
index b0b9753b2..abbb4a685 100644
--- a/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
+++ b/lib/lib_basic/NeoPixelBus-2.6.1.4/src/internal/NeoEspBitBangMethod.h
@@ -55,6 +55,14 @@ public:
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
};
+class NeoEspSpeedTm1829
+{
+public:
+ const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
+ const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
+ const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
+};
+
class NeoEspSpeed800Mhz
{
public:
@@ -83,109 +91,22 @@ class NeoEspPinset
{
public:
const static uint8_t IdleLevel = LOW;
-
- inline static void setPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1ts = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
-#endif
- }
-
- inline static void resetPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1tc = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
-#endif
- }
};
class NeoEspPinsetInverted
{
public:
const static uint8_t IdleLevel = HIGH;
-
- inline static void setPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1tc = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
-#endif
- }
-
- inline static void resetPin(const uint32_t pinRegister)
- {
-#if defined(ARDUINO_ARCH_ESP32)
- GPIO.out_w1ts = pinRegister;
-#else
- GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
-#endif
- }
};
+extern void NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period, uint8_t IdleLevel);
+
template class NeoEspBitBangBase
{
public:
- __attribute__((noinline)) static void ICACHE_RAM_ATTR send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
+ static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
- const uint32_t pinRegister = _BV(pin);
- uint8_t mask = 0x80;
- uint8_t subpix = *pixels++;
- uint32_t cyclesStart = 0; // trigger emediately
- uint32_t cyclesNext = 0;
-
- for (;;)
- {
- // do the checks here while we are waiting on time to pass
- uint32_t cyclesBit = T_SPEED::T0H;
- if (subpix & mask)
- {
- cyclesBit = T_SPEED::T1H;
- }
-
- // after we have done as much work as needed for this next bit
- // now wait for the HIGH
- while (((cyclesStart = getCycleCount()) - cyclesNext) < T_SPEED::Period);
-
- // set pin state
- T_PINSET::setPin(pinRegister);
-
- // wait for the LOW
- while ((getCycleCount() - cyclesStart) < cyclesBit);
-
- // reset pin start
- T_PINSET::resetPin(pinRegister);
-
- cyclesNext = cyclesStart;
-
- // next bit
- mask >>= 1;
- if (mask == 0)
- {
- // no more bits to send in this byte
- // check for another byte
- if (pixels >= end)
- {
- // no more bytes to send so stop
- break;
- }
- // reset mask to first bit and get the next byte
- mask = 0x80;
- subpix = *pixels++;
- }
- }
- }
-
-protected:
- static inline uint32_t getCycleCount(void)
- {
- uint32_t ccount;
- __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
- return ccount;
+ NeoEspBitBangBase_send_pixels(pixels, end, pin, T_SPEED::T0H, T_SPEED::T1H, T_SPEED::Period, T_PINSET::IdleLevel);
}
};
@@ -214,6 +135,13 @@ public:
static const uint32_t ResetTimeUs = 200;
};
+// normal is inverted signal
+class NeoEspBitBangSpeedTm1829 : public NeoEspBitBangBase
+{
+public:
+ static const uint32_t ResetTimeUs = 200;
+};
+
class NeoEspBitBangSpeed800Kbps : public NeoEspBitBangBase
{
public:
@@ -257,6 +185,13 @@ public:
static const uint32_t ResetTimeUs = 200;
};
+// normal is inverted signal, so inverted is normal
+class NeoEspBitBangInvertedSpeedTm1829 : public NeoEspBitBangBase
+{
+public:
+ static const uint32_t ResetTimeUs = 200;
+};
+
class NeoEspBitBangInvertedSpeed800Kbps : public NeoEspBitBangBase
{
public:
@@ -369,6 +304,7 @@ typedef NeoEspBitBangMethodBase NeoEsp32
typedef NeoEspBitBangMethodBase NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1814Method;
+typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1829Method;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangApa106Method;
@@ -381,6 +317,7 @@ typedef NeoEspBitBangMethodBase NeoEsp32BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1814InvertedMethod;
+typedef NeoEspBitBangMethodBase NeoEsp32BitBangTm1829InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp32BitBangApa106InvertedMethod;
@@ -395,6 +332,7 @@ typedef NeoEspBitBangMethodBase NeoEsp82
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1814Method;
+typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1829Method;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangApa106Method;
@@ -407,6 +345,7 @@ typedef NeoEspBitBangMethodBase NeoEsp8266BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1814InvertedMethod;
+typedef NeoEspBitBangMethodBase NeoEsp8266BitBangTm1829InvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase NeoEsp8266BitBangApa106InvertedMethod;
@@ -418,4 +357,4 @@ typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMet
#endif
// ESP bitbang doesn't have defaults and should avoided except for testing
-#endif
\ No newline at end of file
+#endif
diff --git a/tasmota/xlgt_01_ws2812.ino b/tasmota/xlgt_01_ws2812.ino
index eaea82135..fcd685931 100644
--- a/tasmota/xlgt_01_ws2812.ino
+++ b/tasmota/xlgt_01_ws2812.ino
@@ -123,113 +123,6 @@ void (* const Ws2812Command[])(void) PROGMEM = {
#endif // No USE_WS2812_DMA
-#ifdef ESP32
-//
-// Below is a quick work-around to ESP32 gcc that prevents templated methods to be in IRAM unless explicitly marked per specialization
-// It will work only for the default WS2812 (800KHz) and inverted and non-inverted
-//
-template <>
-void IRAM_ATTR NeoEspBitBangBase::send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
-{
- const uint32_t pinRegister = _BV(pin);
- uint8_t mask = 0x80;
- uint8_t subpix = *pixels++;
- uint32_t cyclesStart = 0; // trigger emediately
- uint32_t cyclesNext = 0;
-
- for (;;)
- {
- // do the checks here while we are waiting on time to pass
- uint32_t cyclesBit = NeoEspSpeed800Mhz::T0H;
- if (subpix & mask)
- {
- cyclesBit = NeoEspSpeed800Mhz::T1H;
- }
-
- // after we have done as much work as needed for this next bit
- // now wait for the HIGH
- while (((cyclesStart = getCycleCount()) - cyclesNext) < NeoEspSpeed800Mhz::Period);
-
- // set pin state
- NeoEspPinset::setPin(pinRegister);
-
- // wait for the LOW
- while ((getCycleCount() - cyclesStart) < cyclesBit);
-
- // reset pin start
- NeoEspPinset::resetPin(pinRegister);
-
- cyclesNext = cyclesStart;
-
- // next bit
- mask >>= 1;
- if (mask == 0)
- {
- // no more bits to send in this byte
- // check for another byte
- if (pixels >= end)
- {
- // no more bytes to send so stop
- break;
- }
- // reset mask to first bit and get the next byte
- mask = 0x80;
- subpix = *pixels++;
- }
- }
-}
-template <>
-void IRAM_ATTR NeoEspBitBangBase::send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
-{
- const uint32_t pinRegister = _BV(pin);
- uint8_t mask = 0x80;
- uint8_t subpix = *pixels++;
- uint32_t cyclesStart = 0; // trigger emediately
- uint32_t cyclesNext = 0;
-
- for (;;)
- {
- // do the checks here while we are waiting on time to pass
- uint32_t cyclesBit = NeoEspSpeed800Mhz::T0H;
- if (subpix & mask)
- {
- cyclesBit = NeoEspSpeed800Mhz::T1H;
- }
-
- // after we have done as much work as needed for this next bit
- // now wait for the HIGH
- while (((cyclesStart = getCycleCount()) - cyclesNext) < NeoEspSpeed800Mhz::Period);
-
- // set pin state
- NeoEspPinsetInverted::setPin(pinRegister);
-
- // wait for the LOW
- while ((getCycleCount() - cyclesStart) < cyclesBit);
-
- // reset pin start
- NeoEspPinsetInverted::resetPin(pinRegister);
-
- cyclesNext = cyclesStart;
-
- // next bit
- mask >>= 1;
- if (mask == 0)
- {
- // no more bits to send in this byte
- // check for another byte
- if (pixels >= end)
- {
- // no more bytes to send so stop
- break;
- }
- // reset mask to first bit and get the next byte
- mask = 0x80;
- subpix = *pixels++;
- }
- }
-}
-#endif // ESP32
-
NeoPixelBus *strip = nullptr;
struct WsColor {