Skip to content

Instantly share code, notes, and snippets.

@focalintent
Created June 23, 2016 04:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save focalintent/2680020e65de7fd1f6fc6cf8cea4e716 to your computer and use it in GitHub Desktop.
Save focalintent/2680020e65de7fd1f6fc6cf8cea4e716 to your computer and use it in GitHub Desktop.
#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
@deHarro
Copy link

deHarro commented Oct 14, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment