mirror of
https://github.com/wled/WLED.git
synced 2025-07-16 07:16:31 +00:00
Merge branch '0_15' of https://github.com/Aircoookie/WLED into audioreactive-analog
This commit is contained in:
commit
c8a7d44f55
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,5 +1,15 @@
|
|||||||
## WLED changelog
|
## WLED changelog
|
||||||
|
|
||||||
|
#### Build 240503
|
||||||
|
- Using brightness in analog clock overlay (#3944 by @paspiz85)
|
||||||
|
- Add Webpage shortcuts (#3945 by @w00000dy)
|
||||||
|
- ArtNet Poll reply (#3892 by @askask)
|
||||||
|
- Improved brightness change via long button presses (#3933 by @gaaat98)
|
||||||
|
- Relay open drain output (#3920 by @Suxsem)
|
||||||
|
- NEW JSON API: release info (update page, `info.release`)
|
||||||
|
- update esp32 platform to arduino-esp32 v2.0.9 (#3902)
|
||||||
|
- various optimisations and bugfixes (#3952, #3922, #3878, #3926, #3919, #3904 @DedeHai)
|
||||||
|
|
||||||
#### Build 2404120
|
#### Build 2404120
|
||||||
- v0.15.0-b3
|
- v0.15.0-b3
|
||||||
- fix for #3896 & WS2815 current saving
|
- fix for #3896 & WS2815 current saving
|
||||||
|
@ -36,6 +36,8 @@ def create_release(source):
|
|||||||
def bin_rename_copy(source, target, env):
|
def bin_rename_copy(source, target, env):
|
||||||
_create_dirs()
|
_create_dirs()
|
||||||
variant = env["PIOENV"]
|
variant = env["PIOENV"]
|
||||||
|
builddir = os.path.join(env["PROJECT_BUILD_DIR"], variant)
|
||||||
|
source_map = os.path.join(builddir, env["PROGNAME"] + ".map")
|
||||||
|
|
||||||
# create string with location and file names based on variant
|
# create string with location and file names based on variant
|
||||||
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
||||||
@ -44,7 +46,11 @@ def bin_rename_copy(source, target, env):
|
|||||||
|
|
||||||
# copy firmware.map to map/<variant>.map
|
# copy firmware.map to map/<variant>.map
|
||||||
if os.path.isfile("firmware.map"):
|
if os.path.isfile("firmware.map"):
|
||||||
shutil.move("firmware.map", map_file)
|
print("Found linker mapfile firmware.map")
|
||||||
|
shutil.copy("firmware.map", map_file)
|
||||||
|
if os.path.isfile(source_map):
|
||||||
|
print(f"Found linker mapfile {source_map}")
|
||||||
|
shutil.copy(source_map, map_file)
|
||||||
|
|
||||||
def bin_gzip(source, target):
|
def bin_gzip(source, target):
|
||||||
# only create gzip for esp8266
|
# only create gzip for esp8266
|
||||||
|
@ -471,8 +471,7 @@ monitor_filters = esp32_exception_decoder
|
|||||||
|
|
||||||
[env:esp32s3_4M_qspi]
|
[env:esp32s3_4M_qspi]
|
||||||
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
|
;; ESP32-S3, with 4MB FLASH and <= 4MB PSRAM (memory_type: qio_qspi)
|
||||||
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
|
board = lolin_s3_mini ;; -S3 mini, 4MB flash 2MB PSRAM
|
||||||
board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB
|
|
||||||
platform = ${esp32s3.platform}
|
platform = ${esp32s3.platform}
|
||||||
platform_packages = ${esp32s3.platform_packages}
|
platform_packages = ${esp32s3.platform_packages}
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
|
@ -183,7 +183,6 @@ constexpr uint16_t samplesFFT_2 = 256; // meaningfull part of FFT resul
|
|||||||
// These are the input and output vectors. Input vectors receive computed results from FFT.
|
// These are the input and output vectors. Input vectors receive computed results from FFT.
|
||||||
static float vReal[samplesFFT] = {0.0f}; // FFT sample inputs / freq output - these are our raw result bins
|
static float vReal[samplesFFT] = {0.0f}; // FFT sample inputs / freq output - these are our raw result bins
|
||||||
static float vImag[samplesFFT] = {0.0f}; // imaginary parts
|
static float vImag[samplesFFT] = {0.0f}; // imaginary parts
|
||||||
static float windowWeighingFactors[samplesFFT] = {0.0f};
|
|
||||||
|
|
||||||
// Create FFT object
|
// Create FFT object
|
||||||
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
// lib_deps += https://github.com/kosme/arduinoFFT#develop @ 1.9.2
|
||||||
@ -196,7 +195,8 @@ static float windowWeighingFactors[samplesFFT] = {0.0f};
|
|||||||
|
|
||||||
#include <arduinoFFT.h>
|
#include <arduinoFFT.h>
|
||||||
|
|
||||||
static ArduinoFFT<float> FFT = ArduinoFFT<float>( vReal, vImag, samplesFFT, SAMPLE_RATE, windowWeighingFactors);
|
/* Create FFT object with weighing factor storage */
|
||||||
|
static ArduinoFFT<float> FFT = ArduinoFFT<float>( vReal, vImag, samplesFFT, SAMPLE_RATE, true);
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
||||||
@ -1121,6 +1121,11 @@ class AudioReactive : public Usermod {
|
|||||||
delay(100); // Give that poor microphone some time to setup.
|
delay(100); // Give that poor microphone some time to setup.
|
||||||
|
|
||||||
useBandPassFilter = false;
|
useBandPassFilter = false;
|
||||||
|
|
||||||
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
if ((i2sckPin == I2S_PIN_NO_CHANGE) && (i2ssdPin >= 0) && (i2swsPin >= 0) && ((dmType == 1) || (dmType == 4)) ) dmType = 5; // dummy user support: SCK == -1 --means--> PDM microphone
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (dmType) {
|
switch (dmType) {
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
// stub cases for not-yet-supported I2S modes on other ESP32 chips
|
// stub cases for not-yet-supported I2S modes on other ESP32 chips
|
||||||
|
@ -110,11 +110,11 @@ void WS2812FX::setUpMatrix() {
|
|||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t x, y, pix=0; //pixel
|
unsigned x, y, pix=0; //pixel
|
||||||
for (size_t pan = 0; pan < panel.size(); pan++) {
|
for (size_t pan = 0; pan < panel.size(); pan++) {
|
||||||
Panel &p = panel[pan];
|
Panel &p = panel[pan];
|
||||||
uint16_t h = p.vertical ? p.height : p.width;
|
unsigned h = p.vertical ? p.height : p.width;
|
||||||
uint16_t v = p.vertical ? p.width : p.height;
|
unsigned v = p.vertical ? p.width : p.height;
|
||||||
for (size_t j = 0; j < v; j++){
|
for (size_t j = 0; j < v; j++){
|
||||||
for(size_t i = 0; i < h; i++) {
|
for(size_t i = 0; i < h; i++) {
|
||||||
y = (p.vertical?p.rightStart:p.bottomStart) ? v-j-1 : j;
|
y = (p.vertical?p.rightStart:p.bottomStart) ? v-j-1 : j;
|
||||||
@ -163,8 +163,8 @@ void WS2812FX::setUpMatrix() {
|
|||||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||||
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y)
|
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y)
|
||||||
{
|
{
|
||||||
uint16_t width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
|
unsigned width = virtualWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
|
||||||
uint16_t height = virtualHeight(); // segment height in logical pixels (is always >= 1)
|
unsigned height = virtualHeight(); // segment height in logical pixels (is always >= 1)
|
||||||
return isActive() ? (x%width) + (y%height) * width : 0;
|
return isActive() ? (x%width) + (y%height) * width : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
|
|
||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
if (reverse_y) y = virtualHeight() - y - 1;
|
if (reverse_y) y = virtualHeight() - y - 1;
|
||||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (transpose) { unsigned t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
|
|
||||||
x *= groupLength(); // expand to physical pixels
|
x *= groupLength(); // expand to physical pixels
|
||||||
y *= groupLength(); // expand to physical pixels
|
y *= groupLength(); // expand to physical pixels
|
||||||
@ -189,7 +189,7 @@ void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
|||||||
uint32_t tmpCol = col;
|
uint32_t tmpCol = col;
|
||||||
for (int j = 0; j < grouping; j++) { // groupping vertically
|
for (int j = 0; j < grouping; j++) { // groupping vertically
|
||||||
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
||||||
uint16_t xX = (x+g), yY = (y+j);
|
unsigned xX = (x+g), yY = (y+j);
|
||||||
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
@ -221,16 +221,16 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
|||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||||
|
|
||||||
const uint16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
|
|
||||||
float fX = x * (cols-1);
|
float fX = x * (cols-1);
|
||||||
float fY = y * (rows-1);
|
float fY = y * (rows-1);
|
||||||
if (aa) {
|
if (aa) {
|
||||||
uint16_t xL = roundf(fX-0.49f);
|
unsigned xL = roundf(fX-0.49f);
|
||||||
uint16_t xR = roundf(fX+0.49f);
|
unsigned xR = roundf(fX+0.49f);
|
||||||
uint16_t yT = roundf(fY-0.49f);
|
unsigned yT = roundf(fY-0.49f);
|
||||||
uint16_t yB = roundf(fY+0.49f);
|
unsigned yB = roundf(fY+0.49f);
|
||||||
float dL = (fX - xL)*(fX - xL);
|
float dL = (fX - xL)*(fX - xL);
|
||||||
float dR = (xR - fX)*(xR - fX);
|
float dR = (xR - fX)*(xR - fX);
|
||||||
float dT = (fY - yT)*(fY - yT);
|
float dT = (fY - yT)*(fY - yT);
|
||||||
@ -266,7 +266,7 @@ uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
|
|||||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
|
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return 0; // if pixel would fall out of virtual segment just exit
|
||||||
if (reverse ) x = virtualWidth() - x - 1;
|
if (reverse ) x = virtualWidth() - x - 1;
|
||||||
if (reverse_y) y = virtualHeight() - y - 1;
|
if (reverse_y) y = virtualHeight() - y - 1;
|
||||||
if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (transpose) { unsigned t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
x *= groupLength(); // expand to physical pixels
|
x *= groupLength(); // expand to physical pixels
|
||||||
y *= groupLength(); // expand to physical pixels
|
y *= groupLength(); // expand to physical pixels
|
||||||
if (x >= width() || y >= height()) return 0;
|
if (x >= width() || y >= height()) return 0;
|
||||||
@ -276,8 +276,8 @@ uint32_t IRAM_ATTR Segment::getPixelColorXY(int x, int y) {
|
|||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void Segment::blurRow(uint32_t row, fract8 blur_amount, bool smear){
|
void Segment::blurRow(uint32_t row, fract8 blur_amount, bool smear){
|
||||||
if (!isActive() || blur_amount == 0) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
|
|
||||||
if (row >= rows) return;
|
if (row >= rows) return;
|
||||||
// blur one row
|
// blur one row
|
||||||
@ -309,8 +309,8 @@ void Segment::blurRow(uint32_t row, fract8 blur_amount, bool smear){
|
|||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void Segment::blurCol(uint32_t col, fract8 blur_amount, bool smear) {
|
void Segment::blurCol(uint32_t col, fract8 blur_amount, bool smear) {
|
||||||
if (!isActive() || blur_amount == 0) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint_fast16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint_fast16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
|
|
||||||
if (col >= cols) return;
|
if (col >= cols) return;
|
||||||
// blur one column
|
// blur one column
|
||||||
@ -342,34 +342,34 @@ void Segment::blurCol(uint32_t col, fract8 blur_amount, bool smear) {
|
|||||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||||
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
||||||
if (!isActive() || blur_amount == 0) return; // not active
|
if (!isActive() || blur_amount == 0) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
const uint16_t dim1 = vertical ? rows : cols;
|
const unsigned dim1 = vertical ? rows : cols;
|
||||||
const uint16_t dim2 = vertical ? cols : rows;
|
const unsigned dim2 = vertical ? cols : rows;
|
||||||
if (i >= dim2) return;
|
if (i >= dim2) return;
|
||||||
const float seep = blur_amount/255.f;
|
const float seep = blur_amount/255.f;
|
||||||
const float keep = 3.f - 2.f*seep;
|
const float keep = 3.f - 2.f*seep;
|
||||||
// 1D box blur
|
// 1D box blur
|
||||||
CRGB tmp[dim1];
|
CRGB tmp[dim1];
|
||||||
for (int j = 0; j < dim1; j++) {
|
for (unsigned j = 0; j < dim1; j++) {
|
||||||
uint16_t x = vertical ? i : j;
|
unsigned x = vertical ? i : j;
|
||||||
uint16_t y = vertical ? j : i;
|
unsigned y = vertical ? j : i;
|
||||||
int16_t xp = vertical ? x : x-1; // "signed" to prevent underflow
|
int xp = vertical ? x : x-1; // "signed" to prevent underflow
|
||||||
int16_t yp = vertical ? y-1 : y; // "signed" to prevent underflow
|
int yp = vertical ? y-1 : y; // "signed" to prevent underflow
|
||||||
uint16_t xn = vertical ? x : x+1;
|
unsigned xn = vertical ? x : x+1;
|
||||||
uint16_t yn = vertical ? y+1 : y;
|
unsigned yn = vertical ? y+1 : y;
|
||||||
CRGB curr = getPixelColorXY(x,y);
|
CRGB curr = getPixelColorXY(x,y);
|
||||||
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : getPixelColorXY(xp,yp);
|
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : getPixelColorXY(xp,yp);
|
||||||
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : getPixelColorXY(xn,yn);
|
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : getPixelColorXY(xn,yn);
|
||||||
uint16_t r, g, b;
|
unsigned r, g, b;
|
||||||
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
||||||
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
||||||
b = (curr.b*keep + (prev.b + next.b)*seep) / 3;
|
b = (curr.b*keep + (prev.b + next.b)*seep) / 3;
|
||||||
tmp[j] = CRGB(r,g,b);
|
tmp[j] = CRGB(r,g,b);
|
||||||
}
|
}
|
||||||
for (int j = 0; j < dim1; j++) {
|
for (unsigned j = 0; j < dim1; j++) {
|
||||||
uint16_t x = vertical ? i : j;
|
unsigned x = vertical ? i : j;
|
||||||
uint16_t y = vertical ? j : i;
|
unsigned y = vertical ? j : i;
|
||||||
setPixelColorXY(x, y, tmp[j]);
|
setPixelColorXY(x, y, tmp[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,14 +389,14 @@ void Segment::box_blur(uint16_t i, bool vertical, fract8 blur_amount) {
|
|||||||
// it can be used to (slowly) clear the LEDs to black.
|
// it can be used to (slowly) clear the LEDs to black.
|
||||||
|
|
||||||
void Segment::blur1d(fract8 blur_amount) {
|
void Segment::blur1d(fract8 blur_amount) {
|
||||||
const uint16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
for (unsigned y = 0; y < rows; y++) blurRow(y, blur_amount);
|
for (unsigned y = 0; y < rows; y++) blurRow(y, blur_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Segment::moveX(int8_t delta, bool wrap) {
|
void Segment::moveX(int8_t delta, bool wrap) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
if (!delta || abs(delta) >= cols) return;
|
if (!delta || abs(delta) >= cols) return;
|
||||||
uint32_t newPxCol[cols];
|
uint32_t newPxCol[cols];
|
||||||
for (int y = 0; y < rows; y++) {
|
for (int y = 0; y < rows; y++) {
|
||||||
@ -413,8 +413,8 @@ void Segment::moveX(int8_t delta, bool wrap) {
|
|||||||
|
|
||||||
void Segment::moveY(int8_t delta, bool wrap) {
|
void Segment::moveY(int8_t delta, bool wrap) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
if (!delta || abs(delta) >= rows) return;
|
if (!delta || abs(delta) >= rows) return;
|
||||||
uint32_t newPxCol[rows];
|
uint32_t newPxCol[rows];
|
||||||
for (int x = 0; x < cols; x++) {
|
for (int x = 0; x < cols; x++) {
|
||||||
@ -474,13 +474,13 @@ void Segment::draw_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
if (!isActive() || radius == 0) return; // not active
|
if (!isActive() || radius == 0) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
for (int16_t y = -radius; y <= radius; y++) {
|
for (int y = -radius; y <= radius; y++) {
|
||||||
for (int16_t x = -radius; x <= radius; x++) {
|
for (int x = -radius; x <= radius; x++) {
|
||||||
if (x * x + y * y <= radius * radius &&
|
if (x * x + y * y <= radius * radius &&
|
||||||
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
|
int(cx)+x>=0 && int(cy)+y>=0 &&
|
||||||
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
|
int(cx)+x<cols && int(cy)+y<rows)
|
||||||
setPixelColorXY(cx + x, cy + y, col);
|
setPixelColorXY(cx + x, cy + y, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,9 +488,9 @@ void Segment::fill_circle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
|||||||
|
|
||||||
void Segment::nscale8(uint8_t scale) {
|
void Segment::nscale8(uint8_t scale) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
for (unsigned y = 0; y < rows; y++) for (unsigned x = 0; x < cols; x++) {
|
||||||
setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,12 +498,12 @@ void Segment::nscale8(uint8_t scale) {
|
|||||||
//line function
|
//line function
|
||||||
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
|
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = virtualWidth();
|
const unsigned cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const unsigned rows = virtualHeight();
|
||||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||||
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
const int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||||
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
const int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||||
int16_t err = (dx>dy ? dx : -dy)/2, e2;
|
int err = (dx>dy ? dx : -dy)/2, e2;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
setPixelColorXY(x0,y0,c);
|
setPixelColorXY(x0,y0,c);
|
||||||
if (x0==x1 && y0==y1) break;
|
if (x0==x1 && y0==y1) break;
|
||||||
@ -525,8 +525,8 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported
|
||||||
chr -= 32; // align with font table entries
|
chr -= 32; // align with font table entries
|
||||||
const uint16_t cols = virtualWidth();
|
const int cols = virtualWidth();
|
||||||
const uint16_t rows = virtualHeight();
|
const int rows = virtualHeight();
|
||||||
const int font = w*h;
|
const int font = w*h;
|
||||||
|
|
||||||
CRGB col = CRGB(color);
|
CRGB col = CRGB(color);
|
||||||
@ -565,7 +565,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
// extract the fractional parts and derive their inverses
|
// extract the fractional parts and derive their inverses
|
||||||
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
unsigned xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
||||||
// calculate the intensities for each affected pixel
|
// calculate the intensities for each affected pixel
|
||||||
uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy),
|
uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy),
|
||||||
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
|
WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};
|
||||||
|
@ -327,7 +327,7 @@ void Segment::stopTransition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::handleTransition() {
|
void Segment::handleTransition() {
|
||||||
uint16_t _progress = progress();
|
unsigned _progress = progress();
|
||||||
if (_progress == 0xFFFFU) stopTransition();
|
if (_progress == 0xFFFFU) stopTransition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,9 +412,9 @@ void Segment::restoreSegenv(tmpsegd_t &tmpSeg) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
|
uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
|
||||||
uint32_t prog = progress();
|
unsigned prog = progress();
|
||||||
if (prog < 0xFFFFU) {
|
if (prog < 0xFFFFU) {
|
||||||
uint32_t curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
|
unsigned curBri = (useCct ? cct : (on ? opacity : 0)) * prog;
|
||||||
curBri += (useCct ? _t->_cctT : _t->_briT) * (0xFFFFU - prog);
|
curBri += (useCct ? _t->_cctT : _t->_briT) * (0xFFFFU - prog);
|
||||||
return curBri / 0xFFFFU;
|
return curBri / 0xFFFFU;
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ uint8_t IRAM_ATTR Segment::currentBri(bool useCct) {
|
|||||||
|
|
||||||
uint8_t IRAM_ATTR Segment::currentMode() {
|
uint8_t IRAM_ATTR Segment::currentMode() {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
uint16_t prog = progress();
|
unsigned prog = progress();
|
||||||
if (modeBlending && prog < 0xFFFFU) return _t->_modeT;
|
if (modeBlending && prog < 0xFFFFU) return _t->_modeT;
|
||||||
#endif
|
#endif
|
||||||
return mode;
|
return mode;
|
||||||
@ -440,13 +440,13 @@ uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
|
|||||||
|
|
||||||
CRGBPalette16 IRAM_ATTR &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
CRGBPalette16 IRAM_ATTR &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||||
loadPalette(targetPalette, pal);
|
loadPalette(targetPalette, pal);
|
||||||
uint16_t prog = progress();
|
unsigned prog = progress();
|
||||||
if (strip.paletteFade && prog < 0xFFFFU) {
|
if (strip.paletteFade && prog < 0xFFFFU) {
|
||||||
// blend palettes
|
// blend palettes
|
||||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||||
// minimum blend time is 100ms maximum is 65535ms
|
// minimum blend time is 100ms maximum is 65535ms
|
||||||
uint16_t noOfBlends = ((255U * prog) / 0xFFFFU) - _t->_prevPaletteBlends;
|
unsigned noOfBlends = ((255U * prog) / 0xFFFFU) - _t->_prevPaletteBlends;
|
||||||
for (int i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
for (unsigned i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
||||||
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
||||||
}
|
}
|
||||||
return targetPalette;
|
return targetPalette;
|
||||||
@ -576,7 +576,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
mode = fx;
|
mode = fx;
|
||||||
// load default values from effect string
|
// load default values from effect string
|
||||||
if (loadDefaults) {
|
if (loadDefaults) {
|
||||||
int16_t sOpt;
|
int sOpt;
|
||||||
sOpt = extractModeDefaults(fx, "sx"); speed = (sOpt >= 0) ? sOpt : DEFAULT_SPEED;
|
sOpt = extractModeDefaults(fx, "sx"); speed = (sOpt >= 0) ? sOpt : DEFAULT_SPEED;
|
||||||
sOpt = extractModeDefaults(fx, "ix"); intensity = (sOpt >= 0) ? sOpt : DEFAULT_INTENSITY;
|
sOpt = extractModeDefaults(fx, "ix"); intensity = (sOpt >= 0) ? sOpt : DEFAULT_INTENSITY;
|
||||||
sOpt = extractModeDefaults(fx, "c1"); custom1 = (sOpt >= 0) ? sOpt : DEFAULT_C1;
|
sOpt = extractModeDefaults(fx, "c1"); custom1 = (sOpt >= 0) ? sOpt : DEFAULT_C1;
|
||||||
@ -610,21 +610,21 @@ void Segment::setPalette(uint8_t pal) {
|
|||||||
|
|
||||||
// 2D matrix
|
// 2D matrix
|
||||||
uint16_t IRAM_ATTR Segment::virtualWidth() const {
|
uint16_t IRAM_ATTR Segment::virtualWidth() const {
|
||||||
uint16_t groupLen = groupLength();
|
unsigned groupLen = groupLength();
|
||||||
uint16_t vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
unsigned vWidth = ((transpose ? height() : width()) + groupLen - 1) / groupLen;
|
||||||
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
if (mirror) vWidth = (vWidth + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vWidth;
|
return vWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t IRAM_ATTR Segment::virtualHeight() const {
|
uint16_t IRAM_ATTR Segment::virtualHeight() const {
|
||||||
uint16_t groupLen = groupLength();
|
unsigned groupLen = groupLength();
|
||||||
uint16_t vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
|
unsigned vHeight = ((transpose ? width() : height()) + groupLen - 1) / groupLen;
|
||||||
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
if (mirror_y) vHeight = (vHeight + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vHeight;
|
return vHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t IRAM_ATTR Segment::nrOfVStrips() const {
|
uint16_t IRAM_ATTR Segment::nrOfVStrips() const {
|
||||||
uint16_t vLen = 1;
|
unsigned vLen = 1;
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
switch (map1D2D) {
|
switch (map1D2D) {
|
||||||
@ -641,9 +641,9 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const {
|
|||||||
uint16_t IRAM_ATTR Segment::virtualLength() const {
|
uint16_t IRAM_ATTR Segment::virtualLength() const {
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
uint16_t vW = virtualWidth();
|
unsigned vW = virtualWidth();
|
||||||
uint16_t vH = virtualHeight();
|
unsigned vH = virtualHeight();
|
||||||
uint16_t vLen = vW * vH; // use all pixels from segment
|
unsigned vLen = vW * vH; // use all pixels from segment
|
||||||
switch (map1D2D) {
|
switch (map1D2D) {
|
||||||
case M12_pBar:
|
case M12_pBar:
|
||||||
vLen = vH;
|
vLen = vH;
|
||||||
@ -656,8 +656,8 @@ uint16_t IRAM_ATTR Segment::virtualLength() const {
|
|||||||
return vLen;
|
return vLen;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint16_t groupLen = groupLength(); // is always >= 1
|
unsigned groupLen = groupLength(); // is always >= 1
|
||||||
uint16_t vLength = (length() + groupLen - 1) / groupLen;
|
unsigned vLength = (length() + groupLen - 1) / groupLen;
|
||||||
if (mirror) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
if (mirror) vLength = (vLength + 1) /2; // divide by 2 if mirror, leave at least a single LED
|
||||||
return vLength;
|
return vLength;
|
||||||
}
|
}
|
||||||
@ -674,8 +674,8 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
uint16_t vH = virtualHeight(); // segment height in logical pixels
|
int vH = virtualHeight(); // segment height in logical pixels
|
||||||
uint16_t vW = virtualWidth();
|
int vW = virtualWidth();
|
||||||
switch (map1D2D) {
|
switch (map1D2D) {
|
||||||
case M12_Pixels:
|
case M12_Pixels:
|
||||||
// use all available pixels as a long strip
|
// use all available pixels as a long strip
|
||||||
@ -732,7 +732,7 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t len = length();
|
unsigned len = length();
|
||||||
uint8_t _bri_t = currentBri();
|
uint8_t _bri_t = currentBri();
|
||||||
if (_bri_t < 255) {
|
if (_bri_t < 255) {
|
||||||
col = color_fade(col, _bri_t);
|
col = color_fade(col, _bri_t);
|
||||||
@ -785,8 +785,8 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
|||||||
|
|
||||||
float fC = i * (virtualLength()-1);
|
float fC = i * (virtualLength()-1);
|
||||||
if (aa) {
|
if (aa) {
|
||||||
uint16_t iL = roundf(fC-0.49f);
|
unsigned iL = roundf(fC-0.49f);
|
||||||
uint16_t iR = roundf(fC+0.49f);
|
unsigned iR = roundf(fC+0.49f);
|
||||||
float dL = (fC - iL)*(fC - iL);
|
float dL = (fC - iL)*(fC - iL);
|
||||||
float dR = (iR - fC)*(iR - fC);
|
float dR = (iR - fC)*(iR - fC);
|
||||||
uint32_t cIL = getPixelColor(iL | (vStrip<<16));
|
uint32_t cIL = getPixelColor(iL | (vStrip<<16));
|
||||||
@ -803,7 +803,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
|||||||
setPixelColor(iL | (vStrip<<16), col);
|
setPixelColor(iL | (vStrip<<16), col);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPixelColor(uint16_t(roundf(fC)) | (vStrip<<16), col);
|
setPixelColor(int(roundf(fC)) | (vStrip<<16), col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -818,8 +818,8 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i)
|
|||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (is2D()) {
|
if (is2D()) {
|
||||||
uint16_t vH = virtualHeight(); // segment height in logical pixels
|
unsigned vH = virtualHeight(); // segment height in logical pixels
|
||||||
uint16_t vW = virtualWidth();
|
unsigned vW = virtualWidth();
|
||||||
switch (map1D2D) {
|
switch (map1D2D) {
|
||||||
case M12_Pixels:
|
case M12_Pixels:
|
||||||
return getPixelColorXY(i % vW, i / vW);
|
return getPixelColorXY(i % vW, i / vW);
|
||||||
@ -875,9 +875,9 @@ uint8_t Segment::differs(Segment& b) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Segment::refreshLightCapabilities() {
|
void Segment::refreshLightCapabilities() {
|
||||||
uint8_t capabilities = 0;
|
unsigned capabilities = 0;
|
||||||
uint16_t segStartIdx = 0xFFFFU;
|
unsigned segStartIdx = 0xFFFFU;
|
||||||
uint16_t segStopIdx = 0;
|
unsigned segStopIdx = 0;
|
||||||
|
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
_capabilities = 0;
|
_capabilities = 0;
|
||||||
@ -887,7 +887,7 @@ void Segment::refreshLightCapabilities() {
|
|||||||
if (start < Segment::maxWidth * Segment::maxHeight) {
|
if (start < Segment::maxWidth * Segment::maxHeight) {
|
||||||
// we are withing 2D matrix (includes 1D segments)
|
// we are withing 2D matrix (includes 1D segments)
|
||||||
for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) {
|
for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) {
|
||||||
uint16_t index = strip.getMappedPixelIndex(x + Segment::maxWidth * y); // convert logical address to physical
|
unsigned index = strip.getMappedPixelIndex(x + Segment::maxWidth * y); // convert logical address to physical
|
||||||
if (index < 0xFFFFU) {
|
if (index < 0xFFFFU) {
|
||||||
if (segStartIdx > index) segStartIdx = index;
|
if (segStartIdx > index) segStartIdx = index;
|
||||||
if (segStopIdx < index) segStopIdx = index;
|
if (segStopIdx < index) segStopIdx = index;
|
||||||
@ -912,7 +912,7 @@ void Segment::refreshLightCapabilities() {
|
|||||||
if (!cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT;
|
if (!cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT;
|
||||||
if (correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider)
|
if (correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider)
|
||||||
if (bus->hasWhite()) {
|
if (bus->hasWhite()) {
|
||||||
uint8_t aWM = Bus::getGlobalAWMode() == AW_GLOBAL_DISABLED ? bus->getAutoWhiteMode() : Bus::getGlobalAWMode();
|
unsigned aWM = Bus::getGlobalAWMode() == AW_GLOBAL_DISABLED ? bus->getAutoWhiteMode() : Bus::getGlobalAWMode();
|
||||||
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
||||||
// if auto white calculation from RGB is active (Accurate/Brighter), force RGB controls even if there are no RGB busses
|
// if auto white calculation from RGB is active (Accurate/Brighter), force RGB controls even if there are no RGB busses
|
||||||
if (!whiteSlider) capabilities |= SEG_CAPABILITY_RGB;
|
if (!whiteSlider) capabilities |= SEG_CAPABILITY_RGB;
|
||||||
@ -928,8 +928,8 @@ void Segment::refreshLightCapabilities() {
|
|||||||
*/
|
*/
|
||||||
void Segment::fill(uint32_t c) {
|
void Segment::fill(uint32_t c) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const int cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const int rows = virtualHeight(); // will be 1 for 1D
|
||||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
if (is2D()) setPixelColorXY(x, y, c);
|
if (is2D()) setPixelColorXY(x, y, c);
|
||||||
else setPixelColor(x, c);
|
else setPixelColor(x, c);
|
||||||
@ -941,8 +941,8 @@ void Segment::fill(uint32_t c) {
|
|||||||
*/
|
*/
|
||||||
void Segment::fade_out(uint8_t rate) {
|
void Segment::fade_out(uint8_t rate) {
|
||||||
if (!isActive()) return; // not active
|
if (!isActive()) return; // not active
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const int cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const int rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
rate = (255-rate) >> 1;
|
rate = (255-rate) >> 1;
|
||||||
float mappedRate = float(rate) +1.1f;
|
float mappedRate = float(rate) +1.1f;
|
||||||
@ -979,8 +979,8 @@ void Segment::fade_out(uint8_t rate) {
|
|||||||
// fades all pixels to black using nscale8()
|
// fades all pixels to black using nscale8()
|
||||||
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
void Segment::fadeToBlackBy(uint8_t fadeBy) {
|
||||||
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
if (!isActive() || fadeBy == 0) return; // optimization - no scaling to apply
|
||||||
const uint16_t cols = is2D() ? virtualWidth() : virtualLength();
|
const int cols = is2D() ? virtualWidth() : virtualLength();
|
||||||
const uint16_t rows = virtualHeight(); // will be 1 for 1D
|
const int rows = virtualHeight(); // will be 1 for 1D
|
||||||
|
|
||||||
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) {
|
||||||
if (is2D()) setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), 255-fadeBy));
|
if (is2D()) setPixelColorXY(x, y, color_fade(getPixelColorXY(x,y), 255-fadeBy));
|
||||||
@ -1065,7 +1065,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
|
|||||||
// default palette or no RGB support on segment
|
// default palette or no RGB support on segment
|
||||||
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) return (pbri == 255) ? color : color_fade(color, pbri, true);
|
if ((palette == 0 && mcol < NUM_COLORS) || !_isRGB) return (pbri == 255) ? color : color_fade(color, pbri, true);
|
||||||
|
|
||||||
uint8_t paletteIndex = i;
|
unsigned paletteIndex = i;
|
||||||
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
|
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
|
||||||
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
|
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
|
||||||
if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||||
@ -1132,7 +1132,7 @@ void WS2812FX::finalizeInit(void) {
|
|||||||
_hasWhiteChannel |= bus->hasWhite();
|
_hasWhiteChannel |= bus->hasWhite();
|
||||||
//refresh is required to remain off if at least one of the strips requires the refresh.
|
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||||
_isOffRefreshRequired |= bus->isOffRefreshRequired();
|
_isOffRefreshRequired |= bus->isOffRefreshRequired();
|
||||||
uint16_t busEnd = bus->getStart() + bus->getLength();
|
unsigned busEnd = bus->getStart() + bus->getLength();
|
||||||
if (busEnd > _length) _length = busEnd;
|
if (busEnd > _length) _length = busEnd;
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
if ((!IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType()))) continue;
|
if ((!IS_DIGITAL(bus->getType()) || IS_2PIN(bus->getType()))) continue;
|
||||||
@ -1176,10 +1176,10 @@ void WS2812FX::service() {
|
|||||||
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
if (nowUp > seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC))
|
||||||
{
|
{
|
||||||
doShow = true;
|
doShow = true;
|
||||||
uint16_t delay = FRAMETIME;
|
unsigned delay = FRAMETIME;
|
||||||
|
|
||||||
if (!seg.freeze) { //only run effect function if not frozen
|
if (!seg.freeze) { //only run effect function if not frozen
|
||||||
int16_t oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
|
int oldCCT = BusManager::getSegmentCCT(); // store original CCT value (actually it is not Segment based)
|
||||||
_virtualSegmentLength = seg.virtualLength(); //SEGLEN
|
_virtualSegmentLength = seg.virtualLength(); //SEGLEN
|
||||||
_colors_t[0] = gamma32(seg.currentColor(0));
|
_colors_t[0] = gamma32(seg.currentColor(0));
|
||||||
_colors_t[1] = gamma32(seg.currentColor(1));
|
_colors_t[1] = gamma32(seg.currentColor(1));
|
||||||
@ -1203,7 +1203,7 @@ void WS2812FX::service() {
|
|||||||
Segment::modeBlend(true); // set semaphore
|
Segment::modeBlend(true); // set semaphore
|
||||||
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
seg.swapSegenv(_tmpSegData); // temporarily store new mode state (and swap it with transitional state)
|
||||||
_virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed)
|
_virtualSegmentLength = seg.virtualLength(); // update SEGLEN (mapping may have changed)
|
||||||
uint16_t d2 = (*_mode[tmpMode])(); // run old mode
|
unsigned d2 = (*_mode[tmpMode])(); // run old mode
|
||||||
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state)
|
seg.restoreSegenv(_tmpSegData); // restore mode state (will also update transitional state)
|
||||||
delay = MIN(delay,d2); // use shortest delay
|
delay = MIN(delay,d2); // use shortest delay
|
||||||
Segment::modeBlend(false); // unset semaphore
|
Segment::modeBlend(false); // unset semaphore
|
||||||
@ -1378,13 +1378,13 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthTotal(void) {
|
uint16_t WS2812FX::getLengthTotal(void) {
|
||||||
uint16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
unsigned len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
||||||
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t WS2812FX::getLengthPhysical(void) {
|
uint16_t WS2812FX::getLengthPhysical(void) {
|
||||||
uint16_t len = 0;
|
unsigned len = 0;
|
||||||
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
for (size_t b = 0; b < BusManager::getNumBusses(); b++) {
|
||||||
Bus *bus = BusManager::getBus(b);
|
Bus *bus = BusManager::getBus(b);
|
||||||
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
if (bus->getType() >= TYPE_NET_DDP_RGB) continue; //exclude non-physical network busses
|
||||||
@ -1461,8 +1461,8 @@ void WS2812FX::resetSegments() {
|
|||||||
|
|
||||||
void WS2812FX::makeAutoSegments(bool forceReset) {
|
void WS2812FX::makeAutoSegments(bool forceReset) {
|
||||||
if (autoSegments) { //make one segment per bus
|
if (autoSegments) { //make one segment per bus
|
||||||
uint16_t segStarts[MAX_NUM_SEGMENTS] = {0};
|
unsigned segStarts[MAX_NUM_SEGMENTS] = {0};
|
||||||
uint16_t segStops [MAX_NUM_SEGMENTS] = {0};
|
unsigned segStops [MAX_NUM_SEGMENTS] = {0};
|
||||||
size_t s = 0;
|
size_t s = 0;
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
|
@ -466,7 +466,22 @@ void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
|||||||
//does no index check
|
//does no index check
|
||||||
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
||||||
if (!_valid) return 0;
|
if (!_valid) return 0;
|
||||||
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
// TODO getting the reverse from CCT is involved (a quick approximation when CCT blending is ste to 0 implemented)
|
||||||
|
switch (_type) {
|
||||||
|
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
|
||||||
|
return RGBW32(0, 0, 0, _data[0]);
|
||||||
|
case TYPE_ANALOG_2CH: //warm white + cold white
|
||||||
|
if (cctICused) return RGBW32(0, 0, 0, _data[0]);
|
||||||
|
else return RGBW32(0, 0, 0, _data[0] + _data[1]);
|
||||||
|
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
|
||||||
|
if (cctICused) return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
||||||
|
else return RGBW32(_data[0], _data[1], _data[2], _data[3] + _data[4]);
|
||||||
|
case TYPE_ANALOG_4CH: //RGBW
|
||||||
|
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
||||||
|
case TYPE_ANALOG_3CH: //standard dumb RGB
|
||||||
|
return RGBW32(_data[0], _data[1], _data[2], 0);
|
||||||
|
}
|
||||||
|
return RGBW32(_data[0], _data[0], _data[0], _data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ESP8266
|
#ifndef ESP8266
|
||||||
|
@ -496,6 +496,11 @@ class PolyBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) {
|
static void* create(uint8_t busType, uint8_t* pins, uint16_t len, uint8_t channel, uint16_t clock_kHz = 0U) {
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
|
||||||
|
// NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation
|
||||||
|
// since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation
|
||||||
|
if (channel > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32
|
||||||
|
#endif
|
||||||
void* busPtr = nullptr;
|
void* busPtr = nullptr;
|
||||||
switch (busType) {
|
switch (busType) {
|
||||||
case I_NONE: break;
|
case I_NONE: break;
|
||||||
|
@ -10,9 +10,10 @@
|
|||||||
#define WLED_LONG_REPEATED_ACTION 400 // how often a repeated action (e.g. dimming) is fired on long press on button IDs >0
|
#define WLED_LONG_REPEATED_ACTION 400 // how often a repeated action (e.g. dimming) is fired on long press on button IDs >0
|
||||||
#define WLED_LONG_AP 5000 // how long button 0 needs to be held to activate WLED-AP
|
#define WLED_LONG_AP 5000 // how long button 0 needs to be held to activate WLED-AP
|
||||||
#define WLED_LONG_FACTORY_RESET 10000 // how long button 0 needs to be held to trigger a factory reset
|
#define WLED_LONG_FACTORY_RESET 10000 // how long button 0 needs to be held to trigger a factory reset
|
||||||
#define WLED_LONG_BRI_STEPS 16 // how long to wait before increasing/decreasing brightness on long press
|
#define WLED_LONG_BRI_STEPS 16 // how much to increase/decrease the brightness with each long press repetition
|
||||||
|
|
||||||
static const char _mqtt_topic_button[] PROGMEM = "%s/button/%d"; // optimize flash usage
|
static const char _mqtt_topic_button[] PROGMEM = "%s/button/%d"; // optimize flash usage
|
||||||
|
static bool buttonBriDirection = false; // true: increase brightness, false: decrease brightness
|
||||||
|
|
||||||
void shortPressAction(uint8_t b)
|
void shortPressAction(uint8_t b)
|
||||||
{
|
{
|
||||||
@ -41,7 +42,6 @@ void longPressAction(uint8_t b)
|
|||||||
switch (b) {
|
switch (b) {
|
||||||
case 0: setRandomColor(col); colorUpdated(CALL_MODE_BUTTON); break;
|
case 0: setRandomColor(col); colorUpdated(CALL_MODE_BUTTON); break;
|
||||||
case 1:
|
case 1:
|
||||||
// increase bri on true, decrease on false
|
|
||||||
if(buttonBriDirection) {
|
if(buttonBriDirection) {
|
||||||
if (bri == 255) break; // avoid unnecessary updates to brightness
|
if (bri == 255) break; // avoid unnecessary updates to brightness
|
||||||
if (bri >= 255 - WLED_LONG_BRI_STEPS) bri = 255;
|
if (bri >= 255 - WLED_LONG_BRI_STEPS) bri = 255;
|
||||||
|
@ -272,6 +272,7 @@ function onLoad()
|
|||||||
|
|
||||||
selectSlot(0);
|
selectSlot(0);
|
||||||
updateTablinks(0);
|
updateTablinks(0);
|
||||||
|
handleLocationHash();
|
||||||
cpick.on("input:end", () => {setColor(1);});
|
cpick.on("input:end", () => {setColor(1);});
|
||||||
cpick.on("color:change", () => {updatePSliders()});
|
cpick.on("color:change", () => {updatePSliders()});
|
||||||
pmtLS = localStorage.getItem('wledPmt');
|
pmtLS = localStorage.getItem('wledPmt');
|
||||||
@ -304,7 +305,6 @@ function updateTablinks(tabI)
|
|||||||
{
|
{
|
||||||
var tablinks = gEBCN("tablinks");
|
var tablinks = gEBCN("tablinks");
|
||||||
for (var i of tablinks) i.classList.remove('active');
|
for (var i of tablinks) i.classList.remove('active');
|
||||||
if (pcMode) return;
|
|
||||||
tablinks[tabI].classList.add('active');
|
tablinks[tabI].classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +315,21 @@ function openTab(tabI, force = false)
|
|||||||
_C.classList.toggle('smooth', false);
|
_C.classList.toggle('smooth', false);
|
||||||
_C.style.setProperty('--i', iSlide);
|
_C.style.setProperty('--i', iSlide);
|
||||||
updateTablinks(tabI);
|
updateTablinks(tabI);
|
||||||
|
switch (tabI) {
|
||||||
|
case 0: window.location.hash = "Colors"; break;
|
||||||
|
case 1: window.location.hash = "Effects"; break;
|
||||||
|
case 2: window.location.hash = "Segments"; break;
|
||||||
|
case 3: window.location.hash = "Presets"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleLocationHash() {
|
||||||
|
switch (window.location.hash) {
|
||||||
|
case "#Colors": openTab(0); break;
|
||||||
|
case "#Effects": openTab(1); break;
|
||||||
|
case "#Segments": openTab(2); break;
|
||||||
|
case "#Presets": openTab(3); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeout;
|
var timeout;
|
||||||
@ -3051,8 +3066,7 @@ function togglePcMode(fromB = false)
|
|||||||
pcMode = (wW >= 1024) && pcModeA;
|
pcMode = (wW >= 1024) && pcModeA;
|
||||||
if (cpick) cpick.resize(pcMode && wW>1023 && wW<1250 ? 230 : 260); // for tablet in landscape
|
if (cpick) cpick.resize(pcMode && wW>1023 && wW<1250 ? 230 : 260); // for tablet in landscape
|
||||||
if (!fromB && ((wW < 1024 && lastw < 1024) || (wW >= 1024 && lastw >= 1024))) return; // no change in size and called from size()
|
if (!fromB && ((wW < 1024 && lastw < 1024) || (wW >= 1024 && lastw >= 1024))) return; // no change in size and called from size()
|
||||||
openTab(0, true);
|
if (pcMode) openTab(0, true);
|
||||||
updateTablinks(0);
|
|
||||||
gId('buttonPcm').className = (pcMode) ? "active":"";
|
gId('buttonPcm').className = (pcMode) ? "active":"";
|
||||||
gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto";
|
gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto";
|
||||||
sCol('--bh', gId('bot').clientHeight + "px");
|
sCol('--bh', gId('bot').clientHeight + "px");
|
||||||
@ -3214,6 +3228,7 @@ size();
|
|||||||
_C.style.setProperty('--n', N);
|
_C.style.setProperty('--n', N);
|
||||||
|
|
||||||
window.addEventListener('resize', size, true);
|
window.addEventListener('resize', size, true);
|
||||||
|
window.addEventListener('hashchange', handleLocationHash);
|
||||||
|
|
||||||
_C.addEventListener('mousedown', lock, false);
|
_C.addEventListener('mousedown', lock, false);
|
||||||
_C.addEventListener('touchstart', lock, false);
|
_C.addEventListener('touchstart', lock, false);
|
||||||
|
@ -346,7 +346,6 @@ void handleArtnetPollReply(IPAddress ipAddress) {
|
|||||||
|
|
||||||
switch (DMXMode) {
|
switch (DMXMode) {
|
||||||
case DMX_MODE_DISABLED:
|
case DMX_MODE_DISABLED:
|
||||||
return; // nothing to do
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DMX_MODE_SINGLE_RGB:
|
case DMX_MODE_SINGLE_RGB:
|
||||||
@ -391,9 +390,17 @@ void handleArtnetPollReply(IPAddress ipAddress) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t i = startUniverse; i <= endUniverse; ++i) {
|
if (DMXMode != DMX_MODE_DISABLED) {
|
||||||
sendArtnetPollReply(&artnetPollReply, ipAddress, i);
|
for (uint16_t i = startUniverse; i <= endUniverse; ++i) {
|
||||||
|
sendArtnetPollReply(&artnetPollReply, ipAddress, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WLED_ENABLE_DMX
|
||||||
|
if (e131ProxyUniverse > 0 && (DMXMode == DMX_MODE_DISABLED || (e131ProxyUniverse < startUniverse || e131ProxyUniverse > endUniverse))) {
|
||||||
|
sendArtnetPollReply(&artnetPollReply, ipAddress, e131ProxyUniverse);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareArtnetPollReply(ArtPollReply *reply) {
|
void prepareArtnetPollReply(ArtPollReply *reply) {
|
||||||
|
@ -143,20 +143,8 @@ void handleImprovWifiScan();
|
|||||||
void sendImprovIPRPCResult(ImprovRPCType type);
|
void sendImprovIPRPCResult(ImprovRPCType type);
|
||||||
|
|
||||||
//ir.cpp
|
//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 initIR();
|
||||||
|
void deInitIR();
|
||||||
void handleIR();
|
void handleIR();
|
||||||
|
|
||||||
//json.cpp
|
//json.cpp
|
||||||
|
@ -381,11 +381,15 @@ void updateFSInfo() {
|
|||||||
// original idea by @akaricchi (https://github.com/Akaricchi)
|
// original idea by @akaricchi (https://github.com/Akaricchi)
|
||||||
// returns a pointer to the PSRAM buffer, updates size parameter
|
// returns a pointer to the PSRAM buffer, updates size parameter
|
||||||
static const uint8_t *getPresetCache(size_t &size) {
|
static const uint8_t *getPresetCache(size_t &size) {
|
||||||
static unsigned long presetsCachedTime;
|
static unsigned long presetsCachedTime = 0;
|
||||||
static uint8_t *presetsCached;
|
static uint8_t *presetsCached = nullptr;
|
||||||
static size_t presetsCachedSize;
|
static size_t presetsCachedSize = 0;
|
||||||
|
static byte presetsCachedValidate = 0;
|
||||||
|
|
||||||
if (presetsModifiedTime != presetsCachedTime) {
|
//if (presetsModifiedTime != presetsCachedTime) DEBUG_PRINTLN(F("getPresetCache(): presetsModifiedTime changed."));
|
||||||
|
//if (presetsCachedValidate != cacheInvalidate) DEBUG_PRINTLN(F("getPresetCache(): cacheInvalidate changed."));
|
||||||
|
|
||||||
|
if ((presetsModifiedTime != presetsCachedTime) || (presetsCachedValidate != cacheInvalidate)) {
|
||||||
if (presetsCached) {
|
if (presetsCached) {
|
||||||
free(presetsCached);
|
free(presetsCached);
|
||||||
presetsCached = nullptr;
|
presetsCached = nullptr;
|
||||||
@ -396,6 +400,7 @@ static const uint8_t *getPresetCache(size_t &size) {
|
|||||||
File file = WLED_FS.open(FPSTR(getPresetsFileName()), "r");
|
File file = WLED_FS.open(FPSTR(getPresetsFileName()), "r");
|
||||||
if (file) {
|
if (file) {
|
||||||
presetsCachedTime = presetsModifiedTime;
|
presetsCachedTime = presetsModifiedTime;
|
||||||
|
presetsCachedValidate = cacheInvalidate;
|
||||||
presetsCachedSize = 0;
|
presetsCachedSize = 0;
|
||||||
presetsCached = (uint8_t*)ps_malloc(file.size() + 1);
|
presetsCached = (uint8_t*)ps_malloc(file.size() + 1);
|
||||||
if (presetsCached) {
|
if (presetsCached) {
|
||||||
|
254
wled00/ir.cpp
254
wled00/ir.cpp
@ -1,20 +1,14 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_INFRARED
|
||||||
#include "ir_codes.h"
|
#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;
|
IRrecv* irrecv;
|
||||||
//change pin in NpbWrapper.h
|
|
||||||
|
|
||||||
decode_results results;
|
decode_results results;
|
||||||
|
|
||||||
unsigned long irCheckedTime = 0;
|
unsigned long irCheckedTime = 0;
|
||||||
uint32_t lastValidCode = 0;
|
uint32_t lastValidCode = 0;
|
||||||
byte lastRepeatableAction = ACTION_NONE;
|
byte lastRepeatableAction = ACTION_NONE;
|
||||||
@ -35,16 +29,16 @@ uint8_t lastIR6ColourIdx = 0;
|
|||||||
// print("%d values: %s" % (len(result), result))
|
// print("%d values: %s" % (len(result), result))
|
||||||
//
|
//
|
||||||
// It would be hard to maintain repeatable steps if calculating this on the fly.
|
// 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
|
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);
|
const size_t numBrightnessSteps = sizeof(brightnessSteps) / sizeof(uint8_t);
|
||||||
|
|
||||||
// increment `bri` to the next `brightnessSteps` value
|
// increment `bri` to the next `brightnessSteps` value
|
||||||
void incBrightness()
|
static void incBrightness()
|
||||||
{
|
{
|
||||||
// dumb incremental search is efficient enough for so few items
|
// 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)
|
if (brightnessSteps[index] > bri)
|
||||||
{
|
{
|
||||||
@ -56,7 +50,7 @@ void incBrightness()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// decrement `bri` to the next `brightnessSteps` value
|
// decrement `bri` to the next `brightnessSteps` value
|
||||||
void decBrightness()
|
static void decBrightness()
|
||||||
{
|
{
|
||||||
// dumb incremental search is efficient enough for so few items
|
// dumb incremental search is efficient enough for so few items
|
||||||
for (int index = numBrightnessSteps - 1; index >= 0; --index)
|
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);
|
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;
|
int16_t new_val = (int16_t) property + amount;
|
||||||
if (lowerBoundary >= higherBoundary) return property;
|
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);
|
return (byte)constrain(new_val, 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeEffect(uint8_t fx)
|
static void changeEffect(uint8_t fx)
|
||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
strip.setMode(i, fx);
|
strip.setMode(i, fx);
|
||||||
@ -100,10 +94,10 @@ void changeEffect(uint8_t fx)
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changePalette(uint8_t pal)
|
static void changePalette(uint8_t pal)
|
||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.setPalette(pal);
|
seg.setPalette(pal);
|
||||||
@ -116,13 +110,13 @@ void changePalette(uint8_t pal)
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeEffectSpeed(int8_t amount)
|
static void changeEffectSpeed(int8_t amount)
|
||||||
{
|
{
|
||||||
if (effectCurrent != 0) {
|
if (effectCurrent != 0) {
|
||||||
int16_t new_val = (int16_t) effectSpeed + amount;
|
int16_t new_val = (int16_t) effectSpeed + amount;
|
||||||
effectSpeed = (byte)constrain(new_val,0,255);
|
effectSpeed = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
@ -134,10 +128,7 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the hue of the primary color
|
} else { // if Effect == "solid Color", change the hue of the primary color
|
||||||
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col = CRGB(sseg.colors[0]);
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
|
||||||
fastled_col.blue = B(sseg.colors[0]);
|
|
||||||
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||||
int16_t new_val = (int16_t)prim_hsv.h + amount;
|
int16_t new_val = (int16_t)prim_hsv.h + amount;
|
||||||
if (new_val > 255) new_val -= 255; // roll-over if bigger than 255
|
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;
|
prim_hsv.h = (byte)new_val;
|
||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
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;
|
lastRepeatableValue = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeEffectIntensity(int8_t amount)
|
static void changeEffectIntensity(int8_t amount)
|
||||||
{
|
{
|
||||||
if (effectCurrent != 0) {
|
if (effectCurrent != 0) {
|
||||||
int16_t new_val = (int16_t) effectIntensity + amount;
|
int16_t new_val = (int16_t) effectIntensity + amount;
|
||||||
effectIntensity = (byte)constrain(new_val,0,255);
|
effectIntensity = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
@ -181,16 +172,13 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the saturation of the primary color
|
} else { // if Effect == "solid Color", change the saturation of the primary color
|
||||||
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col = CRGB(sseg.colors[0]);
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
|
||||||
fastled_col.blue = B(sseg.colors[0]);
|
|
||||||
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||||
int16_t new_val = (int16_t) prim_hsv.s + amount;
|
int16_t new_val = (int16_t) prim_hsv.s + amount;
|
||||||
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
|
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
|
||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
for (unsigned i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
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;
|
lastRepeatableValue = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeColor(uint32_t c, int16_t cct=-1)
|
static void changeColor(uint32_t c, int16_t cct=-1)
|
||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
// main segment may not be selected!
|
// 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);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
byte capabilities = seg.getLightCapabilities();
|
byte capabilities = seg.getLightCapabilities();
|
||||||
@ -249,7 +237,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
stateChanged = true;
|
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();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
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);
|
changeColor(RGBW32(r, g, b, w), cct);
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR(uint32_t code)
|
static void decodeIR24(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)
|
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_BRIGHTER : incBrightness(); break;
|
case IR24_BRIGHTER : incBrightness(); break;
|
||||||
@ -356,7 +279,7 @@ void decodeIR24(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR24OLD(uint32_t code)
|
static void decodeIR24OLD(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_OLD_BRIGHTER : incBrightness(); break;
|
case IR24_OLD_BRIGHTER : incBrightness(); break;
|
||||||
@ -388,7 +311,7 @@ void decodeIR24OLD(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR24CT(uint32_t code)
|
static void decodeIR24CT(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR24_CT_BRIGHTER : incBrightness(); break;
|
case IR24_CT_BRIGHTER : incBrightness(); break;
|
||||||
@ -420,7 +343,7 @@ void decodeIR24CT(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR40(uint32_t code)
|
static void decodeIR40(uint32_t code)
|
||||||
{
|
{
|
||||||
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
byte r = R(seg.colors[0]);
|
||||||
@ -473,7 +396,7 @@ void decodeIR40(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR44(uint32_t code)
|
static void decodeIR44(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR44_BPLUS : incBrightness(); break;
|
case IR44_BPLUS : incBrightness(); break;
|
||||||
@ -525,7 +448,7 @@ void decodeIR44(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR21(uint32_t code)
|
static void decodeIR21(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR21_BRIGHTER: incBrightness(); break;
|
case IR21_BRIGHTER: incBrightness(); break;
|
||||||
@ -554,7 +477,7 @@ void decodeIR21(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR6(uint32_t code)
|
static void decodeIR6(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR6_POWER: toggleOnOff(); break;
|
case IR6_POWER: toggleOnOff(); break;
|
||||||
@ -587,7 +510,7 @@ void decodeIR6(uint32_t code)
|
|||||||
lastValidCode = code;
|
lastValidCode = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeIR9(uint32_t code)
|
static void decodeIR9(uint32_t code)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case IR9_POWER : toggleOnOff(); break;
|
case IR9_POWER : toggleOnOff(); break;
|
||||||
@ -628,7 +551,7 @@ Sample:
|
|||||||
"label": "Preset 1, fallback to Saw - Party if not found"},
|
"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 objKey[10];
|
||||||
char fileName[16];
|
char fileName[16];
|
||||||
@ -701,41 +624,102 @@ void decodeIRJson(uint32_t code)
|
|||||||
releaseJSONBufferLock();
|
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()
|
void initIR()
|
||||||
{
|
{
|
||||||
if (irEnabled > 0)
|
if (irEnabled > 0) {
|
||||||
{
|
|
||||||
irrecv = new IRrecv(irPin);
|
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()
|
void handleIR()
|
||||||
{
|
{
|
||||||
if (irEnabled > 0 && millis() - irCheckedTime > 120 && !strip.isUpdating())
|
unsigned long currentTime = millis();
|
||||||
{
|
unsigned timeDiff = currentTime - irCheckedTime;
|
||||||
irCheckedTime = millis();
|
if (timeDiff > 120 && irEnabled > 0 && irrecv) {
|
||||||
if (irEnabled > 0)
|
if (strip.isUpdating() && timeDiff < 240) return; // be nice, but not too nice
|
||||||
{
|
irCheckedTime = currentTime;
|
||||||
if (irrecv == NULL)
|
if (irrecv->decode(&results)) {
|
||||||
{
|
if (results.value != 0) { // only print results if anything is received ( != 0 )
|
||||||
initIR(); return;
|
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);
|
||||||
if (irrecv->decode(&results))
|
irrecv->resume();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,6 +487,8 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doAdvancePlaylist = root[F("np")] | doAdvancePlaylist; //advances to next preset in playlist when true
|
||||||
|
|
||||||
JsonObject wifi = root[F("wifi")];
|
JsonObject wifi = root[F("wifi")];
|
||||||
if (!wifi.isNull()) {
|
if (!wifi.isNull()) {
|
||||||
bool apMode = getBoolVal(wifi[F("ap")], apActive);
|
bool apMode = getBoolVal(wifi[F("ap")], apActive);
|
||||||
|
391
wled00/mqtt.cpp
391
wled00/mqtt.cpp
@ -1,197 +1,194 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MQTT communication protocol for home automation
|
* MQTT communication protocol for home automation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_MQTT
|
#ifdef WLED_ENABLE_MQTT
|
||||||
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
||||||
|
|
||||||
void parseMQTTBriPayload(char* payload)
|
void parseMQTTBriPayload(char* payload)
|
||||||
{
|
{
|
||||||
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
||||||
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(CALL_MODE_DIRECT_CHANGE);}
|
||||||
else {
|
else {
|
||||||
uint8_t in = strtoul(payload, NULL, 10);
|
uint8_t in = strtoul(payload, NULL, 10);
|
||||||
if (in == 0 && bri > 0) briLast = bri;
|
if (in == 0 && bri > 0) briLast = bri;
|
||||||
bri = in;
|
bri = in;
|
||||||
stateUpdated(CALL_MODE_DIRECT_CHANGE);
|
stateUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onMqttConnect(bool sessionPresent)
|
void onMqttConnect(bool sessionPresent)
|
||||||
{
|
{
|
||||||
//(re)subscribe to required topics
|
//(re)subscribe to required topics
|
||||||
char subuf[38];
|
char subuf[38];
|
||||||
|
|
||||||
if (mqttDeviceTopic[0] != 0) {
|
if (mqttDeviceTopic[0] != 0) {
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strcat_P(subuf, PSTR("/col"));
|
strcat_P(subuf, PSTR("/col"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
strcat_P(subuf, PSTR("/api"));
|
strcat_P(subuf, PSTR("/api"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mqttGroupTopic[0] != 0) {
|
if (mqttGroupTopic[0] != 0) {
|
||||||
strlcpy(subuf, mqttGroupTopic, 33);
|
strlcpy(subuf, mqttGroupTopic, 33);
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strcat_P(subuf, PSTR("/col"));
|
strcat_P(subuf, PSTR("/col"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
strlcpy(subuf, mqttGroupTopic, 33);
|
strlcpy(subuf, mqttGroupTopic, 33);
|
||||||
strcat_P(subuf, PSTR("/api"));
|
strcat_P(subuf, PSTR("/api"));
|
||||||
mqtt->subscribe(subuf, 0);
|
mqtt->subscribe(subuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
usermods.onMqttConnect(sessionPresent);
|
usermods.onMqttConnect(sessionPresent);
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("MQTT ready"));
|
DEBUG_PRINTLN(F("MQTT ready"));
|
||||||
publishMqtt();
|
publishMqtt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||||
static char *payloadStr;
|
static char *payloadStr;
|
||||||
|
|
||||||
DEBUG_PRINT(F("MQTT msg: "));
|
DEBUG_PRINT(F("MQTT msg: "));
|
||||||
DEBUG_PRINTLN(topic);
|
DEBUG_PRINTLN(topic);
|
||||||
|
|
||||||
// paranoia check to avoid npe if no payload
|
// paranoia check to avoid npe if no payload
|
||||||
if (payload==nullptr) {
|
if (payload==nullptr) {
|
||||||
DEBUG_PRINTLN(F("no payload -> leave"));
|
DEBUG_PRINTLN(F("no payload -> leave"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 0) { // start (1st partial packet or the only packet)
|
if (index == 0) { // start (1st partial packet or the only packet)
|
||||||
if (payloadStr) delete[] payloadStr; // fail-safe: release buffer
|
if (payloadStr) delete[] payloadStr; // fail-safe: release buffer
|
||||||
payloadStr = new char[total+1]; // allocate new buffer
|
payloadStr = new char[total+1]; // allocate new buffer
|
||||||
}
|
}
|
||||||
if (payloadStr == nullptr) return; // buffer not allocated
|
if (payloadStr == nullptr) return; // buffer not allocated
|
||||||
|
|
||||||
// copy (partial) packet to buffer and 0-terminate it if it is last packet
|
// copy (partial) packet to buffer and 0-terminate it if it is last packet
|
||||||
char* buff = payloadStr + index;
|
char* buff = payloadStr + index;
|
||||||
memcpy(buff, payload, len);
|
memcpy(buff, payload, len);
|
||||||
if (index + len >= total) { // at end
|
if (index + len >= total) { // at end
|
||||||
payloadStr[total] = '\0'; // terminate c style string
|
payloadStr[total] = '\0'; // terminate c style string
|
||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("MQTT partial packet received."));
|
DEBUG_PRINTLN(F("MQTT partial packet received."));
|
||||||
return; // process next packet
|
return; // process next packet
|
||||||
}
|
}
|
||||||
DEBUG_PRINTLN(payloadStr);
|
DEBUG_PRINTLN(payloadStr);
|
||||||
|
|
||||||
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
||||||
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
if (strncmp(topic, mqttDeviceTopic, topicPrefixLen) == 0) {
|
||||||
topic += topicPrefixLen;
|
topic += topicPrefixLen;
|
||||||
} else {
|
} else {
|
||||||
topicPrefixLen = strlen(mqttGroupTopic);
|
topicPrefixLen = strlen(mqttGroupTopic);
|
||||||
if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) {
|
if (strncmp(topic, mqttGroupTopic, topicPrefixLen) == 0) {
|
||||||
topic += topicPrefixLen;
|
topic += topicPrefixLen;
|
||||||
} else {
|
} else {
|
||||||
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
||||||
usermods.onMqttMessage(topic, payloadStr);
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
delete[] payloadStr;
|
delete[] payloadStr;
|
||||||
payloadStr = nullptr;
|
payloadStr = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Prefix is stripped from the topic at this point
|
//Prefix is stripped from the topic at this point
|
||||||
|
|
||||||
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
||||||
colorFromDecOrHexString(col, payloadStr);
|
colorFromDecOrHexString(col, payloadStr);
|
||||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||||
if (!requestJSONBufferLock(15)) {
|
if (requestJSONBufferLock(15)) {
|
||||||
delete[] payloadStr;
|
if (payloadStr[0] == '{') { //JSON API
|
||||||
payloadStr = nullptr;
|
deserializeJson(*pDoc, payloadStr);
|
||||||
return;
|
deserializeState(pDoc->as<JsonObject>());
|
||||||
}
|
} else { //HTTP API
|
||||||
if (payloadStr[0] == '{') { //JSON API
|
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
||||||
deserializeJson(*pDoc, payloadStr);
|
apireq += payloadStr;
|
||||||
deserializeState(pDoc->as<JsonObject>());
|
handleSet(nullptr, apireq);
|
||||||
} else { //HTTP API
|
}
|
||||||
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
releaseJSONBufferLock();
|
||||||
apireq += payloadStr;
|
}
|
||||||
handleSet(nullptr, apireq);
|
} else if (strlen(topic) != 0) {
|
||||||
}
|
// non standard topic, check with usermods
|
||||||
releaseJSONBufferLock();
|
usermods.onMqttMessage(topic, payloadStr);
|
||||||
} else if (strlen(topic) != 0) {
|
} else {
|
||||||
// non standard topic, check with usermods
|
// topmost topic (just wled/MAC)
|
||||||
usermods.onMqttMessage(topic, payloadStr);
|
parseMQTTBriPayload(payloadStr);
|
||||||
} else {
|
}
|
||||||
// topmost topic (just wled/MAC)
|
delete[] payloadStr;
|
||||||
parseMQTTBriPayload(payloadStr);
|
payloadStr = nullptr;
|
||||||
}
|
}
|
||||||
delete[] payloadStr;
|
|
||||||
payloadStr = nullptr;
|
|
||||||
}
|
void publishMqtt()
|
||||||
|
{
|
||||||
|
if (!WLED_MQTT_CONNECTED) return;
|
||||||
void publishMqtt()
|
DEBUG_PRINTLN(F("Publish MQTT"));
|
||||||
{
|
|
||||||
if (!WLED_MQTT_CONNECTED) return;
|
#ifndef USERMOD_SMARTNEST
|
||||||
DEBUG_PRINTLN(F("Publish MQTT"));
|
char s[10];
|
||||||
|
char subuf[48];
|
||||||
#ifndef USERMOD_SMARTNEST
|
|
||||||
char s[10];
|
sprintf_P(s, PSTR("%u"), bri);
|
||||||
char subuf[48];
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
|
strcat_P(subuf, PSTR("/g"));
|
||||||
sprintf_P(s, PSTR("%u"), bri);
|
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
|
||||||
strcat_P(subuf, PSTR("/g"));
|
sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2]));
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
|
strcat_P(subuf, PSTR("/c"));
|
||||||
sprintf_P(s, PSTR("#%06X"), (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2]));
|
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
|
||||||
strcat_P(subuf, PSTR("/c"));
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, s); // optionally retain message (#2263)
|
strcat_P(subuf, PSTR("/status"));
|
||||||
|
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
|
||||||
strcat_P(subuf, PSTR("/status"));
|
char apires[1024]; // allocating 1024 bytes from stack can be risky
|
||||||
mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT
|
XML_response(nullptr, apires);
|
||||||
|
strlcpy(subuf, mqttDeviceTopic, 33);
|
||||||
char apires[1024]; // allocating 1024 bytes from stack can be risky
|
strcat_P(subuf, PSTR("/v"));
|
||||||
XML_response(nullptr, apires);
|
mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
|
||||||
strlcpy(subuf, mqttDeviceTopic, 33);
|
#endif
|
||||||
strcat_P(subuf, PSTR("/v"));
|
}
|
||||||
mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263)
|
|
||||||
#endif
|
|
||||||
}
|
//HA autodiscovery was removed in favor of the native integration in HA v0.102.0
|
||||||
|
|
||||||
|
bool initMqtt()
|
||||||
//HA autodiscovery was removed in favor of the native integration in HA v0.102.0
|
{
|
||||||
|
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
|
||||||
bool initMqtt()
|
|
||||||
{
|
if (mqtt == nullptr) {
|
||||||
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
|
mqtt = new AsyncMqttClient();
|
||||||
|
mqtt->onMessage(onMqttMessage);
|
||||||
if (mqtt == nullptr) {
|
mqtt->onConnect(onMqttConnect);
|
||||||
mqtt = new AsyncMqttClient();
|
}
|
||||||
mqtt->onMessage(onMqttMessage);
|
if (mqtt->connected()) return true;
|
||||||
mqtt->onConnect(onMqttConnect);
|
|
||||||
}
|
DEBUG_PRINTLN(F("Reconnecting MQTT"));
|
||||||
if (mqtt->connected()) return true;
|
IPAddress mqttIP;
|
||||||
|
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
||||||
DEBUG_PRINTLN(F("Reconnecting MQTT"));
|
{
|
||||||
IPAddress mqttIP;
|
mqtt->setServer(mqttIP, mqttPort);
|
||||||
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
} else {
|
||||||
{
|
mqtt->setServer(mqttServer, mqttPort);
|
||||||
mqtt->setServer(mqttIP, mqttPort);
|
}
|
||||||
} else {
|
mqtt->setClientId(mqttClientID);
|
||||||
mqtt->setServer(mqttServer, mqttPort);
|
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
|
||||||
}
|
|
||||||
mqtt->setClientId(mqttClientID);
|
#ifndef USERMOD_SMARTNEST
|
||||||
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
|
strlcpy(mqttStatusTopic, mqttDeviceTopic, 33);
|
||||||
|
strcat_P(mqttStatusTopic, PSTR("/status"));
|
||||||
#ifndef USERMOD_SMARTNEST
|
mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message
|
||||||
strlcpy(mqttStatusTopic, mqttDeviceTopic, 33);
|
#endif
|
||||||
strcat_P(mqttStatusTopic, PSTR("/status"));
|
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
||||||
mqtt->setWill(mqttStatusTopic, 0, true, "offline"); // LWT message
|
mqtt->connect();
|
||||||
#endif
|
return true;
|
||||||
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
}
|
||||||
mqtt->connect();
|
#endif
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@ -25,11 +25,11 @@ void _overlayAnalogClock()
|
|||||||
{
|
{
|
||||||
if (secondPixel < analogClock12pixel)
|
if (secondPixel < analogClock12pixel)
|
||||||
{
|
{
|
||||||
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
|
strip.setRange(analogClock12pixel, overlayMax, color_fade(0xFF0000, bri));
|
||||||
strip.setRange(overlayMin, secondPixel, 0xFF0000);
|
strip.setRange(overlayMin, secondPixel, color_fade(0xFF0000, bri));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
|
strip.setRange(analogClock12pixel, secondPixel, color_fade(0xFF0000, bri));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (analogClock5MinuteMarks)
|
if (analogClock5MinuteMarks)
|
||||||
@ -38,12 +38,12 @@ void _overlayAnalogClock()
|
|||||||
{
|
{
|
||||||
unsigned pix = analogClock12pixel + roundf((overlaySize / 12.0f) *i);
|
unsigned pix = analogClock12pixel + roundf((overlaySize / 12.0f) *i);
|
||||||
if (pix > overlayMax) pix -= overlaySize;
|
if (pix > overlayMax) pix -= overlaySize;
|
||||||
strip.setPixelColor(pix, 0x00FFAA);
|
strip.setPixelColor(pix, color_fade(0x00FFAA, bri));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, color_fade(0xFF0000, bri));
|
||||||
strip.setPixelColor(minutePixel, 0x00FF00);
|
strip.setPixelColor(minutePixel, color_fade(0x00FF00, bri));
|
||||||
strip.setPixelColor(hourPixel, 0x0000FF);
|
strip.setPixelColor(hourPixel, color_fade(0x0000FF, bri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ void handlePlaylist() {
|
|||||||
static unsigned long presetCycledTime = 0;
|
static unsigned long presetCycledTime = 0;
|
||||||
if (currentPlaylist < 0 || playlistEntries == nullptr) return;
|
if (currentPlaylist < 0 || playlistEntries == nullptr) return;
|
||||||
|
|
||||||
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
|
if (millis() - presetCycledTime > (100 * playlistEntryDur) || doAdvancePlaylist) {
|
||||||
presetCycledTime = millis();
|
presetCycledTime = millis();
|
||||||
if (bri == 0 || nightlightActive) return;
|
if (bri == 0 || nightlightActive) return;
|
||||||
|
|
||||||
@ -149,6 +149,7 @@ void handlePlaylist() {
|
|||||||
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
|
strip.setTransition(fadeTransition ? playlistEntries[playlistIndex].tr * 100 : 0);
|
||||||
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
playlistEntryDur = playlistEntries[playlistIndex].dur;
|
||||||
applyPresetFromPlaylist(playlistEntries[playlistIndex].preset);
|
applyPresetFromPlaylist(playlistEntries[playlistIndex].preset);
|
||||||
|
doAdvancePlaylist = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
}
|
}
|
||||||
#ifndef WLED_DISABLE_INFRARED
|
#ifndef WLED_DISABLE_INFRARED
|
||||||
if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) {
|
if (irPin>=0 && pinManager.isPinAllocated(irPin, PinOwner::IR)) {
|
||||||
pinManager.deallocatePin(irPin, PinOwner::IR);
|
deInitIR();
|
||||||
|
pinManager.deallocatePin(irPin, PinOwner::IR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) {
|
for (uint8_t s=0; s<WLED_MAX_BUTTONS; s++) {
|
||||||
@ -233,6 +234,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
irPin = -1;
|
irPin = -1;
|
||||||
}
|
}
|
||||||
irEnabled = request->arg(F("IT")).toInt();
|
irEnabled = request->arg(F("IT")).toInt();
|
||||||
|
initIR();
|
||||||
#endif
|
#endif
|
||||||
irApplyToAllSelected = !request->hasArg(F("MSO"));
|
irApplyToAllSelected = !request->hasArg(F("MSO"));
|
||||||
|
|
||||||
@ -901,6 +903,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
applyPreset(presetCycCurr);
|
applyPreset(presetCycCurr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos = req.indexOf(F("NP")); //advances to next preset in a playlist
|
||||||
|
if (pos > 0) doAdvancePlaylist = true;
|
||||||
|
|
||||||
//set brightness
|
//set brightness
|
||||||
updateVal(req.c_str(), "&A=", &bri);
|
updateVal(req.c_str(), "&A=", &bri);
|
||||||
|
|
||||||
|
@ -505,6 +505,13 @@ void WLED::setup()
|
|||||||
initServer();
|
initServer();
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
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.
|
// Seed FastLED random functions with an esp random value, which already works properly at this point.
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
const uint32_t seed32 = esp_random();
|
const uint32_t seed32 = esp_random();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2404120
|
#define VERSION 2405030
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -594,7 +594,6 @@ WLED_GLOBAL bool buttonPressedBefore[WLED_MAX_BUTTONS] _INIT({false});
|
|||||||
WLED_GLOBAL bool buttonLongPressed[WLED_MAX_BUTTONS] _INIT({false});
|
WLED_GLOBAL bool buttonLongPressed[WLED_MAX_BUTTONS] _INIT({false});
|
||||||
WLED_GLOBAL unsigned long buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
|
WLED_GLOBAL unsigned long buttonPressedTime[WLED_MAX_BUTTONS] _INIT({0});
|
||||||
WLED_GLOBAL unsigned long buttonWaitTime[WLED_MAX_BUTTONS] _INIT({0});
|
WLED_GLOBAL unsigned long buttonWaitTime[WLED_MAX_BUTTONS] _INIT({0});
|
||||||
WLED_GLOBAL bool buttonBriDirection _INIT(false);
|
|
||||||
WLED_GLOBAL bool disablePullUp _INIT(false);
|
WLED_GLOBAL bool disablePullUp _INIT(false);
|
||||||
WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESHOLD);
|
WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESHOLD);
|
||||||
|
|
||||||
@ -646,6 +645,7 @@ WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255,
|
|||||||
WLED_GLOBAL byte timerMonth[] _INIT_N(({28,28,28,28,28,28,28,28}));
|
WLED_GLOBAL byte timerMonth[] _INIT_N(({28,28,28,28,28,28,28,28}));
|
||||||
WLED_GLOBAL byte timerDay[] _INIT_N(({1,1,1,1,1,1,1,1}));
|
WLED_GLOBAL byte timerDay[] _INIT_N(({1,1,1,1,1,1,1,1}));
|
||||||
WLED_GLOBAL byte timerDayEnd[] _INIT_N(({31,31,31,31,31,31,31,31}));
|
WLED_GLOBAL byte timerDayEnd[] _INIT_N(({31,31,31,31,31,31,31,31}));
|
||||||
|
WLED_GLOBAL bool doAdvancePlaylist _INIT(false);
|
||||||
|
|
||||||
//improv
|
//improv
|
||||||
WLED_GLOBAL byte improvActive _INIT(0); //0: no improv packet received, 1: improv active, 2: provisioning
|
WLED_GLOBAL byte improvActive _INIT(0); //0: no improv packet received, 1: improv active, 2: provisioning
|
||||||
|
Loading…
x
Reference in New Issue
Block a user