Skip to content
Open
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
4 changes: 1 addition & 3 deletions wled00/FX_fcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,9 @@ bool Segment::allocateData(size_t len) {
if (len == 0) return false; // nothing to do
if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation)
if (call == 0) {
if (_dataLen < FAIR_DATA_PER_SEG) { // segment data is small
//DEBUG_PRINTF_P(PSTR("-- Clearing data (%d): %p\n"), len, this);
memset(data, 0, len); // erase buffer if called during effect initialisation
return true; // no need to reallocate
}
}
else
return true;
Expand Down Expand Up @@ -198,7 +196,7 @@ void Segment::deallocateData() {
DEBUG_PRINTF_P(PSTR("---- Released data (%p): inconsistent UsedSegmentData (%d/%d), cowardly refusing to free nothing.\n"), this, _dataLen, Segment::getUsedSegmentData());
}
data = nullptr;
Segment::addUsedSegmentData(_dataLen <= Segment::getUsedSegmentData() ? -_dataLen : -Segment::getUsedSegmentData());
Segment::addUsedSegmentData(-_dataLen); // addUsedSegmentData guards agains negative and sets zero if underrun so this is safe
_dataLen = 0;
}

Expand Down
78 changes: 21 additions & 57 deletions wled00/bus_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
this->_len = (display->width() * display->height()); // note: this returns correct number of pixels but incorrect dimensions if using virtual display (updated below)

DEBUGBUS_PRINTF("Length: %u\n", _len);
if (this->_len >= MAX_LEDS) {
if (this->_len > MAX_LEDS) {
DEBUGBUS_PRINTLN("MatrixPanel_I2S_DMA Too many LEDS - playing safe");
return;
}
Expand Down Expand Up @@ -1033,7 +1033,6 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
display->clearScreen(); // initially clear the screen buffer
DEBUGBUS_PRINTLN("MatrixPanel_I2S_DMA clear ok");

if (_ledBuffer) d_free(_ledBuffer); // should not happen
if (_ledsDirty) d_free(_ledsDirty); // should not happen
DEBUGBUS_PRINTLN("MatrixPanel_I2S_DMA allocate memory");
_ledsDirty = (byte*) d_malloc(getBitArrayBytes(_len)); // create LEDs dirty bits
Expand All @@ -1048,9 +1047,6 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
return; // fail is we cannot get memory for the buffer
}
setBitArray(_ledsDirty, _len, false); // reset dirty bits

// create LEDs buffer (initialized to BLACK), prefer DRAM if enough heap is available (faster in case global _pixels buffer is in PSRAM as not both will fit the cache)
_ledBuffer = static_cast<CRGB*>(allocate_buffer(_len * sizeof(CRGB), BFRALLOC_PREFER_DRAM | BFRALLOC_CLEAR));
}

PANEL_CHAIN_TYPE chainType = CHAIN_NONE; // default for quarter-scan panels that do not use chaining
Expand Down Expand Up @@ -1098,52 +1094,38 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
DEBUGBUS_PRINT(F("MatrixPanel_I2S_DMA "));
DEBUGBUS_PRINTF_P(PSTR("%sstarted, width=%u, %u pixels.\n"), _valid? "":"not ", _panelWidth, _len);

if (_ledBuffer != nullptr) DEBUGBUS_PRINTLN(F("MatrixPanel_I2S_DMA LEDS buffer enabled."));
if (_ledsDirty != nullptr) DEBUGBUS_PRINTLN(F("MatrixPanel_I2S_DMA LEDS dirty bit optimization enabled."));
if ((_ledBuffer != nullptr) || (_ledsDirty != nullptr)) {
DEBUGBUS_PRINT(F("MatrixPanel_I2S_DMA LEDS buffer uses "));
DEBUGBUS_PRINT((_ledBuffer? _len*sizeof(CRGB) :0) + (_ledsDirty? getBitArrayBytes(_len) :0));
if (_ledsDirty != nullptr) {
DEBUGBUS_PRINTLN(F("MatrixPanel_I2S_DMA LEDS dirty bit optimization enabled."));
DEBUGBUS_PRINT(F("MatrixPanel_I2S_DMA LEDS dirty buffer uses "));
DEBUGBUS_PRINT((_ledsDirty? getBitArrayBytes(_len) :0));
DEBUGBUS_PRINTLN(F(" bytes."));
}
}

void IRAM_ATTR BusHub75Matrix::setPixelColor(unsigned pix, uint32_t c) {
if (!_valid) return; // note: no need to check pix >= _len as that is checked in containsPixel()
// if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
if ((c == IS_BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
setBitInArray(_ledsDirty, pix, c != IS_BLACK); // dirty = true means "color is not BLACK"

if (_ledBuffer) {
CRGB fastled_col = CRGB(c);
if (_ledBuffer[pix] != fastled_col) {
_ledBuffer[pix] = fastled_col;
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
}
}
else {
if ((c == IS_BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
setBitInArray(_ledsDirty, pix, c != IS_BLACK); // dirty = true means "color is not BLACK"
uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);

uint8_t r = R(c);
uint8_t g = G(c);
uint8_t b = B(c);

if (virtualDisp != nullptr) {
int x = pix % _panelWidth; // TODO: check if using & and shift would be faster here, it limits to power-of-2 widths though
int y = pix / _panelWidth;
virtualDisp->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
} else {
int x = pix % _panelWidth;
int y = pix / _panelWidth;
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
}
if (virtualDisp != nullptr) {
int x = pix % _panelWidth; // TODO: check if using & and shift would be faster here, it limits to power-of-2 widths though
int y = pix / _panelWidth;
virtualDisp->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
} else {
int x = pix % _panelWidth;
int y = pix / _panelWidth;
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
}
}

uint32_t BusHub75Matrix::getPixelColor(unsigned pix) const {
if (!_valid) return IS_BLACK; // note: no need to check pix >= _len as that is checked in containsPixel()
if (_ledBuffer)
return uint32_t(_ledBuffer[pix]); // fastled-slim already returns RGB, no need to mask out the upper byte
else
return getBitFromArray(_ledsDirty, pix) ? IS_DARKGREY: IS_BLACK; // just a hack - we only know if the pixel is black or not
return getBitFromArray(_ledsDirty, pix) ? IS_DARKGREY: IS_BLACK; // just a hack - we only know if the pixel is black or not
}

void BusHub75Matrix::setBrightness(uint8_t b) {
Expand All @@ -1153,25 +1135,8 @@ void BusHub75Matrix::setBrightness(uint8_t b) {
}

void BusHub75Matrix::show(void) {
if (!_valid) return;
if (_ledBuffer) {
// write out buffered LEDs
unsigned height = _isVirtual ? virtualDisp->height() : display->height();
unsigned width = _panelWidth;

//while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
size_t pix = 0; // running pixel index
for (int y=0; y<height; y++) for (int x=0; x<width; x++) {
if (getBitFromArray(_ledsDirty, pix) == true) { // only repaint the "dirty" pixels
CRGB c = _ledBuffer[pix];
//c.nscale8_video(_bri); // apply brightness
if (_isVirtual) virtualDisp->drawPixelRGB888(int16_t(x), int16_t(y), c.r, c.g, c.b);
else display->drawPixelRGB888(int16_t(x), int16_t(y), c.r, c.g, c.b);
}
pix++;
}
setBitArray(_ledsDirty, _len, false); // buffer shown - reset all dirty bits
}
// show() is a no-op: pixels were already written directly in setPixelColor(),
// the DMA driver handles continuous refresh asynchronously
}

void BusHub75Matrix::cleanup() {
Expand All @@ -1189,7 +1154,6 @@ void BusHub75Matrix::cleanup() {
#else // runtime reconfiguration is not working on -S3, request reboot from user instead
errorFlag = ERR_REBOOT_NEEDED;
#endif
if (_ledBuffer != nullptr) d_free(_ledBuffer); _ledBuffer = nullptr;
if (_ledsDirty != nullptr) d_free(_ledsDirty); _ledsDirty = nullptr;
}

Expand Down
2 changes: 1 addition & 1 deletion wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit");
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
#define MAX_LEDS 2048 //due to memory constraints S2
#else
#define MAX_LEDS 16384
#define MAX_LEDS 16384 // note: S3 can take more but 24576 is already unstable using HUB75 (DMA buffers)
#endif
#endif

Expand Down
4 changes: 2 additions & 2 deletions wled00/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,8 +906,8 @@ void *allocate_buffer(size_t size, uint32_t type) {
buffer = d_malloc(size);
#else
if (type & BFRALLOC_PREFER_DRAM) {
if (getContiguousFreeHeap() < 3*(MIN_HEAP_SIZE/2) + size && size > PSRAM_THRESHOLD)
buffer = p_malloc(size); // prefer PSRAM for large allocations & when DRAM is low
if ((getContiguousFreeHeap() < 3*(MIN_HEAP_SIZE/2) + size && size > PSRAM_THRESHOLD) || size > 2*PSRAM_THRESHOLD)
buffer = p_malloc(size); // prefer PSRAM for large allocations & when DRAM is low or when buffer is huge
else
buffer = d_malloc(size); // allocate in DRAM if enough free heap is available, PSRAM as fallback
}
Expand Down
Loading