diff --git a/NeoPixelBus.cpp b/NeoPixelBus.cpp index 1bba22f..f1de042 100644 --- a/NeoPixelBus.cpp +++ b/NeoPixelBus.cpp @@ -32,12 +32,28 @@ License along with NeoPixel. If not, see #include "NeoPixelBus.h" #if defined(ESP8266) -// due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are -// moved into a C file so the attribute will be applied correctly -extern "C" void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin); -extern "C" void ICACHE_RAM_ATTR send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin); + + #ifdef ESPUARTWS2812 + extern "C" { + #include "eagle_soc.h" + #include "uart_register.h" + #include + } + #define UART_INV_MASK (0x3f<<19) + #define UART 1 + + #else + // due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are + // moved into a C file so the attribute will be applied correctly + extern "C" void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin); + extern "C" void ICACHE_RAM_ATTR send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin); + #endif + #endif + + + NeoPixelBus::NeoPixelBus(uint16_t n, uint8_t p, uint8_t t) : _countPixels(n), _sizePixels(n * 3), @@ -46,7 +62,11 @@ NeoPixelBus::NeoPixelBus(uint16_t n, uint8_t p, uint8_t t) : _activeAnimations(0), _flagsPixels(t) { + +#ifndef ESPUARTWS2812 setPin(p); +#endif + _pixels = (uint8_t *)malloc(_sizePixels); if (_pixels) @@ -69,16 +89,28 @@ NeoPixelBus::~NeoPixelBus() if (_animations) free(_animations); +#ifndef ESPUARTWS2812 pinMode(_pin, INPUT); +#endif + } -void NeoPixelBus::Begin(void) -{ - pinMode(_pin, OUTPUT); - digitalWrite(_pin, LOW); + void NeoPixelBus::Begin(void) + { + +#ifdef ESPUARTWS2812 + /* Serial rate is 4x 800KHz for WS2811 */ + Serial1.begin(3200000, SERIAL_6N1, SERIAL_TX_ONLY); + CLEAR_PERI_REG_MASK(UART_CONF0(UART), UART_INV_MASK); + //SET_PERI_REG_MASK(UART_CONF0(UART), UART_TXD_INV); + SET_PERI_REG_MASK(UART_CONF0(UART), (BIT(22))); +#else + pinMode(_pin, OUTPUT); + digitalWrite(_pin, LOW); +#endif + Dirty(); + } - Dirty(); -} void NeoPixelBus::Show(void) { @@ -111,7 +143,9 @@ void NeoPixelBus::Show(void) // state, computes 'pin high' and 'pin low' values, and writes these back // to the PORT register as needed. +#ifndef ESPUARTWS2812 noInterrupts(); // Need 100% focus on instruction timing +#endif #ifdef __AVR__ @@ -724,8 +758,28 @@ void NeoPixelBus::Show(void) if ((_flagsPixels & NEO_SPDMASK) == NEO_KHZ800) { #endif +#ifndef ESPUARTWS2812 // 800 KHz bitstream send_pixels_800(p, end, _pin); +#else + + char buff[4]; + + do + { + uint8_t subpix = *p++; + + buff[0] = data[(subpix >> 6) & 3]; + buff[1] = data[(subpix >> 4) & 3]; + buff[2] = data[(subpix >> 2) & 3]; + buff[3] = data[subpix & 3]; + Serial1.write(buff, sizeof(buff)); + + } while (p < end); + + + +#endif #ifdef INCLUDE_NEO_KHZ400_SUPPORT } @@ -973,7 +1027,10 @@ void NeoPixelBus::Show(void) #endif // end Architecture select +#ifndef ESPUARTWS2812 interrupts(); +#endif + ResetDirty(); _endTime = micros(); // Save EOD time for latch on next call } diff --git a/NeoPixelBus.h b/NeoPixelBus.h index bbb778a..b29e349 100644 --- a/NeoPixelBus.h +++ b/NeoPixelBus.h @@ -20,6 +20,8 @@ License along with NeoPixel. If not, see #include #include "RgbColor.h" +#define ESPUARTWS2812 // drive neopixels by UART on GPIO2 on ESP8266 thanks to Forkineye. https://github.com/forkineye/ESPixelStick + // '_flagsPixels' flags for LED _pixels (third parameter to constructor): #define NEO_RGB 0x00 // Wired for RGB data order #define NEO_GRB 0x01 // Wired for GRB data order @@ -120,6 +122,12 @@ private: uint8_t _pinMask; // Output PORT bitmask #endif +#ifdef ESPUARTWS2812 + /* 6 bit UART lookup table, first 2 bits ignored. Start and stop bits are part of the pixel stream. */ +const char data[4] = { 0b00110111, 0b00000111, 0b00110100, 0b00000100 }; +#endif + + struct FadeAnimation { uint16_t time;