diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h new file mode 100644 index 000000000..f8638c7f8 --- /dev/null +++ b/wled00/NpbWrapper.h @@ -0,0 +1,176 @@ +//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103 + +#define WORKAROUND_ESP32_BITBANG +//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support + +//uncomment this if red and green are swapped +//#define SWAPRG + +//automatically uses the right driver method for each platform +#ifdef ARDUINO_ARCH_ESP32 +#ifdef WORKAROUND_ESP32_BITBANG +#define PIXELMETHOD NeoEsp32BitBangWs2813Method +#else +#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method +#endif +#else +#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod +#endif +//handle swapping Red and Green automatically +#ifdef SWAPRG +#define PIXELFEATURE3 NeoRgbFeature +#define PIXELFEATURE4 NeoRgbwFeature +#else +#define PIXELFEATURE3 NeoGrbFeature +#define PIXELFEATURE4 NeoGrbwFeature +#endif + +#include + +enum NeoPixelType +{ + NeoPixelType_None = 0, + NeoPixelType_Grb = 1, + NeoPixelType_Grbw = 2, + NeoPixelType_End = 3 +}; + +class NeoPixelWrapper +{ +public: + NeoPixelWrapper() : + // initialize each member to null + _pGrb(NULL), + _pGrbw(NULL), + _type(NeoPixelType_None) + { + + } + + ~NeoPixelWrapper() + { + cleanup(); + } + + void Begin(NeoPixelType type, uint16_t countPixels, uint8_t pin) + { + cleanup(); + _type = type; + + switch (_type) { + + case NeoPixelType_Grb: + _pGrb = new NeoPixelBrightnessBus(countPixels, pin); + _pGrb->Begin(); + break; + + case NeoPixelType_Grbw: + _pGrbw = new NeoPixelBrightnessBus(countPixels, pin); + _pGrbw->Begin(); + break; + } + } + + void Show() + { + #ifdef ARDUINO_ARCH_ESP32 + #ifdef WORKAROUND_ESP32_BITBANG + delay(1); + portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139) + #endif + #endif + + switch (_type) { + case NeoPixelType_Grb: _pGrb->Show(); break; + case NeoPixelType_Grbw: _pGrbw->Show(); break; + } + + #ifdef ARDUINO_ARCH_ESP32 + #ifdef WORKAROUND_ESP32_BITBANG + portENABLE_INTERRUPTS(); + #endif + #endif + } + bool CanShow() const + { + switch (_type) { + case NeoPixelType_Grb: _pGrb->CanShow(); break; + case NeoPixelType_Grbw: _pGrbw->CanShow(); break; + } + } + + void SetPixelColor(uint16_t indexPixel, RgbColor color) + { + switch (_type) { + case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break; + case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break; + } + } + + void SetPixelColor(uint16_t indexPixel, RgbwColor color) + { + switch (_type) { + case NeoPixelType_Grb: _pGrbw->SetPixelColor(indexPixel, color); break; + case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break; + } + } + + void SetBrightness(byte b) + { + switch (_type) { + case NeoPixelType_Grb: _pGrb->SetBrightness(b); break; + case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break; + } + } + + RgbColor GetPixelColor(uint16_t indexPixel) const + { + switch (_type) { + case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break; + case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break; + } + return 0; + } + +// NOTE: Due to feature differences, some support RGBW but the method name +// here needs to be unique, thus GetPixeColorRgbw + RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const + { + switch (_type) { + case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break; + case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break; + } + return 0; + } + + void ClearTo(RgbColor color) + { + switch (_type) { + case NeoPixelType_Grb: _pGrb->ClearTo(color); break; + case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break; + } + } + + void ClearTo(RgbwColor color) + { + switch (_type) { + case NeoPixelType_Grb: break; + case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break; + } + } + +private: + NeoPixelType _type; + + // have a member for every possible type + NeoPixelBrightnessBus* _pGrb; + NeoPixelBrightnessBus* _pGrbw; + + void cleanup() + { + switch (_type) { + case NeoPixelType_Grb: delete _pGrb ; _pGrb = NULL; break; + case NeoPixelType_Grbw: delete _pGrbw; _pGrbw = NULL; break; + } + } +}; diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index 96f5bc1b9..21db57a29 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -37,9 +37,9 @@ #define CALL_MODE(n) (this->*_mode[n])(); -void WS2812FX::init() { +void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin) { for (int i=0; i < _led_count; i++) _locked[i] = false; - begin(); + begin(supportWhite,countPixels,pin); WS2812FX::setBrightness(_brightness); show(); } @@ -386,7 +386,7 @@ void WS2812FX::mode_breath(void) { setPixelColor(i, _color); // set all LEDs to selected color } int b = map(breath_brightness, 0, 255, 0, _brightness); // keep brightness below brightness set by user - NeoPixelBrightnessBus::SetBrightness(b); // set new brightness to leds + bus->SetBrightness(b); // set new brightness to leds show(); _mode_color = breath_brightness; // we use _mode_color to store the brightness @@ -1896,11 +1896,6 @@ void WS2812FX::unlockAll() _locked[x] = false; } -void WS2812FX::setLedCount(uint16_t i) -{ - _led_count = i; -} - void WS2812FX::setFastUpdateMode(bool y) { _fastStandard = y; @@ -1935,11 +1930,7 @@ double WS2812FX::getPowerEstimate(byte leds, uint32_t c, byte b) double _mARequired = 100; //ESP power double _mul = (double)b/255; double _sum = ((c & 0xFF000000) >> 24) + ((c & 0x00FF0000) >> 16) + ((c & 0x0000FF00) >> 8) + ((c & 0x000000FF) >> 0); - #ifdef RGBW - _sum /= 1024; - #else - _sum /= 768; - #endif + _sum /= (_rgbwMode)? 1024:768; double _mAPerLed = 50*(_mul*_sum); _mARequired += leds*_mAPerLed; return _mARequired; @@ -2027,11 +2018,13 @@ void WS2812FX::setCustomChase(byte i1, byte i2, byte is, byte np, byte ns, byte //Added for quick NeoPixelBus compatibility with Adafruit syntax void WS2812FX::setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w) { - #ifdef RGBW - NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w)); - #else - NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b)); - #endif + if (_rgbwMode) + { + bus->SetPixelColor(i, RgbwColor(r,g,b,w)); + } else + { + bus->SetPixelColor(i, RgbColor(r,g,b)); + } } void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) @@ -2039,11 +2032,13 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) if (_reverseMode) i = _led_count - 1 -i; if (!_cronixieMode) { - #ifdef RGBW - NeoPixelBrightnessBus::SetPixelColor(i, RgbwColor(r,g,b,w)); - #else - NeoPixelBrightnessBus::SetPixelColor(i, RgbColor(r,g,b)); - #endif + if (_rgbwMode) + { + bus->SetPixelColor(i, RgbwColor(r,g,b,w)); + } else + { + bus->SetPixelColor(i, RgbColor(r,g,b)); + } } else { if(i>6)return; byte o = 10*i; @@ -2112,51 +2107,44 @@ uint32_t WS2812FX::getPixelColor(uint16_t i) default: return 0; } } - #ifdef RGBW - RgbwColor lColor = NeoPixelBrightnessBus::GetPixelColor(i); - return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B; - #else - RgbColor lColor = NeoPixelBrightnessBus::GetPixelColor(i); - return lColor.R*65536 + lColor.G*256 + lColor.B; - #endif + if (_rgbwMode) + { + RgbwColor lColor = bus->GetPixelColorRgbw(i); + return lColor.W*16777216 + lColor.R*65536 + lColor.G*256 + lColor.B; + } else { + RgbColor lColor = bus->GetPixelColor(i); + return lColor.R*65536 + lColor.G*256 + lColor.B; + } } void WS2812FX::setBrightness(byte b) { _brightness = constrain(b, BRIGHTNESS_MIN, BRIGHTNESS_MAX); - NeoPixelBrightnessBus::SetBrightness(_brightness); + bus->SetBrightness(_brightness); if (_mode_last_call_time + _mode_delay > millis()+50 || b == 0) show(); //only update right away if long time until next refresh } void WS2812FX::show() { - #ifdef ARDUINO_ARCH_ESP32 - #ifdef WORKAROUND_ESP32_BITBANG - delay(1); - portDISABLE_INTERRUPTS(); //this is a workaround to prevent flickering (see https://github.com/adafruit/Adafruit_NeoPixel/issues/139) - #endif - #endif - NeoPixelBrightnessBus::Show(); - - #ifdef ARDUINO_ARCH_ESP32 - #ifdef WORKAROUND_ESP32_BITBANG - portENABLE_INTERRUPTS(); - #endif - #endif + bus->Show(); } void WS2812FX::clear() { - #ifdef RGBW - NeoPixelBrightnessBus::ClearTo(RgbwColor(0)); - #else - NeoPixelBrightnessBus::ClearTo(RgbColor(0)); - #endif + bus->ClearTo(RgbColor(0)); } -void WS2812FX::begin() +void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin) { - NeoPixelBrightnessBus::Begin(); + if (supportWhite == _rgbwMode && countPixels == _led_count && _locked != NULL) return; + _rgbwMode = supportWhite; + _led_count = countPixels; + _cc_i2 = _led_count -1; + uint8_t ty = 1; + if (supportWhite) ty =2; + bus->Begin((NeoPixelType)ty, countPixels, pin); + if (_locked != NULL) delete _locked; + _locked = new bool[countPixels]; } //For some reason min and max are not declared here diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 69161e9be..d39fe0588 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -1,25 +1,4 @@ -//#define RGBW -#define PIN 2 //strip pin. Only change for ESP32 -#define WORKAROUND_ESP32_BITBANG -//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support - -//automatically uses the right driver method for each platform -#ifdef ARDUINO_ARCH_ESP32 -#ifdef WORKAROUND_ESP32_BITBANG -#define PIXELMETHOD NeoEsp32BitBangWs2813Method -#else -#define PIXELMETHOD NeoEsp32RmtWS2813_V3Method -#endif -#else -#define PIXELMETHOD NeoEsp8266Uart800KbpsMethod -#endif - -//selects correct feature for RGB/RGBW -#ifdef RGBW -#define PIXELFEATURE NeoGrbwFeature -#else -#define PIXELFEATURE NeoGrbFeature -#endif +//pixelmethod now in NpbWrapper.h /* WS2812FX.h - Library for WS2812 LED effects. @@ -50,14 +29,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Modified to work with WLED - differs from Github WS2812FX + Heavily modified to work with WLED - differs from Github WS2812FX */ #ifndef WS2812FX_h #define WS2812FX_h #include "Arduino.h" -#include +#include "NpbWrapper.h" #define DEFAULT_BRIGHTNESS 50 #define DEFAULT_MODE 0 @@ -132,10 +111,10 @@ #define FX_MODE_CC_RANDOM 57 -class WS2812FX : public NeoPixelBrightnessBus { +class WS2812FX { typedef void (WS2812FX::*mode_ptr)(void); public: - WS2812FX(uint16_t n) : NeoPixelBrightnessBus(n,PIN) { + WS2812FX(){ _mode[FX_MODE_STATIC] = &WS2812FX::mode_static; _mode[FX_MODE_BLINK] = &WS2812FX::mode_blink; @@ -200,7 +179,7 @@ class WS2812FX : public NeoPixelBrightnessBus { _speed = DEFAULT_SPEED; _brightness = DEFAULT_BRIGHTNESS; _running = false; - _led_count = n; + _led_count = 255; _mode_last_call_time = 0; _mode_delay = 0; _color = DEFAULT_COLOR; @@ -211,7 +190,7 @@ class WS2812FX : public NeoPixelBrightnessBus { _cc_fe = false; _cc_is = 0; _cc_i1 = 0; - _cc_i2 = n-1; + _cc_i2 = 254; _cc_num1 = 5; _cc_num2 = 5; _ccStep = 1; @@ -220,15 +199,16 @@ class WS2812FX : public NeoPixelBrightnessBus { _counter_ccStep = 0; _fastStandard = false; _reverseMode = false; - _locked = new bool[n]; + _locked = NULL; _cronixieDigits = new byte[6]; + bus = new NeoPixelWrapper(); } void show(void), setPixelColor(uint16_t i, byte r, byte g, byte b), setPixelColor(uint16_t i, byte r, byte g, byte b, byte w), - init(void), + init(bool supportWhite, uint16_t countPixels, uint8_t pin), service(void), start(void), stop(void), @@ -271,7 +251,6 @@ class WS2812FX : public NeoPixelBrightnessBus { unlockAll(void), setFastUpdateMode(bool b), trigger(void), - setLedCount(uint16_t i), setFade(int sp); bool @@ -295,9 +274,10 @@ class WS2812FX : public NeoPixelBrightnessBus { getSafePowerMultiplier(double safeMilliAmps, byte leds, uint32_t c, byte b); private: + NeoPixelWrapper *bus; void - begin(void), + begin(bool supportWhite, uint16_t countPixels, uint8_t pin), clear(void), setPixelColor(uint16_t i, uint32_t c), setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w), @@ -367,6 +347,7 @@ class WS2812FX : public NeoPixelBrightnessBus { bool _triggered, + _rgbwMode, _fastStandard, _reverseMode, _cronixieMode, diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 367308c7c..891ce42f2 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -33,7 +33,7 @@ #include "WS2812FX.h" //version in format yymmddb (b = daily build) -#define VERSION 1804111 +#define VERSION 1804121 const String versionString = "0.6.3"; //AP and OTA default passwords (change them!) @@ -50,7 +50,7 @@ bool useRGBW = false; //#define DEBUG //Hardware-settings (only changeble via code) -#define LEDCOUNT 255 //maximum, exact count set-able via settings +#define PIN 2 //strip pin. Only change for ESP32 byte buttonPin = 0; //needs pull-up byte auxPin = 15; //use e.g. for external relay byte auxDefaultState = 0; //0: input 1: high 2: low @@ -252,7 +252,7 @@ byte ntpPacketBuffer[NTP_PACKET_SIZE]; unsigned long ntpLastSyncTime = 999000000L; unsigned long ntpPacketSentTime = 999000000L; -WS2812FX strip = WS2812FX(LEDCOUNT); +WS2812FX strip = WS2812FX(); #ifdef DEBUG #define DEBUG_PRINT(x) Serial.print (x) diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 26a2a939c..de883c0a3 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -259,7 +259,7 @@ void loadSettingsFromEEPROM(bool first) if (apChannel > 13 || apChannel < 1) apChannel = 1; apHide = EEPROM.read(228); if (apHide > 1) apHide = 1; - ledCount = EEPROM.read(229); if (ledCount > LEDCOUNT) ledCount = LEDCOUNT; + ledCount = EEPROM.read(229); notifyButton = EEPROM.read(230); notifyTwice = EEPROM.read(231); buttonEnabled = EEPROM.read(232); diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index c3caef93c..36695b5a2 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -115,8 +115,7 @@ void handleSettingsSet(byte subPage) if (server.hasArg("LC")) { int i = server.arg("LC").toInt(); - if (i >= 0 && i <= LEDCOUNT) ledCount = i; - strip.setLedCount(ledCount); + if (i >= 0 && i <= 1200) ledCount = i; } if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default { @@ -383,7 +382,7 @@ void handleSettingsSet(byte subPage) aOtaEnabled = server.hasArg("AO"); } } - + strip.init(useRGBW,ledCount,PIN); saveSettingsToEEPROM(); } diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 3a0e80339..9033e5820 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -5,7 +5,7 @@ void wledInit() { EEPROM.begin(EEPSIZE); - if (!EEPROM.read(397)) strip.init(); //quick init + if (!EEPROM.read(397)) strip.init(EEPROM.read(372),EEPROM.read(229),PIN); //quick init Serial.begin(115200); Serial.setTimeout(50); @@ -256,8 +256,7 @@ void wledInit() void initStrip() { // Initialize NeoPixel Strip and button - if (initLedsLast) strip.init(); - strip.setLedCount(ledCount); + if (initLedsLast) strip.init(useRGBW,ledCount,PIN); strip.setReverseMode(reverseMode); strip.setColor(0); strip.setBrightness(255); @@ -494,12 +493,6 @@ String getBuildInfo() info += "version: " + versionString + "\r\n"; info += "build: " + (String)VERSION + "\r\n"; info += "eepver: " + String(EEPVER) + "\r\n"; - #ifdef RGBW - info += "rgbw: true\r\n"; - #else - info += "rgbw: false\r\n"; - #endif - info += "max-leds: " + (String)LEDCOUNT + "\r\n"; #ifdef USEFS info += "spiffs: true\r\n"; #else