@@ -270,12 +270,6 @@ bool BusDigital::canShow() {
270270
271271void BusDigital::setBrightness (uint8_t b) {
272272 if (_bri == b) return ;
273- // Fix for turning off onboard LED breaking bus
274- #ifdef LED_BUILTIN
275- if (_bri == 0 ) { // && b > 0, covered by guard if above
276- if (_pins[0 ] == LED_BUILTIN || _pins[1 ] == LED_BUILTIN) reinit ();
277- }
278- #endif
279273 Bus::setBrightness (b);
280274 PolyBus::setBrightness (_busPtr, _iType, b);
281275}
@@ -707,6 +701,7 @@ int BusManager::add(BusConfig &bc) {
707701}
708702
709703void BusManager::useParallelOutput (void ) {
704+ _parallelOutputs = 8 ; // hardcoded since we use NPB I2S x8 methods
710705 PolyBus::setParallelI2S1Output ();
711706}
712707
@@ -717,9 +712,81 @@ void BusManager::removeAll() {
717712 while (!canAllShow ()) yield ();
718713 for (unsigned i = 0 ; i < numBusses; i++) delete busses[i];
719714 numBusses = 0 ;
715+ _parallelOutputs = 1 ;
720716 PolyBus::setParallelI2S1Output (false );
721717}
722718
719+ #ifdef ESP32_DATA_IDLE_HIGH
720+ // #2478
721+ // If enabled, RMT idle level is set to HIGH when off
722+ // to prevent leakage current when using an N-channel MOSFET to toggle LED power
723+ void BusManager::esp32RMTInvertIdle () {
724+ bool idle_out;
725+ unsigned rmt = 0 ;
726+ for (unsigned u = 0 ; u < numBusses (); u++) {
727+ #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, only has 1 I2S but NPB does not support it ATM
728+ if (u > 1 ) return ;
729+ rmt = u;
730+ #elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, only has 1 I2S bus, supported in NPB
731+ if (u > 3 ) return ;
732+ rmt = u;
733+ #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, has 2 I2S but NPB does not support them ATM
734+ if (u > 3 ) return ;
735+ rmt = u;
736+ #else
737+ if (u < _parallelOutputs) continue ;
738+ if (u >= _parallelOutputs + 8 ) return ; // only 8 RMT channels
739+ rmt = u - _parallelOutputs;
740+ #endif
741+ if (busses[u]->getLength ()==0 || !IS_DIGITAL (busses[u]->getType ()) || IS_2PIN (busses[u]->getType ())) continue ;
742+ // assumes that bus number to rmt channel mapping stays 1:1
743+ rmt_channel_t ch = static_cast <rmt_channel_t >(rmt);
744+ rmt_idle_level_t lvl;
745+ rmt_get_idle_level (ch, &idle_out, &lvl);
746+ if (lvl == RMT_IDLE_LEVEL_HIGH) lvl = RMT_IDLE_LEVEL_LOW;
747+ else if (lvl == RMT_IDLE_LEVEL_LOW) lvl = RMT_IDLE_LEVEL_HIGH;
748+ else continue ;
749+ rmt_set_idle_level (ch, idle_out, lvl);
750+ }
751+ }
752+ #endif
753+
754+ void BusManager::on () {
755+ #ifdef ESP8266
756+ // Fix for turning off onboard LED breaking bus
757+ if (pinManager.getPinOwner (LED_BUILTIN) == PinOwner::BusDigital) {
758+ for (unsigned i = 0 ; i < numBusses; i++) {
759+ uint8_t pins[2 ] = {255 ,255 };
760+ if (IS_DIGITAL (busses[i]->getType ()) && busses[i]->getPins (pins)) {
761+ if (pins[0 ] == LED_BUILTIN || pins[1 ] == LED_BUILTIN) {
762+ BusDigital *bus = static_cast <BusDigital*>(busses[i]);
763+ bus->reinit ();
764+ break ;
765+ }
766+ }
767+ }
768+ }
769+ #endif
770+ #ifdef ESP32_DATA_IDLE_HIGH
771+ esp32RMTInvertIdle ();
772+ #endif
773+ }
774+
775+ void BusManager::off () {
776+ #ifdef ESP8266
777+ // turn off built-in LED if strip is turned off
778+ // this will break digital bus so will need to be re-initialised on On
779+ if (pinManager.getPinOwner (LED_BUILTIN) == PinOwner::BusDigital) {
780+ for (unsigned i = 0 ; i < numBusses; i++) if (busses[i]->isOffRefreshRequired ()) return ;
781+ pinMode (LED_BUILTIN, OUTPUT);
782+ digitalWrite (LED_BUILTIN, HIGH);
783+ }
784+ #endif
785+ #ifdef ESP32_DATA_IDLE_HIGH
786+ esp32RMTInvertIdle ();
787+ #endif
788+ }
789+
723790void BusManager::show () {
724791 _milliAmpsUsed = 0 ;
725792 for (unsigned i = 0 ; i < numBusses; i++) {
@@ -799,4 +866,5 @@ uint8_t BusManager::numBusses = 0;
799866Bus* BusManager::busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
800867ColorOrderMap BusManager::colorOrderMap = {};
801868uint16_t BusManager::_milliAmpsUsed = 0 ;
802- uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
869+ uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
870+ uint8_t BusManager::_parallelOutputs = 1 ;
0 commit comments