diff --git a/src/internal/NeoEspBitBangMethod.h b/src/internal/NeoEspBitBangMethod.h index 77e3434..3615602 100644 --- a/src/internal/NeoEspBitBangMethod.h +++ b/src/internal/NeoEspBitBangMethod.h @@ -185,10 +185,10 @@ typedef NeoEspBitBangMethodBase NeoEsp8266BitBangSk681 typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsMethod; typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsMethod; -typedef NeoEsp8266BitBangWs2812xMethod NeoEsp32BitBangWs2813Method; -typedef NeoEsp8266BitBang800KbpsMethod NeoEsp32BitBangWs2812Method; -typedef NeoEsp8266BitBangSk6812Method NeoEsp32BitBangLc8812Method; -typedef NeoEsp8266BitBang400KbpsMethod NeoEsp32BitBangApa106Method; +typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method; +typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method; +typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method; +typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method; #endif // ESP bitbang doesn't have defaults and should avoided except for testing diff --git a/src/internal/NeoPixelEsp.c b/src/internal/NeoPixelEsp.c index 52415ff..f28a575 100644 --- a/src/internal/NeoPixelEsp.c +++ b/src/internal/NeoPixelEsp.c @@ -36,7 +36,9 @@ License along with NeoPixel. If not, see #define ICACHE_RAM_ATTR IRAM_ATTR #endif -inline uint32_t _getCycleCount() +static uint32_t _getCycleCount(void) __attribute__((always_inline)); + +static inline uint32_t _getCycleCount(void) { uint32_t ccount; __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); @@ -53,99 +55,115 @@ inline uint32_t _getCycleCount() void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin) { const uint32_t pinRegister = _BV(pin); - uint8_t mask; - uint8_t subpix; - uint32_t cyclesStart; + uint8_t mask = 0x80; + uint8_t subpix = *pixels++; + uint32_t cyclesStart = 0; // trigger emediately + uint32_t cyclesNext = 0; - // trigger emediately - cyclesStart = _getCycleCount() - CYCLES_800; - do + for (;;) { - subpix = *pixels++; - for (mask = 0x80; mask != 0; mask >>= 1) - { - // do the checks here while we are waiting on time to pass - uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_800_T1H : CYCLES_800_T0H; - uint32_t cyclesNext = cyclesStart; + // do the checks here while we are waiting on time to pass + uint32_t cyclesBit = CYCLES_800_T0H; + if (subpix & mask) + { + cyclesBit = CYCLES_800_T1H; + } - // after we have done as much work as needed for this next bit - // now wait for the HIGH - do - { - // cache and use this count so we don't incur another - // instruction before we turn the bit high - cyclesStart = _getCycleCount(); - } while ((cyclesStart - cyclesNext) < CYCLES_800); + // after we have done as much work as needed for this next bit + // now wait for the HIGH + while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_800); - // set high + // set high #if defined(ARDUINO_ARCH_ESP32) - GPIO.out_w1ts = pinRegister; + GPIO.out_w1ts = pinRegister; #else - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); #endif - - // wait for the LOW - do - { - cyclesNext = _getCycleCount(); - } while ((cyclesNext - cyclesStart) < cyclesBit); - - // set low + + // wait for the LOW + while ((_getCycleCount() - cyclesStart) < cyclesBit); + + // set low #if defined(ARDUINO_ARCH_ESP32) - GPIO.out_w1tc = pinRegister; + GPIO.out_w1tc = pinRegister; #else - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); #endif - } - } while (pixels < end); + 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 bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin) { - const uint32_t pinRegister = _BV(pin); - uint8_t mask; - uint8_t subpix; - uint32_t cyclesStart; + const uint32_t pinRegister = _BV(pin); + uint8_t mask = 0x80; + uint8_t subpix = *pixels++; + uint32_t cyclesStart = 0; // trigger emediately + uint32_t cyclesNext = 0; - // trigger emediately - cyclesStart = _getCycleCount() - CYCLES_400; - do - { - subpix = *pixels++; - for (mask = 0x80; mask; mask >>= 1) - { - uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_400_T1H : CYCLES_400_T0H; - uint32_t cyclesNext = cyclesStart; + for (;;) + { + // do the checks here while we are waiting on time to pass + uint32_t cyclesBit = CYCLES_400_T0H; + if (subpix & mask) + { + cyclesBit = CYCLES_400_T1H; + } - // after we have done as much work as needed for this next bit - // now wait for the HIGH - do - { - // cache and use this count so we don't incur another - // instruction before we turn the bit high - cyclesStart = _getCycleCount(); - } while ((cyclesStart - cyclesNext) < CYCLES_400); + // after we have done as much work as needed for this next bit + // now wait for the HIGH + while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_400); + // set high #if defined(ARDUINO_ARCH_ESP32) - GPIO.out_w1ts = pinRegister; + GPIO.out_w1ts = pinRegister; #else - GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); #endif - // wait for the LOW - do - { - cyclesNext = _getCycleCount(); - } while ((cyclesNext - cyclesStart) < cyclesBit); + // wait for the LOW + while ((_getCycleCount() - cyclesStart) < cyclesBit); - // set low + // set low #if defined(ARDUINO_ARCH_ESP32) - GPIO.out_w1tc = pinRegister; + GPIO.out_w1tc = pinRegister; #else - GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); #endif - } - } while (pixels < end); + 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