Convert BusManager class to namespace

- use unique_ptr/make_unique for busses
This commit is contained in:
Blaž Kristan 2025-01-21 17:50:36 +01:00
parent 32a75c1ff5
commit ee7ec20f29
6 changed files with 94 additions and 102 deletions

View File

@ -63,6 +63,8 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const
#define W(c) (byte((c) >> 24))
static ColorOrderMap _colorOrderMap = {};
bool ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
if (count() >= WLED_MAX_COLOR_ORDER_MAPPINGS || len == 0 || (colorOrder & 0x0F) > COL_ORDER_MAX) return false; // upper nibble contains W swap information
_mappings.push_back({start,len,colorOrder});
@ -72,10 +74,8 @@ bool ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
// upper nibble contains W swap information
// when ColorOrderMap's upper nibble contains value >0 then swap information is used from it, otherwise global swap is used
for (unsigned i = 0; i < count(); i++) {
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
return _mappings[i].colorOrder | ((_mappings[i].colorOrder >> 4) ? 0 : (defaultColorOrder & 0xF0));
}
for (const auto& map : _mappings) {
if (pix >= map.start && pix < (map.start + map.len)) return map.colorOrder | ((map.colorOrder >> 4) ? 0 : (defaultColorOrder & 0xF0));
}
return defaultColorOrder;
}
@ -124,13 +124,12 @@ uint8_t *Bus::allocateData(size_t size) {
}
BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
BusDigital::BusDigital(const BusConfig &bc, uint8_t nr)
: Bus(bc.type, bc.start, bc.autoWhite, bc.count, bc.reversed, (bc.refreshReq || bc.type == TYPE_TM1814))
, _skip(bc.skipAmount) //sacrificial pixels
, _colorOrder(bc.colorOrder)
, _milliAmpsPerLed(bc.milliAmpsPerLed)
, _milliAmpsMax(bc.milliAmpsMax)
, _colorOrderMap(com)
{
if (!isDigital(bc.type) || !bc.count) return;
if (!PinManager::allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
@ -819,13 +818,17 @@ uint32_t BusManager::memUsage(unsigned maxChannels, unsigned maxCount, unsigned
int BusManager::add(const BusConfig &bc) {
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
if (Bus::isVirtual(bc.type)) {
busses[numBusses] = new BusNetwork(bc);
busses.push_back(make_unique<BusNetwork>(bc));
//busses.push_back(new BusNetwork(bc));
} else if (Bus::isDigital(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
busses.push_back(make_unique<BusDigital>(bc, numDigital));
//busses.push_back(new BusDigital(bc, numDigital));
} else if (Bus::isOnOff(bc.type)) {
busses[numBusses] = new BusOnOff(bc);
busses.push_back(make_unique<BusOnOff>(bc));
//busses.push_back(new BusOnOff(bc));
} else {
busses[numBusses] = new BusPwm(bc);
busses.push_back(make_unique<BusPwm>(bc));
//busses.push_back(new BusPwm(bc));
}
return numBusses++;
}
@ -865,9 +868,8 @@ void BusManager::removeAll() {
DEBUG_PRINTLN(F("Removing all."));
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (unsigned i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
_parallelOutputs = 1;
//for (auto &bus : busses) delete bus; // needed when not using std::unique_ptr C++ >11
busses.clear();
PolyBus::setParallelI2S1Output(false);
}
@ -914,8 +916,8 @@ void BusManager::on() {
uint8_t pins[2] = {255,255};
if (busses[i]->isDigital() && busses[i]->getPins(pins)) {
if (pins[0] == LED_BUILTIN || pins[1] == LED_BUILTIN) {
BusDigital *bus = static_cast<BusDigital*>(busses[i]);
bus->begin();
BusDigital &b = static_cast<BusDigital&>(*bus);
b.begin();
break;
}
}
@ -943,16 +945,10 @@ void BusManager::off() {
}
void BusManager::show() {
_milliAmpsUsed = 0;
for (unsigned i = 0; i < numBusses; i++) {
busses[i]->show();
_milliAmpsUsed += busses[i]->getUsedCurrent();
}
}
void BusManager::setStatusPixel(uint32_t c) {
for (unsigned i = 0; i < numBusses; i++) {
busses[i]->setStatusPixel(c);
_gMilliAmpsUsed = 0;
for (auto &bus : busses) {
bus->show();
_gMilliAmpsUsed += bus->getUsedCurrent();
}
}
@ -995,17 +991,8 @@ bool BusManager::canAllShow() {
return true;
}
Bus* BusManager::getBus(uint8_t busNr) {
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
ColorOrderMap& BusManager::getColorOrderMap() { return _colorOrderMap; }
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
uint16_t BusManager::getTotalLength() {
unsigned len = 0;
for (unsigned i=0; i<numBusses; i++) len += busses[i]->getLength();
return len;
}
bool PolyBus::useParallelI2S = false;
@ -1016,9 +1003,7 @@ uint8_t Bus::_gAWM = 255;
uint16_t BusDigital::_milliAmpsTotal = 0;
uint8_t BusManager::numBusses = 0;
Bus* BusManager::busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
ColorOrderMap BusManager::colorOrderMap = {};
uint16_t BusManager::_milliAmpsUsed = 0;
uint16_t BusManager::_milliAmpsMax = ABL_MILLIAMPS_DEFAULT;
uint8_t BusManager::_parallelOutputs = 1;
std::vector<std::unique_ptr<Bus>> BusManager::busses;
//std::vector<Bus*> BusManager::busses;
uint16_t BusManager::_gMilliAmpsUsed = 0;
uint16_t BusManager::_gMilliAmpsMax = ABL_MILLIAMPS_DEFAULT;

View File

@ -8,6 +8,20 @@
#include "const.h"
#include "pin_manager.h"
#include <vector>
#include <memory>
#include <bits/unique_ptr.h>
#if __cplusplus >= 201402L
using std::make_unique;
#else
// Really simple C++11 shim for non-array case; implementation from cppreference.com
template<class T, class... Args>
std::unique_ptr<T>
make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif
//colors.cpp
uint16_t approximateKelvinFromRGB(uint32_t rgb);
@ -198,7 +212,7 @@ class Bus {
class BusDigital : public Bus {
public:
BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com);
BusDigital(const BusConfig &bc, uint8_t nr);
~BusDigital() { cleanup(); }
void show() override;
@ -229,7 +243,6 @@ class BusDigital : public Bus {
uint8_t _milliAmpsPerLed;
uint16_t _milliAmpsMax;
void * _busPtr;
const ColorOrderMap &_colorOrderMap;
static uint16_t _milliAmpsTotal; // is overwitten/recalculated on each show()
@ -374,61 +387,58 @@ struct BusConfig {
#endif
#endif
class BusManager {
public:
BusManager() {};
namespace BusManager {
//utility to get the approx. memory usage of a given BusConfig
static uint32_t memUsage(const BusConfig &bc);
static uint32_t memUsage(unsigned channels, unsigned count, unsigned buses = 1);
static uint16_t currentMilliamps() { return _milliAmpsUsed + MA_FOR_ESP; }
static uint16_t ablMilliampsMax() { return _milliAmpsMax; }
extern std::vector<std::unique_ptr<Bus>> busses;
//extern std::vector<Bus*> busses;
extern uint16_t _gMilliAmpsUsed;
extern uint16_t _gMilliAmpsMax;
static int add(const BusConfig &bc);
static void useParallelOutput(); // workaround for inaccessible PolyBus
#ifdef ESP32_DATA_IDLE_HIGH
void esp32RMTInvertIdle() ;
#endif
inline uint8_t getNumVirtualBusses() {
int j = 0;
for (const auto &bus : busses) j += bus->isVirtual();
return j;
}
//do not call this method from system context (network callback)
static void removeAll();
unsigned memUsage();
inline uint16_t currentMilliamps() { return _gMilliAmpsUsed + MA_FOR_ESP; }
//inline uint16_t ablMilliampsMax() { unsigned sum = 0; for (auto &bus : busses) sum += bus->getMaxCurrent(); return sum; }
inline uint16_t ablMilliampsMax() { return _gMilliAmpsMax; } // used for compatibility reasons (and enabling virtual global ABL)
inline void setMilliampsMax(uint16_t max) { _gMilliAmpsMax = max;}
static void on();
static void off();
void useParallelOutput(); // workaround for inaccessible PolyBus
bool hasParallelOutput(); // workaround for inaccessible PolyBus
static void show();
static bool canAllShow();
static void setStatusPixel(uint32_t c);
[[gnu::hot]] static void setPixelColor(unsigned pix, uint32_t c);
static void setBrightness(uint8_t b);
// for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K
// WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT()
static void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
static inline void setMilliampsMax(uint16_t max) { _milliAmpsMax = max;}
[[gnu::hot]] static uint32_t getPixelColor(unsigned pix);
static inline int16_t getSegmentCCT() { return Bus::getCCT(); }
//do not call this method from system context (network callback)
void removeAll();
int add(const BusConfig &bc);
static Bus* getBus(uint8_t busNr);
void on();
void off();
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
static uint16_t getTotalLength();
static inline uint8_t getNumBusses() { return numBusses; }
static String getLEDTypesJSONString();
[[gnu::hot]] void setPixelColor(unsigned pix, uint32_t c);
[[gnu::hot]] uint32_t getPixelColor(unsigned pix);
void show();
bool canAllShow();
inline void setStatusPixel(uint32_t c) { for (auto &bus : busses) bus->setStatusPixel(c);}
inline void setBrightness(uint8_t b) { for (auto &bus : busses) bus->setBrightness(b); }
// for setSegmentCCT(), cct can only be in [-1,255] range; allowWBCorrection will convert it to K
// WARNING: setSegmentCCT() is a misleading name!!! much better would be setGlobalCCT() or just setCCT()
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
inline int16_t getSegmentCCT() { return Bus::getCCT(); }
inline Bus& getBus(uint8_t busNr) { return *busses[std::min((size_t)busNr, busses.size()-1)]; }
inline uint8_t getNumBusses() { return busses.size(); }
static inline ColorOrderMap& getColorOrderMap() { return colorOrderMap; }
private:
static uint8_t numBusses;
static Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
static ColorOrderMap colorOrderMap;
static uint16_t _milliAmpsUsed;
static uint16_t _milliAmpsMax;
static uint8_t _parallelOutputs;
#ifdef ESP32_DATA_IDLE_HIGH
static void esp32RMTInvertIdle() ;
#endif
static uint8_t getNumVirtualBusses() {
int j = 0;
for (int i=0; i<numBusses; i++) if (busses[i]->isVirtual()) j++;
return j;
}
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
inline uint16_t getTotalLength(bool onlyPhysical = false) {
unsigned len = 0;
for (const auto &bus : busses) if (!(bus->isVirtual() && onlyPhysical)) len += bus->getLength();
return len;
}
String getLEDTypesJSONString();
ColorOrderMap& getColorOrderMap();
};
#endif

View File

@ -876,8 +876,7 @@ void serializeConfig() {
const ColorOrderMap& com = BusManager::getColorOrderMap();
for (size_t s = 0; s < com.count(); s++) {
const ColorOrderMapEntry *entry = com.get(s);
if (!entry) break;
if (!entry || !entry->len) break;
JsonObject co = hw_com.createNestedObject();
co["start"] = entry->start;
co["len"] = entry->len;

View File

@ -208,8 +208,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
type |= request->hasArg(rf) << 7; // off refresh override
// actual finalization is done in WLED::loop() (removing old busses and adding new)
// this may happen even before this loop is finished so we do "doInitBusses" after the loop
if (busConfigs[s] != nullptr) delete busConfigs[s];
busConfigs[s] = new(std::nothrow) BusConfig(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, useGlobalLedBuffer, maPerLed, maMax);
busConfigs.emplace_back(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode, freq, useGlobalLedBuffer, maPerLed, maMax);
busesChanged = true;
}
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed

View File

@ -891,12 +891,11 @@ WLED_GLOBAL ESPAsyncE131 ddp _INIT_N(((handleE131Packet)));
WLED_GLOBAL bool e131NewData _INIT(false);
// led fx library object
WLED_GLOBAL BusManager busses _INIT(BusManager());
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after
WLED_GLOBAL bool doInitBusses _INIT(false);
WLED_GLOBAL int8_t loadLedmap _INIT(-1);
WLED_GLOBAL uint8_t currentLedmap _INIT(0);
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
WLED_GLOBAL std::vector<BusConfig> busConfigs; //temporary, to remember values from network callback until after
WLED_GLOBAL bool doInitBusses _INIT(false);
WLED_GLOBAL int8_t loadLedmap _INIT(-1);
WLED_GLOBAL uint8_t currentLedmap _INIT(0);
#ifndef ESP8266
WLED_GLOBAL char *ledmapNames[WLED_MAX_LEDMAPS-1] _INIT_N(({nullptr}));
#endif

View File

@ -357,7 +357,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
const ColorOrderMap& com = BusManager::getColorOrderMap();
for (int s = 0; s < com.count(); s++) {
const ColorOrderMapEntry* entry = com.get(s);
if (entry == nullptr) break;
if (!entry || !entry->len) break;
settingsScript.printf_P(PSTR("addCOM(%d,%d,%d);"), entry->start, entry->len, entry->colorOrder);
}