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 {