From 8e9db0adde084f5140c0114cc39a0c3676d8d823 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Apr 2023 17:34:01 +0200 Subject: [PATCH] more accurate FPS forESP32 the standard millis() code is very inaccurate in the "high FPS" ranges. This replaces it with the esp32 high resolution timer. --- wled00/FX.cpp | 2 +- wled00/FX.h | 8 ++++++++ wled00/FX_fcn.cpp | 19 ++++++++++++++++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5c308736..3229710f 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2809,7 +2809,7 @@ uint16_t mode_bouncing_balls(void) { // number of balls based on intensity setting to max of 7 (cycles colors) // non-chosen color is a random color uint16_t numBalls = (SEGMENT.intensity * (maxNumBalls - 1)) / 255 + 1; // minimum 1 ball - const float gravity = -9.81; // standard value of gravity + constexpr float gravity = -9.81; // standard value of gravity const bool hasCol2 = SEGCOLOR(2); const unsigned long time = millis(); diff --git a/wled00/FX.h b/wled00/FX.h index c20d02b6..7be3cac2 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -689,6 +689,10 @@ class WS2812FX { // 96 bytes _targetFps(WLED_FPS), _frametime(FRAMETIME_FIXED), _cumulativeFps(2), +#ifdef ARDUINO_ARCH_ESP32 + _cumulativeFps500(2*500), // WLEDMM more accurate FPS measurement for ESP32 + _lastShow500(0), +#endif _isServicing(false), _isOffRefreshRequired(false), _hasWhiteChannel(false), @@ -907,6 +911,10 @@ class WS2812FX { // 96 bytes uint8_t _targetFps; uint16_t _frametime; uint16_t _cumulativeFps; +#ifdef ARDUINO_ARCH_ESP32 + uint64_t _cumulativeFps500; // WLEDMM more accurate FPS measurement for ESP32 + uint64_t _lastShow500; +#endif // will require only 1 byte struct { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 20c6ca19..bc88546d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -26,6 +26,9 @@ #include "wled.h" #include "FX.h" #include "palettes.h" +#ifdef ARDUINO_ARCH_ESP32 +#include // WLEDMM to get esp_timer_get_time() +#endif /* Custom per-LED mapping has moved! @@ -206,7 +209,7 @@ void Segment::setUpLeds() { else if (!leds) { #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) if (psramFound()) - leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); + leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // WLEDMM: stupid - PSRAM is too slow for this !!! else #endif leds = (CRGB*)malloc(sizeof(CRGB)*length()); @@ -1631,6 +1634,16 @@ void WS2812FX::show(void) { if (diff > 0) fpsCurr = 1000 / diff; _cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2; _lastShow = now; +#ifdef ARDUINO_ARCH_ESP32 // WLEDMM more accurate FPS measurement for ESP32 + uint64_t now500 = esp_timer_get_time() / 2; // native timer; micros /2 -> millis * 500 + int64_t diff500 = now500 - _lastShow500; + if ((diff500 > 300) && (diff500 < 800000)) { // exclude stupid values (timer rollover, major hickups) + float fpcCurr500 = 500000.0f / float(diff500); + if (fpcCurr500 > 2) + _cumulativeFps500 = (3 * _cumulativeFps500 + (500.0 * fpcCurr500)) / 4; // average for some smoothing + } + _lastShow500 = now500; +#endif } /** @@ -1647,7 +1660,11 @@ bool WS2812FX::isUpdating() { */ uint16_t WS2812FX::getFps() { if (millis() - _lastShow > 2000) return 0; +#ifdef ARDUINO_ARCH_ESP32 + return ((_cumulativeFps500 + 250) / 500); // +250 for proper rounding +#else return _cumulativeFps +1; +#endif } void WS2812FX::setTargetFps(uint8_t fps) {