From 74849c46ed900b8689d2219e4a366834c4fb14ca Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 19:26:52 +0000 Subject: [PATCH 1/7] rename VirtualMatrixPanel to virtualDisp rather than fourScanPanel --- wled00/bus_manager.cpp | 60 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 4cd339a400..f930f4100f 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -524,7 +524,7 @@ void BusNetwork::cleanup() { // BusHub75Matrix "global" variables (static members) MatrixPanel_I2S_DMA* BusHub75Matrix::activeDisplay = nullptr; -VirtualMatrixPanel* BusHub75Matrix::activeFourScanPanel = nullptr; +VirtualMatrixPanel* BusHub75Matrix::activevirtualDisp = nullptr; HUB75_I2S_CFG BusHub75Matrix::activeMXconfig = HUB75_I2S_CFG(); uint8_t BusHub75Matrix::activeType = 0; uint8_t BusHub75Matrix::instanceCount = 0; @@ -571,7 +571,7 @@ uint8_t BusHub75Matrix::instanceCount = 0; BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { MatrixPanel_I2S_DMA* display = nullptr; - VirtualMatrixPanel* fourScanPanel = nullptr; + VirtualMatrixPanel* virtualDisp = nullptr; HUB75_I2S_CFG mxconfig; size_t lastHeap = ESP.getFreeHeap(); @@ -849,7 +849,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh delete activeDisplay; //#endif activeDisplay = nullptr; - activeFourScanPanel = nullptr; + activevirtualDisp = nullptr; #if defined(CONFIG_IDF_TARGET_ESP32S3) // runtime reconfiguration is not working on -S3 USER_PRINTLN("\n\n****** MatrixPanel_I2S_DMA !KABOOM WARNING! Reboot needed to change driver options ***********\n"); errorFlag = ERR_REBOOT_NEEDED; @@ -864,13 +864,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh newDisplay = true; } else { display = activeDisplay; // continue with existing matrix object - fourScanPanel = activeFourScanPanel; + virtualDisp = activevirtualDisp; } if (display == nullptr) { USER_PRINTLN("****** MatrixPanel_I2S_DMA !KABOOM! driver allocation failed ***********"); activeDisplay = nullptr; - activeFourScanPanel = nullptr; + activevirtualDisp = nullptr; USER_PRINT(F("heap usage: ")); USER_PRINTLN(int(lastHeap - ESP.getFreeHeap())); return; } @@ -950,32 +950,32 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh switch(bc.type) { case 105: USER_PRINTLN("MatrixPanel_I2S_DMA FOUR_SCAN_32PX_HIGH - 32x32"); - if (!fourScanPanel) fourScanPanel = new VirtualMatrixPanel((*display), 1, 1, 32, 32); - fourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH); - fourScanPanel->setRotation(0); + if (!virtualDisp) virtualDisp = new VirtualMatrixPanel((*display), 1, 1, 32, 32); + virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH); + virtualDisp->setRotation(0); break; case 106: USER_PRINTLN("MatrixPanel_I2S_DMA FOUR_SCAN_32PX_HIGH - 64x32"); - if (!fourScanPanel) fourScanPanel = new VirtualMatrixPanel((*display), 1, 1, 64, 32); - fourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH); - fourScanPanel->setRotation(0); + if (!virtualDisp) virtualDisp = new VirtualMatrixPanel((*display), 1, 1, 64, 32); + virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_32PX_HIGH); + virtualDisp->setRotation(0); break; case 107: USER_PRINTLN("MatrixPanel_I2S_DMA FOUR_SCAN_64PX_HIGH"); - if (!fourScanPanel) fourScanPanel = new VirtualMatrixPanel((*display), 1, 1, 64, 64); - fourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_64PX_HIGH); - fourScanPanel->setRotation(0); + if (!virtualDisp) virtualDisp = new VirtualMatrixPanel((*display), 1, 1, 64, 64); + virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_64PX_HIGH); + virtualDisp->setRotation(0); break; case 108: // untested USER_PRINTLN("MatrixPanel_I2S_DMA 128x64 FOUR_SCAN_64PX_HIGH"); - if (!fourScanPanel) fourScanPanel = new VirtualMatrixPanel((*display), 1, 1, 128, 64); - fourScanPanel->setPhysicalPanelScanRate(FOUR_SCAN_64PX_HIGH); - fourScanPanel->setRotation(0); + if (!virtualDisp) virtualDisp = new VirtualMatrixPanel((*display), 1, 1, 128, 64); + virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_64PX_HIGH); + virtualDisp->setRotation(0); break; } if (_valid) { - _panelWidth = fourScanPanel ? fourScanPanel->width() : display->width(); // cache width - it will never change + _panelWidth = virtualDisp ? virtualDisp->width() : display->width(); // cache width - it will never change } USER_PRINT(F("MatrixPanel_I2S_DMA ")); @@ -993,7 +993,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh // config is active, copy to global activeType = bc.type; activeDisplay = display; - activeFourScanPanel = fourScanPanel; + activevirtualDisp = virtualDisp; if (newDisplay) memcpy(&activeMXconfig, &mxconfig, sizeof(mxconfig)); } instanceCount++; @@ -1018,7 +1018,7 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c else { // no double buffer allocated --> directly draw pixel MatrixPanel_I2S_DMA* display = BusHub75Matrix::activeDisplay; - VirtualMatrixPanel* fourScanPanel = BusHub75Matrix::activeFourScanPanel; + VirtualMatrixPanel* virtualDisp = BusHub75Matrix::activevirtualDisp; #ifndef NO_CIE1931 c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction #endif @@ -1026,11 +1026,11 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c uint8_t g = G(c); uint8_t b = B(c); - if(fourScanPanel != nullptr) { + if(virtualDisp != nullptr) { int width = _panelWidth; int x = pix % width; int y = pix / width; - fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + virtualDisp->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } else { int width = _panelWidth; int x = pix % width; @@ -1068,10 +1068,10 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { if (_ledBuffer) { // write out buffered LEDs - VirtualMatrixPanel* fourScanPanel = BusHub75Matrix::activeFourScanPanel; - bool isFourScan = (fourScanPanel != nullptr); - //if (isFourScan) fourScanPanel->setRotation(0); - unsigned height = isFourScan ? fourScanPanel->height() : display->height(); + VirtualMatrixPanel* virtualDisp = BusHub75Matrix::activevirtualDisp; + bool isVirtualDisp = (virtualDisp != nullptr); + //if (isVirtualDisp) virtualDisp->setRotation(0); + unsigned height = isVirtualDisp ? virtualDisp->height() : display->height(); unsigned width = _panelWidth; // Cache pointers to LED array and bitmask array, to avoid repeated accesses @@ -1095,7 +1095,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { uint8_t g = c.g; uint8_t b = c.b; #endif - if (isFourScan) fourScanPanel->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); + if (isVirtualDisp) virtualDisp->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); else display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b); } pix ++; @@ -1106,7 +1106,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) { void BusHub75Matrix::cleanup() { MatrixPanel_I2S_DMA* display = BusHub75Matrix::activeDisplay; - VirtualMatrixPanel* fourScanPanel = BusHub75Matrix::activeFourScanPanel; + VirtualMatrixPanel* virtualDisp = BusHub75Matrix::activevirtualDisp; if (display) display->clearScreen(); #if !defined(CONFIG_IDF_TARGET_ESP32S3) // S3: don't stop, as we want to re-use the driver later @@ -1119,11 +1119,11 @@ void BusHub75Matrix::cleanup() { _valid = false; deallocatePins(); - //if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior + //if (virtualDisp != nullptr) delete virtualDisp; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior #if !defined(CONFIG_IDF_TARGET_ESP32S3) // S3: don't delete, as we want to re-use the driver later if (display) delete display; activeDisplay = nullptr; - activeFourScanPanel = nullptr; + activevirtualDisp = nullptr; USER_PRINTLN("HUB75 deleted."); #else USER_PRINTLN("HUB75 cleanup done."); From 08ee13df126c1e414edcbbc05c131f9d0ba7640d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 19:32:56 +0000 Subject: [PATCH 2/7] HUB75 - use CHAIN_BOTTOM_LEFT_UP when panel width count and panel height count are set --- wled00/bus_manager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index f930f4100f..b495887499 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -972,6 +972,11 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh virtualDisp->setPhysicalPanelScanRate(FOUR_SCAN_64PX_HIGH); virtualDisp->setRotation(0); break; + default: + if(bc.pins[2] > 1 && bc.pins[3] > 0 && bc.pins[4]) { + virtualDisp = new VirtualMatrixPanel((*display), bc.pins[3], bc.pins[4], mxconfig.mx_width, mxconfig.mx_height, CHAIN_BOTTOM_LEFT_UP); + } + break; } if (_valid) { From 72d6e6d459bad88508ebaf6b40ca7518695d1236 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 19:42:22 +0000 Subject: [PATCH 3/7] rename VirtualMatrixPanel to virtualDisp rather than fourScanPanel --- wled00/bus_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 9259bd1ff4..d72a3babe4 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -407,7 +407,7 @@ class BusHub75Matrix : public Bus { // C++ dirty trick: private static variables are actually _not_ part of the class (however only visibile to class instances). // These variables persist when BusHub75Matrix gets deleted. static MatrixPanel_I2S_DMA *activeDisplay; // active display object - static VirtualMatrixPanel *activeFourScanPanel; // active fourScan object + static VirtualMatrixPanel *activevirtualDisp; // active fourScan object static HUB75_I2S_CFG activeMXconfig; // last used mxconfig static uint8_t activeType; // last used type static uint8_t instanceCount; // active instances - 0 or 1 From 973e8134a9ebb592bebc9d838292618fa8c047e8 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 22:08:02 +0000 Subject: [PATCH 4/7] Further work on VirtualMatrixPanel chain --- wled00/bus_manager.cpp | 7 +++++-- wled00/bus_manager.h | 8 +++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index b495887499..f6bdba0be1 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -664,6 +664,9 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh else if (numPixels <= MAX_PIXELS_4BIT) mxconfig.setPixelColorDepthBits(4); // 12bit else mxconfig.setPixelColorDepthBits(3); // 9bit + rows = bc.pins[3]; + cols = bc.pins[4]; + #if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3 @@ -973,8 +976,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh virtualDisp->setRotation(0); break; default: - if(bc.pins[2] > 1 && bc.pins[3] > 0 && bc.pins[4]) { - virtualDisp = new VirtualMatrixPanel((*display), bc.pins[3], bc.pins[4], mxconfig.mx_width, mxconfig.mx_height, CHAIN_BOTTOM_LEFT_UP); + if(mxconfig.chain_length > 1 && rows > 0 && cols > 0) { + virtualDisp = new VirtualMatrixPanel((*display), bc.pins[3], bc.pins[4], mxconfig.mx_width, mxconfig.mx_height, (PANEL_CHAIN_TYPE)bc.skipAmount); } break; } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index d72a3babe4..ac97a2e576 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -389,7 +389,11 @@ class BusHub75Matrix : public Bus { uint8_t getPins(uint8_t* pinArray) const override { pinArray[0] = activeMXconfig.chain_length; - return 1; + pinArray[1] = -1; + pinArray[2] = -1; + pinArray[3] = rows; + pinArray[4] = cols; + return 5; } // Fake value due to keep finaliseInit happy void deallocatePins(); @@ -404,6 +408,8 @@ class BusHub75Matrix : public Bus { unsigned _panelWidth = 0; CRGB *_ledBuffer = nullptr; byte *_ledsDirty = nullptr; + unsigned rows = 0; + unsigned cols = 0; // C++ dirty trick: private static variables are actually _not_ part of the class (however only visibile to class instances). // These variables persist when BusHub75Matrix gets deleted. static MatrixPanel_I2S_DMA *activeDisplay; // active display object From 967c1ee9c8fd09efee130934d69547c715c4e649 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 22:19:19 +0000 Subject: [PATCH 5/7] Add docs --- wled00/bus_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index f6bdba0be1..3634a3007f 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -977,6 +977,7 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh break; default: if(mxconfig.chain_length > 1 && rows > 0 && cols > 0) { + USER_PRINTF("MatrixPanel_I2S_DMA VirtualMatrixPanel %ux%u - %ux%u\n", mxconfig.mx_width, mxconfig.mx_height, rows, cols); virtualDisp = new VirtualMatrixPanel((*display), bc.pins[3], bc.pins[4], mxconfig.mx_width, mxconfig.mx_height, (PANEL_CHAIN_TYPE)bc.skipAmount); } break; From ccd701f14c9042e75f9a5693bb76ab4ee8c93b8a Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 14 Nov 2024 23:18:09 +0000 Subject: [PATCH 6/7] Limit to 4 panels in 2x2 layout --- wled00/bus_manager.cpp | 12 ++++++++---- wled00/bus_manager.h | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 3634a3007f..6e8191ddb4 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -664,8 +664,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh else if (numPixels <= MAX_PIXELS_4BIT) mxconfig.setPixelColorDepthBits(4); // 12bit else mxconfig.setPixelColorDepthBits(3); // 9bit - rows = bc.pins[3]; - cols = bc.pins[4]; + rows = min(bc.pins[3], (uint8_t) 2); // TODO higher limit + cols = min(bc.pins[4], (uint8_t) 2); // TODO higher limit #if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3 @@ -976,9 +976,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh virtualDisp->setRotation(0); break; default: - if(mxconfig.chain_length > 1 && rows > 0 && cols > 0) { + if(mxconfig.chain_length > 1 && rows >= 1 && cols >= 1) { // More than 1 panel, not just horizontal layout + // TODO: special case of 128x64 panels actually being 64x64 chain of two internally USER_PRINTF("MatrixPanel_I2S_DMA VirtualMatrixPanel %ux%u - %ux%u\n", mxconfig.mx_width, mxconfig.mx_height, rows, cols); - virtualDisp = new VirtualMatrixPanel((*display), bc.pins[3], bc.pins[4], mxconfig.mx_width, mxconfig.mx_height, (PANEL_CHAIN_TYPE)bc.skipAmount); + virtualDisp = new VirtualMatrixPanel((*display), rows, cols, mxconfig.mx_width, mxconfig.mx_height, (PANEL_CHAIN_TYPE)bc.skipAmount); + } + else { + USER_PRINTLN("MatrixPanel_I2S_DMA PANEL_CHAIN_TYPE.CHAIN_NONE"); } break; } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index ac97a2e576..78dc6f7658 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -408,8 +408,8 @@ class BusHub75Matrix : public Bus { unsigned _panelWidth = 0; CRGB *_ledBuffer = nullptr; byte *_ledsDirty = nullptr; - unsigned rows = 0; - unsigned cols = 0; + int rows = 0; + int cols = 0; // C++ dirty trick: private static variables are actually _not_ part of the class (however only visibile to class instances). // These variables persist when BusHub75Matrix gets deleted. static MatrixPanel_I2S_DMA *activeDisplay; // active display object From 6ccb38d96457101c72d920060edcd96b9f3f30c0 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sun, 16 Feb 2025 17:59:32 +0000 Subject: [PATCH 7/7] Fix merge conflict --- wled00/bus_manager.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e3bd3c9433..ea8afba569 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1190,12 +1190,8 @@ void BusHub75Matrix::cleanup() { _valid = false; deallocatePins(); -<<<<<<< HEAD - //if (virtualDisp != nullptr) delete virtualDisp; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior -======= _len = 0; - //if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior ->>>>>>> mdev + //if (virtualDisp != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior #if !defined(CONFIG_IDF_TARGET_ESP32S3) // S3: don't delete, as we want to re-use the driver later if (display) delete display; activeDisplay = nullptr;