Files
McLighting/Arduino/McLighting/helper_functions.h
T
bpohvoodoo 4c93854524 Bumpt to 3.1.0BETA6
* Version Bump to 3.1.0.BETA6
 * bugfixes for IR remote control
 * Implemented segments to IR Remote
 * Power supply update
 * bugfix for Button definitions as speed and brightness were interchanged
 * adressed issue #59
 * known problems:
 * Homeassistant will allways use active segment
 * E1.31 is only working for one segment at the moment
2019-12-16 21:04:10 +01:00

319 lines
12 KiB
C

// Prototypes
bool readSegmentStateFS(uint8_t _seg);
// End Prototypes
// Call convertColors whenever main_color, back_color or xtra_color changes.
void convertColors() {
hexcolors_trans[0] = (uint32_t)(main_color.white << 24) | (main_color.red << 16) | (main_color.green << 8) | main_color.blue;
hexcolors_trans[1] = (uint32_t)(back_color.white << 24) | (back_color.red << 16) | (back_color.green << 8) | back_color.blue;
hexcolors_trans[2] = (uint32_t)(xtra_color.white << 24) | (xtra_color.red << 16) | (xtra_color.green << 8) | xtra_color.blue;
}
/*uint32_t* convertColors2(uint8_t _w, uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _w2, uint8_t _r2, uint8_t _g2, uint8_t _b2, uint8_t _w3, uint8_t _r3, uint8_t _g3, uint8_t _b3) {
uint32_t _hexcolors[3] = {};
_hexcolors[0] = (uint32_t)(_w << 24) | (_r << 16) | (_g << 8) | _b;
_hexcolors[1] = (uint32_t)(_w2 << 24) | (_r2 << 16) | (_g2 << 8) | _b2;
_hexcolors[2] = (uint32_t)(_w3 << 24) | (_r3 << 16) | (_g3 << 8) | _b3;
return _hexcolors;
}*/
uint16_t convertSpeed(uint8_t _mcl_speed) {
uint16_t _fx_speed = 0;
if (_mcl_speed < 50) {
_fx_speed = 65535 - (_mcl_speed * 1000);
} else if (_mcl_speed < 100) {
_fx_speed = 16675 - ((_mcl_speed-49) * 250);
} else if (_mcl_speed < 150) {
_fx_speed = 4075 - ((_mcl_speed-99) * 50);
} else if (_mcl_speed < 200) {
_fx_speed = 1550 - ((_mcl_speed-149) * 25);
} else {
_fx_speed = 280 - ((_mcl_speed-199) * 5);
}
_fx_speed = constrain(_fx_speed, SPEED_MIN, SPEED_MAX);
return _fx_speed;
}
/*uint8_t unconvertSpeed(uint16_t _fx_speed) {
uint16_t _mcl_speed = 0;
if (_fx_speed <= 280) {
_mcl_speed = ((280 - _fx_speed)/5) + 199;
} else if (_fx_speed < 1550) {
_mcl_speed = ((1550 - _fx_speed)/25) + 149;
} else if (_fx_speed < 4075) {
_mcl_speed = ((4075 - _fx_speed)/50) + 99;
} else if (_mcl_speed < 16500) {
_mcl_speed = ((16675 - _fx_speed)/250) + 49;
} else {
_mcl_speed = ((65535 - _fx_speed)/1000);
}
return _mcl_speed;
}*/
bool checkPin(uint8_t pin) {
#if defined(USE_WS2812FX_DMA)
#if USE_WS2812FX_DMA == 0
pin = 3;
#endif
#if USE_WS2812FX_DMA == 1
pin = 1;
#endif
#if USE_WS2812FX_DMA == 2
pin = 2;
#endif
#endif
if (((pin >= 0 && pin <= 5) || (pin >= 12 && pin <= 16)) && (pin != Config.pin)) {
Config.pin = pin;
return true;
}
return false;
}
neoPixelType checkRGBOrder(char rgbOrder[5]) {
for( uint8_t i=0 ; i < sizeof(rgbOrder) ; ++i ) rgbOrder[i] = toupper(rgbOrder[i]) ;
DBG_OUTPUT_PORT.printf("Checking RGB Order: %s ...", rgbOrder);
neoPixelType returnOrder = 0;
if (strcmp(rgbOrder, "GRB") == 0) {
returnOrder = NEO_GRB;
} else if (strcmp(rgbOrder, "GBR") == 0) {
returnOrder = NEO_GBR;
} else if (strcmp(rgbOrder, "RGB") == 0) {
returnOrder = NEO_RGB;
} else if (strcmp(rgbOrder, "RBG") == 0) {
returnOrder = NEO_RBG;
} else if (strcmp(rgbOrder, "BRG") == 0) {
returnOrder = NEO_BRG;
} else if (strcmp(rgbOrder, "BGR") == 0) {
returnOrder = NEO_BGR;
} else if (strcmp(rgbOrder, "WGRB") == 0) {
returnOrder = NEO_WGRB;
} else if (strcmp(rgbOrder, "WGBR") == 0) {
returnOrder = NEO_WGBR;
} else if (strcmp(rgbOrder, "WRGB") == 0) {
returnOrder = NEO_WRGB;
} else if (strcmp(rgbOrder, "WRBG") == 0) {
returnOrder = NEO_WRBG;
} else if (strcmp(rgbOrder, "WBRG") == 0) {
returnOrder = NEO_WBRG;
} else if (strcmp(rgbOrder, "WBGR") == 0) {
returnOrder = NEO_WBGR;
} else if (strcmp(rgbOrder, "GWRB") == 0) {
returnOrder = NEO_GWRB;
} else if (strcmp(rgbOrder, "GWBR") == 0) {
returnOrder = NEO_GWBR;
} else if (strcmp(rgbOrder, "RWGB") == 0) {
returnOrder = NEO_RWGB;
} else if (strcmp(rgbOrder, "RWBG") == 0) {
returnOrder = NEO_RWBG;
} else if (strcmp(rgbOrder, "BWRG") == 0) {
returnOrder = NEO_BWRG;
} else if (strcmp(rgbOrder, "BWGR") == 0) {
returnOrder = NEO_BWGR;
} else if (strcmp(rgbOrder, "GRWB") == 0) {
returnOrder = NEO_GRWB;
} else if (strcmp(rgbOrder, "GBWR") == 0) {
returnOrder = NEO_GBWR;
} else if (strcmp(rgbOrder, "RGWB") == 0) {
returnOrder = NEO_RGWB;
} else if (strcmp(rgbOrder, "RBWG") == 0) {
returnOrder = NEO_RBWG;
} else if (strcmp(rgbOrder, "BRWG") == 0){
returnOrder = NEO_BRWG;
} else if (strcmp(rgbOrder, "BGWR") == 0) {
returnOrder = NEO_GRBW;
} else if (strcmp(rgbOrder, "GRBW") == 0) {
returnOrder = NEO_GRBW;
} else if (strcmp(rgbOrder, "GBWR") == 0) {
returnOrder = NEO_GBRW;
} else if (strcmp(rgbOrder, "RGBW") == 0) {
returnOrder = NEO_RGBW;
} else if (strcmp(rgbOrder, "RBGW") == 0) {
returnOrder = NEO_RBGW;
} else if (strcmp(rgbOrder, "BRGW") == 0) {
returnOrder = NEO_BRGW;
} else if (strcmp(rgbOrder, "BGRW") == 0) {
returnOrder = NEO_BGRW;
} else {
DBG_OUTPUT_PORT.print("invalid input!");
uint16_t check = checkRGBOrder(Config.RGBOrder);
if (check != 0) {
returnOrder = static_cast<neoPixelType>(check);
strcpy(rgbOrder, Config.RGBOrder);
} else {
returnOrder = static_cast<neoPixelType>(checkRGBOrder(RGBORDER));
strcpy(rgbOrder, RGBORDER);
}
}
DBG_OUTPUT_PORT.println("success!");
strcpy(Config.RGBOrder, rgbOrder);
return returnOrder;
}
// function to Initialize the strip
void initStrip(uint16_t _stripSize = Config.stripSize, uint8_t _num_segments = Config.segments, char _RGBOrder[5] = Config.RGBOrder, uint8_t _pin = Config.pin){
DBG_OUTPUT_PORT.println("Initializing strip!");
/*#if defined(USE_WS2812FX_DMA)
if (dma != NULL) {
delete(dma);
}
#endif*/
if (strip != NULL) {
strip->strip_off();
delay(10);
if(strip->isRunning()) strip->stop();
strip->resetSegments();
strip->resetSegmentRuntimes();
delete(strip);
Config.stripSize = _stripSize;
strcpy(Config.RGBOrder, _RGBOrder);
Config.pin = _pin;
}
if (ledstates != NULL) {
delete(ledstates);
}
ledstates = new uint8_t [_stripSize];
#if !defined(LED_TYPE_WS2811)
strip = new WS2812FX(_stripSize, _pin, checkRGBOrder(_RGBOrder) + NEO_KHZ800);
#else
strip = new WS2812FX(_stripSize, _pin, checkRGBOrder(_RGBOrder) + NEO_KHZ400);
#endif
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit...if you must, connect GND first.
strip->init();
#if defined(USE_WS2812FX_DMA)
initDMA(_stripSize);
strip->setCustomShow(DMA_Show);
#endif
//parameters: index, start, stop, mode, color, speed, options
for (uint8_t _seg=0; _seg < Config.segments; _seg++) {
if (_seg != State.segment) { // Read actual segment last
(readSegmentStateFS(_seg)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
memcpy(segState.colors[_seg], hexcolors_trans, sizeof(hexcolors_trans));
strip->setSegment(_seg, segState.start, segState.stop, segState.mode[_seg], segState.colors[_seg], convertSpeed(segState.speed[_seg]), segState.options);
}
}
//read actual segment last to set all vars correctly
(readSegmentStateFS(State.segment)) ? DBG_OUTPUT_PORT.println("Segment state config FS read Success!") : DBG_OUTPUT_PORT.println("Segment state config FS read failure!");
memcpy(segState.colors[State.segment], hexcolors_trans, sizeof(hexcolors_trans));
strip->setSegment(State.segment, segState.start, segState.stop , segState.mode[State.segment], hexcolors_trans, convertSpeed(segState.speed[State.segment]), segState.options);
fx_speed = segState.speed[State.segment];
fx_mode = segState.mode[State.segment];
brightness_trans = State.brightness;
prevsegment = State.segment;
strip->setCustomMode(0, F("Autoplay"), handleAuto);
strip->setCustomMode(1, F("Custom WS"), handleCustomWS);
strip->setCustomMode(9, F("Segment OFF"), handleSegmentOFF);
#if defined(CUSTOM_WS2812FX_ANIMATIONS)
strip->setCustomMode(2, F("TV"), handleTV);
strip->setCustomMode(3, F("E1.31"), handleE131);
strip->setCustomMode(4, F("Fire 2012"), handleFire2012);
strip->setCustomMode(5, F("Gradient"), handleGradient);
DBG_OUTPUT_PORT.print("Number of Segments: ");
DBG_OUTPUT_PORT.println(strip->getNumSegments());
if (e131 != NULL) { delete(e131); }
e131 = new ESPAsyncE131(END_UNIVERSE - START_UNIVERSE + 1);
float universe_leds = 170.0; // a universe has only 512 (0..511) channels: 3*170 or 4*128 <= 512
if (strstr(Config.RGBOrder, "W") != NULL) {
//universe_leds = 128.0;
}
float float_enduni = _stripSize/universe_leds;
uint8_t END_UNIVERSE = _stripSize/universe_leds;
if (float_enduni > END_UNIVERSE) {
END_UNIVERSE = END_UNIVERSE +1;
}
// if (e131.begin(E131_UNICAST)) // Listen via Unicast
if (e131->begin(E131_MULTICAST, START_UNIVERSE, END_UNIVERSE)) {// Listen via Multicast
DBG_OUTPUT_PORT.println(F("Listening for data..."));
} else {
DBG_OUTPUT_PORT.println(F("*** e131.begin failed ***"));
}
#endif
}
void getSegmentParams(uint8_t _seg) {
segState.start = strip->getSegment(_seg)->start;;
segState.stop = strip->getSegment(_seg)->stop;;
//segState.mode[_seg] = strip->getMode(_seg);
//segState.speed[_seg] = unconvertSpeed(strip->getSpeed(_seg));
//fx_mode = segState.mode[_seg];
//fx_speed = segState.speed[_seg];
main_color.white = ((segState.colors[_seg][0] >> 24) & 0xFF);
main_color.red = ((segState.colors[_seg][0] >> 16) & 0xFF);
main_color.green = ((segState.colors[_seg][0] >> 8) & 0xFF);
main_color.blue = ((segState.colors[_seg][0]) & 0xFF);
back_color.white = ((segState.colors[_seg][1] >> 24) & 0xFF);
back_color.red = ((segState.colors[_seg][1] >> 16) & 0xFF);
back_color.green = ((segState.colors[_seg][1] >> 8) & 0xFF);
back_color.blue = ((segState.colors[_seg][1]) & 0xFF);
xtra_color.white = ((segState.colors[_seg][2] >> 24) & 0xFF);
xtra_color.red = ((segState.colors[_seg][2] >> 16) & 0xFF);
xtra_color.green = ((segState.colors[_seg][2] >> 8) & 0xFF);
xtra_color.blue = ((segState.colors[_seg][2] >> 0) & 0xFF);
segState.options = strip->getOptions(_seg);
}
void setSegmentSize() {
strip->strip_off();
delay(10);
if(strip->isRunning()) strip->stop();
strip->resetSegmentRuntimes();
strip->setSegment(State.segment, segState.start, segState.stop , segState.mode[State.segment], hexcolors_trans, convertSpeed(segState.speed[State.segment]), segState.options);
}
uint8_t calculateColorTransitionSteps(uint8_t _seg) {
//compare all colors and calculate steps
int _trans_cnt_max = 0;
int _calculate_max[4] = {};
for (uint8_t i=0; i<3; i++){
for (uint8_t j=0; j<4; j++) {
_calculate_max[j] = ((strip->getColors(_seg)[i] >> ((3-j)*8)) & 0xFF) - ((hexcolors_trans[i] >> ((3-j)*8)) & 0xFF);
_calculate_max[j] = abs(_calculate_max[j]);
_trans_cnt_max = max(_trans_cnt_max, _calculate_max[j]);
}
}
return _trans_cnt_max;
}
uint8_t convertColorsFade(uint8_t _seg) {
if (Config.transEffect) {
if (trans_cnt > 1) {
//memcpy(segState.colors[_seg], strip->getColors(_seg), sizeof(segState.colors[_seg]));
DBG_OUTPUT_PORT.println("Color transistion aborted. Restarting...!");
trans_cnt = 1;
}
return calculateColorTransitionSteps(_seg);
} else {
return 0;
}
}
uint32_t scale_wrgb(uint32_t wrgb, uint8_t level) {
uint8_t w = (uint16_t)(((wrgb >> 24) & 0xFF) * level / 255);
uint8_t r = (uint16_t)(((wrgb >> 16) & 0xFF) * level / 255);
uint8_t g = (uint16_t)(((wrgb >> 8) & 0xFF) * level / 255);
uint8_t b = (uint16_t)(((wrgb) & 0xFF) * level / 255);
return (w << 24) | (r << 16) | (g << 8) | b;
}
uint32_t trans(uint32_t _newcolor, uint32_t _oldcolor, uint8_t _level, uint8_t _steps) {
if (_steps == 0) { _steps = 1; };
_level = (uint16_t)(_level * 255 / _steps);
_newcolor = scale_wrgb(_newcolor, _level);
_oldcolor = scale_wrgb(_oldcolor, 255-_level);
return _newcolor + _oldcolor;
}