diff --git a/src/internal/NeoEspBitBangMethod.cpp b/src/internal/NeoEspBitBangMethod.cpp
new file mode 100644
index 0000000..1166d80
--- /dev/null
+++ b/src/internal/NeoEspBitBangMethod.cpp
@@ -0,0 +1,154 @@
+/*-------------------------------------------------------------------------
+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
+
+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)
+{
+ 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 defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+
+ // wait for the LOW
+ while ((getCycleCount() - cyclesStart) < cyclesBit);
+
+ // reset pin start
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+
+ 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++;
+ }
+ }
+}
+
+void ICACHE_RAM_ATTR NeoEspBitBangBase_send_pixels_inv(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
+{
+ 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 defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1tc = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
+#endif
+
+ // wait for the LOW
+ while ((getCycleCount() - cyclesStart) < cyclesBit);
+
+ // reset pin start
+#if defined(ARDUINO_ARCH_ESP32)
+ GPIO.out_w1ts = pinRegister;
+#else
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
+#endif
+
+ 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
diff --git a/src/internal/NeoEspBitBangMethod.h b/src/internal/NeoEspBitBangMethod.h
index f817bfc..6e24ffe 100644
--- a/src/internal/NeoEspBitBangMethod.h
+++ b/src/internal/NeoEspBitBangMethod.h
@@ -87,27 +87,17 @@ public:
const static uint32_t Period = (F_CPU / 606061 - CYCLES_LOOPTEST); // 1.65us
};
+extern void NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period);
+extern void NeoEspBitBangBase_send_pixels_inv(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period);
+
class NeoEspPinset
{
public:
const static uint8_t IdleLevel = LOW;
- inline static void setPin(const uint32_t pinRegister)
+ inline static void send_pixels_impl(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
{
-#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
+ NeoEspBitBangBase_send_pixels(pixels, end, pin, t0h, t1h, period);
}
};
@@ -116,84 +106,18 @@ class NeoEspPinsetInverted
public:
const static uint8_t IdleLevel = HIGH;
- inline static void setPin(const uint32_t pinRegister)
+ inline static void send_pixels_impl(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
{
-#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
+ NeoEspBitBangBase_send_pixels_inv(pixels, end, pin, t0h, t1h, period);
}
};
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;
+ T_PINSET::send_pixels_impl(pixels, end, pin, T_SPEED::T0H, T_SPEED::T1H, T_SPEED::Period);
}
};