WSLed/src/wsLED.cpp

146 lines
3.6 KiB
C++
Raw Normal View History

2020-04-04 09:52:53 +02:00
// Ovladani signalizacni chytre LED diody
#include "wsLED.h"
// due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
// moved into a C file so the attribute will be applied correctly
extern "C" void ICACHE_RAM_ATTR send_pixels_800(uint8_t* pixel, size_t count, uint8_t pin);
#define countof(a) (sizeof(a) / sizeof(a[0]))
static const uint16_t LB[] PROGMEM = {
0x201 , 0x202 , 0x103 , 0x104 , 0x105 , 0x106 , 0x107 , 0x109 , 0x10a , 0x10c , 0x10e , 0x110 , 0x112 , 0x114 , 0x116 , 0x119 , 0x11c , 0x11e , 0x122 , 0x125 , 0x128 , 0x12c , 0x130 , 0x134,
0x139 , 0x13d , 0x142 , 0x147 , 0x14d , 0x152 , 0x158 , 0x15e , 0x165 , 0x16b , 0x172 , 0x179 , 0x180 , 0x187 , 0x18e , 0x196 , 0x19d , 0x1a5 , 0x1ac , 0x1b3 , 0x1bb , 0x1c2 , 0x1c9 , 0x1cf,
0x1d6 , 0x1dc , 0x1e2 , 0x1e7 , 0x1ec , 0x1f0 , 0x1f4 , 0x1f7 , 0x1fa , 0x1fc , 0x1fd , 0x3fe , 0x1fd , 0x1fb , 0x1f8 , 0x1f5 , 0x1f2 , 0x1ed , 0x1e9 , 0x1e4 , 0x1de , 0x1d8 , 0x1d2 , 0x1cb,
0x1c4 , 0x1bd , 0x1b6 , 0x1af , 0x1a7 , 0x1a0 , 0x198 , 0x191 , 0x18a , 0x182 , 0x17b , 0x174 , 0x16d , 0x167 , 0x161 , 0x15a , 0x154 , 0x14f , 0x149 , 0x144 , 0x13f , 0x13a , 0x136 , 0x131,
0x12d , 0x12a , 0x126 , 0x123 , 0x11f , 0x11c , 0x11a , 0x117 , 0x115 , 0x112 , 0x110 , 0x10e , 0x10c , 0x10b , 0x109 , 0x108 , 0x107 , 0x105 , 0x104 , 0x203 , 0x102 , 0x201 , 0x2a00
};
inline bool wsLED::canShow(void)
{
return (micros() - _endtime) >= 50L;
}
void wsLED::show(void)
{
uint8_t color[3];
for (uint8_t i = 0; i < 3; i++) {
// https://github.com/FastLED/FastLED/wiki/FastLED-Color-Correction
uint16_t c = (uint16_t)_color[i] * (1 + (uint16_t)_scale);
color[i] = (uint8_t)(c >> 8);
}
while (!canShow())
__asm__ volatile ("nop");
#if defined(ARDUINO_ARCH_ESP32)
uint32_t volatile register ilevel = XTOS_DISABLE_ALL_INTERRUPTS;
#else
noInterrupts();
//cli();
#endif
send_pixels_800(color, 1, _pin);
#if defined(ARDUINO_ARCH_ESP32)
XTOS_RESTORE_INTLEVEL(ilevel);
#else
interrupts();
//sei();
#endif
_endtime = micros();
}
wsLED::wsLED(int pin, int order)
{
_pin = pin;
_order = order;
}
void wsLED::begin(void)
{
pinMode(_pin, OUTPUT);
_color[0] = _color[1] = _color[2] = 0;
show();
}
void wsLED::setColor(LEDRGB &color)
{
_color[(_order >> 6) & 7] = color.r;
_color[(_order >> 3) & 7] = color.g;
_color[_order & 7] = color.b;
}
void ICACHE_RAM_ATTR wsLED::rtLed(void)
{
switch (_ledState) {
case LED_BLINK:
_scale = 0xff;
if (_subState) {
_subState = 0;
setColor(_color2);
} else {
_subState = 1;
setColor(_color1);
}
show();
break;
case LED_BREATH: {
++_subState;
_subState %= countof(LB);
uint16_t val = pgm_read_word(&LB[_subState]);
_scale = (uint8_t)val;
show();
val >>= 8;
_handler.attach_ms(30ul * val, lh, this);
break;
}
default:
_handler.attach_ms(300, lh, this); // jen pomale casovani
break;
}
}
void ICACHE_RAM_ATTR wsLED::lh(wsLED *ptr)
{
wsLED *pled = ptr;
pled->rtLed();
}
void wsLED::setColors(LEDRGB color1, LEDRGB color2)
{
_color1 = color1;
_color2 = color2;
}
void wsLED::blink(int speed)
{
_handler.detach();
_ledState = LED_BLINK;
_subState = 1;
_handler.attach_ms(300, lh, this);
}
void wsLED::breath(void)
{
_handler.detach();
_ledState = LED_BREATH;
_subState = 0;
setColor(_color1);
_handler.attach_ms(1, lh, this);
}
void wsLED::setOrder(int neworder)
{
_order = neworder;
}