-
-
Save focalintent/2680020e65de7fd1f6fc6cf8cea4e716 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
FASTLED_NAMESPACE_BEGIN | |
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES | |
extern uint32_t _frame_cnt; | |
extern uint32_t _retry_cnt; | |
#endif | |
// Info on reading cycle counter from https://github.com/kbeckmann/nodemcu-firmware/blob/ws2812-dual/app/modules/ws2812.c | |
__attribute__ ((always_inline)) inline static uint32_t __clock_cycles() { | |
uint32_t cyc; | |
__asm__ __volatile__ ("rsr %0,ccount":"=a" (cyc)); | |
return cyc; | |
} | |
#define FASTLED_HAS_CLOCKLESS 1 | |
template <int DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 5> | |
class ClocklessController : public CPixelLEDController<RGB_ORDER> { | |
typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t; | |
typedef typename FastPin<DATA_PIN>::port_t data_t; | |
data_t mPinMask; | |
data_ptr_t mPort; | |
CMinWait<WAIT_TIME> mWait; | |
public: | |
virtual void init() { | |
FastPin<DATA_PIN>::setOutput(); | |
mPinMask = FastPin<DATA_PIN>::mask(); | |
mPort = FastPin<DATA_PIN>::port(); | |
} | |
virtual uint16_t getMaxRefreshRate() const { return 400; } | |
protected: | |
virtual void showPixels(PixelController<RGB_ORDER> & pixels) { | |
// mWait.wait(); | |
int cnt = FASTLED_INTERRUPT_RETRY_COUNT; | |
while((showRGBInternal(pixels)==0) && cnt--) { | |
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES | |
_retry_cnt++; | |
#endif | |
os_intr_unlock(); | |
delayMicroseconds(WAIT_TIME); | |
os_intr_lock(); | |
} | |
// mWait.mark(); | |
} | |
#define _ESP_ADJ (0) | |
#define _ESP_ADJ2 (0) | |
template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & last_mark, register uint32_t b) { | |
b = ~b; b <<= 24; | |
for(register uint32_t i = BITS; i > 0; i--) { | |
while((__clock_cycles() - last_mark) < (T1+T2+T3)); | |
last_mark = __clock_cycles(); | |
FastPin<DATA_PIN>::hi(); | |
while((__clock_cycles() - last_mark) < T1); | |
if(b & 0x80000000L) { FastPin<DATA_PIN>::lo(); } | |
b <<= 1; | |
while((__clock_cycles() - last_mark) < (T1+T2)); | |
FastPin<DATA_PIN>::lo(); | |
} | |
} | |
// This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then | |
// gcc will use register Y for the this pointer. | |
static uint32_t ICACHE_RAM_ATTR showRGBInternal(PixelController<RGB_ORDER> pixels) { | |
// Setup the pixel controller and load/scale the first byte | |
pixels.preStepFirstByteDithering(); | |
register uint32_t b = pixels.loadAndScale0(); | |
pixels.preStepFirstByteDithering(); | |
os_intr_lock(); | |
uint32_t start = __clock_cycles(); | |
uint32_t last_mark = start; | |
while(pixels.has(1)) { | |
// Write first byte, read next byte | |
writeBits<8+XTRA0>(last_mark, b); | |
b = pixels.loadAndScale1(); | |
// Write second byte, read 3rd byte | |
writeBits<8+XTRA0>(last_mark, b); | |
b = pixels.loadAndScale2(); | |
// Write third byte, read 1st byte of next pixel | |
writeBits<8+XTRA0>(last_mark, b); | |
b = pixels.advanceAndLoadAndScale0(); | |
// write out all 0's for the 4th byte for RGBW strips - this is a | |
// hack and will break your RGB WS2812 strips. | |
writeBits<8+XTRA0>(last_mark, 0); | |
#if (FASTLED_ALLOW_INTERRUPTS == 1) | |
os_intr_unlock(); | |
#endif | |
pixels.stepDithering(); | |
#if (FASTLED_ALLOW_INTERRUPTS == 1) | |
os_intr_lock(); | |
// if interrupts took longer than 45µs, punt on the current frame | |
if((int32_t)(__clock_cycles()-last_mark) > 0) { | |
if((int32_t)(__clock_cycles()-last_mark) > (T1+T2+T3+((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US))) { sei(); return 0; } | |
} | |
#endif | |
}; | |
os_intr_unlock(); | |
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES | |
_frame_cnt++; | |
#endif | |
return __clock_cycles() - start; | |
} | |
}; | |
FASTLED_NAMESPACE_END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Daniel!
I searched the web for recent findings in adapting FastLED for SK6812 GRBW LED strips and came here from issues/106#issuecomment-227946878.
I did my first steps with ESP8266 and a LED matrix consiting of SK6812 GRBW LEDs building a so called WordClock.
On the search for a means of setting the color of my LEDs I stumbeled over the work from Jason Coon and adapted his demo to fit to my hardware, getting stopped by FastLED not supporting RGBW LEDs, still.
So I impemented your proposal.
Let me tell you that your hack for Yosef Shlomo works fine for me, too.
Additional I found, that you missed to adapt the wait time in line 19 of this hack from 5 to the new value 50.
After changing this value to 50 (as in the main project) the transitions and effects in Jasons demo are flickerless and no more spurious pixels occur in the dark part behind the animations.
Thanks!
Harald