diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index a06d4f843..69a742c3d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -44,8 +44,8 @@ */ //factory defaults LED setup -//#define PIXEL_COUNTS 30, 30, 30, 30 -//#define DATA_PINS 16, 1, 3, 4 +//#define PIXEL_COUNTS 30 +//#define DATA_PINS 2 (8266/C3) or 16 //#define DEFAULT_LED_TYPE TYPE_WS2812_RGB #ifndef PIXEL_COUNTS @@ -56,8 +56,8 @@ #define DATA_PINS LEDPIN #endif -#ifndef DEFAULT_LED_TYPE - #define DEFAULT_LED_TYPE TYPE_WS2812_RGB +#ifndef LED_TYPES + #define LED_TYPES DEFAULT_LED_TYPE #endif #ifndef DEFAULT_LED_COLOR_ORDER @@ -1215,17 +1215,30 @@ void WS2812FX::finalizeInit(void) { //if busses failed to load, add default (fresh install, FS issue, ...) if (BusManager::getNumBusses() == 0) { DEBUG_PRINTLN(F("No busses, init default")); + constexpr unsigned defDataTypes[] = {LED_TYPES}; const unsigned defDataPins[] = {DATA_PINS}; const unsigned defCounts[] = {PIXEL_COUNTS}; - const unsigned defNumPins = ((sizeof defDataPins) / (sizeof defDataPins[0])); + const unsigned defNumTypes = ((sizeof defDataTypes) / (sizeof defDataTypes[0])); + constexpr unsigned defNumPins = ((sizeof defDataPins) / (sizeof defDataPins[0])); const unsigned defNumCounts = ((sizeof defCounts) / (sizeof defCounts[0])); - // if number of pins is divisible by counts, use number of counts to determine number of buses, otherwise use pins - const unsigned defNumBusses = defNumPins > defNumCounts && defNumPins%defNumCounts == 0 ? defNumCounts : defNumPins; - const unsigned pinsPerBus = defNumPins / defNumBusses; + + static_assert(Bus::getNumberOfPins(defDataTypes[0]) <= defNumPins, + "The first LED type configured requires more pins than have been defined!"); + unsigned prevLen = 0; - for (unsigned i = 0; i < defNumBusses && i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) { - uint8_t defPin[5]; // max 5 pins - for (unsigned j = 0; j < pinsPerBus; j++) defPin[j] = defDataPins[i*pinsPerBus + j]; + unsigned pinsIndex = 0; + for (unsigned i = 0; i < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; i++) { + uint8_t defPin[OUTPUT_MAX_PINS]; // max 5 pins + // if we have less types than requested outputs and they do not align, use last known type to set current type + unsigned dataType = defDataTypes[(i < defNumTypes) ? i : defNumTypes -1]; + unsigned busPins = Bus::getNumberOfPins(dataType); + // check if we have enough pins left to configure an output of this type + if (pinsIndex + busPins > defNumPins) { + DEBUG_PRINTLN(F("LED outputs misaligned with defined pins. Some pins will remain unused.")); + break; + } + for (unsigned j = 0; j < busPins && j < OUTPUT_MAX_PINS; j++) defPin[j] = defDataPins[pinsIndex + j]; + pinsIndex += busPins; // when booting without config (1st boot) we need to make sure GPIOs defined for LED output don't clash with hardware // i.e. DEBUG (GPIO1), DMX (2), SPI RAM/FLASH (16&17 on ESP32-WROVER/PICO), etc if (pinManager.isPinAllocated(defPin[0])) { @@ -1235,8 +1248,10 @@ void WS2812FX::finalizeInit(void) { unsigned start = prevLen; // if we have less counts than pins and they do not align, use last known count to set current count unsigned count = defCounts[(i < defNumCounts) ? i : defNumCounts -1]; + // analog always has length 1 + if (Bus::isPWM(dataType)) count = 1; prevLen += count; - BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer); + BusConfig defCfg = BusConfig(dataType, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer); if (BusManager::add(defCfg) == -1) break; } } diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e5918ce95..77e60ba4f 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -673,7 +673,7 @@ void BusNetwork::cleanup(void) { //utility to get the approx. memory usage of a given BusConfig uint32_t BusManager::memUsage(BusConfig &bc) { - if (Bus::isOnOff(bc.type) || Bus::isPWM(bc.type)) return 5; + if (Bus::isOnOff(bc.type) || Bus::isPWM(bc.type)) return OUTPUT_MAX_PINS; unsigned len = bc.count + bc.skipAmount; unsigned channels = Bus::getNumberOfChannels(bc.type); diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 1d1136fd8..f6aa4b579 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -267,8 +267,8 @@ class BusPwm : public Bus { void cleanup(void) { deallocatePins(); } private: - uint8_t _pins[5]; - uint8_t _pwmdata[5]; + uint8_t _pins[OUTPUT_MAX_PINS]; + uint8_t _pwmdata[OUTPUT_MAX_PINS]; #ifdef ARDUINO_ARCH_ESP32 uint8_t _ledcStart; #endif @@ -346,10 +346,7 @@ struct BusConfig { { refreshReq = (bool) GET_BIT(busType,7); type = busType & 0x7F; // bit 7 may be/is hacked to include refresh info (1=refresh in off state, 0=no refresh) - size_t nPins = 1; - if (Bus::isVirtual(type)) nPins = 4; //virtual network bus. 4 "pins" store IP address - else if (Bus::is2Pin(type)) nPins = 2; - else if (Bus::isPWM(type)) nPins = Bus::numPWMPins(type); + size_t nPins = Bus::getNumberOfPins(type); for (size_t i = 0; i < nPins; i++) pins[i] = ppins[i]; } diff --git a/wled00/const.h b/wled00/const.h index bdc80aab9..cb50a108f 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -466,6 +466,9 @@ #define NTP_PACKET_SIZE 48 // size of NTP receive buffer #define NTP_MIN_PACKET_SIZE 48 // min expected size - NTP v4 allows for "extended information" appended to the standard fields +// Maximum number of pins per output. 5 for RGBCCT analog LEDs. +#define OUTPUT_MAX_PINS 5 + //maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses #ifndef MAX_LEDS #ifdef ESP8266 @@ -577,6 +580,10 @@ #endif #endif +#ifndef DEFAULT_LED_TYPE + #define DEFAULT_LED_TYPE TYPE_WS2812_RGB +#endif + #ifndef DEFAULT_LED_COUNT #define DEFAULT_LED_COUNT 30 #endif