make "target FPS" work
This commit is contained in:
@@ -43,13 +43,14 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented
|
||||
#endif
|
||||
|
||||
/* Not used in all effects yet */
|
||||
#define FPS_UNLIMITED 249
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH) // WLEDMM go faster on ESP32
|
||||
#define WLED_FPS 120
|
||||
#define FRAMETIME_FIXED (strip.getFrameTime() < 10 ? 12 : 24)
|
||||
#define WLED_FPS_SLOW 60
|
||||
#define FRAMETIME_FIXED_SLOW (15) // = 66 FPS => 1000/66
|
||||
//#define FRAMETIME _frametime
|
||||
#define FRAMETIME strip.getFrameTime()
|
||||
#define MIN_SHOW_DELAY (max(2, (_frametime*5)/8)) // WLEDMM support higher framerates (up to 250fps) -- 5/8 = 62%
|
||||
#else
|
||||
#define WLED_FPS 42
|
||||
#define FRAMETIME_FIXED (1000/WLED_FPS)
|
||||
@@ -57,6 +58,7 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented
|
||||
#define FRAMETIME_FIXED_SLOW (1000/WLED_FPS_SLOW)
|
||||
//#define FRAMETIME _frametime
|
||||
#define FRAMETIME strip.getFrameTime()
|
||||
#define MIN_SHOW_DELAY (_frametime < 16 ? 8 : 15)
|
||||
#endif
|
||||
|
||||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
|
||||
@@ -82,8 +84,6 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented
|
||||
assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */
|
||||
#define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip.getMaxSegments())
|
||||
|
||||
#define MIN_SHOW_DELAY (_frametime < 16 ? (_frametime <8? (_frametime <7? (_frametime <6 ? 2 :3) :4) : 8) : 15) // WLEDMM support higher framerates (up to 250fps)
|
||||
|
||||
#define NUM_COLORS 3 /* number of colors per segment */
|
||||
#define SEGMENT strip._segments[strip.getCurrSegmentId()]
|
||||
#define SEGENV strip._segments[strip.getCurrSegmentId()]
|
||||
@@ -852,6 +852,7 @@ class WS2812FX { // 96 bytes
|
||||
customMappingTableSize(0), //WLEDMM
|
||||
customMappingSize(0),
|
||||
_lastShow(0),
|
||||
_lastServiceShow(0),
|
||||
_segment_index(0),
|
||||
_mainSegment(0)
|
||||
{
|
||||
@@ -1097,6 +1098,7 @@ class WS2812FX { // 96 bytes
|
||||
uint16_t customMappingSize;
|
||||
|
||||
/*uint32_t*/ unsigned long _lastShow; // WLEDMM avoid losing precision
|
||||
unsigned long _lastServiceShow; // WLEDMM last call of strip.show (timestamp)
|
||||
|
||||
uint8_t _segment_index;
|
||||
uint8_t _mainSegment;
|
||||
|
||||
@@ -1873,13 +1873,19 @@ void WS2812FX::service() {
|
||||
if (OTAisRunning) return; // WLEDMM avoid flickering during OTA
|
||||
|
||||
now = nowUp + timebase;
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH)
|
||||
if ((_frametime > 2) && (_frametime < 32) && (nowUp - _lastShow) < (_frametime/2)) return; // WLEDMM experimental - stabilizes frametimes but increases CPU load
|
||||
else if (nowUp - _lastShow < MIN_SHOW_DELAY) return; // WLEDMM fallback
|
||||
#else
|
||||
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
||||
unsigned long elapsed = nowUp - _lastServiceShow;
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH) // WLEDMM go faster on ESP32
|
||||
//if (_suspend) return;
|
||||
if (elapsed < 2) return; // keep wifi alive
|
||||
if ( !_triggered && (_targetFps < FPS_UNLIMITED) && (_targetFps > 0)) {
|
||||
if (elapsed < MIN_SHOW_DELAY) return; // WLEDMM too early for service
|
||||
}
|
||||
#else // legacy
|
||||
if (elapsed < MIN_SHOW_DELAY) return;
|
||||
#endif
|
||||
|
||||
bool doShow = false;
|
||||
unsigned speedLimit = (_targetFps < FPS_UNLIMITED) ? (0.85f * FRAMETIME) : 1; // WLEDMM lower limit for effect frametime
|
||||
|
||||
_isServicing = true;
|
||||
_segment_index = 0;
|
||||
@@ -1914,6 +1920,8 @@ void WS2812FX::service() {
|
||||
// actual code may be a bit more involved as effects have runtime data including allocated memory
|
||||
//if (seg.transitional && seg._modeP) (*_mode[seg._modeP])(progress());
|
||||
frameDelay = (*_mode[seg.currentMode(seg.mode)])();
|
||||
|
||||
if (frameDelay < speedLimit) frameDelay = FRAMETIME; // WLEDMM limit effects that want to go faster than target FPS
|
||||
if (seg.mode != FX_MODE_HALLOWEEN_EYES) seg.call++;
|
||||
if (seg.transitional && frameDelay > FRAMETIME) frameDelay = FRAMETIME; // force faster updates during transition
|
||||
|
||||
@@ -1929,6 +1937,7 @@ void WS2812FX::service() {
|
||||
if(doShow) {
|
||||
yield();
|
||||
show();
|
||||
_lastServiceShow = nowUp; // WLEDMM use correct timestamp
|
||||
}
|
||||
_triggered = false;
|
||||
_isServicing = false;
|
||||
@@ -2053,25 +2062,30 @@ void WS2812FX::show(void) {
|
||||
estimateCurrentAndLimitBri();
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH)
|
||||
unsigned long b4show = millis(); // WLEDMM the time before calling "show"
|
||||
unsigned long now = millis();
|
||||
#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
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 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
|
||||
busses.show();
|
||||
unsigned long now = millis();
|
||||
#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
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned long diff = now - _lastShow;
|
||||
uint16_t fpsCurr = 200;
|
||||
if (diff > 0) fpsCurr = 1000 / diff;
|
||||
_cumulativeFps = (3 * _cumulativeFps + fpsCurr +2) >> 2; // "+2" for proper rounding (2/4 = 0.5)
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH)
|
||||
_lastShow = b4show; // WLEDMM this is more accurate, however it also increases CPU load - strip.service will run more frequently
|
||||
#else
|
||||
_lastShow = now;
|
||||
#endif
|
||||
_lastServiceShow = 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);
|
||||
@@ -2107,6 +2121,7 @@ void WS2812FX::setTargetFps(uint8_t fps) {
|
||||
if (fps > 0 && fps <= 251) _targetFps = fps; // WLEDMM allow higher framerates
|
||||
_frametime = 1000 / _targetFps;
|
||||
if (_frametime < 1) _frametime = 1; // WLEDMM better safe than sorry
|
||||
if (fps >= FPS_UNLIMITED) _frametime = 3; // WLEDMM unlimited mode
|
||||
}
|
||||
|
||||
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||
|
||||
Reference in New Issue
Block a user