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