Add HUB75 support
This commit is contained in:
@@ -461,3 +461,18 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=
|
||||
-D HW_PIN_MISOSPI=9
|
||||
; -D STATUSLED=15
|
||||
lib_deps = ${esp32s2.lib_deps}
|
||||
|
||||
|
||||
[env:esp32dev_hub75]
|
||||
board = esp32dev
|
||||
upload_speed = 921600
|
||||
platform = ${esp32_idf_V4.platform}
|
||||
platform_packages = ${esp32_idf_V4.platform_packages}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32_V4} -D WLED_RELEASE_NAME=ESP32_hub75
|
||||
-D WLED_ENABLE_HUB75MATRIX -D NO_GFX
|
||||
lib_deps = ${esp32_idf_V4.lib_deps}
|
||||
https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA.git @ 3.0.10
|
||||
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
@@ -605,6 +605,188 @@ void BusNetwork::cleanup() {
|
||||
freeData();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
|
||||
BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
|
||||
mxconfig.double_buff = false; // <------------- Turn on double buffer
|
||||
|
||||
switch(bc.type) {
|
||||
case 101:
|
||||
mxconfig.mx_width = 32;
|
||||
mxconfig.mx_height = 32;
|
||||
break;
|
||||
case 102:
|
||||
mxconfig.mx_width = 64;
|
||||
mxconfig.mx_height = 32;
|
||||
break;
|
||||
case 103:
|
||||
mxconfig.mx_width = 64;
|
||||
mxconfig.mx_height = 64;
|
||||
break;
|
||||
}
|
||||
|
||||
mxconfig.chain_length = max((u_int8_t) 1, min(bc.pins[0], (u_int8_t) 4)); // prevent bad data preventing boot due to low memory
|
||||
|
||||
if(mxconfig.mx_width >= 64 && (bc.pins[0] > 1)) {
|
||||
DEBUG_PRINTF("WARNING, only single panel can be used of 64 pixel boards due to memory")
|
||||
mxconfig.chain_length = 1;
|
||||
}
|
||||
|
||||
// mxconfig.driver = HUB75_I2S_CFG::SHIFTREG;
|
||||
|
||||
#if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3
|
||||
|
||||
// https://www.adafruit.com/product/5778
|
||||
|
||||
DEBUG_PRINTF("MatrixPanel_I2S_DMA - Matrix Portal S3 config");
|
||||
|
||||
mxconfig.gpio.r1 = 42;
|
||||
mxconfig.gpio.g1 = 41;
|
||||
mxconfig.gpio.b1 = 40;
|
||||
mxconfig.gpio.r2 = 38;
|
||||
mxconfig.gpio.g2 = 39;
|
||||
mxconfig.gpio.b2 = 37;
|
||||
|
||||
mxconfig.gpio.lat = 47;
|
||||
mxconfig.gpio.oe = 14;
|
||||
mxconfig.gpio.clk = 2;
|
||||
|
||||
mxconfig.gpio.a = 45;
|
||||
mxconfig.gpio.b = 36;
|
||||
mxconfig.gpio.c = 48;
|
||||
mxconfig.gpio.d = 35;
|
||||
mxconfig.gpio.e = 21;
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
|
||||
ESP32 with SmartMatrix's default pinout - ESP32_FORUM_PINOUT
|
||||
|
||||
https://github.com/pixelmatix/SmartMatrix/blob/teensylc/src/MatrixHardware_ESP32_V0.h
|
||||
|
||||
Can use a board like https://github.com/rorosaurus/esp32-hub75-driver
|
||||
|
||||
#define R1_PIN GPIO_NUM_2
|
||||
#define G1_PIN GPIO_NUM_15
|
||||
#define B1_PIN GPIO_NUM_4
|
||||
#define R2_PIN GPIO_NUM_16
|
||||
#define G2_PIN GPIO_NUM_27
|
||||
#define B2_PIN GPIO_NUM_17
|
||||
|
||||
#define A_PIN GPIO_NUM_5
|
||||
#define B_PIN GPIO_NUM_18
|
||||
#define C_PIN GPIO_NUM_19
|
||||
#define D_PIN GPIO_NUM_21
|
||||
#define E_PIN GPIO_NUM_12
|
||||
#define LAT_PIN GPIO_NUM_26
|
||||
#define OE_PIN GPIO_NUM_25
|
||||
|
||||
#define CLK_PIN GPIO_NUM_22
|
||||
*/
|
||||
|
||||
DEBUG_PRINTF("MatrixPanel_I2S_DMA - ESP32 config");
|
||||
|
||||
mxconfig.gpio.r1 = 2;
|
||||
mxconfig.gpio.g1 = 15;
|
||||
mxconfig.gpio.b1 = 4;
|
||||
mxconfig.gpio.r2 = 16;
|
||||
mxconfig.gpio.g2 = 27;
|
||||
mxconfig.gpio.b2 = 17;
|
||||
|
||||
mxconfig.gpio.lat = 26;
|
||||
mxconfig.gpio.oe = 25;
|
||||
mxconfig.gpio.clk = 22;
|
||||
|
||||
mxconfig.gpio.a = 5;
|
||||
mxconfig.gpio.b = 18;
|
||||
mxconfig.gpio.c = 19;
|
||||
mxconfig.gpio.d = 21;
|
||||
mxconfig.gpio.e = 12;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
DEBUG_PRINTF("MatrixPanel_I2S_DMA config - %ux%u length: %u\n", mxconfig.mx_width, mxconfig.mx_height, mxconfig.chain_length);
|
||||
|
||||
// OK, now we can create our matrix object
|
||||
display = new MatrixPanel_I2S_DMA(mxconfig);
|
||||
|
||||
this->_len = (display->width() * display->height());
|
||||
|
||||
pinManager.allocatePin(mxconfig.gpio.r1, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.g1, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.b1, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.r2, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.g2, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.b2, true, PinOwner::HUB75);
|
||||
|
||||
pinManager.allocatePin(mxconfig.gpio.lat, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.oe, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.clk, true, PinOwner::HUB75);
|
||||
|
||||
pinManager.allocatePin(mxconfig.gpio.a, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.b, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.c, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.d, true, PinOwner::HUB75);
|
||||
pinManager.allocatePin(mxconfig.gpio.e, true, PinOwner::HUB75);
|
||||
|
||||
// display->setLatBlanking(4);
|
||||
|
||||
DEBUG_PRINTF("MatrixPanel_I2S_DMA created");
|
||||
// let's adjust default brightness
|
||||
display->setBrightness8(25); // range is 0-255, 0 - 0%, 255 - 100%
|
||||
|
||||
// Allocate memory and start DMA display
|
||||
if( not display->begin() ) {
|
||||
DEBUG_PRINTF("****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("MatrixPanel_I2S_DMA started");
|
||||
}
|
||||
|
||||
void BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
r = R(c);
|
||||
g = G(c);
|
||||
b = B(c);
|
||||
x = pix % display->width();
|
||||
y = floor(pix / display->width());
|
||||
display->drawPixelRGB888(x, y, r, g, b);
|
||||
}
|
||||
|
||||
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
||||
this->display->setBrightness(b);
|
||||
}
|
||||
|
||||
void BusHub75Matrix::deallocatePins() {
|
||||
|
||||
pinManager.deallocatePin(mxconfig.gpio.r1, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.g1, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.b1, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.r2, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.g2, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.b2, PinOwner::HUB75);
|
||||
|
||||
pinManager.deallocatePin(mxconfig.gpio.lat, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.oe, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.clk, PinOwner::HUB75);
|
||||
|
||||
pinManager.deallocatePin(mxconfig.gpio.a, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.b, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.c, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.d, PinOwner::HUB75);
|
||||
pinManager.deallocatePin(mxconfig.gpio.e, PinOwner::HUB75);
|
||||
|
||||
}
|
||||
#endif
|
||||
// ***************************************************************************
|
||||
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
uint32_t BusManager::memUsage(BusConfig &bc) {
|
||||
@@ -637,6 +819,10 @@ int BusManager::add(BusConfig &bc) {
|
||||
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
|
||||
if (IS_VIRTUAL(bc.type)) {
|
||||
busses[numBusses] = new BusNetwork(bc);
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
} else if (bc.type >= TYPE_HUB75MATRIX && bc.type <= (TYPE_HUB75MATRIX + 10)) {
|
||||
busses[numBusses] = new BusHub75Matrix(bc);
|
||||
#endif
|
||||
} else if (IS_DIGITAL(bc.type)) {
|
||||
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
|
||||
} else if (bc.type == TYPE_ONOFF) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef BusManager_h
|
||||
#define BusManager_h
|
||||
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
|
||||
#endif
|
||||
/*
|
||||
* Class for addressing various light types
|
||||
*/
|
||||
@@ -56,6 +59,7 @@ struct BusConfig {
|
||||
if (type >= TYPE_NET_DDP_RGB && type < 96) nPins = 4; //virtual network bus. 4 "pins" store IP address
|
||||
else if (type > 47) nPins = 2;
|
||||
else if (type > 40 && type < 46) nPins = NUM_PWM_PINS(type);
|
||||
else if (type >= TYPE_HUB75MATRIX && type <= (TYPE_HUB75MATRIX + 10)) nPins = 0;
|
||||
for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i];
|
||||
}
|
||||
|
||||
@@ -313,6 +317,51 @@ class BusNetwork : public Bus {
|
||||
bool _broadcastLock;
|
||||
};
|
||||
|
||||
#ifdef WLED_ENABLE_HUB75MATRIX
|
||||
class BusHub75Matrix : public Bus {
|
||||
public:
|
||||
BusHub75Matrix(BusConfig &bc);
|
||||
|
||||
uint16_t getMaxPixels() override { return 4096; };
|
||||
|
||||
bool hasRGB() { return true; }
|
||||
bool hasWhite() { return false; }
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
void show() {
|
||||
if(mxconfig.double_buff) {
|
||||
display->flipDMABuffer(); // Show the back buffer, set currently output buffer to the back (i.e. no longer being sent to LED panels)
|
||||
display->clearScreen(); // Now clear the back-buffer
|
||||
}
|
||||
}
|
||||
|
||||
void setBrightness(uint8_t b, bool immediate);
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
pinArray[0] = mxconfig.chain_length;
|
||||
return 1;
|
||||
} // Fake value due to keep finaliseInit happy
|
||||
|
||||
void deallocatePins();
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
delete display;
|
||||
_valid = false;
|
||||
}
|
||||
|
||||
~BusHub75Matrix() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
MatrixPanel_I2S_DMA *display = nullptr;
|
||||
HUB75_I2S_CFG mxconfig;
|
||||
uint8_t r, g, b, x, y;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
class BusManager {
|
||||
public:
|
||||
|
||||
@@ -280,6 +280,9 @@
|
||||
#define TYPE_LPD8806 52
|
||||
#define TYPE_P9813 53
|
||||
#define TYPE_LPD6803 54
|
||||
|
||||
#define TYPE_HUB75MATRIX 100 // 100 - 110
|
||||
|
||||
//Network types (master broadcast) (80-95)
|
||||
#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus)
|
||||
#define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus, unused)
|
||||
|
||||
@@ -23,6 +23,19 @@
|
||||
function isD2P(t) { return t > 47 && t < 64; } // is digital 2 pin type
|
||||
function is16b(t) { return t == 26 || t == 29 } // is digital 16 bit type
|
||||
function isVir(t) { return t >= 80 && t < 96; } // is virtual type
|
||||
function hideHub75() {
|
||||
var s = d.getElementsByTagName("select");
|
||||
for (i=0; i<s.length; i++) {
|
||||
// is the field a LED type?
|
||||
if (s[i].name.substring(0,2)=="LT") {
|
||||
var selectobject = s[i];
|
||||
for (var j=(selectobject.length - 1); j > 0; j--) {
|
||||
var t = parseInt(selectobject.options[j].value);
|
||||
if(t >= 100 && t <= 110) selectobject.remove(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
@@ -413,6 +426,9 @@ ${i+1}:
|
||||
<!--option value="81">E1.31 RGB (network)</option-->
|
||||
<option value="82">Art-Net RGB (network)</option>
|
||||
<option value="88">DDP RGBW (network)</option>
|
||||
<option value="101">Hub75Matrix 32x32</option>
|
||||
<option value="102">Hub75Matrix 64x32</option>
|
||||
<option value="103">Hub75Matrix 64x64</option>
|
||||
</select><br>
|
||||
<div id="abl${i}">
|
||||
mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
||||
|
||||
@@ -35,6 +35,7 @@ enum struct PinOwner : uint8_t {
|
||||
DMX = 0x8A, // 'DMX' == hard-coded to IO2
|
||||
HW_I2C = 0x8B, // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32)
|
||||
HW_SPI = 0x8C, // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32)
|
||||
HUB75 = 0x8E, // 'Hub75' == Hub75 driver
|
||||
// Use UserMod IDs from const.h here
|
||||
UM_Unspecified = USERMOD_ID_UNSPECIFIED, // 0x01
|
||||
UM_Example = USERMOD_ID_EXAMPLE, // 0x02 // Usermod "usermod_v2_example.h"
|
||||
|
||||
@@ -770,5 +770,9 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
#else
|
||||
oappend(SET_F("gId(\"somp\").remove(1);")); // remove 2D option from dropdown
|
||||
#endif
|
||||
#ifndef WLED_ENABLE_HUB75MATRIX
|
||||
oappend(SET_F("hideHub75();")); // WLEDMM hide HUB75 LED types
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user