First commit.

This commit is contained in:
2020-07-17 18:55:06 +02:00
commit b47a0ab935
247 changed files with 30192 additions and 0 deletions

View File

@ -0,0 +1,159 @@
#ifndef __INC_CLOCKLESS_BLOCK_ESP8266_H
#define __INC_CLOCKLESS_BLOCK_ESP8266_H
#define FASTLED_HAS_BLOCKLESS 1
#define FIX_BITS(bits) (((bits & 0x0fL) << 12) | (bits & 0x30))
#define MIN(X,Y) (((X)<(Y)) ? (X):(Y))
#define USED_LANES (MIN(LANES, 6))
#define PORT_MASK (((1 << USED_LANES)-1) & 0x0000FFFFL)
#define PIN_MASK FIX_BITS(PORT_MASK)
FASTLED_NAMESPACE_BEGIN
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
extern uint32_t _frame_cnt;
extern uint32_t _retry_cnt;
#endif
template <uint8_t LANES, int FIRST_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = GRB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50>
class InlineBlockClocklessController : public CPixelLEDController<RGB_ORDER, LANES, PORT_MASK> {
typedef typename FastPin<FIRST_PIN>::port_ptr_t data_ptr_t;
typedef typename FastPin<FIRST_PIN>::port_t data_t;
CMinWait<WAIT_TIME> mWait;
public:
virtual int size() { return CLEDController::size() * LANES; }
virtual void showPixels(PixelController<RGB_ORDER, LANES, PORT_MASK> & pixels) {
// mWait.wait();
/*uint32_t clocks = */
int cnt=FASTLED_INTERRUPT_RETRY_COUNT;
while(!showRGBInternal(pixels) && cnt--) {
os_intr_unlock();
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
_retry_cnt++;
#endif
delayMicroseconds(WAIT_TIME * 10);
os_intr_lock();
}
// #if FASTLED_ALLOW_INTTERUPTS == 0
// Adjust the timer
// long microsTaken = CLKS_TO_MICROS(clocks);
// MS_COUNTER += (1 + (microsTaken / 1000));
// #endif
// mWait.mark();
}
template<int PIN> static void initPin() {
_ESPPIN<PIN, 1<<(PIN & 0xFF)>::setOutput();
}
virtual void init() {
void (* funcs[])() ={initPin<12>, initPin<13>, initPin<14>, initPin<15>, initPin<4>, initPin<5>};
for (uint8_t i = 0; i < USED_LANES; ++i) {
funcs[i]();
}
}
virtual uint16_t getMaxRefreshRate() const { return 400; }
typedef union {
uint8_t bytes[8];
uint16_t shorts[4];
uint32_t raw[2];
} Lines;
#define ESP_ADJUST 0 // (2*(F_CPU/24000000))
#define ESP_ADJUST2 0
template<int BITS,int PX> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & last_mark, register Lines & b, PixelController<RGB_ORDER, LANES, PORT_MASK> &pixels) { // , register uint32_t & b2) {
Lines b2 = b;
transpose8x1_noinline(b.bytes,b2.bytes);
register uint8_t d = pixels.template getd<PX>(pixels);
register uint8_t scale = pixels.template getscale<PX>(pixels);
for(register uint32_t i = 0; i < USED_LANES; i++) {
while((__clock_cycles() - last_mark) < (T1+T2+T3));
last_mark = __clock_cycles();
*FastPin<FIRST_PIN>::sport() = PIN_MASK;
uint32_t nword = (uint32_t)(~b2.bytes[7-i]);
while((__clock_cycles() - last_mark) < (T1-6));
*FastPin<FIRST_PIN>::cport() = FIX_BITS(nword);
while((__clock_cycles() - last_mark) < (T1+T2));
*FastPin<FIRST_PIN>::cport() = PIN_MASK;
b.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale);
}
for(register uint32_t i = USED_LANES; i < 8; i++) {
while((__clock_cycles() - last_mark) < (T1+T2+T3));
last_mark = __clock_cycles();
*FastPin<FIRST_PIN>::sport() = PIN_MASK;
uint32_t nword = (uint32_t)(~b2.bytes[7-i]);
while((__clock_cycles() - last_mark) < (T1-6));
*FastPin<FIRST_PIN>::cport() = FIX_BITS(nword);
while((__clock_cycles() - last_mark) < (T1+T2));
*FastPin<FIRST_PIN>::cport() = PIN_MASK;
}
}
// 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, LANES, PORT_MASK> &allpixels) {
// Setup the pixel controller and load/scale the first byte
Lines b0;
for(int i = 0; i < USED_LANES; i++) {
b0.bytes[i] = allpixels.loadAndScale0(i);
}
allpixels.preStepFirstByteDithering();
os_intr_lock();
uint32_t _start = __clock_cycles();
uint32_t last_mark = _start;
while(allpixels.has(1)) {
// Write first byte, read next byte
writeBits<8+XTRA0,1>(last_mark, b0, allpixels);
// Write second byte, read 3rd byte
writeBits<8+XTRA0,2>(last_mark, b0, allpixels);
allpixels.advanceData();
// Write third byte
writeBits<8+XTRA0,0>(last_mark, b0, allpixels);
#if (FASTLED_ALLOW_INTERRUPTS == 1)
os_intr_unlock();
#endif
allpixels.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))) { os_intr_unlock(); return 0; }
}
#endif
};
os_intr_unlock();
#ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
_frame_cnt++;
#endif
return __clock_cycles() - _start;
}
};
FASTLED_NAMESPACE_END
#endif

View File

@ -0,0 +1,117 @@
#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 = 50>
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 <<= 24; b = ~b;
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();
#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

View File

@ -0,0 +1,5 @@
#pragma once
#include "fastpin_esp8266.h"
#include "clockless_esp8266.h"
#include "clockless_block_esp8266.h"

View File

@ -0,0 +1,101 @@
#pragma once
FASTLED_NAMESPACE_BEGIN
struct FASTLED_ESP_IO {
volatile uint32_t _GPO;
volatile uint32_t _GPOS;
volatile uint32_t _GPOC;
};
#define _GPB (*(FASTLED_ESP_IO*)(0x60000000+(0x300)))
template<uint8_t PIN, uint32_t MASK> class _ESPPIN {
public:
typedef volatile uint32_t * port_ptr_t;
typedef uint32_t port_t;
inline static void setOutput() { pinMode(PIN, OUTPUT); }
inline static void setInput() { pinMode(PIN, INPUT); }
inline static void hi() __attribute__ ((always_inline)) { if(PIN < 16) { _GPB._GPOS = MASK; } else { GP16O |= MASK; } }
inline static void lo() __attribute__ ((always_inline)) { if(PIN < 16) { _GPB._GPOC = MASK; } else { GP16O &= ~MASK; } }
inline static void set(register port_t val) __attribute__ ((always_inline)) { if(PIN < 16) { _GPB._GPO = val; } else { GP16O = val; }}
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
inline static void toggle() __attribute__ ((always_inline)) { if(PIN < 16) { _GPB._GPO ^= MASK; } else { GP16O ^= MASK; } }
inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); }
inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); }
inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; }
inline static port_t hival() __attribute__ ((always_inline)) { if (PIN<16) { return GPO | MASK; } else { return GP16O | MASK; } }
inline static port_t loval() __attribute__ ((always_inline)) { if (PIN<16) { return GPO & ~MASK; } else { return GP16O & ~MASK; } }
inline static port_ptr_t port() __attribute__ ((always_inline)) { if(PIN<16) { return &_GPB._GPO; } else { return &GP16O; } }
inline static port_ptr_t sport() __attribute__ ((always_inline)) { return &_GPB._GPOS; } // there is no GP160 support for this
inline static port_ptr_t cport() __attribute__ ((always_inline)) { return &_GPB._GPOC; }
inline static port_t mask() __attribute__ ((always_inline)) { return MASK; }
inline static bool isset() __attribute__ ((always_inline)) { return (PIN < 16) ? (GPO & MASK) : (GP16O & MASK); }
};
#define _FL_DEFPIN(PIN, REAL_PIN) template<> class FastPin<PIN> : public _ESPPIN<REAL_PIN, (1<<(REAL_PIN & 0xFF))> {};
#ifdef FASTLED_ESP8266_RAW_PIN_ORDER
#define MAX_PIN 16
_FL_DEFPIN(0,0); _FL_DEFPIN(1,1); _FL_DEFPIN(2,2); _FL_DEFPIN(3,3);
_FL_DEFPIN(4,4); _FL_DEFPIN(5,5);
// These pins should be disabled, as they always cause WDT resets
// _FL_DEFPIN(6,6); _FL_DEFPIN(7,7);
// _FL_DEFPIN(8,8); _FL_DEFPIN(9,9); _FL_DEFPIN(10,10); _FL_DEFPIN(11,11);
_FL_DEFPIN(12,12); _FL_DEFPIN(13,13); _FL_DEFPIN(14,14); _FL_DEFPIN(15,15);
_FL_DEFPIN(16,16);
#define PORTA_FIRST_PIN 12
#elif defined(FASTLED_ESP8266_D1_PIN_ORDER)
#define MAX_PIN 15
_FL_DEFPIN(0,3);
_FL_DEFPIN(1,1);
_FL_DEFPIN(2,16);
_FL_DEFPIN(3,5);
_FL_DEFPIN(4,4);
_FL_DEFPIN(5,14);
_FL_DEFPIN(6,12);
_FL_DEFPIN(7,13);
_FL_DEFPIN(8,0);
_FL_DEFPIN(9,2);
_FL_DEFPIN(10,15);
_FL_DEFPIN(11,13);
_FL_DEFPIN(12,12);
_FL_DEFPIN(13,14);
_FL_DEFPIN(14,4);
_FL_DEFPIN(15,5);
#define PORTA_FIRST_PIN 12
#else // if defined(FASTLED_ESP8266_NODEMCU_PIN_ORDER)
#define MAX_PIN 10
// This seems to be the standard Dxx pin mapping on most of the esp boards that i've found
_FL_DEFPIN(0,16); _FL_DEFPIN(1,5); _FL_DEFPIN(2,4); _FL_DEFPIN(3,0);
_FL_DEFPIN(4,2); _FL_DEFPIN(5,14); _FL_DEFPIN(6,12); _FL_DEFPIN(7,13);
_FL_DEFPIN(8,15); _FL_DEFPIN(9,3); _FL_DEFPIN(10,1);
#define PORTA_FIRST_PIN 6
// The rest of the pins - these are generally not available
// _FL_DEFPIN(11,6);
// _FL_DEFPIN(12,7); _FL_DEFPIN(13,8); _FL_DEFPIN(14,9); _FL_DEFPIN(15,10);
// _FL_DEFPIN(16,11);
#endif
#define HAS_HARDWARE_PIN_SUPPORT
#define FASTLED_NAMESPACE_END

View File

@ -0,0 +1,39 @@
#pragma once
#ifndef ESP8266
#define ESP8266
#endif
#define FASTLED_ESP8266
// Use system millis timer
#define FASTLED_HAS_MILLIS
typedef volatile uint32_t RoReg;
typedef volatile uint32_t RwReg;
typedef uint32_t prog_uint32_t;
// Default to NOT using PROGMEM here
#ifndef FASTLED_USE_PROGMEM
# define FASTLED_USE_PROGMEM 0
#endif
#ifndef FASTLED_ALLOW_INTERRUPTS
# define FASTLED_ALLOW_INTERRUPTS 1
# define INTERRUPT_THRESHOLD 0
#endif
#define NEED_CXX_BITS
// These can be overridden
#if !defined(FASTLED_ESP8266_RAW_PIN_ORDER) && !defined(FASTLED_ESP8266_NODEMCU_PIN_ORDER) && !defined(FASTLED_ESP8266_D1_PIN_ORDER)
# ifdef ARDUINO_ESP8266_NODEMCU
# define FASTLED_ESP8266_NODEMCU_PIN_ORDER
# else
# define FASTLED_ESP8266_RAW_PIN_ORDER
# endif
#endif
// #define cli() os_intr_lock();
// #define sei() os_intr_lock();