#ifndef __leds_H__ #define __leds_H__ #include "Arduino.h" #include 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; uint32_t * _state_flag; uint32_t _state_mask; int _fadestep = 0; unsigned long _last_faded_ms = 0; bool _fading_done = false; uint16_t _prev_state = 0; Adafruit_NeoPixel * _stripe; int _tcr_firstPixelHue; int _tcr_b ; 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; uint16_t _blue_color, _blue_pixel; unsigned long _last_rainbowcycle = 0; uint32_t _wheel(byte pos); public: enum led_update {UP_RAINBOW = 1, UP_FADE = 2, UP_BLUE = 4}; leds(Adafruit_NeoPixel * stripe, uint32_t * state_flag, uint16_t state_mask, uint16_t H, uint8_t S, unsigned int pixel_first, unsigned int pixel_last ); ~leds(); bool update(); bool update(led_update type); 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(); bool do_rainbowCycle(); void theaterChaseRainbow(); void blueCycle(); bool do_blueCycle(); }; leds::leds(Adafruit_NeoPixel * stripe, uint32_t * state_flag, uint16_t state_mask, uint16_t H, uint8_t S, unsigned int pixel_first, unsigned int pixel_last ) { _blue_color = 0; _blue_pixel = 0; _tcr_firstPixelHue = 0; _tcr_b = 0; _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::update() { return(update(UP_FADE)); } bool leds::update(led_update type) { if(type == UP_RAINBOW ) { return(do_rainbowCycle()); } if(type == UP_BLUE ) { return(do_blueCycle()); } if(type == UP_FADE) { return(do_fade()); } return(false); } bool leds::do_rainbowCycle() { bool updated = false; uint16_t curr_state = _state_mask & *_state_flag; if(curr_state == 0) { clear(); } else { rainbowCycle(); updated = true; } return(updated); } bool leds::do_blueCycle() { bool updated = false; uint16_t curr_state = _state_mask & *_state_flag; if(curr_state == 0) { clear(); } else { blueCycle(); updated = true; } return(updated); } 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(_fadestep0) _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::theaterChaseRainbow() { if((millis() - _last_rainbowcycle) > WAIT_RAINBOWCYCLE_MS) { _last_rainbowcycle = millis(); _tcr_b++; if(_tcr_b >= 3) _tcr_b = 0; clear(); // Set all pixels in RAM to 0 (off) for(int c=_tcr_b; c<_pixel_nr; c += 3) { int hue = _tcr_firstPixelHue + c * 65536L / _pixel_nr; uint32_t color = _stripe->gamma32(_stripe->ColorHSV(hue)); // hue -> RGB _pixels[c].color = color; } _setLeds(); _tcr_firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames } } 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); _pixels[nr].color = _wheel(((nr * 256 / _pixel_nr) + _rainbow_color) & 255); } _setLeds(); } } void leds::blueCycle() { if((millis() - _last_rainbowcycle) > 2*WAIT_RAINBOWCYCLE_MS) { //Serial.printf("Rainbow! Next color\n"); _last_rainbowcycle = millis(); _blue_color++; if(_blue_color >= 3) _blue_color = 0; for(size_t nr = _blue_color; nr< _pixel_nr; nr = nr+3) { if(_blue_pixel >= 3) _blue_pixel = 0; uint32_t color = _stripe->ColorHSV(43690,255, 1 + _blue_pixel*10); //Serial.printf(" blue_color is %d, cnt is %d , color is %d, pixel is %d\n", _blue_color, _blue_pixel, color, nr); _pixels[nr].color = color; _blue_pixel++; } _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