@@ -1034,10 +1034,10 @@ void Segment::blur(uint8_t blur_amount, bool smear) const {
10341034 }
10351035#endif
10361036 uint8_t keep = smear ? 255 : 255 - blur_amount;
1037- uint8_t seep = blur_amount >> ( 1 + smear) ;
1037+ uint8_t seep = blur_amount >> 1 ;
10381038 unsigned vlength = vLength ();
10391039 uint32_t carryover = BLACK;
1040- uint32_t lastnew;
1040+ uint32_t lastnew; // not necessary to initialize lastnew and last, as both will be initialized by the first loop iteration
10411041 uint32_t last;
10421042 uint32_t curnew = BLACK;
10431043 for (unsigned i = 0 ; i < vlength; i++) {
@@ -1198,7 +1198,12 @@ void WS2812FX::finalizeInit() {
11981198void WS2812FX::service () {
11991199 unsigned long nowUp = millis (); // Be aware, millis() rolls over every 49 days
12001200 now = nowUp + timebase;
1201- if (nowUp - _lastShow < MIN_FRAME_DELAY || _suspend) return ;
1201+ unsigned long elapsed = nowUp - _lastServiceShow;
1202+ if (_suspend || elapsed <= MIN_FRAME_DELAY) return ; // keep wifi alive - no matter if triggered or unlimited
1203+ if (!_triggered && (_targetFps != FPS_UNLIMITED)) { // unlimited mode = no frametime
1204+ if (elapsed < _frametime) return ; // too early for service
1205+ }
1206+
12021207 bool doShow = false ;
12031208
12041209 _isServicing = true ;
@@ -1255,15 +1260,16 @@ void WS2812FX::service() {
12551260 }
12561261
12571262 #ifdef WLED_DEBUG
1258- if (millis () - nowUp > _frametime) DEBUG_PRINTF_P (PSTR (" Slow effects %u/%d.\n " ), (unsigned )(millis ()-nowUp), (int )_frametime);
1263+ if ((_targetFps != FPS_UNLIMITED) && ( millis () - nowUp > _frametime) ) DEBUG_PRINTF_P (PSTR (" Slow effects %u/%d.\n " ), (unsigned )(millis ()-nowUp), (int )_frametime);
12591264 #endif
12601265 if (doShow && !_suspend) {
12611266 yield ();
12621267 Segment::handleRandomPalette (); // slowly transition random palette; move it into for loop when each segment has individual random palette
1268+ _lastServiceShow = nowUp; // update timestamp, for precise FPS control
12631269 show ();
12641270 }
12651271 #ifdef WLED_DEBUG
1266- if (millis () - nowUp > _frametime) DEBUG_PRINTF_P (PSTR (" Slow strip %u/%d.\n " ), (unsigned )(millis ()-nowUp), (int )_frametime);
1272+ if ((_targetFps != FPS_UNLIMITED) && ( millis () - nowUp > _frametime) ) DEBUG_PRINTF_P (PSTR (" Slow strip %u/%d.\n " ), (unsigned )(millis ()-nowUp), (int )_frametime);
12671273 #endif
12681274
12691275 _triggered = false ;
@@ -1612,8 +1618,8 @@ void WS2812FX::show() {
16121618 if (newBri != _brightness) BusManager::setBrightness (_brightness);
16131619
16141620 if (diff > 0 ) { // skip calculation if no time has passed
1615- int fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math (shift left for better precision)
1616- _cumulativeFps + = ((fpsCurr - ( _cumulativeFps << FPS_CALC_SHIFT)) / FPS_CALC_AVG + (( 1 <<FPS_CALC_SHIFT)/FPS_CALC_AVG)) >> FPS_CALC_SHIFT; // simple PI controller over FPS_CALC_AVG frames
1621+ size_t fpsCurr = (1000 << FPS_CALC_SHIFT) / diff; // fixed point math
1622+ _cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2 ) / ( FPS_CALC_AVG + 1 ); // "+FPS_CALC_AVG/2" for proper rounding
16171623 _lastShow = showNow;
16181624 }
16191625}
@@ -1653,8 +1659,9 @@ void WS2812FX::waitForIt() {
16531659};
16541660
16551661void WS2812FX::setTargetFps (unsigned fps) {
1656- if (fps > 0 && fps <= 120 ) _targetFps = fps;
1657- _frametime = 1000 / _targetFps;
1662+ if (fps <= 250 ) _targetFps = fps;
1663+ if (_targetFps > 0 ) _frametime = 1000 / _targetFps;
1664+ else _frametime = MIN_FRAME_DELAY; // unlimited mode
16581665}
16591666
16601667void WS2812FX::setCCT (uint16_t k) {
0 commit comments