- included IR optimisations & code rearrangement
This commit is contained in:
Blaz Kristan 2024-05-03 15:45:15 +02:00
parent fa1aa1fe80
commit 2ff49cf657
4 changed files with 130 additions and 149 deletions

View File

@ -143,20 +143,8 @@ void handleImprovWifiScan();
void sendImprovIPRPCResult(ImprovRPCType type);
//ir.cpp
void applyRepeatActions();
byte relativeChange(byte property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
void decodeIR(uint32_t code);
void decodeIR24(uint32_t code);
void decodeIR24OLD(uint32_t code);
void decodeIR24CT(uint32_t code);
void decodeIR40(uint32_t code);
void decodeIR44(uint32_t code);
void decodeIR21(uint32_t code);
void decodeIR6(uint32_t code);
void decodeIR9(uint32_t code);
void decodeIRJson(uint32_t code);
void initIR();
void deInitIR();
void handleIR();
//json.cpp

View File

@ -1,20 +1,14 @@
#include "wled.h"
#ifndef WLED_DISABLE_INFRARED
#include "ir_codes.h"
/*
* Infrared sensor support for generic 24/40/44 key RGB remotes
* Infrared sensor support for several generic RGB remotes and custom JSON remote
*/
#if defined(WLED_DISABLE_INFRARED)
void handleIR(){}
#else
IRrecv* irrecv;
//change pin in NpbWrapper.h
decode_results results;
unsigned long irCheckedTime = 0;
uint32_t lastValidCode = 0;
byte lastRepeatableAction = ACTION_NONE;
@ -35,16 +29,16 @@ uint8_t lastIR6ColourIdx = 0;
// print("%d values: %s" % (len(result), result))
//
// It would be hard to maintain repeatable steps if calculating this on the fly.
const byte brightnessSteps[] = {
const uint8_t brightnessSteps[] = {
5, 7, 9, 12, 16, 20, 26, 34, 43, 56, 72, 93, 119, 154, 198, 255
};
const size_t numBrightnessSteps = sizeof(brightnessSteps) / sizeof(uint8_t);
// increment `bri` to the next `brightnessSteps` value
void incBrightness()
static void incBrightness()
{
// dumb incremental search is efficient enough for so few items
for (uint8_t index = 0; index < numBrightnessSteps; ++index)
for (unsigned index = 0; index < numBrightnessSteps; ++index)
{
if (brightnessSteps[index] > bri)
{
@ -56,7 +50,7 @@ void incBrightness()
}
// decrement `bri` to the next `brightnessSteps` value
void decBrightness()
static void decBrightness()
{
// dumb incremental search is efficient enough for so few items
for (int index = numBrightnessSteps - 1; index >= 0; --index)
@ -70,12 +64,12 @@ void decBrightness()
}
}
void presetFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID)
static void presetFallback(uint8_t presetID, uint8_t effectID, uint8_t paletteID)
{
applyPresetWithFallback(presetID, CALL_MODE_BUTTON_PRESET, effectID, paletteID);
}
byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte higherBoundary)
static byte relativeChange(byte property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF)
{
int16_t new_val = (int16_t) property + amount;
if (lowerBoundary >= higherBoundary) return property;
@ -84,10 +78,10 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
return (byte)constrain(new_val, 0, 255);
}
void changeEffect(uint8_t fx)
static void changeEffect(uint8_t fx)
{
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
strip.setMode(i, fx);
@ -100,10 +94,10 @@ void changeEffect(uint8_t fx)
stateChanged = true;
}
void changePalette(uint8_t pal)
static void changePalette(uint8_t pal)
{
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.setPalette(pal);
@ -116,13 +110,13 @@ void changePalette(uint8_t pal)
stateChanged = true;
}
void changeEffectSpeed(int8_t amount)
static void changeEffectSpeed(int8_t amount)
{
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.speed = effectSpeed;
@ -134,10 +128,7 @@ void changeEffectSpeed(int8_t amount)
}
} else { // if Effect == "solid Color", change the hue of the primary color
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
CRGB fastled_col;
fastled_col.red = R(sseg.colors[0]);
fastled_col.green = G(sseg.colors[0]);
fastled_col.blue = B(sseg.colors[0]);
CRGB fastled_col = CRGB(sseg.colors[0]);
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
int16_t new_val = (int16_t)prim_hsv.h + amount;
if (new_val > 255) new_val -= 255; // roll-over if bigger than 255
@ -145,7 +136,7 @@ void changeEffectSpeed(int8_t amount)
prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -163,13 +154,13 @@ void changeEffectSpeed(int8_t amount)
lastRepeatableValue = amount;
}
void changeEffectIntensity(int8_t amount)
static void changeEffectIntensity(int8_t amount)
{
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectIntensity + amount;
effectIntensity = (byte)constrain(new_val,0,255);
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.intensity = effectIntensity;
@ -181,16 +172,13 @@ void changeEffectIntensity(int8_t amount)
}
} else { // if Effect == "solid Color", change the saturation of the primary color
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
CRGB fastled_col;
fastled_col.red = R(sseg.colors[0]);
fastled_col.green = G(sseg.colors[0]);
fastled_col.blue = B(sseg.colors[0]);
CRGB fastled_col = CRGB(sseg.colors[0]);
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
int16_t new_val = (int16_t) prim_hsv.s + amount;
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
hsv2rgb_rainbow(prim_hsv, fastled_col);
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
@ -208,11 +196,11 @@ void changeEffectIntensity(int8_t amount)
lastRepeatableValue = amount;
}
void changeColor(uint32_t c, int16_t cct=-1)
static void changeColor(uint32_t c, int16_t cct=-1)
{
if (irApplyToAllSelected) {
// main segment may not be selected!
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
byte capabilities = seg.getLightCapabilities();
@ -249,7 +237,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
stateChanged = true;
}
void changeWhite(int8_t amount, int16_t cct=-1)
static void changeWhite(int8_t amount, int16_t cct=-1)
{
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
byte r = R(seg.colors[0]);
@ -259,72 +247,7 @@ void changeWhite(int8_t amount, int16_t cct=-1)
changeColor(RGBW32(r, g, b, w), cct);
}
void decodeIR(uint32_t code)
{
if (code == 0xFFFFFFFF) {
//repeated code, continue brightness up/down
irTimesRepeated++;
applyRepeatActions();
return;
}
lastValidCode = 0; irTimesRepeated = 0;
lastRepeatableAction = ACTION_NONE;
if (irEnabled == 8) { // any remote configurable with ir.json file
decodeIRJson(code);
stateUpdated(CALL_MODE_BUTTON);
return;
}
if (code > 0xFFFFFF) return; //invalid code
switch (irEnabled) {
case 1:
if (code > 0xF80000) decodeIR24OLD(code); // white 24-key remote (old) - it sends 0xFF0000 values
else decodeIR24(code); // 24-key remote - 0xF70000 to 0xF80000
break;
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
case 5: decodeIR21(code); break; // white 21-key remote
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
// sets bright plain white
case 7: decodeIR9(code); break;
//case 8: return; // ir.json file, handled above switch statement
}
if (nightlightActive && bri == 0) nightlightActive = false;
stateUpdated(CALL_MODE_BUTTON); //for notifier, IR is considered a button input
}
void applyRepeatActions()
{
if (irEnabled == 8) {
decodeIRJson(lastValidCode);
return;
} else switch (lastRepeatableAction) {
case ACTION_BRIGHT_UP : incBrightness(); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_BRIGHT_DOWN : decBrightness(); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_SPEED_UP : changeEffectSpeed(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_SPEED_DOWN : changeEffectSpeed(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_INTENSITY_UP : changeEffectIntensity(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_INTENSITY_DOWN : changeEffectIntensity(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
default: break;
}
if (lastValidCode == IR40_WPLUS) {
changeWhite(10);
stateUpdated(CALL_MODE_BUTTON);
} else if (lastValidCode == IR40_WMINUS) {
changeWhite(-10);
stateUpdated(CALL_MODE_BUTTON);
} else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 ) {
nightlightActive = true;
nightlightStartTime = millis();
stateUpdated(CALL_MODE_BUTTON);
}
}
void decodeIR24(uint32_t code)
static void decodeIR24(uint32_t code)
{
switch (code) {
case IR24_BRIGHTER : incBrightness(); break;
@ -356,7 +279,7 @@ void decodeIR24(uint32_t code)
lastValidCode = code;
}
void decodeIR24OLD(uint32_t code)
static void decodeIR24OLD(uint32_t code)
{
switch (code) {
case IR24_OLD_BRIGHTER : incBrightness(); break;
@ -388,7 +311,7 @@ void decodeIR24OLD(uint32_t code)
lastValidCode = code;
}
void decodeIR24CT(uint32_t code)
static void decodeIR24CT(uint32_t code)
{
switch (code) {
case IR24_CT_BRIGHTER : incBrightness(); break;
@ -420,7 +343,7 @@ void decodeIR24CT(uint32_t code)
lastValidCode = code;
}
void decodeIR40(uint32_t code)
static void decodeIR40(uint32_t code)
{
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
byte r = R(seg.colors[0]);
@ -473,7 +396,7 @@ void decodeIR40(uint32_t code)
lastValidCode = code;
}
void decodeIR44(uint32_t code)
static void decodeIR44(uint32_t code)
{
switch (code) {
case IR44_BPLUS : incBrightness(); break;
@ -525,7 +448,7 @@ void decodeIR44(uint32_t code)
lastValidCode = code;
}
void decodeIR21(uint32_t code)
static void decodeIR21(uint32_t code)
{
switch (code) {
case IR21_BRIGHTER: incBrightness(); break;
@ -554,7 +477,7 @@ void decodeIR21(uint32_t code)
lastValidCode = code;
}
void decodeIR6(uint32_t code)
static void decodeIR6(uint32_t code)
{
switch (code) {
case IR6_POWER: toggleOnOff(); break;
@ -587,7 +510,7 @@ void decodeIR6(uint32_t code)
lastValidCode = code;
}
void decodeIR9(uint32_t code)
static void decodeIR9(uint32_t code)
{
switch (code) {
case IR9_POWER : toggleOnOff(); break;
@ -628,7 +551,7 @@ Sample:
"label": "Preset 1, fallback to Saw - Party if not found"},
}
*/
void decodeIRJson(uint32_t code)
static void decodeIRJson(uint32_t code)
{
char objKey[10];
char fileName[16];
@ -701,41 +624,102 @@ void decodeIRJson(uint32_t code)
releaseJSONBufferLock();
}
static void applyRepeatActions()
{
if (irEnabled == 8) {
decodeIRJson(lastValidCode);
return;
} else switch (lastRepeatableAction) {
case ACTION_BRIGHT_UP : incBrightness(); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_BRIGHT_DOWN : decBrightness(); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_SPEED_UP : changeEffectSpeed(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_SPEED_DOWN : changeEffectSpeed(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_INTENSITY_UP : changeEffectIntensity(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
case ACTION_INTENSITY_DOWN : changeEffectIntensity(lastRepeatableValue); stateUpdated(CALL_MODE_BUTTON); return;
default: break;
}
if (lastValidCode == IR40_WPLUS) {
changeWhite(10);
stateUpdated(CALL_MODE_BUTTON);
} else if (lastValidCode == IR40_WMINUS) {
changeWhite(-10);
stateUpdated(CALL_MODE_BUTTON);
} else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 ) {
nightlightActive = true;
nightlightStartTime = millis();
stateUpdated(CALL_MODE_BUTTON);
}
}
static void decodeIR(uint32_t code)
{
if (code == 0xFFFFFFFF) {
//repeated code, continue brightness up/down
irTimesRepeated++;
applyRepeatActions();
return;
}
lastValidCode = 0; irTimesRepeated = 0;
lastRepeatableAction = ACTION_NONE;
if (irEnabled == 8) { // any remote configurable with ir.json file
decodeIRJson(code);
stateUpdated(CALL_MODE_BUTTON);
return;
}
if (code > 0xFFFFFF) return; //invalid code
switch (irEnabled) {
case 1:
if (code > 0xF80000) decodeIR24OLD(code); // white 24-key remote (old) - it sends 0xFF0000 values
else decodeIR24(code); // 24-key remote - 0xF70000 to 0xF80000
break;
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
case 5: decodeIR21(code); break; // white 21-key remote
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
// sets bright plain white
case 7: decodeIR9(code); break;
//case 8: return; // ir.json file, handled above switch statement
}
if (nightlightActive && bri == 0) nightlightActive = false;
stateUpdated(CALL_MODE_BUTTON); //for notifier, IR is considered a button input
}
void initIR()
{
if (irEnabled > 0)
{
if (irEnabled > 0) {
irrecv = new IRrecv(irPin);
irrecv->enableIRIn();
if (irrecv) irrecv->enableIRIn();
} else irrecv = nullptr;
}
void deInitIR()
{
if (irrecv) {
irrecv->disableIRIn();
delete irrecv;
}
irrecv = nullptr;
}
void handleIR()
{
if (irEnabled > 0 && millis() - irCheckedTime > 120 && !strip.isUpdating())
{
irCheckedTime = millis();
if (irEnabled > 0)
{
if (irrecv == NULL)
{
initIR(); return;
unsigned long currentTime = millis();
unsigned timeDiff = currentTime - irCheckedTime;
if (timeDiff > 120 && irEnabled > 0 && irrecv) {
if (strip.isUpdating() && timeDiff < 240) return; // be nice, but not too nice
irCheckedTime = currentTime;
if (irrecv->decode(&results)) {
if (results.value != 0) { // only print results if anything is received ( != 0 )
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) // Serial TX pin (GPIO 1 on ESP32 and ESP8266)
Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value);
}
if (irrecv->decode(&results))
{
if (results.value != 0) // only print results if anything is received ( != 0 )
{
if (!pinManager.isPinAllocated(hardwareTX) || pinManager.getPinOwner(hardwareTX) == PinOwner::DebugOut) // Serial TX pin (GPIO 1 on ESP32 and ESP8266)
Serial.printf_P(PSTR("IR recv: 0x%lX\n"), (unsigned long)results.value);
}
decodeIR(results.value);
irrecv->resume();
}
} else if (irrecv != NULL)
{
irrecv->disableIRIn();
delete irrecv; irrecv = NULL;
decodeIR(results.value);
irrecv->resume();
}
}
}

View File

@ -104,7 +104,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
}
#ifndef WLED_DISABLE_INFRARED
if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) {
pinManager.deallocatePin(irPin, PinOwner::IR);
deInitIR();
pinManager.deallocatePin(irPin, PinOwner::IR);
}
#endif
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) {
@ -233,6 +234,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
irPin = -1;
}
irEnabled = request->arg(F("IT")).toInt();
initIR();
#endif
irApplyToAllSelected = !request->hasArg(F("MSO"));

View File

@ -505,6 +505,13 @@ void WLED::setup()
initServer();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#ifndef WLED_DISABLE_INFRARED
// init IR
DEBUG_PRINTLN(F("initIR"));
initIR();
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
#endif
// Seed FastLED random functions with an esp random value, which already works properly at this point.
#if defined(ARDUINO_ARCH_ESP32)
const uint32_t seed32 = esp_random();