WLED/wled00/led.cpp

277 wiersze
8.9 KiB
C++

#include "wled.h"
/*
* LED methods
*/
// applies chosen setment properties to legacy values
void setValuesFromSegment(uint8_t s) {
const Segment& seg = strip.getSegment(s);
2025-02-06 13:57:18 +00:00
colPri[0] = R(seg.colors[0]);
colPri[1] = G(seg.colors[0]);
colPri[2] = B(seg.colors[0]);
colPri[3] = W(seg.colors[0]);
colSec[0] = R(seg.colors[1]);
colSec[1] = G(seg.colors[1]);
colSec[2] = B(seg.colors[1]);
colSec[3] = W(seg.colors[1]);
effectCurrent = seg.mode;
effectSpeed = seg.speed;
2019-12-03 13:15:12 +00:00
effectIntensity = seg.intensity;
effectPalette = seg.palette;
2019-12-03 13:15:12 +00:00
}
// applies global legacy values (colPri, colSec, effectCurrent...) to each selected segment
void applyValuesToSelectedSegs() {
2024-07-09 19:50:27 +00:00
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!(seg.isActive() && seg.isSelected())) continue;
if (effectSpeed != seg.speed) {seg.speed = effectSpeed; stateChanged = true;}
if (effectIntensity != seg.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
if (effectPalette != seg.palette) {seg.setPalette(effectPalette);}
if (effectCurrent != seg.mode) {seg.setMode(effectCurrent);}
2025-02-06 13:57:18 +00:00
uint32_t col0 = RGBW32(colPri[0], colPri[1], colPri[2], colPri[3]);
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
if (col0 != seg.colors[0]) {seg.setColor(0, col0);}
if (col1 != seg.colors[1]) {seg.setColor(1, col1);}
}
}
void toggleOnOff()
{
if (bri == 0)
{
bri = briLast;
strip.restartRuntime();
} else
{
briLast = bri;
bri = 0;
}
stateChanged = true;
}
2018-11-24 10:52:23 +00:00
//scales the brightness with the briMultiplier factor
byte scaledBri(byte in)
{
2024-07-09 19:50:27 +00:00
unsigned val = ((uint16_t)in*briMultiplier)/100;
if (val > 255) val = 255;
return (byte)val;
}
//applies global temporary brightness (briT) to strip
void applyBri() {
if (realtimeOverride || !(realtimeMode && arlsForceMaxBri))
{
//DEBUG_PRINTF_P(PSTR("Applying strip brightness: %d (%d,%d)\n"), (int)briT, (int)bri, (int)briOld);
strip.setBrightness(scaledBri(briT));
}
}
2018-11-24 10:52:23 +00:00
//applies global brightness and sets it as the "current" brightness (no transition)
void applyFinalBri() {
briOld = bri;
briT = bri;
applyBri();
strip.trigger(); // force one last update
}
2018-11-24 10:52:23 +00:00
//called after every state changes, schedules interface updates, handles brightness transition and nightlight activation
//unlike colorUpdated(), does NOT apply any colors or FX to segments
void stateUpdated(byte callMode) {
2018-11-24 10:52:23 +00:00
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa 11: ws send only 12: button preset
setValuesFromFirstSelectedSeg(); // a much better approach would be to use main segment: setValuesFromMainSeg()
2020-12-14 22:32:57 +00:00
if (bri != briOld || stateChanged) {
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
2023-01-06 08:24:29 +00:00
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
2023-07-14 09:07:35 +00:00
if (bri != briOld && nodeBroadcastEnabled) sendSysInfoUDP(); // update on state
2023-01-06 08:24:29 +00:00
//set flag to update ws and mqtt
2020-12-10 15:27:23 +00:00
interfaceUpdateCallMode = callMode;
2020-02-24 16:25:40 +00:00
} else {
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
2023-01-06 08:24:29 +00:00
notify(CALL_MODE_NIGHTLIGHT);
interfaceUpdateCallMode = CALL_MODE_NIGHTLIGHT;
}
}
2023-01-06 08:24:29 +00:00
2024-12-12 18:30:56 +00:00
unsigned long now = millis();
if (callMode != CALL_MODE_NO_NOTIFY && nightlightActive && (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)) {
briNlT = bri;
2024-12-12 18:30:56 +00:00
nightlightDelayMs -= (now - nightlightStartTime);
nightlightStartTime = now;
}
if (briT == 0) {
if (callMode != CALL_MODE_NOTIFICATION) strip.resetTimebase(); //effect start from beginning
2020-02-09 09:35:32 +00:00
}
if (bri > 0) briLast = bri;
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
2023-01-06 08:24:29 +00:00
// notify usermods of state change
UsermodManager::onStateChange(callMode);
if (strip.getTransition() == 0) {
jsonTransitionOnce = false;
transitionActive = false;
applyFinalBri();
strip.trigger();
} else {
if (transitionActive) {
briOld = briT;
} else if (bri != briOld || stateChanged)
strip.setTransitionMode(true); // force all segments to transition mode
transitionActive = true;
transitionStartTime = now;
}
stateChanged = false;
}
2018-11-24 10:52:23 +00:00
void updateInterfaces(uint8_t callMode) {
if (!interfaceUpdateCallMode || millis() - lastInterfaceUpdate < INTERFACE_UPDATE_COOLDOWN) return;
sendDataWs();
2022-01-25 11:47:14 +00:00
lastInterfaceUpdate = millis();
2025-01-27 20:27:01 +00:00
interfaceUpdateCallMode = CALL_MODE_INIT; //disable further updates
2023-10-22 15:53:16 +00:00
2022-01-02 13:27:24 +00:00
if (callMode == CALL_MODE_WS_SEND) return;
2023-01-06 08:24:29 +00:00
2019-03-01 16:10:42 +00:00
#ifndef WLED_DISABLE_ALEXA
if (espalexaDevice != nullptr && callMode != CALL_MODE_ALEXA) {
2019-03-01 16:10:42 +00:00
espalexaDevice->setValue(bri);
2025-02-06 13:57:18 +00:00
espalexaDevice->setColor(colPri[0], colPri[1], colPri[2]);
2019-03-01 16:10:42 +00:00
}
#endif
2024-03-16 14:26:52 +00:00
#ifndef WLED_DISABLE_MQTT
publishMqtt();
#endif
}
2018-11-24 10:52:23 +00:00
void handleTransitions() {
//handle still pending interface update
updateInterfaces(interfaceUpdateCallMode);
2023-01-06 08:24:29 +00:00
2023-11-27 12:27:52 +00:00
if (transitionActive && strip.getTransition() > 0) {
int ti = millis() - transitionStartTime;
int tr = strip.getTransition();
if (ti/tr) {
2023-11-27 12:27:52 +00:00
strip.setTransitionMode(false); // stop all transitions
2023-11-27 13:24:07 +00:00
// restore (global) transition time if not called from UDP notifier or single/temporary transition from JSON (also playlist)
if (jsonTransitionOnce) strip.setTransition(transitionDelay);
transitionActive = false;
2023-11-27 13:24:07 +00:00
jsonTransitionOnce = false;
applyFinalBri();
return;
}
byte briTO = briT;
int deltaBri = (int)bri - (int)briOld;
briT = briOld + (deltaBri * ti / tr);
if (briTO != briT) applyBri();
2016-11-27 15:45:54 +00:00
}
}
2018-11-24 10:52:23 +00:00
// legacy method, applies values from col, effectCurrent, ... to selected segments
void colorUpdated(byte callMode) {
applyValuesToSelectedSegs();
stateUpdated(callMode);
}
void handleNightlight() {
unsigned long now = millis();
if (now < 100 && lastNlUpdate > 0) lastNlUpdate = 0; // take care of millis() rollover
if (now - lastNlUpdate < 100) return; // allow only 10 NL updates per second
lastNlUpdate = now;
2016-11-27 15:45:54 +00:00
if (nightlightActive)
{
if (!nightlightActiveOld) //init
2016-11-27 15:45:54 +00:00
{
nightlightStartTime = millis();
nightlightDelayMs = (unsigned)(nightlightDelayMins*60000);
nightlightActiveOld = true;
briNlT = bri;
2025-02-06 13:57:18 +00:00
for (unsigned i=0; i<4; i++) colNlT[i] = colPri[i]; // remember starting color
if (nightlightMode == NL_MODE_SUN)
{
//save current
colNlT[0] = effectCurrent;
colNlT[1] = effectSpeed;
colNlT[2] = effectPalette;
strip.getFirstSelectedSeg().setMode(FX_MODE_STATIC); // make sure seg runtime is reset if it was in sunrise mode
effectCurrent = FX_MODE_SUNRISE; // colorUpdated() will take care of assigning that to all selected segments
effectSpeed = nightlightDelayMins;
effectPalette = 0;
if (effectSpeed > 60) effectSpeed = 60; //currently limited to 60 minutes
if (bri) effectSpeed += 60; //sunset if currently on
briNlT = !bri; //true == sunrise, false == sunset
if (!bri) bri = briLast;
colorUpdated(CALL_MODE_NO_NOTIFY);
}
2016-11-27 15:45:54 +00:00
}
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
if (nightlightMode == NL_MODE_FADE || nightlightMode == NL_MODE_COLORFADE)
{
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
if (nightlightMode == NL_MODE_COLORFADE) // color fading only is enabled with "NF=2"
{
2025-02-06 13:57:18 +00:00
for (unsigned i=0; i<4; i++) colPri[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
}
colorUpdated(CALL_MODE_NO_NOTIFY);
}
if (nper >= 1) //nightlight duration over
2016-11-27 15:45:54 +00:00
{
nightlightActive = false;
if (nightlightMode == NL_MODE_SET)
{
2018-02-20 21:29:48 +00:00
bri = nightlightTargetBri;
colorUpdated(CALL_MODE_NO_NOTIFY);
}
if (bri == 0) briLast = briNlT;
if (nightlightMode == NL_MODE_SUN)
{
if (!briNlT) { //turn off if sunset
effectCurrent = colNlT[0];
effectSpeed = colNlT[1];
effectPalette = colNlT[2];
toggleOnOff();
applyFinalBri();
}
}
if (macroNl > 0)
2020-11-06 21:12:48 +00:00
applyPreset(macroNl);
nightlightActiveOld = false;
2016-11-27 15:45:54 +00:00
}
} else if (nightlightActiveOld) //early de-init
2016-11-27 15:45:54 +00:00
{
if (nightlightMode == NL_MODE_SUN) { //restore previous effect
effectCurrent = colNlT[0];
effectSpeed = colNlT[1];
effectPalette = colNlT[2];
colorUpdated(CALL_MODE_NO_NOTIFY);
}
nightlightActiveOld = false;
2016-11-27 15:45:54 +00:00
}
}
2020-08-25 15:23:17 +00:00
//utility for FastLED to use our custom timer
uint32_t get_millisecond_timer() {
2020-08-25 15:23:17 +00:00
return strip.now;
}