Skip to content

Commit

Permalink
Delay code written for Arduino was no longer quite right and prone to…
Browse files Browse the repository at this point in the history
… overflow

On ESP32 we can use 64bits and the native libraries and it's OK
  • Loading branch information
bbulkow committed Sep 22, 2020
1 parent 162a962 commit 47f83d4
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
28 changes: 22 additions & 6 deletions components/FastLED-idf/fastled_delay.h
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<int WAIT> 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(); }
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class ClocklessController : public CPixelLEDController<RGB_ORDER>
PixelController<RGB_ORDER> * mPixels;

// -- Make sure we can't call show() too quickly
CMinWait<50> mWait;
CMinWait<55> mWait;

public:

Expand Down
12 changes: 7 additions & 5 deletions components/FastLED-idf/platforms/esp/32/clockless_rmt_esp32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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) ) {

Expand All @@ -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.
Expand Down

0 comments on commit 47f83d4

Please sign in to comment.