diff --git a/wled00/FX.h b/wled00/FX.h index 7fddafbe..c7c5f58d 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -480,7 +480,9 @@ class WS2812FX { gammaCorrectCol = true, applyToAllSelected = true, segmentsAreIdentical(Segment* a, Segment* b), - setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p); + setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p), + // return true if the strip is being sent pixel updates + isUpdating(void); uint8_t mainSegment = 0, diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 4418cfb7..4b9f0ec0 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -218,8 +218,11 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) //you can set it to 0 if the ESP is powered by USB and the LEDs by external void WS2812FX::show(void) { - if (_callback) _callback(); - + + // avoid race condition, caputre _callback value + show_callback callback = _callback; + if (callback) callback(); + //power limit calculation //each LED can draw up 195075 "power units" (approx. 53mA) //one PU is the power it takes to have 1 channel 1 step brighter per brightness step @@ -291,10 +294,24 @@ void WS2812FX::show(void) { bus->SetBrightness(_brightness); } + // some buses send asynchronously and this method will return before + // all of the data has been sent. + // See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods bus->Show(); _lastShow = millis(); } +/** + * Returns a true value if any of the strips are still being updated. + * On some hardware (ESP32), strip updates are done asynchronously. + */ +bool WS2812FX::isUpdating() { + return !bus->CanShow(); +} + +/** + * Forces the next frame to be computed on all active segments. + */ void WS2812FX::trigger() { _triggered = true; } diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 6e56efe5..9d328242 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -296,7 +296,6 @@ public: void Show() { - byte b; switch (_type) { case NeoPixelType_Grb: _pGrb->Show(); break; @@ -304,6 +303,22 @@ public: } } + /** + * This will return true if enough time has passed since the last time Show() was called. + * This also means that calling Show() will not cause any undue waiting. If the method for + * the defined bus is hardware that sends asynchronously, then call CanShow() will let + * you know if it has finished sending the data from the last Show(). + */ + bool CanShow() + { + switch (_type) + { + case NeoPixelType_Grb: return _pGrb->CanShow(); + case NeoPixelType_Grbw: return _pGrbw->CanShow(); + default: return true; + } + } + void SetPixelColor(uint16_t indexPixel, RgbwColor c) { RgbwColor col;