Files
ESP32lib/ext/led/WS2812B_OLD.h
2018-09-22 15:49:40 +02:00

196 lines
4.5 KiB
C++

#ifndef WS2812B_H
#define WS2812B_H
#include "driver/gpio.h"
#include "rom/ets_sys.h"
#include "xtensa/core-macros.h"
#include "../../data/Color.h"
template <int numLEDs> class WS2812B {
#define WS2812B_PIN GPIO_NUM_27
#define LED_SET_PIN_TO_OUTPUT gpio_set_direction(WS2812B_PIN, GPIO_MODE_OUTPUT);
#define LED_SET_PIN_TO_INPUT gpio_set_direction(WS2812B_PIN, GPIO_MODE_INPUT);
//#define LED_SET_PIN_H gpio_set_level(WS2812B_PIN, 1)
//#define LED_SET_PIN_L gpio_set_level(WS2812B_PIN, 0)
//#define ENABLE_INTERRUPTS XTOS_RESTORE_INTLEVEL(ilevel);
//#define DISABLE_INTERRUPTS uint32_t volatile register ilevel = XTOS_DISABLE_ALL_INTERRUPTS
#define LED_SET_PIN_H GPIO.out_w1ts |= (1 << WS2812B_PIN)
#define LED_SET_PIN_L GPIO.out_w1tc |= (1 << WS2812B_PIN)
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
#define ENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
#define DISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
#define SLEEP_US(us) ets_delay_us(us)
//#define NS_PER_TICK ( (1000ul*1000ul*1000ul) / (80ul*1000ul*1000ul) )
// Color* colors;
/** enable/disable each led */
bool enabled[numLEDs] = {true};
/** color-value for each attached LED */
Color colors[numLEDs];
public:
/** ctor */
WS2812B() {
init();
}
void init() {
LED_SET_PIN_TO_OUTPUT;
}
/** set the color for the given LED */
void setColor(const uint8_t idx, const Color rgb) {
colors[idx] = rgb;
}
/** set the color for all LEDs */
void setColor(const Color rgb) {
for (int idx = 0; idx < numLEDs; ++idx) {
colors[idx] = rgb;
}
}
/** enable/disable the given LED */
void setEnabled(const uint8_t idx, const bool en) {
enabled[idx] = en;
}
/** enable/disable all LEDs */
void setEnabled(const bool en) {
for (int idx = 0; idx < numLEDs; ++idx) {
enabled[idx] = en;
}
}
/** is the given LED enabled? */
bool isEnabled(const uint8_t idx) const {
return enabled[idx];
}
Color& getColor(const uint8_t idx) {
return colors[idx];
}
/** flush configured changes */
IRAM_ATTR void flush() {
SLEEP_US(50);
DISABLE_INTERRUPTS();
LED_SET_PIN_TO_OUTPUT;
// process each LED
for (int i = 0; i < 8; ++i) {
//if (i == 0) {LED_SET_PIN_TO_INPUT;}
//if (i > 0) {LED_SET_PIN_TO_OUTPUT;}
const Color rgb = colors[i];
// send each LEDs 24-bit GRB data
//if (enabled[i]) {
// sendByte(rgb.g);
// sendByte(rgb.r);
// sendByte(rgb.b);
//} else {
sendByte(1);
sendByte(2);
sendByte(3);
//}
}
ENABLE_INTERRUPTS();
reset();
}
private:
IRAM_ATTR __attribute__((always_inline)) inline void sendByte(const uint8_t b) {
if (b & 0b10000000) {send1();} else {send0();}
if (b & 0b01000000) {send1();} else {send0();}
if (b & 0b00100000) {send1();} else {send0();}
if (b & 0b00010000) {send1();} else {send0();}
if (b & 0b00001000) {send1();} else {send0();}
if (b & 0b00000100) {send1();} else {send0();}
if (b & 0b00000010) {send1();} else {send0();}
if (b & 0b00000001) {send1();} else {send0();}
}
IRAM_ATTR __attribute__((always_inline)) inline void send1() { // 800ns high, 450ns low
LED_SET_PIN_H;
delay800();
LED_SET_PIN_L;
delay100();
}
IRAM_ATTR __attribute__((always_inline)) inline void send0() { // 400ns high, 850ns low
LED_SET_PIN_H;
delay100();
//delay100();
LED_SET_PIN_L;
delay800();
}
IRAM_ATTR __attribute__((always_inline)) inline void reset() {
LED_SET_PIN_L;
SLEEP_US(50);
}
//#pragma GCC optimize 0
// one NOP is:
// 80 MHz 12.5 ns
// 240 MHz 4.166 ns
IRAM_ATTR __attribute__((always_inline)) inline void delay100() {
// 24 * 4.166ns = 100ns
asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
// for (register int i = 0; i < 24/6; ++i) {
// asm volatile("nop");
// }
}
IRAM_ATTR __attribute__((always_inline)) inline void delay800() {
delay100();
delay100();
delay100();
delay100();
delay100();
delay100();
delay100();
delay100();
// for (register int i = 0; i < 24*8/6-8; ++i) {
// asm volatile("nop");
// }
}
};
#endif // WS2812B_H