Bus wrapper modifications
- NeoPixelBus update 2.8.3 - automatic selection of appropriate I2S bus (`X1xxxxxxMethod`) - removed I2S0 on ESP32 (used by AudioReactive) - renumbered internal bus numbers (iType) - added buffer size reporting Bus modifications - WWA strip support - bus initialisation rewrite - optional parallel I2S (ESP32, S2 & S3)
This commit is contained in:
@@ -18,10 +18,11 @@
|
||||
#endif
|
||||
#include "const.h"
|
||||
#include "pin_manager.h"
|
||||
#include "bus_wrapper.h"
|
||||
#include "bus_manager.h"
|
||||
#include "bus_wrapper.h"
|
||||
|
||||
extern bool cctICused;
|
||||
extern bool useParallelI2S;
|
||||
|
||||
//colors.cpp
|
||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
||||
@@ -121,7 +122,7 @@ uint8_t *Bus::allocateData(size_t size) {
|
||||
}
|
||||
|
||||
|
||||
BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
||||
BusDigital::BusDigital(const BusConfig &bc, uint8_t nr, const ColorOrderMap &com)
|
||||
: 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)
|
||||
@@ -220,7 +221,7 @@ void BusDigital::show() {
|
||||
if (!_valid) return;
|
||||
|
||||
uint8_t cctWW = 0, cctCW = 0;
|
||||
unsigned newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal
|
||||
unsigned newBri = estimateCurrentAndLimitBri(); // will fill _milliAmpsTotal (TODO: could use PolyBus::CalcTotalMilliAmpere())
|
||||
if (newBri < _bri) PolyBus::setBrightness(_busPtr, _iType, newBri); // limit brightness to stay within current limits
|
||||
|
||||
if (_data) {
|
||||
@@ -246,6 +247,7 @@ void BusDigital::show() {
|
||||
// TODO: there is an issue if CCT is calculated from RGB value (_cct==-1), we cannot do that with double buffer
|
||||
Bus::_cct = _data[offset+channels-1];
|
||||
Bus::calculateCCT(c, cctWW, cctCW);
|
||||
if (_type == TYPE_WS2812_WWA) c = RGBW32(cctWW, cctCW, 0, W(c)); // may need swapping
|
||||
}
|
||||
unsigned pix = i;
|
||||
if (_reversed) pix = _len - pix -1;
|
||||
@@ -331,8 +333,8 @@ void IRAM_ATTR BusDigital::setPixelColor(unsigned pix, uint32_t c) {
|
||||
uint8_t cctWW = 0, cctCW = 0;
|
||||
Bus::calculateCCT(c, cctWW, cctCW);
|
||||
wwcw = (cctCW<<8) | cctWW;
|
||||
if (_type == TYPE_WS2812_WWA) c = RGBW32(cctWW, cctCW, 0, W(c)); // may need swapping
|
||||
}
|
||||
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co, wwcw);
|
||||
}
|
||||
}
|
||||
@@ -364,16 +366,24 @@ uint32_t IRAM_ATTR BusDigital::getPixelColor(unsigned pix) const {
|
||||
case 2: c = RGBW32(b, b, b, b); break;
|
||||
}
|
||||
}
|
||||
if (_type == TYPE_WS2812_WWA) {
|
||||
uint8_t w = R(c) | G(c);
|
||||
c = RGBW32(w, w, 0, w);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BusDigital::getPins(uint8_t* pinArray) const {
|
||||
unsigned BusDigital::getPins(uint8_t* pinArray) const {
|
||||
unsigned numPins = is2Pin(_type) + 1;
|
||||
if (pinArray) for (unsigned i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||
return numPins;
|
||||
}
|
||||
|
||||
unsigned BusDigital::getBufferSize() const {
|
||||
return isOk() ? PolyBus::getDataSize(_busPtr, _iType) : 0;
|
||||
}
|
||||
|
||||
void BusDigital::setColorOrder(uint8_t colorOrder) {
|
||||
// upper nibble contains W swap information
|
||||
if ((colorOrder & 0x0F) > 5) return;
|
||||
@@ -397,7 +407,7 @@ std::vector<LEDType> BusDigital::getLEDTypes() {
|
||||
{TYPE_SM16825, "D", PSTR("SM16825 RGBCW")},
|
||||
{TYPE_WS2812_1CH_X3, "D", PSTR("WS2811 White")},
|
||||
//{TYPE_WS2812_2CH_X3, "D", PSTR("WS2811 CCT")}, // not implemented
|
||||
//{TYPE_WS2812_WWA, "D", PSTR("WS2811 WWA")}, // not implemented
|
||||
{TYPE_WS2812_WWA, "D", PSTR("WS2811 WWA")}, // amber ignored
|
||||
{TYPE_WS2801, "2P", PSTR("WS2801")},
|
||||
{TYPE_APA102, "2P", PSTR("APA102")},
|
||||
{TYPE_LPD8806, "2P", PSTR("LPD8806")},
|
||||
@@ -418,8 +428,9 @@ void BusDigital::cleanup() {
|
||||
_valid = false;
|
||||
_busPtr = nullptr;
|
||||
if (_data != nullptr) freeData();
|
||||
PinManager::deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
PinManager::deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
PinManager::deallocateMultiplePins(_pins, 2, PinOwner::BusDigital);
|
||||
//PinManager::deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
//PinManager::deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
}
|
||||
|
||||
|
||||
@@ -448,7 +459,7 @@ void BusDigital::cleanup() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BusPwm::BusPwm(BusConfig &bc)
|
||||
BusPwm::BusPwm(const BusConfig &bc)
|
||||
: Bus(bc.type, bc.start, bc.autoWhite, 1, bc.reversed, bc.refreshReq) // hijack Off refresh flag to indicate usage of dithering
|
||||
{
|
||||
if (!isPWM(bc.type)) return;
|
||||
@@ -610,7 +621,7 @@ void BusPwm::show() {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BusPwm::getPins(uint8_t* pinArray) const {
|
||||
unsigned BusPwm::getPins(uint8_t* pinArray) const {
|
||||
if (!_valid) return 0;
|
||||
unsigned numPins = numPWMPins(_type);
|
||||
if (pinArray) for (unsigned i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||
@@ -646,7 +657,7 @@ void BusPwm::deallocatePins() {
|
||||
}
|
||||
|
||||
|
||||
BusOnOff::BusOnOff(BusConfig &bc)
|
||||
BusOnOff::BusOnOff(const BusConfig &bc)
|
||||
: Bus(bc.type, bc.start, bc.autoWhite, 1, bc.reversed)
|
||||
, _onoffdata(0)
|
||||
{
|
||||
@@ -686,7 +697,7 @@ void BusOnOff::show() {
|
||||
digitalWrite(_pin, _reversed ? !(bool)_data[0] : (bool)_data[0]);
|
||||
}
|
||||
|
||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) const {
|
||||
unsigned BusOnOff::getPins(uint8_t* pinArray) const {
|
||||
if (!_valid) return 0;
|
||||
if (pinArray) pinArray[0] = _pin;
|
||||
return 1;
|
||||
@@ -699,7 +710,7 @@ std::vector<LEDType> BusOnOff::getLEDTypes() {
|
||||
};
|
||||
}
|
||||
|
||||
BusNetwork::BusNetwork(BusConfig &bc)
|
||||
BusNetwork::BusNetwork(const BusConfig &bc)
|
||||
: Bus(bc.type, bc.start, bc.autoWhite, bc.count)
|
||||
, _broadcastLock(false)
|
||||
{
|
||||
@@ -750,7 +761,7 @@ void BusNetwork::show() {
|
||||
_broadcastLock = false;
|
||||
}
|
||||
|
||||
uint8_t BusNetwork::getPins(uint8_t* pinArray) const {
|
||||
unsigned BusNetwork::getPins(uint8_t* pinArray) const {
|
||||
if (pinArray) for (unsigned i = 0; i < 4; i++) pinArray[i] = _client[i];
|
||||
return 4;
|
||||
}
|
||||
@@ -778,7 +789,7 @@ void BusNetwork::cleanup() {
|
||||
|
||||
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
uint32_t BusManager::memUsage(BusConfig &bc) {
|
||||
uint32_t BusManager::memUsage(const BusConfig &bc) {
|
||||
if (Bus::isOnOff(bc.type) || Bus::isPWM(bc.type)) return OUTPUT_MAX_PINS;
|
||||
|
||||
unsigned len = bc.count + bc.skipAmount;
|
||||
@@ -791,19 +802,23 @@ uint32_t BusManager::memUsage(BusConfig &bc) {
|
||||
multiplier = 5;
|
||||
}
|
||||
#else //ESP32 RMT uses double buffer, parallel I2S uses 8x buffer (3 times)
|
||||
multiplier = PolyBus::isParallelI2S1Output() ? 24 : 2;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
multiplier = useParallelI2S ? 24 : 2;
|
||||
#else
|
||||
multiplier = 2;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return (len * multiplier + bc.doubleBuffer * (bc.count + bc.skipAmount)) * channels;
|
||||
}
|
||||
|
||||
uint32_t BusManager::memUsage(unsigned maxChannels, unsigned maxCount, unsigned minBuses) {
|
||||
//ESP32 RMT uses double buffer, parallel I2S uses 8x buffer (3 times)
|
||||
unsigned multiplier = PolyBus::isParallelI2S1Output() ? 3 : 2;
|
||||
return (maxChannels * maxCount * minBuses * multiplier);
|
||||
unsigned BusManager::getTotalBuffers() {
|
||||
unsigned size = 0;
|
||||
for (unsigned i=0; i<numBusses; i++) size += busses[i]->getBufferSize();
|
||||
return size;
|
||||
}
|
||||
|
||||
int BusManager::add(BusConfig &bc) {
|
||||
int BusManager::add(const BusConfig &bc) {
|
||||
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
|
||||
if (Bus::isVirtual(bc.type)) {
|
||||
busses[numBusses] = new BusNetwork(bc);
|
||||
@@ -843,10 +858,13 @@ String BusManager::getLEDTypesJSONString() {
|
||||
}
|
||||
|
||||
void BusManager::useParallelOutput() {
|
||||
_parallelOutputs = 8; // hardcoded since we use NPB I2S x8 methods
|
||||
PolyBus::setParallelI2S1Output();
|
||||
}
|
||||
|
||||
bool BusManager::hasParallelOutput() {
|
||||
return PolyBus::isParallelI2S1Output();
|
||||
}
|
||||
|
||||
//do not call this method from system context (network callback)
|
||||
void BusManager::removeAll() {
|
||||
DEBUG_PRINTLN(F("Removing all."));
|
||||
@@ -854,7 +872,6 @@ void BusManager::removeAll() {
|
||||
while (!canAllShow()) yield();
|
||||
for (unsigned i = 0; i < numBusses; i++) delete busses[i];
|
||||
numBusses = 0;
|
||||
_parallelOutputs = 1;
|
||||
PolyBus::setParallelI2S1Output(false);
|
||||
}
|
||||
|
||||
@@ -876,9 +893,10 @@ void BusManager::esp32RMTInvertIdle() {
|
||||
if (u > 3) return;
|
||||
rmt = u;
|
||||
#else
|
||||
if (u < _parallelOutputs) continue;
|
||||
if (u >= _parallelOutputs + 8) return; // only 8 RMT channels
|
||||
rmt = u - _parallelOutputs;
|
||||
unsigned numI2S = 1 + PolyBus::isParallelI2S1Output()*7;
|
||||
if (u < numI2S) continue;
|
||||
if (u >= numI2S + 8) return; // only 8 RMT channels
|
||||
rmt = u - numI2S;
|
||||
#endif
|
||||
if (busses[u]->getLength()==0 || !busses[u]->isDigital() || busses[u]->is2Pin()) continue;
|
||||
//assumes that bus number to rmt channel mapping stays 1:1
|
||||
@@ -994,7 +1012,7 @@ uint16_t BusManager::getTotalLength() {
|
||||
return len;
|
||||
}
|
||||
|
||||
bool PolyBus::useParallelI2S = false;
|
||||
bool PolyBus::_useParallelI2S = false;
|
||||
|
||||
// Bus static member definition
|
||||
int16_t Bus::_cct = -1;
|
||||
@@ -1008,4 +1026,3 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user