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<NeoEspBitBangSpeed400Kbps> 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

View File

@@ -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