@@ -462,6 +462,232 @@ void BusNetwork::cleanup() {
462462 _data = nullptr ;
463463}
464464
465+ // ***************************************************************************
466+
467+ #ifdef WLED_ENABLE_HUB75MATRIX
468+
469+ BusHub75Matrix::BusHub75Matrix (BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
470+
471+ mxconfig.double_buff = false ; // <------------- Turn on double buffer
472+
473+
474+ fourScanPanel = nullptr ;
475+
476+ switch (bc.type ) {
477+ case 101 :
478+ mxconfig.mx_width = 32 ;
479+ mxconfig.mx_height = 32 ;
480+ break ;
481+ case 102 :
482+ mxconfig.mx_width = 64 ;
483+ mxconfig.mx_height = 32 ;
484+ break ;
485+ case 103 :
486+ mxconfig.mx_width = 64 ;
487+ mxconfig.mx_height = 64 ;
488+ break ;
489+ case 105 :
490+ mxconfig.mx_width = 32 * 2 ;
491+ mxconfig.mx_height = 32 / 2 ;
492+ break ;
493+ case 106 :
494+ mxconfig.mx_width = 64 * 2 ;
495+ mxconfig.mx_height = 64 / 2 ;
496+ break ;
497+ }
498+
499+ 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
500+
501+ if (mxconfig.mx_width >= 64 && (bc.pins [0 ] > 1 )) {
502+ USER_PRINT (" WARNING, only single panel can be used of 64 pixel boards due to memory" )
503+ mxconfig.chain_length = 1 ;
504+ }
505+
506+ // mxconfig.driver = HUB75_I2S_CFG::SHIFTREG;
507+
508+ #if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3) // MatrixPortal ESP32-S3
509+
510+ // https://www.adafruit.com/product/5778
511+
512+ USER_PRINTLN (" MatrixPanel_I2S_DMA - Matrix Portal S3 config" );
513+
514+ mxconfig.gpio .r1 = 42 ;
515+ mxconfig.gpio .g1 = 41 ;
516+ mxconfig.gpio .b1 = 40 ;
517+ mxconfig.gpio .r2 = 38 ;
518+ mxconfig.gpio .g2 = 39 ;
519+ mxconfig.gpio .b2 = 37 ;
520+
521+ mxconfig.gpio .lat = 47 ;
522+ mxconfig.gpio .oe = 14 ;
523+ mxconfig.gpio .clk = 2 ;
524+
525+ mxconfig.gpio .a = 45 ;
526+ mxconfig.gpio .b = 36 ;
527+ mxconfig.gpio .c = 48 ;
528+ mxconfig.gpio .d = 35 ;
529+ mxconfig.gpio .e = 21 ;
530+
531+ #elif defined(ESP32_FORUM_PINOUT) // Common format for boards designed for SmartMatrix
532+
533+ USER_PRINTLN (" MatrixPanel_I2S_DMA - ESP32_FORUM_PINOUT" );
534+
535+ /*
536+ ESP32 with SmartMatrix's default pinout - ESP32_FORUM_PINOUT
537+
538+ https://github.com/pixelmatix/SmartMatrix/blob/teensylc/src/MatrixHardware_ESP32_V0.h
539+
540+ Can use a board like https://github.com/rorosaurus/esp32-hub75-driver
541+ */
542+
543+ mxconfig.gpio .r1 = 2 ;
544+ mxconfig.gpio .g1 = 15 ;
545+ mxconfig.gpio .b1 = 4 ;
546+ mxconfig.gpio .r2 = 16 ;
547+ mxconfig.gpio .g2 = 27 ;
548+ mxconfig.gpio .b2 = 17 ;
549+
550+ mxconfig.gpio .lat = 26 ;
551+ mxconfig.gpio .oe = 25 ;
552+ mxconfig.gpio .clk = 22 ;
553+
554+ mxconfig.gpio .a = 5 ;
555+ mxconfig.gpio .b = 18 ;
556+ mxconfig.gpio .c = 19 ;
557+ mxconfig.gpio .d = 21 ;
558+ mxconfig.gpio .e = 12 ;
559+
560+ #else
561+ USER_PRINTLN (" MatrixPanel_I2S_DMA - Default pins" );
562+ /*
563+ https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA?tab=readme-ov-file
564+
565+ Boards
566+
567+ https://esp32trinity.com/
568+ https://www.electrodragon.com/product/rgb-matrix-panel-drive-interface-board-for-esp32-dma/
569+
570+ */
571+ mxconfig.gpio .r1 = 25 ;
572+ mxconfig.gpio .g1 = 26 ;
573+ mxconfig.gpio .b1 = 27 ;
574+ mxconfig.gpio .r2 = 14 ;
575+ mxconfig.gpio .g2 = 12 ;
576+ mxconfig.gpio .b2 = 13 ;
577+
578+ mxconfig.gpio .lat = 4 ;
579+ mxconfig.gpio .oe = 15 ;
580+ mxconfig.gpio .clk = 16 ;
581+
582+ mxconfig.gpio .a = 23 ;
583+ mxconfig.gpio .b = 19 ;
584+ mxconfig.gpio .c = 5 ;
585+ mxconfig.gpio .d = 17 ;
586+ mxconfig.gpio .e = 18 ;
587+
588+ #endif
589+
590+
591+ USER_PRINTF (" MatrixPanel_I2S_DMA config - %ux%u length: %u\n " , mxconfig.mx_width , mxconfig.mx_height , mxconfig.chain_length );
592+
593+ // OK, now we can create our matrix object
594+ display = new MatrixPanel_I2S_DMA (mxconfig);
595+
596+ this ->_len = (display->width () * display->height ());
597+
598+ pinManager.allocatePin (mxconfig.gpio .r1 , true , PinOwner::HUB75);
599+ pinManager.allocatePin (mxconfig.gpio .g1 , true , PinOwner::HUB75);
600+ pinManager.allocatePin (mxconfig.gpio .b1 , true , PinOwner::HUB75);
601+ pinManager.allocatePin (mxconfig.gpio .r2 , true , PinOwner::HUB75);
602+ pinManager.allocatePin (mxconfig.gpio .g2 , true , PinOwner::HUB75);
603+ pinManager.allocatePin (mxconfig.gpio .b2 , true , PinOwner::HUB75);
604+
605+ pinManager.allocatePin (mxconfig.gpio .lat , true , PinOwner::HUB75);
606+ pinManager.allocatePin (mxconfig.gpio .oe , true , PinOwner::HUB75);
607+ pinManager.allocatePin (mxconfig.gpio .clk , true , PinOwner::HUB75);
608+
609+ pinManager.allocatePin (mxconfig.gpio .a , true , PinOwner::HUB75);
610+ pinManager.allocatePin (mxconfig.gpio .b , true , PinOwner::HUB75);
611+ pinManager.allocatePin (mxconfig.gpio .c , true , PinOwner::HUB75);
612+ pinManager.allocatePin (mxconfig.gpio .d , true , PinOwner::HUB75);
613+ pinManager.allocatePin (mxconfig.gpio .e , true , PinOwner::HUB75);
614+
615+ // display->setLatBlanking(4);
616+
617+ USER_PRINTLN (" MatrixPanel_I2S_DMA created" );
618+ // let's adjust default brightness
619+ display->setBrightness8 (25 ); // range is 0-255, 0 - 0%, 255 - 100%
620+
621+ // Allocate memory and start DMA display
622+ if ( not display->begin () ) {
623+ USER_PRINTLN (" ****** MatrixPanel_I2S_DMA !KABOOM! I2S memory allocation failed ***********" );
624+ return ;
625+ }
626+ else {
627+ _valid = true ;
628+ }
629+
630+ switch (bc.type ) {
631+ case 105 :
632+ USER_PRINTLN (" MatrixPanel_I2S_DMA FOUR_SCAN_32PX_HIGH" );
633+ fourScanPanel = new VirtualMatrixPanel ((*display), 1 , 1 , 32 , 32 );
634+ fourScanPanel->setPhysicalPanelScanRate (FOUR_SCAN_32PX_HIGH);
635+ fourScanPanel->setRotation (0 );
636+ break ;
637+ case 106 :
638+ USER_PRINTLN (" MatrixPanel_I2S_DMA FOUR_SCAN_64PX_HIGH" );
639+ fourScanPanel = new VirtualMatrixPanel ((*display), 1 , 1 , 64 , 64 );
640+ fourScanPanel->setPhysicalPanelScanRate (FOUR_SCAN_64PX_HIGH);
641+ fourScanPanel->setRotation (0 );
642+ break ;
643+ }
644+
645+
646+ USER_PRINTLN (" MatrixPanel_I2S_DMA started" );
647+ }
648+
649+ void BusHub75Matrix::setPixelColor (uint16_t pix, uint32_t c) {
650+ r = R (c);
651+ g = G (c);
652+ b = B (c);
653+ if (fourScanPanel != nullptr ) {
654+ x = pix % fourScanPanel->width ();
655+ y = floor (pix / fourScanPanel->width ());
656+ fourScanPanel->drawPixelRGB888 (x, y, r, g, b);
657+ }
658+ else {
659+ x = pix % display->width ();
660+ y = floor (pix / display->width ());
661+ display->drawPixelRGB888 (x, y, r, g, b);
662+ }
663+ }
664+
665+ void BusHub75Matrix::setBrightness (uint8_t b, bool immediate) {
666+ this ->display ->setBrightness (b);
667+ }
668+
669+ void BusHub75Matrix::deallocatePins () {
670+
671+ pinManager.deallocatePin (mxconfig.gpio .r1 , PinOwner::HUB75);
672+ pinManager.deallocatePin (mxconfig.gpio .g1 , PinOwner::HUB75);
673+ pinManager.deallocatePin (mxconfig.gpio .b1 , PinOwner::HUB75);
674+ pinManager.deallocatePin (mxconfig.gpio .r2 , PinOwner::HUB75);
675+ pinManager.deallocatePin (mxconfig.gpio .g2 , PinOwner::HUB75);
676+ pinManager.deallocatePin (mxconfig.gpio .b2 , PinOwner::HUB75);
677+
678+ pinManager.deallocatePin (mxconfig.gpio .lat , PinOwner::HUB75);
679+ pinManager.deallocatePin (mxconfig.gpio .oe , PinOwner::HUB75);
680+ pinManager.deallocatePin (mxconfig.gpio .clk , PinOwner::HUB75);
681+
682+ pinManager.deallocatePin (mxconfig.gpio .a , PinOwner::HUB75);
683+ pinManager.deallocatePin (mxconfig.gpio .b , PinOwner::HUB75);
684+ pinManager.deallocatePin (mxconfig.gpio .c , PinOwner::HUB75);
685+ pinManager.deallocatePin (mxconfig.gpio .d , PinOwner::HUB75);
686+ pinManager.deallocatePin (mxconfig.gpio .e , PinOwner::HUB75);
687+
688+ }
689+ #endif
690+ // ***************************************************************************
465691
466692// utility to get the approx. memory usage of a given BusConfig
467693uint32_t BusManager::memUsage (BusConfig &bc) {
@@ -487,8 +713,14 @@ uint32_t BusManager::memUsage(BusConfig &bc) {
487713
488714int BusManager::add (BusConfig &bc) {
489715 if (getNumBusses () - getNumVirtualBusses () >= WLED_MAX_BUSSES) return -1 ;
716+ USER_PRINTF (" BusManager::add(bc.type=%u)\n " , bc.type );
490717 if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96 ) {
491718 busses[numBusses] = new BusNetwork (bc);
719+ #ifdef WLED_ENABLE_HUB75MATRIX
720+ } else if (bc.type >= TYPE_HUB75MATRIX && bc.type <= (TYPE_HUB75MATRIX + 10 )) {
721+ USER_PRINTLN (" BusManager::add - Adding BusHub75Matrix" );
722+ busses[numBusses] = new BusHub75Matrix (bc);
723+ #endif
492724 } else if (IS_DIGITAL (bc.type )) {
493725 busses[numBusses] = new BusDigital (bc, numBusses, colorOrderMap);
494726 } else if (bc.type == TYPE_ONOFF) {
0 commit comments