improved FPS calc resolution, added averaging & multiplier compileflags

Fixed point calculation for improved accuracy, dithering in debug builds only.
Averaging and optional multiplier can be set as compile flags, example for speed testing with long averaging and a 10x multiplier:

-D FPS_CALC_AVG=200
-D FPS_MULTIPLIER=10

The calculation resolution is limited (9.7bit fixed point) so values larger than 200 can hit resolution limit and get stuck before reaching the final value.

If WLED_DEBUG is defined, dithering is added to the returned value so sub-frame accuracy is possible in post-processingwithout enabling the multiplier.
This commit is contained in:
Damian Schneider
2024-11-04 08:10:05 +01:00
parent 70323b9477
commit bf37ac53a3
2 changed files with 20 additions and 6 deletions

View File

@@ -1412,10 +1412,12 @@ void WS2812FX::show() {
unsigned long showNow = millis();
size_t diff = showNow - _lastShow;
size_t fpsCurr = 200;
if (diff > 0) fpsCurr = 1000 / diff;
_cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
_lastShow = showNow;
if (diff > 0) { // skip calculation if no time has passed
size_t fpsCurr = (1000<<7) / diff; // fixed point 9.7 bit
_cumulativeFps = (FPS_CALC_AVG * _cumulativeFps + fpsCurr + FPS_CALC_AVG / 2) / (FPS_CALC_AVG + 1); // "+FPS_CALC_AVG/2" for proper rounding
_lastShow = showNow;
}
}
/**
@@ -1432,7 +1434,11 @@ bool WS2812FX::isUpdating() const {
*/
uint16_t WS2812FX::getFps() const {
if (millis() - _lastShow > 2000) return 0;
return _cumulativeFps +1;
#ifdef WLED_DEBUG
return (FPS_MULTIPLIER * (_cumulativeFps + (random16() & 63))) >> 7; // + random("0.5") for dithering
#else
return (FPS_MULTIPLIER * _cumulativeFps) >> 7; // _cumulativeFps is stored in fixed point 9.7 bit
#endif
}
void WS2812FX::setTargetFps(uint8_t fps) {