BitBang enhancements (#286)

This commit is contained in:
Michael Miller
2019-08-28 17:08:14 -07:00
committed by GitHub
parent b237440d63
commit c71e200dd6
2 changed files with 91 additions and 73 deletions

View File

@@ -185,10 +185,10 @@ typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812> NeoEsp8266BitBangSk681
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp8266BitBang800KbpsMethod; typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp8266BitBang400KbpsMethod; typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp32BitBangWs2813Method; typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp32BitBangWs2812Method; typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
typedef NeoEsp8266BitBangSk6812Method NeoEsp32BitBangLc8812Method; typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
typedef NeoEsp8266BitBang400KbpsMethod NeoEsp32BitBangApa106Method; typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method;
#endif #endif
// ESP bitbang doesn't have defaults and should avoided except for testing // ESP bitbang doesn't have defaults and should avoided except for testing

View File

@@ -36,7 +36,9 @@ License along with NeoPixel. If not, see
#define ICACHE_RAM_ATTR IRAM_ATTR #define ICACHE_RAM_ATTR IRAM_ATTR
#endif #endif
inline uint32_t _getCycleCount() static uint32_t _getCycleCount(void) __attribute__((always_inline));
static inline uint32_t _getCycleCount(void)
{ {
uint32_t ccount; uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); __asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
@@ -53,29 +55,23 @@ inline uint32_t _getCycleCount()
void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin) void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin)
{ {
const uint32_t pinRegister = _BV(pin); const uint32_t pinRegister = _BV(pin);
uint8_t mask; uint8_t mask = 0x80;
uint8_t subpix; uint8_t subpix = *pixels++;
uint32_t cyclesStart; uint32_t cyclesStart = 0; // trigger emediately
uint32_t cyclesNext = 0;
// trigger emediately for (;;)
cyclesStart = _getCycleCount() - CYCLES_800;
do
{
subpix = *pixels++;
for (mask = 0x80; mask != 0; mask >>= 1)
{ {
// do the checks here while we are waiting on time to pass // 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 cyclesBit = CYCLES_800_T0H;
uint32_t cyclesNext = cyclesStart; if (subpix & mask)
{
cyclesBit = CYCLES_800_T1H;
}
// after we have done as much work as needed for this next bit // after we have done as much work as needed for this next bit
// now wait for the HIGH // now wait for the HIGH
do while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_800);
{
// 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);
// set high // set high
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
@@ -85,10 +81,7 @@ void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint
#endif #endif
// wait for the LOW // wait for the LOW
do while ((_getCycleCount() - cyclesStart) < cyclesBit);
{
cyclesNext = _getCycleCount();
} while ((cyclesNext - cyclesStart) < cyclesBit);
// set low // set low
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
@@ -96,36 +89,48 @@ void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint
#else #else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif #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++;
}
} }
} while (pixels < end);
} }
void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin) void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin)
{ {
const uint32_t pinRegister = _BV(pin); const uint32_t pinRegister = _BV(pin);
uint8_t mask; uint8_t mask = 0x80;
uint8_t subpix; uint8_t subpix = *pixels++;
uint32_t cyclesStart; uint32_t cyclesStart = 0; // trigger emediately
uint32_t cyclesNext = 0;
// trigger emediately for (;;)
cyclesStart = _getCycleCount() - CYCLES_400;
do
{ {
subpix = *pixels++; // do the checks here while we are waiting on time to pass
for (mask = 0x80; mask; mask >>= 1) uint32_t cyclesBit = CYCLES_400_T0H;
if (subpix & mask)
{ {
uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_400_T1H : CYCLES_400_T0H; cyclesBit = CYCLES_400_T1H;
uint32_t cyclesNext = cyclesStart; }
// after we have done as much work as needed for this next bit // after we have done as much work as needed for this next bit
// now wait for the HIGH // now wait for the HIGH
do while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_400);
{
// 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);
// set high
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister; GPIO.out_w1ts = pinRegister;
#else #else
@@ -133,10 +138,7 @@ void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint
#endif #endif
// wait for the LOW // wait for the LOW
do while ((_getCycleCount() - cyclesStart) < cyclesBit);
{
cyclesNext = _getCycleCount();
} while ((cyclesNext - cyclesStart) < cyclesBit);
// set low // set low
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
@@ -144,8 +146,24 @@ void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint
#else #else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif #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++;
}
} }
} while (pixels < end);
} }
#endif #endif