Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ lib_deps =
willmmiles/AsyncTCP @ 1.3.1
bitbank2/AnimatedGIF@^1.4.7
https://github.com/Aircoookie/GifDecoder#bc3af18
${esp32.AR_lib_deps}
build_flags =
-D CONFIG_ASYNC_TCP_USE_WDT=0
-D WLED_ENABLE_GIF
Expand Down Expand Up @@ -267,7 +268,7 @@ lib_deps =
board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs
# additional build flags for audioreactive - must be applied globally
AR_build_flags = ;; -fsingle-precision-constant ;; forces ArduinoFFT to use float math (2x faster)
AR_lib_deps = ;; for pre-usermod-library platformio_override compatibility
AR_lib_deps = https://github.com/netmindz/WLED-AR-Usermod.git


[esp32_idf_V4]
Expand Down
2,071 changes: 0 additions & 2,071 deletions usermods/audioreactive/audio_reactive.cpp

This file was deleted.

773 changes: 0 additions & 773 deletions usermods/audioreactive/audio_source.h

This file was deleted.

15 changes: 0 additions & 15 deletions usermods/audioreactive/library.json

This file was deleted.

5 changes: 0 additions & 5 deletions usermods/audioreactive/override_sqrt.py

This file was deleted.

73 changes: 0 additions & 73 deletions usermods/audioreactive/readme.md

This file was deleted.

73 changes: 43 additions & 30 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ Segment::Segment(const Segment &orig) {
_dataLen = 0;
pixels = nullptr;
if (!stop) return; // nothing to do if segment is inactive/invalid
if (orig.name) { name = static_cast<char*>(d_malloc(strlen(orig.name)+1)); if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
if (orig.pixels) {
// allocate pixel buffer: prefer IRAM/PSRAM
pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * orig.length()));
if (pixels) memcpy(pixels, orig.pixels, sizeof(uint32_t) * orig.length());
else {
DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
if (pixels) {
memcpy(pixels, orig.pixels, sizeof(uint32_t) * orig.length());
if (orig.name) { name = static_cast<char*>(d_malloc(strlen(orig.name)+1)); if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
} else {
DEBUGFX_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
errorFlag = ERR_NORAM_PX;
stop = 0; // mark segment as inactive/invalid
}
Expand Down Expand Up @@ -107,12 +109,14 @@ Segment& Segment::operator= (const Segment &orig) {
pixels = nullptr;
if (!stop) return *this; // nothing to do if segment is inactive/invalid
// copy source data
if (orig.name) { name = static_cast<char*>(d_malloc(strlen(orig.name)+1)); if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
if (orig.pixels) {
// allocate pixel buffer: prefer IRAM/PSRAM
pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * orig.length()));
if (pixels) memcpy(pixels, orig.pixels, sizeof(uint32_t) * orig.length());
else {
if (pixels) {
memcpy(pixels, orig.pixels, sizeof(uint32_t) * orig.length());
if (orig.name) { name = static_cast<char*>(d_malloc(strlen(orig.name)+1)); if (name) strcpy(name, orig.name); }
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
} else {
DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
errorFlag = ERR_NORAM_PX;
stop = 0; // mark segment as inactive/invalid
Expand Down Expand Up @@ -281,8 +285,9 @@ void Segment::startTransition(uint16_t dur, bool segmentCopy) {
if (_t->_oldSegment) {
_t->_oldSegment->palette = _t->_palette; // restore original palette and colors (from start of transition)
for (unsigned i = 0; i < NUM_COLORS; i++) _t->_oldSegment->colors[i] = _t->_colors[i];
DEBUGFX_PRINTF_P(PSTR("-- Updated transition with segment copy: S=%p T(%p) O[%p] OP[%p]\n"), this, _t, _t->_oldSegment, _t->_oldSegment->pixels);
if (!_t->_oldSegment->isActive()) stopTransition();
}
DEBUG_PRINTF_P(PSTR("-- Updated transition with segment copy: S=%p T(%p) O[%p] OP[%p]\n"), this, _t, _t->_oldSegment, _t->_oldSegment->pixels);
}
return;
}
Expand All @@ -298,13 +303,12 @@ void Segment::startTransition(uint16_t dur, bool segmentCopy) {
#endif
for (int i=0; i<NUM_COLORS; i++) _t->_colors[i] = colors[i];
if (segmentCopy) _t->_oldSegment = new(std::nothrow) Segment(*this); // store/copy current segment settings
#ifdef WLED_DEBUG
if (_t->_oldSegment) {
DEBUG_PRINTF_P(PSTR("-- Started transition: S=%p T(%p) O[%p] OP[%p]\n"), this, _t, _t->_oldSegment, _t->_oldSegment->pixels);
DEBUGFX_PRINTF_P(PSTR("-- Started transition: S=%p T(%p) O[%p] OP[%p]\n"), this, _t, _t->_oldSegment, _t->_oldSegment->pixels);
if (!_t->_oldSegment->isActive()) stopTransition();
} else {
DEBUG_PRINTF_P(PSTR("-- Started transition without old segment: S=%p T(%p)\n"), this, _t);
DEBUGFX_PRINTF_P(PSTR("-- Started transition without old segment: S=%p T(%p)\n"), this, _t);
}
#endif
};
}

Expand Down Expand Up @@ -425,14 +429,15 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui

unsigned oldLength = length();

DEBUG_PRINTF_P(PSTR("Segment geometry: %d,%d -> %d,%d [%d,%d]\n"), (int)i1, (int)i2, (int)i1Y, (int)i2Y, (int)grp, (int)spc);
DEBUGFX_PRINTF_P(PSTR("Segment geometry: %d,%d -> %d,%d [%d,%d]\n"), (int)i1, (int)i2, (int)i1Y, (int)i2Y, (int)grp, (int)spc);
markForReset();
startTransition(strip.getTransition()); // start transition prior to change (if segment is deactivated (start>stop) no transition will happen)
stateChanged = true; // send UDP/WS broadcast
if (_t) stopTransition(); // we can't use transition if segment dimensions changed
stateChanged = true; // send UDP/WS broadcast

// apply change immediately
if (i2 <= i1) { //disable segment
d_free(pixels);
deallocateData();
p_free(pixels);
pixels = nullptr;
stop = 0;
return;
Expand All @@ -449,21 +454,25 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui
#endif
// safety check
if (start >= stop || startY >= stopY) {
d_free(pixels);
deallocateData();
p_free(pixels);
pixels = nullptr;
stop = 0;
return;
}
// re-allocate FX render buffer
// allocate FX render buffer
if (length() != oldLength) {
if (pixels) d_free(pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
// allocate render buffer (always entire segment), prefer IRAM/PSRAM. Note: impact on FPS with PSRAM buffer is low (<2% with QSPI PSRAM) on S2/S3
p_free(pixels);
pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length()));
if (!pixels) {
DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
DEBUGFX_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
deallocateData();
errorFlag = ERR_NORAM_PX;
stop = 0;
return;
}

}
refreshLightCapabilities();
}
Expand Down Expand Up @@ -572,8 +581,8 @@ Segment &Segment::setName(const char *newName) {
if (newLen) {
if (name) d_free(name); // free old name
name = static_cast<char*>(d_malloc(newLen+1));
if (mode == FX_MODE_2DSCROLLTEXT) startTransition(strip.getTransition(), true); // if the name changes in scrolling text mode, we need to copy the segment for blending
if (name) strlcpy(name, newName, newLen+1);
name[newLen] = 0;
return *this;
}
}
Expand Down Expand Up @@ -1210,10 +1219,9 @@ void WS2812FX::finalizeInit() {
deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)

// allocate frame buffer after matrix has been set up (gaps!)
if (_pixels) d_free(_pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
d_free(_pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
_pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t)));
DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), getLengthTotal() * sizeof(uint32_t));

DEBUG_PRINTF_P(PSTR("Heap after strip init: %uB\n"), ESP.getFreeHeap());
}

Expand Down Expand Up @@ -1258,7 +1266,8 @@ void WS2812FX::service() {
// if segment is in transition and no old segment exists we don't need to run the old mode
// (blendSegments() takes care of On/Off transitions and clipping)
Segment *segO = seg.getOldSegment();
if (segO && (seg.mode != segO->mode || blendingStyle != BLEND_STYLE_FADE)) {
if (segO && segO->isActive() && (seg.mode != segO->mode || blendingStyle != BLEND_STYLE_FADE ||
(segO->name != seg.name && segO->name && seg.name && strncmp(segO->name, seg.name, WLED_MAX_SEGNAME_LEN) != 0))) {
Segment::modeBlend(true); // set semaphore for beginDraw() to blend colors and palette
segO->beginDraw(prog); // set up palette & colors (also sets draw dimensions), parent segment has transition progress
_currentSegment = segO; // set current segment
Expand Down Expand Up @@ -1461,8 +1470,10 @@ void WS2812FX::blendSegment(const Segment &topSegment) const {
}
uint32_t c_a = BLACK;
if (x < vCols && y < vRows) c_a = seg->getPixelColorRaw(x + y*vCols); // will get clipped pixel from old segment or unclipped pixel from new segment
if (segO && blendingStyle == BLEND_STYLE_FADE && topSegment.mode != segO->mode && x < oCols && y < oRows) {
// we need to blend old segment using fade as pixels ae not clipped
if (segO && blendingStyle == BLEND_STYLE_FADE
&& (topSegment.mode != segO->mode || (segO->name != topSegment.name && segO->name && topSegment.name && strncmp(segO->name, topSegment.name, WLED_MAX_SEGNAME_LEN) != 0))
&& x < oCols && y < oRows) {
// we need to blend old segment using fade as pixels are not clipped
c_a = color_blend16(c_a, segO->getPixelColorRaw(x + y*oCols), progInv);
} else if (blendingStyle != BLEND_STYLE_FADE) {
// workaround for On/Off transition
Expand Down Expand Up @@ -1616,6 +1627,8 @@ static uint8_t estimateCurrentAndLimitBri(uint8_t brightness, uint32_t *pixels)
}

void WS2812FX::show() {
if (!_pixels) return; // no pixels allocated, nothing to show

unsigned long showNow = millis();
size_t diff = showNow - _lastShow;

Expand Down Expand Up @@ -1888,7 +1901,7 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
for (size_t i = 1; i < s; i++) {
_segments.emplace_back(segStarts[i], segStops[i]);
}
DEBUG_PRINTF_P(PSTR("%d auto segments created.\n"), _segments.size());
DEBUGFX_PRINTF_P(PSTR("%d auto segments created.\n"), _segments.size());

} else {

Expand Down Expand Up @@ -2012,7 +2025,7 @@ bool WS2812FX::deserializeMap(unsigned n) {
}

d_free(customMappingTable);
customMappingTable = static_cast<uint16_t*>(d_malloc(sizeof(uint16_t)*getLengthTotal())); // do not use SPI RAM
customMappingTable = static_cast<uint16_t*>(d_malloc(sizeof(uint16_t)*getLengthTotal())); // prefer DRAM for speed

if (customMappingTable) {
DEBUG_PRINTF_P(PSTR("ledmap allocated: %uB\n"), sizeof(uint16_t)*getLengthTotal());
Expand Down
29 changes: 28 additions & 1 deletion wled00/bus_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <Arduino.h>
#include <IPAddress.h>
#ifdef ARDUINO_ARCH_ESP32
#include <ESPmDNS.h>
#include "src/dependencies/network/Network.h" // for isConnected() (& WiFi)
#include "driver/ledc.h"
#include "soc/ledc_struct.h"
#if !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3))
Expand All @@ -25,6 +27,7 @@
#include "bus_wrapper.h"
#include <bits/unique_ptr.h>

extern char cmDNS[];
extern bool cctICused;
extern bool useParallelI2S;

Expand Down Expand Up @@ -102,7 +105,7 @@ void Bus::calculateCCT(uint32_t c, uint8_t &ww, uint8_t &cw) {
} else {
cct = (approximateKelvinFromRGB(c) - 1900) >> 5; // convert K (from RGB value) to relative format
}

//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
if (cct < _cctBlend) ww = 255;
else ww = ((255-cct) * 255) / (255 - _cctBlend);
Expand Down Expand Up @@ -699,6 +702,10 @@ BusNetwork::BusNetwork(const BusConfig &bc)
_hasCCT = false;
_UDPchannels = _hasWhite + 3;
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
#ifdef ARDUINO_ARCH_ESP32
_hostname = bc.text;
resolveHostname(); // resolve hostname to IP address if needed
#endif
_data = (uint8_t*)d_calloc(_len, _UDPchannels);
_valid = (_data != nullptr);
DEBUGBUS_PRINTF_P(PSTR("%successfully inited virtual strip with type %u and IP %u.%u.%u.%u\n"), _valid?"S":"Uns", bc.type, bc.pins[0], bc.pins[1], bc.pins[2], bc.pins[3]);
Expand Down Expand Up @@ -733,6 +740,19 @@ size_t BusNetwork::getPins(uint8_t* pinArray) const {
return 4;
}

#ifdef ARDUINO_ARCH_ESP32
void BusNetwork::resolveHostname() {
static unsigned long nextResolve = 0;
if (Network.isConnected() && millis() > nextResolve && _hostname.length() > 0) {
nextResolve = millis() + 600000; // resolve only every 10 minutes
IPAddress clnt;
if (strlen(cmDNS) > 0) clnt = MDNS.queryHost(_hostname);
else WiFi.hostByName(_hostname.c_str(), clnt);
if (clnt != IPAddress()) _client = clnt;
}
}
#endif

// credit @willmmiles & @netmindz https://github.com/wled/WLED/pull/4056
std::vector<LEDType> BusNetwork::getLEDTypes() {
return {
Expand Down Expand Up @@ -918,6 +938,13 @@ void BusManager::on() {
}
}
}
#else
for (auto &bus : busses) if (bus->isVirtual()) {
// virtual/network bus should check for IP change if hostname is specified
// otherwise there are no endpoints to force DNS resolution
BusNetwork &b = static_cast<BusNetwork&>(*bus);
b.resolveHostname();
}
#endif
#ifdef ESP32_DATA_IDLE_HIGH
esp32RMTInvertIdle();
Expand Down
Loading
Loading