1010#include " bus_wrapper.h"
1111#include < Arduino.h>
1212
13+ // enable additional debug output
14+ #ifdef WLED_DEBUG
15+ #ifndef ESP8266
16+ #include < rom/rtc.h>
17+ #endif
18+ #define DEBUG_PRINT (x ) Serial.print(x)
19+ #define DEBUG_PRINTLN (x ) Serial.println(x)
20+ #define DEBUG_PRINTF (x... ) Serial.printf(x)
21+ #else
22+ #define DEBUG_PRINT (x )
23+ #define DEBUG_PRINTLN (x )
24+ #define DEBUG_PRINTF (x... )
25+ #endif
26+
1327// temporary struct for passing bus configuration to bus
1428struct BusConfig {
1529 uint8_t type = TYPE_WS2812_RGB;
@@ -23,7 +37,8 @@ struct BusConfig {
2337 type = busType; count = len; start = pstart;
2438 colorOrder = pcolorOrder; reversed = rev; skipAmount = skip;
2539 uint8_t nPins = 1 ;
26- if (type > 47 ) nPins = 2 ;
40+ if (type >= 10 && type <= 15 ) nPins = 4 ;
41+ else if (type > 47 ) nPins = 2 ;
2742 else if (type > 40 && type < 46 ) nPins = NUM_PWM_PINS (type);
2843 for (uint8_t i = 0 ; i < nPins; i++) pins[i] = ppins[i];
2944 }
@@ -74,7 +89,7 @@ class Bus {
7489 }
7590
7691 virtual uint16_t getLength () {
77- return 1 ;
92+ return 1 ; // is this ok? shouldn't it be 0 in virtual function?
7893 }
7994
8095 virtual void setColorOrder () {}
@@ -135,7 +150,7 @@ class BusDigital : public Bus {
135150 _busPtr = PolyBus::create (_iType, _pins, _len, nr);
136151 _valid = (_busPtr != nullptr );
137152 _colorOrder = bc.colorOrder ;
138- // Serial.printf ("Successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n",nr, len, type, pins[0],pins[1],_iType);
153+ DEBUG_PRINTF (" Successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n " ,nr, len, type, pins[0 ],pins[1 ],_iType);
139154 };
140155
141156 inline void show () {
@@ -201,7 +216,7 @@ class BusDigital : public Bus {
201216 }
202217
203218 void cleanup () {
204- // Serial.println ("Digital Cleanup");
219+ DEBUG_PRINTLN (" Digital Cleanup" );
205220 PolyBus::cleanup (_busPtr, _iType);
206221 _iType = I_NONE;
207222 _valid = false ;
@@ -227,6 +242,7 @@ class BusDigital : public Bus {
227242class BusPwm : public Bus {
228243 public:
229244 BusPwm (BusConfig &bc) : Bus(bc.type, bc.start) {
245+ _valid = false ;
230246 if (!IS_PWM (bc.type )) return ;
231247 uint8_t numPins = NUM_PWM_PINS (bc.type );
232248
@@ -280,10 +296,12 @@ class BusPwm : public Bus {
280296
281297 // does no index check
282298 uint32_t getPixelColor (uint16_t pix) {
299+ if (!_valid) return 0 ;
283300 return ((_data[3 ] << 24 ) | (_data[0 ] << 16 ) | (_data[1 ] << 8 ) | (_data[2 ]));
284301 }
285302
286303 void show () {
304+ if (!_valid) return ;
287305 uint8_t numPins = NUM_PWM_PINS (_type);
288306 for (uint8_t i = 0 ; i < numPins; i++) {
289307 uint8_t scaled = (_data[i] * _bri) / 255 ;
@@ -328,20 +346,147 @@ class BusPwm : public Bus {
328346 void deallocatePins () {
329347 uint8_t numPins = NUM_PWM_PINS (_type);
330348 for (uint8_t i = 0 ; i < numPins; i++) {
349+ pinManager.deallocatePin (_pins[i], PinOwner::BusPwm);
331350 if (!pinManager.isPinOk (_pins[i])) continue ;
332351 #ifdef ESP8266
333352 digitalWrite (_pins[i], LOW); // turn off PWM interrupt
334353 #else
335354 if (_ledcStart < 16 ) ledcDetachPin (_pins[i]);
336355 #endif
337- pinManager.deallocatePin (_pins[i], PinOwner::BusPwm);
338356 }
339357 #ifdef ARDUINO_ARCH_ESP32
340358 pinManager.deallocateLedc (_ledcStart, numPins);
341359 #endif
342360 }
343361};
344362
363+
364+ class BusNetwork : public Bus {
365+ public:
366+ BusNetwork (BusConfig &bc) : Bus(bc.type, bc.start) {
367+ _valid = false ;
368+ // switch (bc.type) {
369+ // case TYPE_NET_ARTNET_RGB:
370+ // _rgbw = false;
371+ // _UDPtype = 2;
372+ // break;
373+ // case TYPE_NET_E131_RGB:
374+ // _rgbw = false;
375+ // _UDPtype = 1;
376+ // break;
377+ // case TYPE_NET_DDP_RGB:
378+ // _rgbw = false;
379+ // _UDPtype = 0;
380+ // break;
381+ // default:
382+ _rgbw = false ;
383+ _UDPtype = bc.type - TYPE_NET_DDP_RGB;
384+ // break;
385+ // }
386+ _UDPchannels = _rgbw ? 4 : 3 ;
387+ // _rgbw |= bc.rgbwOverride; // RGBW override in bit 7 or can have a special type
388+ _data = (byte *)malloc (bc.count * _UDPchannels);
389+ if (_data == nullptr ) return ;
390+ memset (_data, 0 , bc.count * _UDPchannels);
391+ _len = bc.count ;
392+ _colorOrder = bc.colorOrder ;
393+ _client = IPAddress (bc.pins [0 ],bc.pins [1 ],bc.pins [2 ],bc.pins [3 ]);
394+ _broadcastLock = false ;
395+ _valid = true ;
396+ _data2 = (byte *)malloc (_len * _UDPchannels);
397+ };
398+
399+ void setPixelColor (uint16_t pix, uint32_t c) {
400+ if (!_valid || pix >= _len) return ;
401+ uint16_t offset = pix * _UDPchannels;
402+ _data[offset] = 0xFF & (c >> 16 );
403+ _data[offset+1 ] = 0xFF & (c >> 8 );
404+ _data[offset+2 ] = 0xFF & (c );
405+ if (_rgbw) _data[offset+3 ] = 0xFF & (c >> 24 );
406+ }
407+
408+ uint32_t getPixelColor (uint16_t pix) {
409+ if (!_valid || pix >= _len) return 0 ;
410+ uint16_t offset = pix * _UDPchannels;
411+ // behave as NeoPixelBus
412+ return (
413+ (_rgbw ? (scale8 (_data[offset+3 ], _bri) << 24 ) : 0 )
414+ | (scale8 (_data[offset] , _bri) << 16 )
415+ | (scale8 (_data[offset+1 ], _bri) << 8 )
416+ | (scale8 (_data[offset+2 ], _bri) )
417+ );
418+ }
419+
420+ void show () {
421+ if (!_valid || !canShow ()) return ;
422+ _broadcastLock = true ;
423+ // apply brightness to second buffer
424+ if (_data2 == nullptr ) {
425+ // but display original buffer if memory allocation failed
426+ realtimeBroadcast (_UDPtype, _client, _len, _data, _rgbw);
427+ } else {
428+ for (uint16_t pix=0 ; pix<_len; pix++) {
429+ uint16_t offset = pix * _UDPchannels;
430+ _data2[offset ] = scale8 (_data[offset ], _bri);
431+ _data2[offset+1 ] = scale8 (_data[offset+1 ], _bri);
432+ _data2[offset+2 ] = scale8 (_data[offset+2 ], _bri);
433+ if (_rgbw) _data2[offset+3 ] = scale8 (_data[offset+3 ], _bri);
434+ }
435+ realtimeBroadcast (_UDPtype, _client, _len, _data2, _rgbw);
436+ }
437+ _broadcastLock = false ;
438+ }
439+
440+ inline bool canShow () {
441+ // this should be a return value from UDP routine if it is still sending data out
442+ return !_broadcastLock;
443+ }
444+
445+ inline void setBrightness (uint8_t b) {
446+ _bri = b;
447+ }
448+
449+ uint8_t getPins (uint8_t * pinArray) {
450+ for (uint8_t i = 0 ; i < 4 ; i++) {
451+ pinArray[i] = _client[i];
452+ }
453+ return 4 ;
454+ }
455+
456+ inline bool isRgbw () {
457+ return _rgbw;
458+ }
459+
460+ inline uint16_t getLength () {
461+ return _len;
462+ }
463+
464+ void cleanup () {
465+ _type = I_NONE;
466+ _valid = false ;
467+ if (_data != nullptr ) free (_data);
468+ _data = nullptr ;
469+ if (_data2 != nullptr ) free (_data2);
470+ _data2 = nullptr ;
471+ }
472+
473+ ~BusNetwork () {
474+ cleanup ();
475+ }
476+
477+ private:
478+ IPAddress _client;
479+ uint16_t _len = 0 ;
480+ uint8_t _colorOrder;
481+ uint8_t _bri = 255 ;
482+ uint8_t _UDPtype;
483+ uint8_t _UDPchannels;
484+ bool _rgbw;
485+ bool _broadcastLock;
486+ byte *_data, *_data2;
487+ };
488+
489+
345490class BusManager {
346491 public:
347492 BusManager () {
@@ -352,7 +497,7 @@ class BusManager {
352497 static uint32_t memUsage (BusConfig &bc) {
353498 uint8_t type = bc.type ;
354499 uint16_t len = bc.count ;
355- if (type < 32 ) {
500+ if (type > 15 && type < 32 ) {
356501 #ifdef ESP8266
357502 if (bc.pins [0 ] == 3 ) { // 8266 DMA uses 5x the mem
358503 if (type > 29 ) return len*20 ; // RGBW
@@ -365,15 +510,17 @@ class BusManager {
365510 return len*6 ;
366511 #endif
367512 }
368-
369- if (type > 31 && type < 48 ) return 5 ;
513+ if (type >= 10 && type <= 15 ) return len* 6 ; // double buffer for network
514+ if (type > 31 && type < 48 ) return 5 ;
370515 if (type == 44 || type == 45 ) return len*4 ; // RGBW
371516 return len*3 ;
372517 }
373518
374519 int add (BusConfig &bc) {
375520 if (numBusses >= WLED_MAX_BUSSES) return -1 ;
376- if (IS_DIGITAL (bc.type )) {
521+ if (bc.type >=10 && bc.type <=15 ) {
522+ busses[numBusses] = new BusNetwork (bc);
523+ } else if (IS_DIGITAL (bc.type )) {
377524 busses[numBusses] = new BusDigital (bc, numBusses);
378525 } else {
379526 busses[numBusses] = new BusPwm (bc);
@@ -444,6 +591,7 @@ class BusManager {
444591 return len;
445592 }
446593
594+ // a workaround
447595 static inline bool isRgbw (uint8_t type) {
448596 return Bus::isRgbw (type);
449597 }
0 commit comments