diff --git a/components/FastLED-idf/fastled_delay.h b/components/FastLED-idf/fastled_delay.h index 4649f7d..b6a97d0 100644 --- a/components/FastLED-idf/fastled_delay.h +++ b/components/FastLED-idf/fastled_delay.h @@ -1,6 +1,11 @@ #ifndef __INC_FL_DELAY_H #define __INC_FL_DELAY_H + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_timer.h" + #include "FastLED.h" ///@file fastled_delay.h @@ -11,18 +16,29 @@ FASTLED_NAMESPACE_BEGIN /// Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not enough time has passed yet /// this should make sure that chipsets that have template class CMinWait { - uint16_t mLastMicros; + uint64_t mLastMicros; public: CMinWait() { mLastMicros = 0; } void wait() { - uint16_t diff; - do { - diff = (micros() & 0xFFFF) - mLastMicros; - } while(diff < WAIT); + // how long I been waiting + uint64_t waited = esp_timer_get_time() - mLastMicros; + // fast path, waited long enough + if (waited >= WAIT) return; + // delay vs spin + if ((WAIT - waited) > (portTICK_PERIOD_MS * 1000)) { + int tickDelay = ((WAIT - waited) / 1000) / portTICK_PERIOD_MS; + //printf("cMinWait: %llu micros means delay %d ticks\n",(WAIT - waited),tickDelay); + vTaskDelay( tickDelay ); + } + else { /*buzz is only other option outch */ + do { + waited = esp_timer_get_time() - mLastMicros; + } while( waited > WAIT); + } } - void mark() { mLastMicros = micros() & 0xFFFF; } + void mark() { mLastMicros = esp_timer_get_time(); } }; diff --git a/components/FastLED-idf/platforms/esp/32/clockless_i2s_esp32.h b/components/FastLED-idf/platforms/esp/32/clockless_i2s_esp32.h index 4c256ce..2042148 100644 --- a/components/FastLED-idf/platforms/esp/32/clockless_i2s_esp32.h +++ b/components/FastLED-idf/platforms/esp/32/clockless_i2s_esp32.h @@ -205,7 +205,7 @@ class ClocklessController : public CPixelLEDController PixelController * mPixels; // -- Make sure we can't call show() too quickly - CMinWait<50> mWait; + CMinWait<55> mWait; public: diff --git a/components/FastLED-idf/platforms/esp/32/clockless_rmt_esp32.cpp b/components/FastLED-idf/platforms/esp/32/clockless_rmt_esp32.cpp index d364ea7..fa657f8 100644 --- a/components/FastLED-idf/platforms/esp/32/clockless_rmt_esp32.cpp +++ b/components/FastLED-idf/platforms/esp/32/clockless_rmt_esp32.cpp @@ -31,7 +31,7 @@ static intr_handle_t gRMT_intr_handle = NULL; static xSemaphoreHandle gTX_sem = NULL; // -- Make sure we can't call show() too quickly (fastled library) -CMinWait<50> gWait; +CMinWait<55> gWait; static bool gInitialized = false; @@ -355,7 +355,12 @@ void ESP32RMTController::showPixels() // -- This Take always succeeds immediately xSemaphoreTake(gTX_sem, portMAX_DELAY); - // -- First, fill all the available channels + // -- Make sure it's been at least 50us since last show + // this is very conservative if you have multiple channels, + // arguably there should be a wait on the startnext of each LED string + gWait.wait(); + + // -- First, fill all the available channels and start them int channel = 0; while ( (channel < FASTLED_RMT_MAX_CHANNELS) && (gNext < gNumControllers) ) { @@ -364,9 +369,6 @@ void ESP32RMTController::showPixels() channel++; } - // -- Make sure it's been at least 50us since last show - gWait.wait(); - // -- Wait here while the data is sent. The interrupt handler // will keep refilling the RMT buffers until it is all // done; then it gives the semaphore back.