Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Garcia <danielgarcia@gmail.com>2016-05-22 15:39:05 +0300
committerDaniel Garcia <danielgarcia@gmail.com>2016-05-22 15:39:05 +0300
commitbaceb63c180d0947a4d505e6458c437f7097bd6d (patch)
tree64ce6b543cf75b636e9238ad8726b4ce496c9243
parent20e5042e9f868c0c56ce08571e0cc3344af9e8f4 (diff)
Tweak 4-way parallel output to work on pins 12-15 on esp8266 - keep blocked out for now, needs some more testing.
-rw-r--r--bitswap.h2
-rw-r--r--platforms/esp/8266/clockless_block_esp8266.h139
-rw-r--r--platforms/esp/8266/clockless_esp8266.h62
-rw-r--r--platforms/esp/8266/fastpin_esp8266.h23
4 files changed, 110 insertions, 116 deletions
diff --git a/bitswap.h b/bitswap.h
index 05b36a9e..64fed49e 100644
--- a/bitswap.h
+++ b/bitswap.h
@@ -168,6 +168,8 @@ __attribute__((always_inline)) inline void slowswap(unsigned char *A, unsigned c
}
}
+void transpose8x1_noinline(unsigned char *A, unsigned char *B);
+
/// Simplified form of bits rotating function. Based on code found here - http://www.hackersdelight.org/hdcodetxt/transpose8.c.txt - rotating
/// data into LSB for a faster write (the code using this data can happily walk the array backwards)
__attribute__((always_inline)) inline void transpose8x1(unsigned char *A, unsigned char *B) {
diff --git a/platforms/esp/8266/clockless_block_esp8266.h b/platforms/esp/8266/clockless_block_esp8266.h
index 03c334e6..7ef284e7 100644
--- a/platforms/esp/8266/clockless_block_esp8266.h
+++ b/platforms/esp/8266/clockless_block_esp8266.h
@@ -4,14 +4,14 @@
#define FASTLED_HAS_BLOCKLESS 1
#define PORTA_FIRST_PIN 0
-#define PORT_MASK (((1<<LANES)-1) & 0xFFFF)
+#define PORT_MASK (((1<<LANES)-1) & 0x0000FFFFL)
#define MIN(X,Y) (((X)<(Y)) ? (X):(Y))
#define USED_LANES (MIN(LANES,16))
#define LAST_PIN (FIRST_PIN + USED_LANES - 1)
FASTLED_NAMESPACE_BEGIN
-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 = 40>
+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 = 5>
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;
@@ -23,15 +23,22 @@ public:
virtual int size() { return CLEDController::size() * LANES; }
virtual void showPixels(PixelController<RGB_ORDER, LANES, PORT_MASK> & pixels) {
- mWait.wait();
- uint32_t clocks = showRGBInternal(pixels);
+ // mWait.wait();
+ /*uint32_t clocks = */
+ int cnt=2;
+ while(!showRGBInternal(pixels) && cnt--) {
+ os_intr_unlock();
+ delayMicroseconds(WAIT_TIME * 10);
+ os_intr_lock();
+ showRGBInternal(pixels);
+ }
// #if FASTLED_ALLOW_INTTERUPTS == 0
// Adjust the timer
// long microsTaken = CLKS_TO_MICROS(clocks);
// MS_COUNTER += (1 + (microsTaken / 1000));
// #endif
- mWait.mark();
+ // mWait.mark();
}
template<int PIN> static void initPin() {
@@ -41,116 +48,89 @@ public:
}
virtual void init() {
- initPin<0>();
- initPin<1>();
- initPin<2>();
- initPin<3>();
- initPin<4>();
- initPin<5>();
- initPin<6>();
- initPin<7>();
- initPin<8>();
- initPin<9>();
- initPin<10>();
- initPin<11>();
+ // initPin<0>();
+ // initPin<1>();
+ // initPin<2>();
+ // initPin<3>();
+ // initPin<4>();
+ // initPin<5>();
+ // initPin<6>();
+ // initPin<7>();
+ // initPin<8>();
+ // initPin<9>();
+ // initPin<10>();
+ // initPin<11>();
initPin<12>();
initPin<13>();
initPin<14>();
initPin<15>();
mPinMask = FastPin<FIRST_PIN>::mask();
mPort = FastPin<FIRST_PIN>::port();
+
+ // Serial.print("Mask is "); Serial.println(PORT_MASK);
}
virtual uint16_t getMaxRefreshRate() const { return 400; }
typedef union {
- uint8_t bytes[12];
- uint16_t shorts[6];
- uint32_t raw[3];
+ uint8_t bytes[8];
+ uint16_t shorts[4];
+ uint32_t raw[2];
} Lines;
-#define ESP_ADJUST (2*(F_CPU/24000000))
+#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 & next_mark, register Lines & b, PixelController<RGB_ORDER, LANES, PORT_MASK> &pixels) { // , register uint32_t & b2) {
- register Lines b2;
- if(USED_LANES>8) {
- transpose8<1,2>(b.bytes,b2.bytes);
- transpose8<1,2>(b.bytes+8,b2.bytes+1);
- } else {
- transpose8x1(b.bytes,b2.bytes);
- }
+ 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/2); i++) {
- while(__clock_cycles() < next_mark);
- next_mark = __clock_cycles() + (T1+T2+T3)-3;
- *FastPin<FIRST_PIN>::sport() = PORT_MASK;
+ for(register uint32_t i = 0; i < USED_LANES; i++) {
+ while((int32_t)(next_mark - __clock_cycles()) > 0);
+ next_mark = __clock_cycles() + (T1+T2+T3) + ESP_ADJUST;
+ *FastPin<FIRST_PIN>::sport() = PORT_MASK << FIRST_PIN;
- while((next_mark - __clock_cycles()) > (T2+T3+ESP_ADJUST));
- if(USED_LANES>8) {
- *FastPin<FIRST_PIN>::cport() = ((~b2.shorts[i]) & PORT_MASK) << FIRST_PIN;
- } else {
- *FastPin<FIRST_PIN>::cport() = ((~b2.bytes[7-i]) & PORT_MASK) << FIRST_PIN;
- }
+ while((int32_t)(next_mark - __clock_cycles()) > (T2+T3+ESP_ADJUST2));
+ *FastPin<FIRST_PIN>::cport() = ((uint32_t)(~b2.bytes[7-i]) & PORT_MASK) << FIRST_PIN;
- while((next_mark - __clock_cycles()) > (T3));
- *FastPin<FIRST_PIN>::cport() = PORT_MASK;
+ while((int32_t)(next_mark - __clock_cycles()) > (T3 + ESP_ADJUST));
+ *FastPin<FIRST_PIN>::cport() = PORT_MASK << FIRST_PIN;
b.bytes[i] = pixels.template loadAndScale<PX>(pixels,i,d,scale);
- b.bytes[i+(USED_LANES/2)] = pixels.template loadAndScale<PX>(pixels,i+(USED_LANES/2),d,scale);
- }
-
- // if folks use an odd numnber of lanes, get the last byte's value here
- if(USED_LANES & 0x01) {
- b.bytes[USED_LANES-1] = pixels.template loadAndScale<PX>(pixels,USED_LANES-1,d,scale);
}
- for(register uint32_t i = USED_LANES/2; i < 8; i++) {
- while(__clock_cycles() < next_mark);
- next_mark = __clock_cycles() + (T1+T2+T3)-3;
- *FastPin<FIRST_PIN>::sport() = PORT_MASK;
- while((next_mark - __clock_cycles()) > (T2+T3+ESP_ADJUST));
- if(USED_LANES>8) {
- *FastPin<FIRST_PIN>::cport() = ((~b2.shorts[i]) & PORT_MASK) << FIRST_PIN;
- } else {
- // b2.bytes[0] = 0;
- *FastPin<FIRST_PIN>::cport() = ((~b2.bytes[7-i]) & PORT_MASK) << FIRST_PIN;
- }
+ for(register uint32_t i = USED_LANES; i < 8; i++) {
+ while((int32_t)(next_mark - __clock_cycles()) > 0);
+ next_mark = __clock_cycles() + (T1+T2+T3) + ESP_ADJUST;
+ *FastPin<FIRST_PIN>::sport() = PORT_MASK << FIRST_PIN;
- while((next_mark - __clock_cycles()) > (T3));
- *FastPin<FIRST_PIN>::cport() = PORT_MASK;
+ while((int32_t)(next_mark - __clock_cycles()) > (T2+T3+ESP_ADJUST2));
+ *FastPin<FIRST_PIN>::cport() = ((uint32_t)(~b2.bytes[7-i]) & PORT_MASK) << FIRST_PIN;
+ while((int32_t)(next_mark - __clock_cycles()) > (T3 + ESP_ADJUST));
+ *FastPin<FIRST_PIN>::cport() = PORT_MASK << FIRST_PIN;
}
}
// 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 showRGBInternal(PixelController<RGB_ORDER, LANES, PORT_MASK> &allpixels) {
- // Get access to the clock
- uint32_t _start = __clock_cycles();
// Setup the pixel controller and load/scale the first byte
- allpixels.preStepFirstByteDithering();
- register Lines b0;
+ Lines b0;
- allpixels.preStepFirstByteDithering();
for(int i = 0; i < USED_LANES; i++) {
b0.bytes[i] = allpixels.loadAndScale0(i);
}
+ allpixels.preStepFirstByteDithering();
os_intr_lock();
- uint32_t next_mark = __clock_cycles() + (T1+T2+T3);
+ uint32_t _start = __clock_cycles();
+ uint32_t next_mark = _start;
while(allpixels.has(1)) {
- #if (FASTLED_ALLOW_INTERRUPTS == 1)
- os_intr_lock();
- // if interrupts took longer than 45µs, punt on the current frame
- if(__clock_cycles() > next_mark) {
- if((__clock_cycles()-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return __clock_cycles(); }
- }
- #endif
- allpixels.stepDithering();
-
// Write first byte, read next byte
writeBits<8+XTRA0,1>(next_mark, b0, allpixels);
@@ -160,9 +140,20 @@ public:
// Write third byte
writeBits<8+XTRA0,0>(next_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()-next_mark) > 0) {
+ if((int32_t)(__clock_cycles()-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { os_intr_unlock(); return 0; }
+ }
+ #endif
};
os_intr_unlock();
diff --git a/platforms/esp/8266/clockless_esp8266.h b/platforms/esp/8266/clockless_esp8266.h
index 7d2fe454..668a8ad1 100644
--- a/platforms/esp/8266/clockless_esp8266.h
+++ b/platforms/esp/8266/clockless_esp8266.h
@@ -9,7 +9,7 @@ __attribute__ ((always_inline)) inline static uint32_t __clock_cycles() {
return cyc;
}
-#ifndef FASTLED_INTERRUPT_RETRY_COUNT
+#ifndef FASTLED_INTERRUPT_RETRY_COUNT
#define FASTLED_INTERRUPT_RETRY_COUNT 2
#endif
@@ -46,34 +46,23 @@ protected:
// mWait.mark();
}
-#define _ESP_ADJ (6)
- template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register uint8_t b) {
- for(register uint32_t i = BITS; i > 0; i--) {
- while(__clock_cycles() < next_mark);
+#define _ESP_ADJ (0)
+#define _ESP_ADJ2 (0)
+
+ template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & next_mark, register uint32_t b) {
+ b = ~b; b <<= 24;
+ for(register uint32_t i = BITS; i > 0; i--) {
+ while((int32_t)(next_mark - __clock_cycles()) > 0);
next_mark = __clock_cycles() + (T1+T2+T3 + _ESP_ADJ);
FastPin<DATA_PIN>::hi();
- if(b&0x80) {
- while((next_mark - __clock_cycles()) > (T3 + _ESP_ADJ));
- FastPin<DATA_PIN>::lo();
- } else {
- while((next_mark - __clock_cycles()) > (T2+T3 + 40));
- FastPin<DATA_PIN>::lo();
- }
- b <<= 1;
- }
+ while((int32_t)(next_mark - __clock_cycles()) > (T2+T3 + _ESP_ADJ2));
+ if(b & 0x80000000L) { FastPin<DATA_PIN>::lo(); }
+ b <<= 1;
- // while(__clock_cycles() < next_mark);
- // next_mark = __clock_cycles() + (T1+T2+T3);
- // FastPin<DATA_PIN>::hi();
- //
- // if(b&0x80) {
- // while((next_mark - __clock_cycles()) > (T3+(2*(F_CPU/24000000))));
- // FastPin<DATA_PIN>::lo();
- // } else {
- // while((next_mark - __clock_cycles()) > (T2+T3+(2*(F_CPU/24000000))));
- // FastPin<DATA_PIN>::lo();
- // }
+ while((int32_t)(next_mark - __clock_cycles()) > (T3 + _ESP_ADJ));
+ 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
@@ -81,20 +70,12 @@ protected:
static uint32_t ICACHE_RAM_ATTR showRGBInternal(PixelController<RGB_ORDER> pixels) {
// Setup the pixel controller and load/scale the first byte
pixels.preStepFirstByteDithering();
- register uint8_t b = pixels.loadAndScale0();
-
+ register uint32_t b = pixels.loadAndScale0();
+ pixels.preStepFirstByteDithering();
os_intr_lock();
uint32_t start = __clock_cycles();
uint32_t next_mark = start + (T1+T2+T3 + _ESP_ADJ);
while(pixels.has(1)) {
- pixels.stepDithering();
- #if (FASTLED_ALLOW_INTERRUPTS == 1)
- os_intr_lock();
- // if interrupts took longer than 45µs, punt on the current frame
- if(__clock_cycles() > next_mark) {
- if((__clock_cycles()-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return 0; }
- }
- #endif
// Write first byte, read next byte
writeBits<8+XTRA0>(next_mark, b);
b = pixels.loadAndScale1();
@@ -106,9 +87,20 @@ protected:
// Write third byte, read 1st byte of next pixel
writeBits<8+XTRA0>(next_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()-next_mark) > 0) {
+ if((int32_t)(__clock_cycles()-next_mark) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return 0; }
+ }
+ #endif
};
os_intr_unlock();
diff --git a/platforms/esp/8266/fastpin_esp8266.h b/platforms/esp/8266/fastpin_esp8266.h
index 04993493..5d4534f8 100644
--- a/platforms/esp/8266/fastpin_esp8266.h
+++ b/platforms/esp/8266/fastpin_esp8266.h
@@ -2,6 +2,15 @@
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:
@@ -11,13 +20,13 @@ public:
inline static void setOutput() { pinMode(PIN, OUTPUT); }
inline static void setInput() { pinMode(PIN, INPUT); }
- inline static void hi() __attribute__ ((always_inline)) { if(PIN < 16) { GPOS = MASK; } else { GP16O |= MASK; } }
- inline static void lo() __attribute__ ((always_inline)) { if(PIN < 16) { GPOC = MASK; } else { GP16O &= ~MASK; } }
- inline static void set(register port_t val) __attribute__ ((always_inline)) { if(PIN < 16) { GPO = val; } else { GP16O = val; }}
+ 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) { GPO ^= MASK; } else { GP16O ^= MASK; } }
+ 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(); }
@@ -25,9 +34,9 @@ public:
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 &GPO; } else { return &GP16O; } }
- inline static port_ptr_t sport() __attribute__ ((always_inline)) { return &GPOS; } // there is no GP160 support for this
- inline static port_ptr_t cport() __attribute__ ((always_inline)) { return &GPOC; }
+ 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); }