Merge pull request #33 from Aircoookie/master

Update from orig
This commit is contained in:
srg74 2020-02-22 17:38:00 -05:00 committed by GitHub
commit a7092ac503
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 597 additions and 158 deletions

View File

@ -77,12 +77,14 @@ arduino_core_2_5_0 = espressif8266@2.0.4
arduino_core_2_5_2 = espressif8266@2.2.3
arduino_core_2_6_1 = espressif8266@2.3.0
arduino_core_2_6_2 = espressif8266@2.3.1
arduino_core_2_6_3 = espressif8266@2.3.3
arduino_core_stage = https://github.com/platformio/platform-espressif8266.git#feature/stage
platform = ${common:esp8266.arduino_core_2_6_2}
platform = ${common:esp8266.arduino_core_2_6_3}
build_flags =
-D ESP8266
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
-Wl,-Teagle.flash.4m1m.ld ;;;; Required for core > v2.5.0 or staging version 4MB Flash 3MB SPIFFs
lib_ignore = AsyncTCP
[common:esp8266_1M]
platform = espressif8266@1.8.0
@ -96,6 +98,7 @@ build_flags =
-D WLED_DISABLE_CRONIXIE
; -D WLED_DISABLE_HUESYNC
; -D WLED_DISABLE_INFRARED
lib_ignore = ${common:esp8266.lib_ignore}
[common:esp8266_512k]
platform = espressif8266@1.8.0
@ -109,12 +112,16 @@ build_flags =
-D WLED_DISABLE_CRONIXIE
-D WLED_DISABLE_HUESYNC
; -D WLED_DISABLE_INFRARED
lib_ignore = ${common:esp8266.lib_ignore}
[common:esp32]
platform = espressif32@1.11.1
platform = espressif32@1.11.2
build_flags =
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
-D ARDUINO_ARCH_ESP32
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html
[env:nodemcuv2]
@ -129,7 +136,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:d1_mini]
board = d1_mini
@ -143,7 +150,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp01_1m]
board = esp01_1m
@ -159,7 +166,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp01]
board = esp01
@ -174,7 +181,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp07]
board = esp07
@ -188,7 +195,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
# see: http://docs.platformio.org/en/latest/platforms/espressif32.html
[env:esp32dev]
@ -202,8 +209,7 @@ build_flags =
${common:esp32.build_flags}
lib_deps =
${common.lib_deps_external}
lib_ignore =
ESPAsyncUDP
lib_ignore = ${common:esp32.lib_ignore}
lib_compat_mode = strict
[env:esp8285_4CH_MagicHome]
@ -220,7 +226,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp8285_4CH_H801]
board = esp8285
@ -237,7 +243,7 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp8285_5CH_H801]
board = esp8285
@ -255,5 +261,4 @@ build_flags =
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = AsyncTCP
lib_ignore = ${common:esp8266.lib_ignore}

View File

@ -39,7 +39,7 @@ void userLoop() {
//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
colorUpdated(6);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
lastTime = millis();
}
}

View File

@ -47,7 +47,7 @@ void userLoop()
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
effectCurrent = FX_MODE_STATIC;
timeStaticStart = millis();
colorUpdated(3);
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
wipeState = 2;
}
} else if (wipeState == 2) { //static
@ -59,7 +59,7 @@ void userLoop()
#ifdef STAIRCASE_WIPE_OFF
effectCurrent = FX_MODE_COLOR_WIPE;
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
colorUpdated(3);
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
wipeState = 4;
#else
turnOff();
@ -93,7 +93,7 @@ void startWipe()
bool doReverse = (userVar0 == 2);
seg.setOption(1, doReverse);
colorUpdated(3);
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
}
void turnOff()
@ -104,7 +104,7 @@ void turnOff()
transitionDelayTemp = 4000; //fade out slowly
#endif
bri = 0;
colorUpdated(3);
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
wipeState = 0;
userVar0 = 0;
previousUserVar0 = 0;

View File

@ -415,7 +415,8 @@ class WS2812FX {
resetSegments(),
setPixelColor(uint16_t n, uint32_t c),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
show(void);
show(void),
setRgbwPwm(void);
bool
reverseMode = false,
@ -627,6 +628,12 @@ class WS2812FX {
uint32_t _lastPaletteChange = 0;
uint32_t _lastShow = 0;
#ifdef WLED_USE_ANALOG_LEDS
uint32_t _analogLastShow = 0;
uint32_t _analogLastColor = 0;
uint8_t _analogLastBri = 0;
#endif
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element

View File

@ -829,6 +829,40 @@ bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
return true;
}
#ifdef WLED_USE_ANALOG_LEDS
void WS2812FX::setRgbwPwm(void) {
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
if (nowUp - _analogLastShow < MIN_SHOW_DELAY) return;
_analogLastShow = nowUp;
RgbwColor color = bus->GetPixelColorRgbw(0);
byte b = getBrightness();
if (color == _analogLastColor && b == _analogLastBri) return;
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
#ifdef WLED_USE_5CH_LEDS
if (color.R == 255 && color.G == 255 && color.B == 255 && color.W == 255) {
bus->SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
} else if (color.R == 127 && color.G == 127 && color.B == 127 && color.W == 255) {
bus->SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
} else if (color.R == 0 && color.G == 0 && color.B == 0 && color.W == 255) {
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else if (color.R == 130 && color.G == 90 && color.B == 0 && color.W == 255) {
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
} else if (color.R == 255 && color.G == 153 && color.B == 0 && color.W == 255) {
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else { // not only white colors
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
}
#else
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
#endif
}
#else
void WS2812FX::setRgbwPwm() {}
#endif
//gamma 2.4 lookup table used for color correction
const byte gammaT[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

View File

@ -3,7 +3,9 @@
#define NpbWrapper_h
//PIN CONFIGURATION
#ifndef LEDPIN
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
#endif
//#define USE_APA102 // Uncomment for using APA102 LEDs.
//#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer)
//#define USE_LPD8806 // Uncomment for using LPD8806
@ -164,7 +166,7 @@ public:
#endif
}
#else // ESP8266
//init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
//init PWM pins
pinMode(RPIN, OUTPUT);
pinMode(GPIN, OUTPUT);
pinMode(BPIN, OUTPUT);
@ -185,9 +187,9 @@ public:
void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0)
{
#ifdef ARDUINO_ARCH_ESP32
ledcWrite(0, r); //RPIN
ledcWrite(1, g); //GPIN
ledcWrite(2, b); //BPIN
ledcWrite(0, r);
ledcWrite(1, g);
ledcWrite(2, b);
switch (_type) {
case NeoPixelType_Grb: break;
#ifdef WLED_USE_5CH_LEDS
@ -196,7 +198,7 @@ public:
case NeoPixelType_Grbw: ledcWrite(3, w); break;
#endif
}
#else
#else // ESP8266
analogWrite(RPIN, r);
analogWrite(GPIN, g);
analogWrite(BPIN, b);
@ -227,11 +229,6 @@ public:
switch (_type) {
case NeoPixelType_Grb: {
_pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
#ifdef WLED_USE_ANALOG_LEDS
if (indexPixel != 0) return; //set analog LEDs from first pixel
byte b = _pGrb->GetBrightness();
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, 0);
#endif
}
break;
case NeoPixelType_Grbw: {
@ -240,28 +237,6 @@ public:
#else
_pGrbw->SetPixelColor(indexPixel, color);
#endif
#ifdef WLED_USE_ANALOG_LEDS
if (indexPixel != 0) return; //set analog LEDs from first pixel
byte b = _pGrbw->GetBrightness();
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
#ifdef WLED_USE_5CH_LEDS
if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) {
SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
} else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
} else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
} else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) {
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
} else { // not only white colors
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
}
#else
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
#endif
#endif
}
break;
}

View File

@ -7,6 +7,19 @@
#define AP_BEHAVIOR_ALWAYS 2 //Always open
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
//Notifier callMode
#define NOTIFIER_CALL_MODE_INIT 0 // no updates on init, can be used to disable updates
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
#define NOTIFIER_CALL_MODE_BUTTON 2
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
#define NOTIFIER_CALL_MODE_FX_CHANGED 6
#define NOTIFIER_CALL_MODE_HUE 7
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
#define NOTIFIER_CALL_MODE_BLYNK 9
#define NOTIFIER_CALL_MODE_ALEXA 10
//RGB to RGBW conversion mode
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel

View File

@ -0,0 +1,312 @@
/*
esp8266_waveform - General purpose waveform generation and control,
supporting outputs on all pins in parallel.
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved.
The core idea is to have a programmable waveform generator with a unique
high and low period (defined in microseconds). TIMER1 is set to 1-shot
mode and is always loaded with the time until the next edge of any live
waveforms.
Up to one waveform generator per pin supported.
Each waveform generator is synchronized to the ESP cycle counter, not the
timer. This allows for removing interrupt jitter and delay as the counter
always increments once per 80MHz clock. Changes to a waveform are
contiguous and only take effect on the next waveform transition,
allowing for smooth transitions.
This replaces older tone(), analogWrite(), and the Servo classes.
Everywhere in the code where "cycles" is used, it means ESP.getCycleTime()
cycles, not TIMER1 cycles (which may be 2 CPU clocks @ 160MHz).
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ESP8266
#include <Arduino.h>
#include "ets_sys.h"
#include "core_esp8266_waveform.h"
extern "C" {
// Maximum delay between IRQs
#define MAXIRQUS (10000)
// Set/clear GPIO 0-15 by bitmask
#define SetGPIO(a) do { GPOS = a; } while (0)
#define ClearGPIO(a) do { GPOC = a; } while (0)
// Waveform generator can create tones, PWM, and servos
typedef struct {
uint32_t nextServiceCycle; // ESP cycle timer when a transition required
uint32_t expiryCycle; // For time-limited waveform, the cycle when this waveform must stop
uint32_t nextTimeHighCycles; // Copy over low->high to keep smooth waveform
uint32_t nextTimeLowCycles; // Copy over high->low to keep smooth waveform
} Waveform;
static Waveform waveform[17]; // State of all possible pins
static volatile uint32_t waveformState = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code
static volatile uint32_t waveformEnabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
// Enable lock-free by only allowing updates to waveformState and waveformEnabled from IRQ service routine
static volatile uint32_t waveformToEnable = 0; // Message to the NMI handler to start a waveform on a inactive pin
static volatile uint32_t waveformToDisable = 0; // Message to the NMI handler to disable a pin from waveform generation
static uint32_t (*timer1CB)() = NULL;
// Non-speed critical bits
#pragma GCC optimize ("Os")
static inline ICACHE_RAM_ATTR uint32_t GetCycleCount() {
uint32_t ccount;
__asm__ __volatile__("esync; rsr %0,ccount":"=a"(ccount));
return ccount;
}
// Interrupt on/off control
static ICACHE_RAM_ATTR void timer1Interrupt();
static bool timerRunning = false;
static void initTimer() {
timer1_disable();
ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL);
ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt);
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE);
timerRunning = true;
}
static void ICACHE_RAM_ATTR deinitTimer() {
ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
timer1_disable();
timer1_isr_init();
timerRunning = false;
}
// Set a callback. Pass in NULL to stop it
void setTimer1Callback(uint32_t (*fn)()) {
timer1CB = fn;
if (!timerRunning && fn) {
initTimer();
timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste
} else if (timerRunning && !fn && !waveformEnabled) {
deinitTimer();
}
}
// Start up a waveform on a pin, or change the current one. Will change to the new
// waveform smoothly on next low->high transition. For immediate change, stopWaveform()
// first, then it will immediately begin.
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS) {
if ((pin > 16) || isFlashInterfacePin(pin)) {
return false;
}
Waveform *wave = &waveform[pin];
// Adjust to shave off some of the IRQ time, approximately
wave->nextTimeHighCycles = microsecondsToClockCycles(timeHighUS);
wave->nextTimeLowCycles = microsecondsToClockCycles(timeLowUS);
wave->expiryCycle = runTimeUS ? GetCycleCount() + microsecondsToClockCycles(runTimeUS) : 0;
if (runTimeUS && !wave->expiryCycle) {
wave->expiryCycle = 1; // expiryCycle==0 means no timeout, so avoid setting it
}
uint32_t mask = 1<<pin;
if (!(waveformEnabled & mask)) {
// Actually set the pin high or low in the IRQ service to guarantee times
wave->nextServiceCycle = GetCycleCount() + microsecondsToClockCycles(1);
waveformToEnable |= mask;
if (!timerRunning) {
initTimer();
timer1_write(microsecondsToClockCycles(10));
} else {
// Ensure timely service....
if (T1L > microsecondsToClockCycles(10)) {
timer1_write(microsecondsToClockCycles(10));
}
}
while (waveformToEnable) {
delay(0); // Wait for waveform to update
}
}
return true;
}
// Speed critical bits
#pragma GCC optimize ("O2")
// Normally would not want two copies like this, but due to different
// optimization levels the inline attribute gets lost if we try the
// other version.
static inline ICACHE_RAM_ATTR uint32_t GetCycleCountIRQ() {
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a"(ccount));
return ccount;
}
static inline ICACHE_RAM_ATTR uint32_t min_u32(uint32_t a, uint32_t b) {
if (a < b) {
return a;
}
return b;
}
// Stops a waveform on a pin
int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
// Can't possibly need to stop anything if there is no timer active
if (!timerRunning) {
return false;
}
// If user sends in a pin >16 but <32, this will always point to a 0 bit
// If they send >=32, then the shift will result in 0 and it will also return false
uint32_t mask = 1<<pin;
if (!(waveformEnabled & mask)) {
return false; // It's not running, nothing to do here
}
waveformToDisable |= mask;
// Ensure timely service....
if (T1L > microsecondsToClockCycles(10)) {
timer1_write(microsecondsToClockCycles(10));
}
while (waveformToDisable) {
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
}
if (!waveformEnabled && !timer1CB) {
deinitTimer();
}
return true;
}
// The SDK and hardware take some time to actually get to our NMI code, so
// decrement the next IRQ's timer value by a bit so we can actually catch the
// real CPU cycle counter we want for the waveforms.
#if F_CPU == 80000000
#define DELTAIRQ (microsecondsToClockCycles(3))
#else
#define DELTAIRQ (microsecondsToClockCycles(2))
#endif
static ICACHE_RAM_ATTR void timer1Interrupt() {
// Optimize the NMI inner loop by keeping track of the min and max GPIO that we
// are generating. In the common case (1 PWM) these may be the same pin and
// we can avoid looking at the other pins.
static int startPin = 0;
static int endPin = 0;
uint32_t nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
uint32_t timeoutCycle = GetCycleCountIRQ() + microsecondsToClockCycles(14);
if (waveformToEnable || waveformToDisable) {
// Handle enable/disable requests from main app.
waveformEnabled = (waveformEnabled & ~waveformToDisable) | waveformToEnable; // Set the requested waveforms on/off
waveformState &= ~waveformToEnable; // And clear the state of any just started
waveformToEnable = 0;
waveformToDisable = 0;
// Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t)
startPin = __builtin_ffs(waveformEnabled) - 1;
// Find the last bit by subtracting off GCC's count-leading-zeros (no offset in this one)
endPin = 32 - __builtin_clz(waveformEnabled);
}
if (waveformEnabled) {
bool done = false;
do {
nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
for (int i = startPin; i <= endPin; i++) {
uint32_t mask = 1<<i;
// If it's not on, ignore!
if (!(waveformEnabled & mask)) {
continue;
}
Waveform *wave = &waveform[i];
uint32_t now = GetCycleCountIRQ();
// Disable any waveforms that are done
if (wave->expiryCycle) {
int32_t expiryToGo = wave->expiryCycle - now;
if (expiryToGo < 0) {
// Done, remove!
waveformEnabled &= ~mask;
if (i == 16) {
GP16O &= ~1;
} else {
ClearGPIO(mask);
}
continue;
}
}
// Check for toggles
int32_t cyclesToGo = wave->nextServiceCycle - now;
if (cyclesToGo < 0) {
cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles));
waveformState ^= mask;
if (waveformState & mask) {
if (i == 16) {
GP16O |= 1; // GPIO16 write slow as it's RMW
} else {
SetGPIO(mask);
}
wave->nextServiceCycle = now + wave->nextTimeHighCycles + cyclesToGo;
nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeHighCycles + cyclesToGo, 1));
} else {
if (i == 16) {
GP16O &= ~1; // GPIO16 write slow as it's RMW
} else {
ClearGPIO(mask);
}
wave->nextServiceCycle = now + wave->nextTimeLowCycles + cyclesToGo;
nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeLowCycles + cyclesToGo, 1));
}
} else {
uint32_t deltaCycles = wave->nextServiceCycle - now;
nextEventCycles = min_u32(nextEventCycles, deltaCycles);
}
}
// Exit the loop if we've hit the fixed runtime limit or the next event is known to be after that timeout would occur
uint32_t now = GetCycleCountIRQ();
int32_t cycleDeltaNextEvent = timeoutCycle - (now + nextEventCycles);
int32_t cyclesLeftTimeout = timeoutCycle - now;
done = (cycleDeltaNextEvent < 0) || (cyclesLeftTimeout < 0);
} while (!done);
} // if (waveformEnabled)
if (timer1CB) {
nextEventCycles = min_u32(nextEventCycles, timer1CB());
}
if (nextEventCycles < microsecondsToClockCycles(10)) {
nextEventCycles = microsecondsToClockCycles(10);
}
nextEventCycles -= DELTAIRQ;
// Do it here instead of global function to save time and because we know it's edge-IRQ
#if F_CPU == 160000000
T1L = nextEventCycles >> 1; // Already know we're in range by MAXIRQUS
#else
T1L = nextEventCycles; // Already know we're in range by MAXIRQUS
#endif
TEIE |= TEIE1; // Edge int enable
}
};
#endif

View File

@ -0,0 +1,71 @@
/*
esp8266_waveform - General purpose waveform generation and control,
supporting outputs on all pins in parallel.
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved.
The core idea is to have a programmable waveform generator with a unique
high and low period (defined in microseconds). TIMER1 is set to 1-shot
mode and is always loaded with the time until the next edge of any live
waveforms.
Up to one waveform generator per pin supported.
Each waveform generator is synchronized to the ESP cycle counter, not the
timer. This allows for removing interrupt jitter and delay as the counter
always increments once per 80MHz clock. Changes to a waveform are
contiguous and only take effect on the next waveform transition,
allowing for smooth transitions.
This replaces older tone(), analogWrite(), and the Servo classes.
Everywhere in the code where "cycles" is used, it means ESP.getCycleTime()
cycles, not TIMER1 cycles (which may be 2 CPU clocks @ 160MHz).
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#ifndef __ESP8266_WAVEFORM_H
#define __ESP8266_WAVEFORM_H
#ifdef __cplusplus
extern "C" {
#endif
// Start or change a waveform of the specified high and low times on specific pin.
// If runtimeUS > 0 then automatically stop it after that many usecs.
// Returns true or false on success or failure.
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS);
// Stop a waveform, if any, on the specified pin.
// Returns true or false on success or failure.
int stopWaveform(uint8_t pin);
// Add a callback function to be called on *EVERY* timer1 trigger. The
// callback returns the number of microseconds until the next desired call.
// However, since it is called every timer1 interrupt, it may be called
// again before this period. It should therefore use the ESP Cycle Counter
// to determine whether or not to perform an operation.
// Pass in NULL to disable the callback and, if no other waveforms being
// generated, stop the timer as well.
// Make sure the CB function has the ICACHE_RAM_ATTR decorator.
void setTimer1Callback(uint32_t (*fn)());
#ifdef __cplusplus
}
#endif
#endif

View File

@ -93,6 +93,18 @@
#include <IRutils.h>
#endif
// remove flicker because PWM signal of RGB channels can become out of phase
#if defined(WLED_USE_ANALOG_LEDS) && defined(ESP8266)
#include "src/dependencies/arduino/core_esp8266_waveform.h"
#endif
// enable additional debug output
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#endif
//version code in format yymmddb (b = daily build)
#define VERSION 2002192
@ -301,7 +313,7 @@ unsigned long buttonWaitTime = 0;
bool notifyDirectDefault = notifyDirect;
bool receiveNotifications = true;
unsigned long notificationSentTime = 0;
byte notificationSentCallMode = 0;
byte notificationSentCallMode = NOTIFIER_CALL_MODE_INIT;
bool notificationTwoRequired = false;
//effects
@ -369,7 +381,7 @@ unsigned long realtimeTimeout = 0;
//mqtt
long lastMqttReconnectAttempt = 0;
long lastInterfaceUpdate = 0;
byte interfaceUpdateCallMode = 0;
byte interfaceUpdateCallMode = NOTIFIER_CALL_MODE_INIT;
char mqttStatusTopic[40] = ""; //this must be global because of async handlers
#if AUXPIN >= 0
@ -526,6 +538,10 @@ void loop() {
handleOverlays();
yield();
#ifdef WLED_USE_ANALOG_LEDS
strip.setRgbwPwm();
#endif
if (doReboot) reset();
if (!realtimeMode) //block stuff if WARLS/Adalight is enabled

View File

@ -3,7 +3,7 @@
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
*/
#define EEPSIZE 2560
#define EEPSIZE 2560 //Maximum is 4096
//eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 16

View File

@ -651,7 +651,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (pos < 1) XML_response(request);
pos = req.indexOf("&NN"); //do not send UDP notifications this time
colorUpdated((pos > 0) ? 5:1);
colorUpdated((pos > 0) ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
return true;
}

View File

@ -99,7 +99,7 @@ void beginStrip()
#endif
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(0);
colorUpdated(NOTIFIER_CALL_MODE_INIT);
//init relay pin
#if RLYPIN >= 0
@ -194,10 +194,10 @@ void initConnection()
WiFi.begin(clientSSID, clientPass);
#ifdef ARDUINO_ARCH_ESP32
if (noWifiSleep) WiFi.setSleep(false);
WiFi.setSleep(!noWifiSleep);
WiFi.setHostname(serverDescription);
#else
if (noWifiSleep) wifi_set_sleep_type(NONE_SLEEP_T);
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
#endif
}

View File

@ -11,15 +11,15 @@ void notify(byte callMode, bool followUp=false)
if (!udpConnected) return;
switch (callMode)
{
case 0: return;
case 1: if (!notifyDirect) return; break;
case 2: if (!notifyButton) return; break;
case 4: if (!notifyDirect) return; break;
case 6: if (!notifyDirect) return; break; //fx change
case 7: if (!notifyHue) return; break;
case 8: if (!notifyDirect) return; break;
case 9: if (!notifyDirect) return; break;
case 10: if (!notifyAlexa) return; break;
case NOTIFIER_CALL_MODE_INIT: return;
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_FX_CHANGED: if (!notifyDirect) return; break; //fx change
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
default: return;
}
byte udpOut[WLEDPACKETSIZE];
@ -91,13 +91,12 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
//E1.31 protocol support
// skip out-of-sequence packets
if (p->sequence_number < e131LastSequenceNumber && p->sequence_number - e131LastSequenceNumber > -20){
if (p->sequence_number < e131LastSequenceNumber && p->sequence_number > 20 && e131LastSequenceNumber < 250){
DEBUG_PRINT("skipping E1.31 frame (last seq=");
DEBUG_PRINT(e131LastSequenceNumber);
DEBUG_PRINT(", current seq=");
DEBUG_PRINT(p->sequence_number);
DEBUG_PRINTLN(")");
e131LastSequenceNumber = p->sequence_number;
return;
}
e131LastSequenceNumber = p->sequence_number;
@ -157,9 +156,9 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
col[3] = p->property_values[DMXAddress+11]; //white
colSec[3] = p->property_values[DMXAddress+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(3); // don't send UDP
return; // don't activate realtime live mode
transitionDelayTemp = 0; // act fast
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode
break;
case DMX_MODE_MULTIPLE_RGB:
@ -329,7 +328,7 @@ void handleNotifications()
if (nightlightActive) nightlightDelayMins = udpIn[7];
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
colorUpdated(3);
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
{

View File

@ -79,6 +79,7 @@ bool colorChanged()
{
if (col[i] != colIT[i]) return true;
if (colSec[i] != colSecIT[i]) return true;
if (col[i] != colNlT[i]) return true;
}
if (bri != briIT) return true;
return false;
@ -89,18 +90,24 @@ void colorUpdated(int callMode)
{
//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
if (callMode != 0 && callMode != 1 && callMode != 5) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
if (callMode != NOTIFIER_CALL_MODE_INIT &&
callMode != NOTIFIER_CALL_MODE_DIRECT_CHANGE &&
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
if (!colorChanged())
{
if (nightlightActive && !nightlightActiveOld && callMode != 3 && callMode != 5)
if (nightlightActive && !nightlightActiveOld &&
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY)
{
notify(4); interfaceUpdateCallMode = 4; return;
notify(NOTIFIER_CALL_MODE_NIGHTLIGHT);
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_NIGHTLIGHT;
return;
}
else if (fxChanged) {
notify(6);
if (callMode != 8) interfaceUpdateCallMode = 6;
notify(NOTIFIER_CALL_MODE_FX_CHANGED);
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = NOTIFIER_CALL_MODE_FX_CHANGED;
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (isPreset) {isPreset = false;}
else {currentPreset = -1;}
@ -110,7 +117,7 @@ void colorUpdated(int callMode)
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (isPreset) {isPreset = false;}
else {currentPreset = -1;}
if (callMode != 5 && nightlightActive && nightlightFade)
if (callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightActive && nightlightFade)
{
briNlT = bri;
nightlightDelayMs -= (millis() - nightlightStartTime);
@ -123,8 +130,8 @@ void colorUpdated(int callMode)
}
if (briT == 0)
{
setLedsStandard(true); //do not color transition if starting from off
if (callMode != 3) resetTimebase(); //effect start from beginning
setLedsStandard(true); //do not color transition if starting from off
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
}
briIT = bri;
@ -135,7 +142,7 @@ void colorUpdated(int callMode)
if (fadeTransition)
{
//set correct delay if not using notification delay
if (callMode != 3 && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
jsonTransitionOnce = false;
if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;}
@ -158,7 +165,7 @@ void colorUpdated(int callMode)
strip.trigger();
}
if (callMode == 8) return;
if (callMode == NOTIFIER_CALL_MODE_PRESET_CYCLE) return;
//set flag to update blynk and mqtt
interfaceUpdateCallMode = callMode;
}
@ -167,12 +174,13 @@ void colorUpdated(int callMode)
void updateInterfaces(uint8_t callMode)
{
#ifndef WLED_DISABLE_ALEXA
if (espalexaDevice != nullptr && callMode != 10) {
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
espalexaDevice->setValue(bri);
espalexaDevice->setColor(col[0], col[1], col[2]);
}
#endif
if (callMode != 9 && callMode != 5) updateBlynk();
if (callMode != NOTIFIER_CALL_MODE_BLYNK &&
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) updateBlynk();
doPublishMqtt = true;
lastInterfaceUpdate = millis();
}
@ -233,7 +241,7 @@ void handleNightlight()
{
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
}
colorUpdated(5);
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
}
if (nper >= 1)
{
@ -241,7 +249,7 @@ void handleNightlight()
if (!nightlightFade)
{
bri = nightlightTargetBri;
colorUpdated(5);
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
}
updateBlynk();
if (bri == 0) briLast = briNlT;
@ -257,7 +265,7 @@ void handleNightlight()
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
if (presetCycCurr > 25) presetCycCurr = 1;
colorUpdated(8);
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);
presetCycledTime = millis();
}
}

View File

@ -7,7 +7,7 @@ void shortPressAction()
if (!macroButton)
{
toggleOnOff();
colorUpdated(2);
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
} else {
applyMacro(macroButton);
}

View File

@ -41,7 +41,7 @@ void onAlexaChange(EspalexaDevice* dev)
if (bri == 0)
{
bri = briLast;
colorUpdated(10);
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
}
} else applyMacro(macroAlexaOn);
} else if (m == EspalexaDeviceProperty::off)
@ -52,13 +52,13 @@ void onAlexaChange(EspalexaDevice* dev)
{
briLast = bri;
bri = 0;
colorUpdated(10);
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
}
} else applyMacro(macroAlexaOff);
} else if (m == EspalexaDeviceProperty::bri)
{
bri = espalexaDevice->getValue();
colorUpdated(10);
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
} else //color
{
uint32_t color = espalexaDevice->getRGB();
@ -67,7 +67,7 @@ void onAlexaChange(EspalexaDevice* dev)
col[1] = ((color >> 8) & 0xFF);
col[2] = (color & 0xFF);
if (useRGBW && col[3] == 0) colorRGBtoRGBW(col); // do not touch white value if EspalexaDevice.cpp did set the white channel
colorUpdated(10);
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
}
}

View File

@ -6,7 +6,7 @@ void handleHue()
{
if (hueReceived)
{
colorUpdated(7); hueReceived = false;
colorUpdated(NOTIFIER_CALL_MODE_HUE); hueReceived = false;
if (hueStoreAllowed && hueNewKey)
{
saveSettingsToEEPROM(); //save api key

View File

@ -41,45 +41,45 @@ void updateBlynk()
BLYNK_WRITE(V0)
{
bri = param.asInt();//bri
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V1)
{
blHue = param.asInt();//hue
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V2)
{
blSat = param.asInt();//sat
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V3)
{
bool on = (param.asInt()>0);
if (!on != !bri) {toggleOnOff(); colorUpdated(9);}
if (!on != !bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BLYNK);}
}
BLYNK_WRITE(V4)
{
effectCurrent = param.asInt()-1;//fx
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V5)
{
effectSpeed = param.asInt();//sx
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V6)
{
effectIntensity = param.asInt();//ix
colorUpdated(9);
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
}
BLYNK_WRITE(V7)

View File

@ -3,6 +3,7 @@
*/
#ifdef WLED_ENABLE_MQTT
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
void parseMQTTBriPayload(char* payload)
{
@ -12,7 +13,7 @@ void parseMQTTBriPayload(char* payload)
uint8_t in = strtoul(payload, NULL, 10);
if (in == 0 && bri > 0) briLast = bri;
bri = in;
colorUpdated(1);
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
}
}
@ -60,7 +61,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
if (strstr(topic, "/col"))
{
colorFromDecOrHexString(col, (char*)payload);
colorUpdated(1);
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
} else if (strstr(topic, "/api"))
{
String apireq = "win&";
@ -129,7 +130,7 @@ bool initMqtt()
strcpy(mqttStatusTopic, mqttDeviceTopic);
strcat(mqttStatusTopic, "/status");
mqtt->setWill(mqttStatusTopic, 0, true, "offline");
mqtt->setKeepAlive(60);
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
mqtt->connect();
return true;
}

View File

@ -154,7 +154,7 @@ bool deserializeState(JsonObject root)
}
}
colorUpdated(noNotification ? 5:1);
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
ps = root["psave"] | -1;
if (ps >= 0) savePreset(ps);
@ -267,14 +267,25 @@ void serializeInfo(JsonObject root)
wifi_info["channel"] = WiFi.channel();
#ifdef ARDUINO_ARCH_ESP32
#ifdef WLED_DEBUG
wifi_info["txPower"] = (int) WiFi.getTxPower();
wifi_info["sleep"] = (bool) WiFi.getSleep();
#endif
root["arch"] = "esp32";
root["core"] = ESP.getSdkVersion();
//root["maxalloc"] = ESP.getMaxAllocHeap();
#ifdef WLED_DEBUG
root["resetReason0"] = (int)rtc_get_reset_reason(0);
root["resetReason1"] = (int)rtc_get_reset_reason(1);
#endif
root["lwip"] = 0;
#else
root["arch"] = "esp8266";
root["core"] = ESP.getCoreVersion();
//root["maxalloc"] = ESP.getMaxFreeBlockSize();
#ifdef WLED_DEBUG
root["resetReason"] = (int)ESP.getResetInfoPtr()->reason;
#endif
root["lwip"] = LWIP_VERSION_MAJOR;
#endif

View File

@ -29,7 +29,7 @@ bool decodeIRCustom(uint32_t code)
default: return false;
}
if (code != IRCUSTOM_MACRO1) colorUpdated(2); //don't update color again if we apply macro, it already does it
if (code != IRCUSTOM_MACRO1) colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //don't update color again if we apply macro, it already does it
return true;
}
@ -51,25 +51,25 @@ void decodeIR(uint32_t code)
irTimesRepeated++;
if (lastValidCode == IR24_BRIGHTER || lastValidCode == IR40_BPLUS )
{
relativeChange(&bri, 10); colorUpdated(2);
relativeChange(&bri, 10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
else if (lastValidCode == IR24_DARKER || lastValidCode == IR40_BMINUS )
{
relativeChange(&bri, -10, 5); colorUpdated(2);
relativeChange(&bri, -10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
if (lastValidCode == IR40_WPLUS)
{
relativeChangeWhite(10); colorUpdated(2);
relativeChangeWhite(10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
else if (lastValidCode == IR40_WMINUS)
{
relativeChangeWhite(-10, 5); colorUpdated(2);
relativeChangeWhite(-10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 )
{
nightlightActive = true;
nightlightStartTime = millis();
colorUpdated(2);
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
return;
}
@ -85,11 +85,12 @@ void decodeIR(uint32_t code)
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,
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
default: return;
}
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
}
//code <= 0xF70000 also invalid
}
@ -125,7 +126,6 @@ void decodeIR24(uint32_t code)
default: return;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
void decodeIR24OLD(uint32_t code)
@ -158,7 +158,6 @@ void decodeIR24OLD(uint32_t code)
default: return;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
@ -194,7 +193,6 @@ void decodeIR24CT(uint32_t code)
default: return;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
@ -253,7 +251,6 @@ void decodeIR40(uint32_t code)
case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
void decodeIR44(uint32_t code)
@ -317,12 +314,11 @@ void decodeIR44(uint32_t code)
case IR44_FADE7 : bri = 255; break;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
void decodeIR21(uint32_t code)
{
switch (code) {
switch (code) {
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
case IR21_OFF: briLast = bri; bri = 0; break;
@ -345,51 +341,42 @@ void decodeIR21(uint32_t code)
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
default: return;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
}
lastValidCode = code;
}
void decodeIR6(uint32_t code)
{
switch (code) {
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
case IR6_VOLUME_UP: /* next effect */ relativeChange(&effectCurrent, 1); break;
case IR6_VOLUME_DOWN:
/* next palette */
relativeChange(&effectPalette, 1);
switch(lastIR6ColourIdx)
{
case 0: colorFromUint32(COLOR_RED); break;
case 1: colorFromUint32(COLOR_REDDISH); break;
case 2:colorFromUint32(COLOR_ORANGE); break;
case 3:colorFromUint32(COLOR_YELLOWISH); break;
case 4:colorFromUint32(COLOR_GREEN); break;
case 5:colorFromUint32(COLOR_GREENISH); break;
case 6:colorFromUint32(COLOR_TURQUOISE); break;
case 7: colorFromUint32(COLOR_CYAN); break;
case 8:colorFromUint32(COLOR_BLUE); break;
case 9:colorFromUint32(COLOR_DEEPBLUE); break;
case 10:colorFromUint32(COLOR_PURPLE); break;
case 11:colorFromUint32(COLOR_PINK); break;
case 12:colorFromUint32(COLOR_WHITE); break;
default:break;
}
lastIR6ColourIdx++;
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0;
switch (code) {
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
case IR6_VOLUME_UP: /* next effect */ relativeChange(&effectCurrent, 1); break;
case IR6_VOLUME_DOWN:
/* next palette */
relativeChange(&effectPalette, 1);
switch(lastIR6ColourIdx) {
case 0: colorFromUint32(COLOR_RED); break;
case 1: colorFromUint32(COLOR_REDDISH); break;
case 2:colorFromUint32(COLOR_ORANGE); break;
case 3:colorFromUint32(COLOR_YELLOWISH); break;
case 4:colorFromUint32(COLOR_GREEN); break;
case 5:colorFromUint32(COLOR_GREENISH); break;
case 6:colorFromUint32(COLOR_TURQUOISE); break;
case 7: colorFromUint32(COLOR_CYAN); break;
case 8:colorFromUint32(COLOR_BLUE); break;
case 9:colorFromUint32(COLOR_DEEPBLUE); break;
case 10:colorFromUint32(COLOR_PURPLE); break;
case 11:colorFromUint32(COLOR_PINK); break;
case 12:colorFromUint32(COLOR_WHITE); break;
default:break;
}
lastIR6ColourIdx++;
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0;
break;
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
}
lastValidCode = code;
colorUpdated(2); //for notifier, IR is considered a button input
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
}
lastValidCode = code;
}