adventsfenster/include/leds.h

294 lines
6.3 KiB
C++

#ifndef __leds_H__
#define __leds_H__
#include "Arduino.h"
#include <Adafruit_NeoPixel.h>
class leds
{
const uint8_t FADESTEPS = 40;
const unsigned long FADE_WAIT_MS = 10;
const uint8_t MAX_BRIGHTNESS = 255;
const uint8_t MIN_BRIGHTNESS = 10;
const unsigned long WAIT_RAINBOWCYCLE_MS = 50;
uint8_t _local_brightness = 255;
float _R = 0;
typedef struct
{
uint16_t lednr;
uint32_t color;
} _pixel;
unsigned int _pixel_nr = 0;
unsigned int _pixel_last, _pixel_first;
_pixel *_pixels;
uint16_t * _state_flag;
uint16_t _state_mask;
int _fadestep = 0;
unsigned long _last_faded_ms = 0;
bool _fading_done = false;
uint16_t _prev_state = 0;
Adafruit_NeoPixel * _stripe;
uint8_t _s = 0;
uint16_t _h = 0;
float _calc_R();
void _setLeds();
void _setLeds(uint32_t color);
void _resetLeds(uint32_t color);
bool _fade(bool fade_in);
bool _fade_off();
bool _fade_on();
uint16_t _rainbow_pixel, _rainbow_color;
unsigned long _last_rainbowcycle = 0;
uint32_t _wheel(byte pos);
public:
leds(Adafruit_NeoPixel * stripe, uint16_t * state_flag, uint16_t state_mask, uint16_t H, uint8_t S, unsigned int pixel_first, unsigned int pixel_last );
~leds();
void clear();
bool colorWipe( uint32_t color );
void add_button_id(uint16_t mask);
bool do_fade();
bool fade_off();
bool fade_on();
void setBrigthness(uint8_t brigthness);
void setHS(uint16_t H, uint8_t S);
void setColor(uint32_t color);
void rainbowCycle();
};
leds::leds(Adafruit_NeoPixel * stripe, uint16_t * state_flag, uint16_t state_mask, uint16_t H, uint8_t S, unsigned int pixel_first, unsigned int pixel_last )
{
_state_flag = state_flag;
_state_mask = state_mask;
_h = H;
_s = S;
_pixel_last = pixel_last;
_pixel_first = pixel_first;
_pixel_nr = 1 + abs(pixel_last - pixel_first);
_pixels = (_pixel *) malloc(sizeof(_pixel) * _pixel_nr);
size_t index = 0;
for(size_t nr=pixel_first; nr<=pixel_last;nr++)
{
_pixels[index].lednr = nr;
index++;
}
_stripe = stripe;
_R = _calc_R();
_setLeds(0);
_rainbow_pixel = 0;
_rainbow_color = 0;
_prev_state = *_state_flag;
_fading_done = true;
}
leds::~leds()
{
if(NULL != _pixels)
free(_pixels);
}
void leds::_setLeds()
{
for(unsigned int nr = 0; nr < _pixel_nr; nr++)
{
_stripe->setPixelColor(_pixels[nr].lednr, _pixels[nr].color);
}
}
void leds::_setLeds(uint32_t color)
{
for(unsigned int nr = 0; nr < _pixel_nr; nr++)
{
//Serial.printf("setting led %d with nr %d in stripe to color %d\n", nr, _pixels[nr].lednr, color);
_stripe->setPixelColor(_pixels[nr].lednr, color);
_pixels[nr].color = color;
}
}
void leds::clear()
{
_setLeds(0);
}
void leds::add_button_id(uint16_t id)
{
_state_mask = _state_mask | id;
}
bool leds::do_fade()
{
bool updated = false;
uint16_t curr_state = _state_mask & *_state_flag;
if(_prev_state != curr_state)
{
//Serial.printf("Current state is 0x%08x\n", curr_state);
_prev_state = curr_state;
_fading_done = false;
}
if(_fading_done == false)
{
updated = true;
if(0 == curr_state)
{
_fade_off();
//Serial.printf("Fading off.\n");
}
else
{
_fade_on();
//Serial.printf("Fading ON\n");
}
}
return updated;
}
bool leds::fade_on()
{
return _fade_on();
}
bool leds::fade_off()
{
return _fade_off();
}
float leds::_calc_R(void)
{
return (FADESTEPS * log10(2))/(log10(_local_brightness));
}
void leds::setBrigthness(uint8_t brigthness)
{
if(brigthness > MAX_BRIGHTNESS)
_local_brightness = MAX_BRIGHTNESS;
else
{
if(brigthness < MIN_BRIGHTNESS)
_local_brightness = MIN_BRIGHTNESS;
else
_local_brightness = brigthness;
}
_R = _calc_R();
uint8_t fade = pow (2, (_fadestep / _R)) - 1;
_setLeds(_stripe->ColorHSV(_h, _s, fade));
}
void leds::setHS(uint16_t H, uint8_t S)
{
_h = H;
_s = S;
uint8_t fade = pow (2, (_fadestep / _R)) - 1;
_setLeds(_stripe->ColorHSV(_h, _s, fade));
}
void leds::setColor(uint32_t color)
{
_setLeds(color);
}
bool leds::_fade(bool fade_in)
{
unsigned long curr_millis = millis();
if( _last_faded_ms > (curr_millis - FADE_WAIT_MS))
return(false);
_last_faded_ms = curr_millis;
if(_fadestep != -1)
{
uint8_t fade = pow (2, (_fadestep / _R)) - 1;
_setLeds(_stripe->ColorHSV(_h, _s, fade));
}
if(true == fade_in)
{
if(_fadestep == -1)
_fadestep = 0;
else
{
if(_fadestep<FADESTEPS)
_fadestep++ ;
else
{
_fadestep = -1;
_fading_done = true;
return(true);
}
}
}
else
{
if(_fadestep == -1)
_fadestep = FADESTEPS;
else
{
if(_fadestep>0)
_fadestep--;
else
{
_fadestep = -1;
_fading_done = true;
return(true);
}
}
}
return(false);
}
bool leds::_fade_on()
{
return _fade(true);
}
bool leds::_fade_off()
{
return _fade(false);
}
void leds::rainbowCycle()
{
if((millis() - _last_rainbowcycle) > WAIT_RAINBOWCYCLE_MS)
{
//Serial.printf("Rainbow! Next color\n");
_last_rainbowcycle = millis();
_rainbow_color++;
if(_rainbow_color >= 256*1)
_rainbow_color = 0;
for(size_t nr = 0; nr< _pixel_nr; ++nr) {
_pixels[nr].color = _wheel(((_rainbow_pixel * 256 / _pixel_nr) + _rainbow_color) & 255);
}
_setLeds();
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t leds::_wheel(byte pos) {
pos = 255 - pos;
if(pos < 85) {
return _stripe->Color(255 - pos * 3, 0, pos * 3);
}
if(pos < 170) {
pos -= 85;
return _stripe->Color(0, pos * 3, 255 - pos * 3);
}
pos -= 170;
return _stripe->Color(pos * 3, 255 - pos * 3, 0);
}
#endif