Merge branch 'dev' into mergedev_210222

This commit is contained in:
Aircoookie 2021-02-22 22:31:12 +01:00 committed by GitHub
commit 37d5b9109f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 3202 additions and 1588 deletions

View File

@ -2,6 +2,16 @@
### Development versions after 0.11.1 release
#### Build 2102050
- Version bump to 0.12.0-a0 "Hikari"
- Added FPS indication in info
- Bumped max outputs from 7 to 10 busses for ESP32
#### Build 2101310
- First alpha configurable multipin
#### Build 2101130
- Added color transitions for all segments and slots and for segment brightness

View File

@ -1,6 +1,6 @@
{
"name": "wled",
"version": "0.11.1",
"version": "0.12.0-a0",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {

View File

@ -12,7 +12,7 @@
default_envs = travis_esp8266, travis_esp32
# Release binaries
; default_envs = nodemcuv2, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom_LEDPIN_3, custom32_LEDPIN_16, custom32_APA102
; default_envs = nodemcuv2, esp01_1m_full, esp32dev
# Single binaries (uncomment your board)
; default_envs = nodemcuv2

View File

@ -398,6 +398,14 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
method: "plaintext",
filter: "html-minify",
},
{
file: "liveviewws.htm",
name: "PAGE_liveviewws",
prepend: "=====(",
append: ")=====",
method: "plaintext",
filter: "html-minify",
},
{
file: "404.htm",
name: "PAGE_404",

View File

@ -0,0 +1,40 @@
Hello! I have written a v2 usermod for the BME280/BMP280 sensor based on the [existing v1 usermod](https://github.com/Aircoookie/WLED/blob/master/usermods/Wemos_D1_mini%2BWemos32_mini_shield/usermod_bme280.cpp). It is not just a refactor, there are many changes which I made to fit my use case, and I hope they will fit the use cases of others as well! Most notably, this usermod is *just* for the BME280 and does not control a display like in the v1 usermod designed for the WeMos shield.
- Requires libraries `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280)) and `Wire`. Please add these under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
- Data is published over MQTT so make sure you've enabled the MQTT sync interface.
- This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else listening on the serial TX pin of your board will get confused by log messages!
To enable, compile with `USERMOD_BME280` defined (i.e. `platformio_override.ini`)
```ini
build_flags =
${common.build_flags_esp8266}
-D USERMOD_BME280
```
or define `USERMOD_BME280` in `my_config.h`
```c++
#define USERMOD_BME280
```
Changes include:
- Adjustable measure intervals
- Temperature and pressure have separate intervals due to pressure not frequently changing at any constant altitude
- Adjustment of number of decimal places in published sensor values
- Separate adjustment for temperature, humidity and pressure values
- Values are rounded to the specified number of decimal places
- Pressure measured in units of hPa instead of Pa
- Calculation of heat index (apparent temperature) and dew point
- These, along with humidity measurements, are disabled if the sensor is a BMP280
- 16x oversampling of sensor during measurement
- Values are only published if they are different from the previous value
- Values are published on startup (continually until the MQTT broker acknowledges a successful publication)
Adjustments are made through preprocessor definitions at the start of the class definition.
MQTT topics are as follows:
Measurement type | MQTT topic
--- | ---
Temperature | `<deviceTopic>/temperature`
Humidity | `<deviceTopic>/humidity`
Pressure | `<deviceTopic>/pressure`
Heat index | `<deviceTopic>/heat_index`
Dew point | `<deviceTopic>/dew_point`

View File

@ -0,0 +1,212 @@
#pragma once
#include "wled.h"
#include <Arduino.h>
#include <Wire.h>
#include <BME280I2C.h> // BME280 sensor
#include <EnvironmentCalculations.h> // BME280 extended measurements
class UsermodBME280 : public Usermod
{
private:
// User-defined configuration
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit
#define TemperatureDecimals 1 // Number of decimal places in published temperaure values
#define HumidityDecimals 0 // Number of decimal places in published humidity values
#define PressureDecimals 2 // Number of decimal places in published pressure values
#define TemperatureInterval 5 // Interval to measure temperature (and humidity, dew point if available) in seconds
#define PressureInterval 300 // Interval to measure pressure in seconds
// Sanity checks
#if !defined(TemperatureDecimals) || TemperatureDecimals < 0
#define TemperatureDecimals 0
#endif
#if !defined(HumidityDecimals) || HumidityDecimals < 0
#define HumidityDecimals 0
#endif
#if !defined(PressureDecimals) || PressureDecimals < 0
#define PressureDecimals 0
#endif
#if !defined(TemperatureInterval) || TemperatureInterval < 0
#define TemperatureInterval 1
#endif
#if !defined(PressureInterval) || PressureInterval < 0
#define PressureInterval TemperatureInterval
#endif
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
uint8_t SCL_PIN = 22;
uint8_t SDA_PIN = 21;
#else // ESP8266 boards
uint8_t SCL_PIN = 5;
uint8_t SDA_PIN = 4;
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
#endif
// BME280 sensor settings
BME280I2C::Settings settings{
BME280::OSR_X16, // Temperature oversampling x16
BME280::OSR_X16, // Humidity oversampling x16
BME280::OSR_X16, // Pressure oversampling x16
// Defaults
BME280::Mode_Forced,
BME280::StandbyTime_1000ms,
BME280::Filter_Off,
BME280::SpiEnable_False,
BME280I2C::I2CAddr_0x76 // I2C address. I2C specific. Default 0x76
};
BME280I2C bme{settings};
uint8_t SensorType;
// Measurement timers
long timer;
long lastTemperatureMeasure = 0;
long lastPressureMeasure = 0;
// Current sensor values
float SensorTemperature;
float SensorHumidity;
float SensorHeatIndex;
float SensorDewPoint;
float SensorPressure;
// Track previous sensor values
float lastTemperature;
float lastHumidity;
float lastHeatIndex;
float lastDewPoint;
float lastPressure;
// Store packet IDs of MQTT publications
uint16_t mqttTemperaturePub = 0;
uint16_t mqttPressurePub = 0;
void UpdateBME280Data(int SensorType)
{
float _temperature, _humidity, _pressure;
#ifdef Celsius
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius);
#else
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Fahrenheit);
#endif
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
SensorTemperature = _temperature;
SensorHumidity = _humidity;
SensorPressure = _pressure;
if (SensorType == 1)
{
SensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
SensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
}
}
public:
void setup()
{
Wire.begin(SDA_PIN, SCL_PIN);
if (!bme.begin())
{
SensorType = 0;
Serial.println("Could not find BME280I2C sensor!");
}
else
{
switch (bme.chipModel())
{
case BME280::ChipModel_BME280:
SensorType = 1;
Serial.println("Found BME280 sensor! Success.");
break;
case BME280::ChipModel_BMP280:
SensorType = 2;
Serial.println("Found BMP280 sensor! No Humidity available.");
break;
default:
SensorType = 0;
Serial.println("Found UNKNOWN sensor! Error!");
}
}
}
void loop()
{
// BME280 sensor MQTT publishing
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
if (SensorType != 0 && mqtt != nullptr)
{
// Timer to fetch new temperature, humidity and pressure data at intervals
timer = millis();
if (timer - lastTemperatureMeasure >= TemperatureInterval * 1000 || mqttTemperaturePub == 0)
{
lastTemperatureMeasure = timer;
UpdateBME280Data(SensorType);
float Temperature = roundf(SensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
float Humidity, HeatIndex, DewPoint;
// If temperature has changed since last measure, create string populated with device topic
// from the UI and values read from sensor, then publish to broker
if (Temperature != lastTemperature)
{
String topic = String(mqttDeviceTopic) + "/temperature";
mqttTemperaturePub = mqtt->publish(topic.c_str(), 0, false, String(Temperature, TemperatureDecimals).c_str());
}
lastTemperature = Temperature; // Update last sensor temperature for next loop
if (SensorType == 1) // Only if sensor is a BME280
{
Humidity = roundf(SensorHumidity * pow(10, HumidityDecimals)) / pow(10, HumidityDecimals);
HeatIndex = roundf(SensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
DewPoint = roundf(SensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
if (Humidity != lastHumidity)
{
String topic = String(mqttDeviceTopic) + "/humidity";
mqtt->publish(topic.c_str(), 0, false, String(Humidity, HumidityDecimals).c_str());
}
if (HeatIndex != lastHeatIndex)
{
String topic = String(mqttDeviceTopic) + "/heat_index";
mqtt->publish(topic.c_str(), 0, false, String(HeatIndex, TemperatureDecimals).c_str());
}
if (DewPoint != lastDewPoint)
{
String topic = String(mqttDeviceTopic) + "/dew_point";
mqtt->publish(topic.c_str(), 0, false, String(DewPoint, TemperatureDecimals).c_str());
}
lastHumidity = Humidity;
lastHeatIndex = HeatIndex;
lastDewPoint = DewPoint;
}
}
if (timer - lastPressureMeasure >= PressureInterval * 1000 || mqttPressurePub == 0)
{
lastPressureMeasure = timer;
float Pressure = roundf(SensorPressure * pow(10, PressureDecimals)) / pow(10, PressureDecimals);
if (Pressure != lastPressure)
{
String topic = String(mqttDeviceTopic) + "/pressure";
mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(Pressure, PressureDecimals).c_str());
}
lastPressure = Pressure;
}
}
}
};

View File

@ -5,11 +5,13 @@
#include <DallasTemperature.h> //DS18B20
//Pin defaults for QuinLed Dig-Uno
#ifndef TEMPERATURE_PIN
#ifdef ARDUINO_ARCH_ESP32
#define TEMPERATURE_PIN 18
#else //ESP8266 boards
#define TEMPERATURE_PIN 14
#endif
#endif
// the frequency to check temperature, 1 minute
#ifndef USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL
@ -58,6 +60,7 @@ class UsermodTemperature : public Usermod {
}
void getTemperature() {
if (strip.isUpdating()) return;
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
temperature = sensor.getTempC(sensorDeviceAddress);
#else
@ -80,30 +83,28 @@ class UsermodTemperature : public Usermod {
disabled = !sensor.getAddress(sensorDeviceAddress, 0);
if (!disabled) {
DEBUG_PRINTLN("Dallas Temperature found");
DEBUG_PRINTLN(F("Dallas Temperature found"));
// set the resolution for this specific device
sensor.setResolution(sensorDeviceAddress, 9, true);
// do not block waiting for reading
sensor.setWaitForConversion(false);
sensor.setWaitForConversion(false);
// allocate pin & prevent other use
if (!pinManager.allocatePin(TEMPERATURE_PIN,false))
disabled = true;
} else {
DEBUG_PRINTLN("Dallas Temperature not found");
DEBUG_PRINTLN(F("Dallas Temperature not found"));
}
}
void loop() {
if (disabled) {
return;
}
if (disabled || strip.isUpdating()) return;
unsigned long now = millis();
// check to see if we are due for taking a measurement
// lastMeasurement will not be updated until the conversion
// is complete the the reading is finished
if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL)
{
return;
}
if (now - lastMeasurement < USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL) return;
// we are due for a measurement, if we are not already waiting
// for a conversion to complete, then make a new request for temps
@ -125,7 +126,7 @@ class UsermodTemperature : public Usermod {
// dont publish super low temperature as the graph will get messed up
// the DallasTemperature library returns -127C or -196.6F when problem
// reading the sensor
strcat(subuf, "/temperature");
strcat_P(subuf, PSTR("/temperature"));
mqtt->publish(subuf, 0, true, String(temperature).c_str());
} else {
// publish something else to indicate status?
@ -136,34 +137,32 @@ class UsermodTemperature : public Usermod {
void addToJsonInfo(JsonObject& root) {
// dont add temperature to info if we are disabled
if (disabled) {
return;
}
if (disabled) return;
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonObject user = root[F("u")];
if (user.isNull()) user = root.createNestedObject(F("u"));
JsonArray temp = user.createNestedArray("Temperature");
JsonArray temp = user.createNestedArray(F("Temperature"));
if (!getTemperatureComplete) {
// if we haven't read the sensor yet, let the user know
// that we are still waiting for the first measurement
temp.add((USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT - millis()) / 1000);
temp.add(" sec until read");
temp.add(F(" sec until read"));
return;
}
if (temperature <= -100) {
temp.add(0);
temp.add(" Sensor Error!");
temp.add(F(" Sensor Error!"));
return;
}
temp.add(temperature);
#ifdef USERMOD_DALLASTEMPERATURE_CELSIUS
temp.add("°C");
temp.add(F("°C"));
#else
temp.add("°F");
temp.add(F("°F"));
#endif
}

View File

@ -1257,7 +1257,7 @@ uint16_t WS2812FX::police_base(uint32_t color1, uint32_t color2, bool all)
for (uint16_t i = idexB; i < idexR; i++) setPixelColor(i, color2);
}
} else { //regular dot-only mode
uint8_t size = 1 + SEGMENT.intensity >> 3;
uint8_t size = 1 + (SEGMENT.intensity >> 3);
if (size > SEGLEN/2) size = 1+ SEGLEN/2;
for (uint8_t i=0; i <= size; i++) {
setPixelColor(idexR+i, color1);

View File

@ -29,12 +29,6 @@
#ifndef WS2812FX_h
#define WS2812FX_h
#ifdef ESP32_MULTISTRIP
#include "../usermods/esp32_multistrip/NpbWrapper.h"
#else
#include "NpbWrapper.h"
#endif
#include "const.h"
#define FASTLED_INTERNAL //remove annoying pragma messages
@ -586,12 +580,11 @@ class WS2812FX {
ablMilliampsMax = 850;
currentMilliamps = 0;
timebase = 0;
bus = new NeoPixelWrapper();
resetSegments();
}
void
init(bool supportWhite, uint16_t countPixels, bool skipFirst),
finalizeInit(bool supportWhite, uint16_t countPixels, bool skipFirst),
service(void),
blur(uint8_t),
fill(uint32_t),
@ -631,6 +624,8 @@ class WS2812FX {
paletteFade = 0,
paletteBlend = 0,
milliampsPerLed = 55,
// getStripType(uint8_t strip=0),
// setStripType(uint8_t type, uint8_t strip=0),
getBrightness(void),
getMode(void),
getSpeed(void),
@ -645,12 +640,19 @@ class WS2812FX {
get_random_wheel_index(uint8_t);
int8_t
// setStripPin(uint8_t strip, int8_t pin),
// getStripPin(uint8_t strip=0),
// setStripPinClk(uint8_t strip, int8_t pin),
// getStripPinClk(uint8_t strip=0),
tristate_square8(uint8_t x, uint8_t pulsewidth, uint8_t attdec);
uint16_t
ablMilliampsMax,
currentMilliamps,
triwave16(uint16_t);
// setStripLen(uint8_t strip, uint16_t len),
// getStripLen(uint8_t strip=0),
triwave16(uint16_t),
getFps();
uint32_t
now,
@ -796,8 +798,6 @@ class WS2812FX {
mode_dynamic_smooth(void);
private:
NeoPixelWrapper *bus;
uint32_t crgb_to_col(CRGB fastled);
CRGB col_to_crgb(uint32_t);
CRGBPalette16 currentPalette;
@ -809,11 +809,12 @@ class WS2812FX {
uint16_t _usedSegmentData = 0;
uint16_t _transitionDur = 750;
uint16_t _cumulativeFps = 2;
void load_gradient_palette(uint8_t);
void handle_palette(void);
bool
shouldStartBus = false,
_useRgbw = false,
_skipFirstMode,
_triggered;
@ -861,12 +862,6 @@ class WS2812FX {
uint32_t _colors_t[3];
uint8_t _bri_t;
#ifdef WLED_USE_ANALOG_LEDS
uint32_t _analogLastShow = 0;
RgbwColor _analogLastColor = 0;
uint8_t _analogLastBri = 0;
#endif
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element

View File

@ -47,7 +47,8 @@
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25]
*/
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
//do not call this method from system context (network callback)
void WS2812FX::finalizeInit(bool supportWhite, uint16_t countPixels, bool skipFirst)
{
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
RESET_RUNTIME;
@ -55,21 +56,35 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
_length = countPixels;
_skipFirstMode = skipFirst;
uint8_t ty = 1;
if (supportWhite) ty = 2;
_lengthRaw = _length;
if (_skipFirstMode) {
_lengthRaw += LED_SKIP_AMOUNT;
}
//if busses failed to load, add default (FS issue...)
if (busses.getNumBusses() == 0) {
uint8_t defPin[] = {LEDPIN};
BusConfig defCfg = BusConfig(TYPE_WS2812_RGB, defPin, 0, _lengthRaw, COL_ORDER_GRB);
busses.add(defCfg);
}
deserializeMap();
bus->Begin((NeoPixelType)ty, _lengthRaw);
_segments[0].start = 0;
_segments[0].stop = _length;
setBrightness(_brightness);
#ifdef ESP8266
for (uint8_t i = 0; i < busses.getNumBusses(); i++) {
Bus* b = busses.getBus(i);
if ((!IS_DIGITAL(b->getType()) || IS_2PIN(b->getType()))) continue;
uint8_t pins[5];
b->getPins(pins);
BusDigital* bd = static_cast<BusDigital*>(b);
if (pins[0] == 3) bd->reinit();
}
#endif
}
void WS2812FX::service() {
@ -168,19 +183,17 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
}
}
RgbwColor col;
col.R = r; col.G = g; col.B = b; col.W = w;
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
if (SEGLEN) {//from segment
//color_blend(getpixel, col, _bri_t); (pseudocode for future blending of segments)
if (_bri_t < 255) {
col.R = scale8(col.R, _bri_t);
col.G = scale8(col.G, _bri_t);
col.B = scale8(col.B, _bri_t);
col.W = scale8(col.W, _bri_t);
r = scale8(r, _bri_t);
g = scale8(g, _bri_t);
b = scale8(b, _bri_t);
w = scale8(w, _bri_t);
}
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
bool reversed = reverseMode ^ IS_REVERSE;
@ -192,12 +205,12 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
if (reverseMode) indexSetRev = REV(indexSet);
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) {
bus->SetPixelColor(indexSet + skip, col);
busses.setPixelColor(indexSet + skip, col);
if (IS_MIRROR) { //set the corresponding mirrored pixel
if (reverseMode) {
bus->SetPixelColor(REV(SEGMENT.start) - indexSet + skip + REV(SEGMENT.stop) + 1, col);
busses.setPixelColor(REV(SEGMENT.start) - indexSet + skip + REV(SEGMENT.stop) + 1, col);
} else {
bus->SetPixelColor(SEGMENT.stop - indexSet + skip + SEGMENT.start - 1, col);
busses.setPixelColor(SEGMENT.stop - indexSet + skip + SEGMENT.start - 1, col);
}
}
}
@ -205,11 +218,13 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
} else { //live data, etc.
if (reverseMode) i = REV(i);
if (i < customMappingSize) i = customMappingTable[i];
bus->SetPixelColor(i + skip, col);
uint32_t col = ((w << 24) | (r << 16) | (g << 8) | (b));
busses.setPixelColor(i + skip, col);
}
if (skip && i == 0) {
for (uint16_t j = 0; j < skip; j++) {
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
busses.setPixelColor(j, BLACK);
}
}
}
@ -260,7 +275,7 @@ void WS2812FX::show(void) {
for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED
{
RgbwColor c = bus->GetPixelColorRaw(i);
RgbwColor c = busses.getPixelColor(i);
if(useWackyWS2815PowerModel)
{
@ -289,25 +304,30 @@ void WS2812FX::show(void) {
uint16_t scaleI = scale * 255;
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
uint8_t newBri = scale8(_brightness, scaleB);
bus->SetBrightness(newBri);
busses.setBrightness(newBri);
currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
} else
{
currentMilliamps = powerSum / puPerMilliamp;
bus->SetBrightness(_brightness);
busses.setBrightness(_brightness);
}
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
currentMilliamps += _length; //add standby power back to estimate
} else {
currentMilliamps = 0;
bus->SetBrightness(_brightness);
busses.setBrightness(_brightness);
}
// some buses send asynchronously and this method will return before
// all of the data has been sent.
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
bus->Show();
_lastShow = millis();
busses.show();
unsigned long now = millis();
unsigned long diff = now - _lastShow;
uint16_t fpsCurr = 200;
if (diff > 0) fpsCurr = 1000 / diff;
_cumulativeFps = (3 * _cumulativeFps + fpsCurr) >> 2;
_lastShow = now;
}
/**
@ -315,7 +335,16 @@ void WS2812FX::show(void) {
* On some hardware (ESP32), strip updates are done asynchronously.
*/
bool WS2812FX::isUpdating() {
return !bus->CanShow();
return !busses.canAllShow();
}
/**
* Returns the refresh rate of the LED strip. Useful for finding out whether a given setup is fast enough.
* Only updates on show() or is set to 0 fps if last show is more than 2 secs ago, so accurary varies
*/
uint16_t WS2812FX::getFps() {
if (millis() - _lastShow > 2000) return 0;
return _cumulativeFps +1;
}
/**
@ -417,17 +446,6 @@ void WS2812FX::setBrightness(uint8_t b) {
{
_segments[i].setOption(SEG_OPTION_FREEZE, false);
}
#if LEDPIN == LED_BUILTIN
shouldStartBus = true;
#endif
} else {
#if LEDPIN == LED_BUILTIN
if (shouldStartBus) {
shouldStartBus = false;
const uint8_t ty = _useRgbw ? 2 : 1;
bus->Begin((NeoPixelType)ty, _lengthRaw);
}
#endif
}
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
}
@ -485,7 +503,7 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
if (i >= _lengthRaw) return 0;
return bus->GetPixelColorRgbw(i);
return busses.getPixelColor(i);
}
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
@ -505,12 +523,13 @@ uint32_t WS2812FX::getLastShow(void) {
return _lastShow;
}
//TODO these need to be on a per-strip basis
uint8_t WS2812FX::getColorOrder(void) {
return bus->GetColorOrder();
return COL_ORDER_GRB;
}
void WS2812FX::setColorOrder(uint8_t co) {
bus->SetColorOrder(co);
//bus->SetColorOrder(co);
}
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
@ -962,44 +981,6 @@ bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
return true;
}
#ifdef WLED_USE_ANALOG_LEDS
void WS2812FX::setRgbwPwm(void) {
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
if (nowUp - _analogLastShow < MIN_SHOW_DELAY) return;
_analogLastShow = nowUp;
RgbwColor c;
uint32_t col = bus->GetPixelColorRgbw(PWM_INDEX);
c.R = col >> 16; c.G = col >> 8; c.B = col; c.W = col >> 24;
byte b = getBrightness();
if (c == _analogLastColor && b == _analogLastBri) return;
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
#ifdef WLED_USE_5CH_LEDS
if (c.R == 255 && c.G == 255 && c.B == 255 && c.W == 255) {
bus->SetRgbwPwm(0, 0, 0, 0, c.W * b / 255);
} else if (c.R == 127 && c.G == 127 && c.B == 127 && c.W == 255) {
bus->SetRgbwPwm(0, 0, 0, c.W * b / 512, c.W * b / 255);
} else if (c.R == 0 && c.G == 0 && c.B == 0 && c.W == 255) {
bus->SetRgbwPwm(0, 0, 0, c.W * b / 255, 0);
} else if (c.R == 130 && c.G == 90 && c.B == 0 && c.W == 255) {
bus->SetRgbwPwm(0, 0, 0, c.W * b / 255, c.W * b / 512);
} else if (c.R == 255 && c.G == 153 && c.B == 0 && c.W == 255) {
bus->SetRgbwPwm(0, 0, 0, c.W * b / 255, 0);
} else { // not only white colors
bus->SetRgbwPwm(c.R * b / 255, c.G * b / 255, c.B * b / 255, c.W * b / 255);
}
#else
bus->SetRgbwPwm(c.R * b / 255, c.G * b / 255, c.B * b / 255, c.W * b / 255);
#endif
_analogLastColor = c;
_analogLastBri = b;
}
#else
void WS2812FX::setRgbwPwm() {}
#endif
//load custom mapping table from JSON file
void WS2812FX::deserializeMap(void) {

View File

@ -1,439 +0,0 @@
//this code is a modified version of https://github.com/Makuna/NeoPixelBus/issues/103
#ifndef NpbWrapper_h
#define NpbWrapper_h
//PIN CONFIGURATION
#ifndef LEDPIN
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
#endif
//#define USE_APA102 // Uncomment for using APA102 LEDs.
//#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer)
//#define USE_LPD8806 // Uncomment for using LPD8806
//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer)
//#define USE_P9813 // Uncomment for using P9813 LEDs (make sure you have NeoPixelBus v2.5.8 or newer)
//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
//#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white
//#define WLED_USE_BWLT11
//#define WLED_USE_SHOJO_PCB
#ifndef BTNPIN
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#endif
#ifndef TOUCHPIN
//#define TOUCHPIN T0 //touch pin. Behaves the same as button. ESP32 only.
#endif
#ifndef IRPIN
#define IRPIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#endif
#ifndef RLYPIN
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
#endif
#ifndef AUXPIN
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
#endif
#ifndef RLYMDE
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
#endif
//enable color order override for a specific range of the strip
//This can be useful if you want to chain multiple strings with incompatible color order
//#define COLOR_ORDER_OVERRIDE
#define COO_MIN 0
#define COO_MAX 35 //not inclusive, this would set the override for LEDs 0-34
#define COO_ORDER COL_ORDER_GRB
//END CONFIGURATION
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
#ifndef CLKPIN
#define CLKPIN 0
#endif
#ifndef DATAPIN
#define DATAPIN 2
#endif
#if BTNPIN == CLKPIN || BTNPIN == DATAPIN
#undef BTNPIN // Deactivate button pin if it conflicts with one of the APA102 pins.
#endif
#endif
#ifdef WLED_USE_ANALOG_LEDS
//PWM pins - PINs 15,13,12,14 (W2 = 04)are used with H801 Wifi LED Controller
#ifdef WLED_USE_H801
#define RPIN 15 //R pin for analog LED strip
#define GPIN 13 //G pin for analog LED strip
#define BPIN 12 //B pin for analog LED strip
#define WPIN 14 //W pin for analog LED strip
#define W2PIN 04 //W2 pin for analog LED strip
#undef BTNPIN
#undef IRPIN
#define IRPIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#elif defined(WLED_USE_BWLT11)
//PWM pins - to use with BW-LT11
#define RPIN 12 //R pin for analog LED strip
#define GPIN 4 //G pin for analog LED strip
#define BPIN 14 //B pin for analog LED strip
#define WPIN 5 //W pin for analog LED strip
#elif defined(WLED_USE_SHOJO_PCB)
//PWM pins - to use with Shojo PCB (https://www.bastelbunker.de/esp-rgbww-wifi-led-controller-vbs-edition/)
#define RPIN 14 //R pin for analog LED strip
#define GPIN 4 //G pin for analog LED strip
#define BPIN 5 //B pin for analog LED strip
#define WPIN 15 //W pin for analog LED strip
#define W2PIN 12 //W2 pin for analog LED strip
#elif defined(WLED_USE_PLJAKOBS_PCB)
// PWM pins - to use with esp_rgbww_controller from patrickjahns/pljakobs (https://github.com/pljakobs/esp_rgbww_controller)
#define RPIN 12 //R pin for analog LED strip
#define GPIN 13 //G pin for analog LED strip
#define BPIN 14 //B pin for analog LED strip
#define WPIN 4 //W pin for analog LED strip
#define W2PIN 5 //W2 pin for analog LED strip
#undef IRPIN
#else
//Enable override of Pins by using the platformio_override.ini file
//PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
#ifndef RPIN
#define RPIN 5 //R pin for analog LED strip
#endif
#ifndef GPIN
#define GPIN 12 //G pin for analog LED strip
#endif
#ifndef BPIN
#define BPIN 15 //B pin for analog LED strip
#endif
#ifndef WPIN
#define WPIN 13 //W pin for analog LED strip
#endif
#endif
#undef RLYPIN
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs
#endif
//automatically uses the right driver method for each platform
#ifdef ARDUINO_ARCH_ESP32
#ifdef USE_APA102
#define PIXELMETHOD DotStarMethod
#elif defined(USE_WS2801)
#define PIXELMETHOD NeoWs2801Method
#elif defined(USE_LPD8806)
#define PIXELMETHOD Lpd8806Method
#elif defined(USE_TM1814)
#define PIXELMETHOD NeoTm1814Method
#elif defined(USE_P9813)
#define PIXELMETHOD P9813Method
#else
#define PIXELMETHOD NeoEsp32Rmt0Ws2812xMethod
#endif
#else //esp8266
//autoselect the right method depending on strip pin
#ifdef USE_APA102
#define PIXELMETHOD DotStarMethod
#elif defined(USE_WS2801)
#define PIXELMETHOD NeoWs2801Method
#elif defined(USE_LPD8806)
#define PIXELMETHOD Lpd8806Method
#elif defined(USE_TM1814)
#define PIXELMETHOD NeoTm1814Method
#elif defined(USE_P9813)
#define PIXELMETHOD P9813Method
#elif LEDPIN == 2
#define PIXELMETHOD NeoEsp8266Uart1Ws2813Method //if you get an error here, try to change to NeoEsp8266UartWs2813Method or update Neopixelbus
#elif LEDPIN == 3
#define PIXELMETHOD NeoEsp8266Dma800KbpsMethod
#else
#define PIXELMETHOD NeoEsp8266BitBang800KbpsMethod
#pragma message "Software BitBang will be used because of your selected LED pin. This may cause flicker. Use GPIO 2 or 3 for best results."
#endif
#endif
//you can now change the color order in the web settings
#ifdef USE_APA102
#define PIXELFEATURE3 DotStarBgrFeature
#define PIXELFEATURE4 DotStarLbgrFeature
#elif defined(USE_LPD8806)
#define PIXELFEATURE3 Lpd8806GrbFeature
#define PIXELFEATURE4 Lpd8806GrbFeature
#elif defined(USE_WS2801)
#define PIXELFEATURE3 NeoRbgFeature
#define PIXELFEATURE4 NeoRbgFeature
#elif defined(USE_TM1814)
#define PIXELFEATURE3 NeoWrgbTm1814Feature
#define PIXELFEATURE4 NeoWrgbTm1814Feature
#elif defined(USE_P9813)
#define PIXELFEATURE3 P9813BgrFeature
#define PIXELFEATURE4 NeoGrbwFeature
#else
#define PIXELFEATURE3 NeoGrbFeature
#define PIXELFEATURE4 NeoGrbwFeature
#endif
#include <NeoPixelBrightnessBus.h>
#include "const.h"
enum NeoPixelType
{
NeoPixelType_None = 0,
NeoPixelType_Grb = 1,
NeoPixelType_Grbw = 2,
NeoPixelType_End = 3
};
class NeoPixelWrapper
{
public:
NeoPixelWrapper() :
// initialize each member to null
_pGrb(NULL),
_pGrbw(NULL),
_type(NeoPixelType_None)
{
}
~NeoPixelWrapper()
{
cleanup();
}
void Begin(NeoPixelType type, uint16_t countPixels)
{
cleanup();
_type = type;
switch (_type)
{
case NeoPixelType_Grb:
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
#else
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
#endif
_pGrb->Begin();
break;
case NeoPixelType_Grbw:
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
#else
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN);
#endif
_pGrbw->Begin();
break;
}
#ifdef WLED_USE_ANALOG_LEDS
#ifdef ARDUINO_ARCH_ESP32
ledcSetup(0, 5000, 8);
ledcAttachPin(RPIN, 0);
ledcSetup(1, 5000, 8);
ledcAttachPin(GPIN, 1);
ledcSetup(2, 5000, 8);
ledcAttachPin(BPIN, 2);
if(_type == NeoPixelType_Grbw)
{
ledcSetup(3, 5000, 8);
ledcAttachPin(WPIN, 3);
#ifdef WLED_USE_5CH_LEDS
ledcSetup(4, 5000, 8);
ledcAttachPin(W2PIN, 4);
#endif
}
#else // ESP8266
//init PWM pins
pinMode(RPIN, OUTPUT);
pinMode(GPIN, OUTPUT);
pinMode(BPIN, OUTPUT);
if(_type == NeoPixelType_Grbw)
{
pinMode(WPIN, OUTPUT);
#ifdef WLED_USE_5CH_LEDS
pinMode(W2PIN, OUTPUT);
#endif
}
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(880); //PWM frequency proven as good for LEDs
#endif
#endif
}
#ifdef WLED_USE_ANALOG_LEDS
void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0)
{
#ifdef ARDUINO_ARCH_ESP32
ledcWrite(0, r);
ledcWrite(1, g);
ledcWrite(2, b);
switch (_type) {
case NeoPixelType_Grb: break;
#ifdef WLED_USE_5CH_LEDS
case NeoPixelType_Grbw: ledcWrite(3, w); ledcWrite(4, w2); break;
#else
case NeoPixelType_Grbw: ledcWrite(3, w); break;
#endif
}
#else // ESP8266
analogWrite(RPIN, r);
analogWrite(GPIN, g);
analogWrite(BPIN, b);
switch (_type) {
case NeoPixelType_Grb: break;
#ifdef WLED_USE_5CH_LEDS
case NeoPixelType_Grbw: analogWrite(WPIN, w); analogWrite(W2PIN, w2); break;
#else
case NeoPixelType_Grbw: analogWrite(WPIN, w); break;
#endif
}
#endif
}
#endif
void Show()
{
switch (_type)
{
case NeoPixelType_Grb: _pGrb->Show(); break;
case NeoPixelType_Grbw: _pGrbw->Show(); break;
}
}
/**
* This will return true if enough time has passed since the last time Show() was called.
* This also means that calling Show() will not cause any undue waiting. If the method for
* the defined bus is hardware that sends asynchronously, then call CanShow() will let
* you know if it has finished sending the data from the last Show().
*/
bool CanShow()
{
switch (_type)
{
case NeoPixelType_Grb: return _pGrb->CanShow();
case NeoPixelType_Grbw: return _pGrbw->CanShow();
default: return true;
}
}
void SetPixelColor(uint16_t indexPixel, RgbwColor c)
{
RgbwColor col;
uint8_t co = _colorOrder;
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
//reorder channels to selected order
switch (co)
{
case 0: col.G = c.G; col.R = c.R; col.B = c.B; break; //0 = GRB, default
case 1: col.G = c.R; col.R = c.G; col.B = c.B; break; //1 = RGB, common for WS2811
case 2: col.G = c.B; col.R = c.R; col.B = c.G; break; //2 = BRG
case 3: col.G = c.R; col.R = c.B; col.B = c.G; break; //3 = RBG
case 4: col.G = c.B; col.R = c.G; col.B = c.R; break; //4 = BGR
default: col.G = c.G; col.R = c.B; col.B = c.R; break; //5 = GBR
}
col.W = c.W;
switch (_type) {
case NeoPixelType_Grb: {
_pGrb->SetPixelColor(indexPixel, RgbColor(col.R,col.G,col.B));
}
break;
case NeoPixelType_Grbw: {
#if defined(USE_LPD8806) || defined(USE_WS2801)
_pGrbw->SetPixelColor(indexPixel, RgbColor(col.R,col.G,col.B));
#else
_pGrbw->SetPixelColor(indexPixel, col);
#endif
}
break;
}
}
void SetBrightness(byte b)
{
switch (_type) {
case NeoPixelType_Grb: _pGrb->SetBrightness(b); break;
case NeoPixelType_Grbw:_pGrbw->SetBrightness(b); break;
}
}
void SetColorOrder(byte colorOrder) {
_colorOrder = colorOrder;
}
uint8_t GetColorOrder() {
return _colorOrder;
}
RgbwColor GetPixelColorRaw(uint16_t indexPixel) const
{
switch (_type) {
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
case NeoPixelType_Grbw: return _pGrbw->GetPixelColor(indexPixel); break;
}
return 0;
}
// NOTE: Due to feature differences, some support RGBW but the method name
// here needs to be unique, thus GetPixeColorRgbw
uint32_t GetPixelColorRgbw(uint16_t indexPixel) const
{
RgbwColor col(0,0,0,0);
switch (_type) {
case NeoPixelType_Grb: col = _pGrb->GetPixelColor(indexPixel); break;
case NeoPixelType_Grbw: col = _pGrbw->GetPixelColor(indexPixel); break;
}
uint8_t co = _colorOrder;
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
switch (co)
{
// W G R B
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
}
return 0;
}
uint8_t* GetPixels(void)
{
switch (_type) {
case NeoPixelType_Grb: return _pGrb->Pixels(); break;
case NeoPixelType_Grbw: return _pGrbw->Pixels(); break;
}
return 0;
}
private:
NeoPixelType _type;
// have a member for every possible type
NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>* _pGrb;
NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>* _pGrbw;
byte _colorOrder = 0;
void cleanup()
{
switch (_type) {
case NeoPixelType_Grb: delete _pGrb ; _pGrb = NULL; break;
case NeoPixelType_Grbw: delete _pGrbw; _pGrbw = NULL; break;
}
}
};
#endif

379
wled00/bus_manager.h Normal file
View File

@ -0,0 +1,379 @@
#ifndef BusManager_h
#define BusManager_h
/*
* Class for addressing various light types
*/
#include "const.h"
#include "pin_manager.h"
#include "bus_wrapper.h"
#include <Arduino.h>
//temporary struct for passing bus configuration to bus
struct BusConfig {
uint8_t type = TYPE_WS2812_RGB;
uint16_t count = 1;
uint16_t start = 0;
uint8_t colorOrder = COL_ORDER_GRB;
bool reversed = false;
uint8_t pins[5] = {LEDPIN, 255, 255, 255, 255};
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false) {
type = busType; count = len; start = pstart; colorOrder = pcolorOrder; reversed = rev;
uint8_t nPins = 1;
if (type > 47) nPins = 2;
else if (type > 41 && type < 46) nPins = NUM_PWM_PINS(type);
for (uint8_t i = 0; i < nPins; i++) pins[i] = ppins[i];
}
};
//parent class of BusDigital and BusPwm
class Bus {
public:
Bus(uint8_t type, uint16_t start) {
_type = type;
_start = start;
};
virtual void show() {}
virtual bool canShow() { return true; }
virtual void setPixelColor(uint16_t pix, uint32_t c) {};
virtual void setBrightness(uint8_t b) {};
virtual uint32_t getPixelColor(uint16_t pix) { return 0; };
virtual void cleanup() {};
virtual ~Bus() { //throw the bus under the bus
//Serial.println("Destructor!");
}
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
uint16_t getStart() {
return _start;
}
void setStart(uint16_t start) {
_start = start;
}
virtual uint16_t getLength() {
return 1;
}
virtual void setColorOrder() {}
virtual uint8_t getColorOrder() {
return COL_ORDER_RGB;
}
uint8_t getType() {
return _type;
}
bool isOk() {
return _valid;
}
bool reversed = false;
protected:
uint8_t _type = TYPE_NONE;
uint8_t _bri = 255;
uint16_t _start = 0;
bool _valid = false;
};
class BusDigital : public Bus {
public:
BusDigital(BusConfig &bc, uint8_t nr) : Bus(bc.type, bc.start) {
if (!IS_DIGITAL(bc.type) || !bc.count) return;
_pins[0] = bc.pins[0];
if (!pinManager.allocatePin(_pins[0])) return;
if (IS_2PIN(bc.type)) {
_pins[1] = bc.pins[1];
if (!pinManager.allocatePin(_pins[1])) {
cleanup(); return;
}
}
_len = bc.count;
reversed = bc.reversed;
_iType = PolyBus::getI(bc.type, _pins, nr);
if (_iType == I_NONE) return;
_busPtr = PolyBus::create(_iType, _pins, _len);
_valid = (_busPtr != nullptr);
_colorOrder = bc.colorOrder;
//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);
};
void show() {
PolyBus::show(_busPtr, _iType);
}
bool canShow() {
return PolyBus::canShow(_busPtr, _iType);
}
void setBrightness(uint8_t b) {
//Fix for turning off onboard LED breaking bus
#ifdef LED_BUILTIN
if (_bri == 0 && b > 0) {
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
}
#endif
_bri = b;
PolyBus::setBrightness(_busPtr, _iType, b);
}
void setPixelColor(uint16_t pix, uint32_t c) {
if (reversed) pix = _len - pix -1;
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrder);
}
uint32_t getPixelColor(uint16_t pix) {
if (reversed) pix = _len - pix -1;
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrder);
}
uint8_t getColorOrder() {
return _colorOrder;
}
uint16_t getLength() {
return _len;
}
uint8_t getPins(uint8_t* pinArray) {
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void setColorOrder(uint8_t colorOrder) {
if (colorOrder > 5) return;
_colorOrder = colorOrder;
}
void reinit() {
PolyBus::begin(_busPtr, _iType, _pins);
}
void cleanup() {
//Serial.println("Digital Cleanup");
PolyBus::cleanup(_busPtr, _iType);
_iType = I_NONE;
_valid = false;
_busPtr = nullptr;
pinManager.deallocatePin(_pins[0]);
pinManager.deallocatePin(_pins[1]);
}
~BusDigital() {
cleanup();
}
private:
uint8_t _colorOrder = COL_ORDER_GRB;
uint8_t _pins[2] = {255, 255};
uint8_t _iType = I_NONE;
uint16_t _len = 0;
void * _busPtr = nullptr;
};
class BusPwm : public Bus {
public:
BusPwm(BusConfig &bc) : Bus(bc.type, bc.start) {
if (!IS_PWM(bc.type)) return;
uint8_t numPins = NUM_PWM_PINS(bc.type);
#ifdef ESP8266
analogWriteRange(255); //same range as one RGB channel
analogWriteFreq(WLED_PWM_FREQ_ESP8266);
#else
_ledcStart = pinManager.allocateLedc(numPins);
if (_ledcStart == 255) { //no more free LEDC channels
deallocatePins(); return;
}
#endif
for (uint8_t i = 0; i < numPins; i++) {
_pins[i] = bc.pins[i];
if (!pinManager.allocatePin(_pins[i])) {
deallocatePins(); return;
}
#ifdef ESP8266
pinMode(_pins[i], OUTPUT);
#else
ledcSetup(_ledcStart + i, WLED_PWM_FREQ_ESP32, 8);
ledcAttachPin(_pins[i], _ledcStart + i);
#endif
}
_valid = true;
};
void setPixelColor(uint16_t pix, uint32_t c) {
if (pix != 0 || !_valid) return; //only react to first pixel
uint8_t r = c >> 16;
uint8_t g = c >> 8;
uint8_t b = c ;
uint8_t w = c >> 24;
switch (_type) {
case TYPE_ANALOG_1CH: //one channel (white), use highest RGBW value
_data[0] = max(r, max(g, max(b, w))); break;
case TYPE_ANALOG_2CH: //warm white + cold white, we'll need some nice handling here, for now just R+G channels
case TYPE_ANALOG_3CH: //standard dumb RGB
case TYPE_ANALOG_4CH: //RGBW
case TYPE_ANALOG_5CH: //we'll want the white handling from 2CH here + RGB
_data[0] = r; _data[1] = g; _data[2] = b; _data[3] = w; _data[4] = 0; break;
default: return;
}
}
//does no index check
uint32_t getPixelColor(uint16_t pix) {
return ((_data[3] << 24) | (_data[0] << 16) | (_data[1] << 8) | (_data[2]));
}
void show() {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
uint8_t scaled = (_data[i] * _bri) / 255;
#ifdef ESP8266
analogWrite(_pins[i], scaled);
#else
ledcWrite(_ledcStart + i, scaled);
#endif
}
}
void setBrightness(uint8_t b) {
_bri = b;
}
uint8_t getPins(uint8_t* pinArray) {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
return numPins;
}
void cleanup() {
deallocatePins();
}
private:
uint8_t _pins[5] = {255, 255, 255, 255, 255};
uint8_t _data[5] = {255, 255, 255, 255, 255};
#ifdef ARDUINO_ARCH_ESP32
uint8_t _ledcStart = 255;
#endif
void deallocatePins() {
uint8_t numPins = NUM_PWM_PINS(_type);
for (uint8_t i = 0; i < numPins; i++) {
if (!pinManager.isPinOk(_pins[i])) continue;
#ifdef ESP8266
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
#else
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
#endif
pinManager.deallocatePin(_pins[i]);
}
#ifdef ARDUINO_ARCH_ESP32
pinManager.deallocateLedc(_ledcStart, numPins);
#endif
}
};
class BusManager {
public:
BusManager() {
};
int add(BusConfig &bc) {
if (numBusses >= WLED_MAX_BUSSES) return -1;
if (IS_DIGITAL(bc.type)) {
busses[numBusses] = new BusDigital(bc, numBusses);
} else {
busses[numBusses] = new BusPwm(bc);
}
numBusses++;
return numBusses -1;
}
//do not call this method from system context (network callback)
void removeAll() {
//Serial.println("Removing all.");
//prevents crashes due to deleting busses while in use.
while (!canAllShow()) yield();
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
numBusses = 0;
}
//void remove(uint8_t id);
void show() {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->show();
}
}
void setPixelColor(uint16_t pix, uint32_t c) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
busses[i]->setPixelColor(pix - bstart, c);
}
}
void setBrightness(uint8_t b) {
for (uint8_t i = 0; i < numBusses; i++) {
busses[i]->setBrightness(b);
}
}
uint32_t getPixelColor(uint16_t pix) {
for (uint8_t i = 0; i < numBusses; i++) {
Bus* b = busses[i];
uint16_t bstart = b->getStart();
if (pix < bstart || pix >= bstart + b->getLength()) continue;
return b->getPixelColor(pix - bstart);
}
return 0;
}
bool canAllShow() {
for (uint8_t i = 0; i < numBusses; i++) {
if (!busses[i]->canShow()) return false;
}
return true;
}
Bus* getBus(uint8_t busNr) {
if (busNr >= numBusses) return nullptr;
return busses[busNr];
}
uint8_t getNumBusses() {
return numBusses;
}
static bool isRgbw(uint8_t type) {
if (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true;
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true;
return false;
}
private:
uint8_t numBusses = 0;
Bus* busses[WLED_MAX_BUSSES];
};
#endif

882
wled00/bus_wrapper.h Normal file
View File

@ -0,0 +1,882 @@
#ifndef BusWrapper_h
#define BusWrapper_h
#include "NeoPixelBrightnessBus.h"
//Hardware SPI Pins
#define P_8266_HS_MOSI 13
#define P_8266_HS_CLK 14
#define P_32_HS_MOSI 13
#define P_32_HS_CLK 14
#define P_32_VS_MOSI 23
#define P_32_VS_CLK 18
//The dirty list of possible bus types. Quite a lot...
#define I_NONE 0
//ESP8266 RGB
#define I_8266_U0_NEO_3 1
#define I_8266_U1_NEO_3 2
#define I_8266_DM_NEO_3 3
#define I_8266_BB_NEO_3 4
//RGBW
#define I_8266_U0_NEO_4 5
#define I_8266_U1_NEO_4 6
#define I_8266_DM_NEO_4 7
#define I_8266_BB_NEO_4 8
//400Kbps
#define I_8266_U0_400_3 9
#define I_8266_U1_400_3 10
#define I_8266_DM_400_3 11
#define I_8266_BB_400_3 12
//TM1418 (RGBW)
#define I_8266_U0_TM1_4 13
#define I_8266_U1_TM1_4 14
#define I_8266_DM_TM1_4 15
#define I_8266_BB_TM1_4 16
/*** ESP32 Neopixel methods ***/
//RGB
#define I_32_R0_NEO_3 17
#define I_32_R1_NEO_3 18
#define I_32_R2_NEO_3 19
#define I_32_R3_NEO_3 20
#define I_32_R4_NEO_3 21
#define I_32_R5_NEO_3 22
#define I_32_R6_NEO_3 23
#define I_32_R7_NEO_3 24
#define I_32_I0_NEO_3 25
#define I_32_I1_NEO_3 26
//RGBW
#define I_32_R0_NEO_4 27
#define I_32_R1_NEO_4 28
#define I_32_R2_NEO_4 29
#define I_32_R3_NEO_4 30
#define I_32_R4_NEO_4 31
#define I_32_R5_NEO_4 32
#define I_32_R6_NEO_4 33
#define I_32_R7_NEO_4 34
#define I_32_I0_NEO_4 35
#define I_32_I1_NEO_4 36
//400Kbps
#define I_32_R0_400_3 37
#define I_32_R1_400_3 38
#define I_32_R2_400_3 39
#define I_32_R3_400_3 40
#define I_32_R4_400_3 41
#define I_32_R5_400_3 42
#define I_32_R6_400_3 43
#define I_32_R7_400_3 44
#define I_32_I0_400_3 45
#define I_32_I1_400_3 46
//TM1418 (RGBW)
#define I_32_R0_TM1_4 47
#define I_32_R1_TM1_4 48
#define I_32_R2_TM1_4 49
#define I_32_R3_TM1_4 50
#define I_32_R4_TM1_4 51
#define I_32_R5_TM1_4 52
#define I_32_R6_TM1_4 53
#define I_32_R7_TM1_4 54
#define I_32_I0_TM1_4 55
#define I_32_I1_TM1_4 56
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
//APA102
#define I_HS_DOT_3 57 //hardware SPI
#define I_SS_DOT_3 58 //soft SPI
//LPD8806
#define I_HS_LPD_3 59
#define I_SS_LPD_3 60
//WS2801
#define I_HS_WS1_3 61
#define I_SS_WS1_3 62
//P9813
#define I_HS_P98_3 63
#define I_SS_P98_3 64
/*** ESP8266 Neopixel methods ***/
#ifdef ESP8266
//RGB
#define B_8266_U0_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart0Ws2813Method> //3 chan, esp8266, gpio1
#define B_8266_U1_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart1Ws2813Method> //3 chan, esp8266, gpio2
#define B_8266_DM_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Dma800KbpsMethod> //3 chan, esp8266, gpio3
#define B_8266_BB_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod> //3 chan, esp8266, bb (any pin but 16)
//RGBW
#define B_8266_U0_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266Uart0Ws2813Method> //4 chan, esp8266, gpio1
#define B_8266_U1_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266Uart1Ws2813Method> //4 chan, esp8266, gpio2
#define B_8266_DM_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266Dma800KbpsMethod> //4 chan, esp8266, gpio3
#define B_8266_BB_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266BitBang800KbpsMethod> //4 chan, esp8266, bb (any pin)
//400Kbps
#define B_8266_U0_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart0400KbpsMethod> //3 chan, esp8266, gpio1
#define B_8266_U1_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart1400KbpsMethod> //3 chan, esp8266, gpio2
#define B_8266_DM_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Dma400KbpsMethod> //3 chan, esp8266, gpio3
#define B_8266_BB_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266BitBang400KbpsMethod> //3 chan, esp8266, bb (any pin)
//TM1418 (RGBW)
#define B_8266_U0_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266Uart0Tm1814Method>
#define B_8266_U1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266Uart1Tm1814Method>
#define B_8266_DM_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266DmaTm1814Method>
#define B_8266_BB_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp8266BitBangTm1814Method>
#endif
/*** ESP32 Neopixel methods ***/
#ifdef ARDUINO_ARCH_ESP32
//RGB
#define B_32_R0_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt0Ws2812xMethod>
#define B_32_R1_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt1Ws2812xMethod>
#define B_32_R2_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt2Ws2812xMethod>
#define B_32_R3_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt3Ws2812xMethod>
#define B_32_R4_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt4Ws2812xMethod>
#define B_32_R5_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt5Ws2812xMethod>
#define B_32_R6_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt6Ws2812xMethod>
#define B_32_R7_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt7Ws2812xMethod>
#define B_32_I0_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s0800KbpsMethod>
#define B_32_I1_NEO_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod>
//RGBW
#define B_32_R0_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt0Ws2812xMethod>
#define B_32_R1_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt1Ws2812xMethod>
#define B_32_R2_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt2Ws2812xMethod>
#define B_32_R3_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt3Ws2812xMethod>
#define B_32_R4_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt4Ws2812xMethod>
#define B_32_R5_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt5Ws2812xMethod>
#define B_32_R6_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt6Ws2812xMethod>
#define B_32_R7_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32Rmt7Ws2812xMethod>
#define B_32_I0_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s0800KbpsMethod>
#define B_32_I1_NEO_4 NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod>
//400Kbps
#define B_32_R0_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt0400KbpsMethod>
#define B_32_R1_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt1400KbpsMethod>
#define B_32_R2_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt2400KbpsMethod>
#define B_32_R3_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt3400KbpsMethod>
#define B_32_R4_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt4400KbpsMethod>
#define B_32_R5_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt5400KbpsMethod>
#define B_32_R6_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt6400KbpsMethod>
#define B_32_R7_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32Rmt7400KbpsMethod>
#define B_32_I0_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s0400KbpsMethod>
#define B_32_I1_400_3 NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod>
//TM1418 (RGBW)
#define B_32_R0_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt0Tm1814Method>
#define B_32_R1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt1Tm1814Method>
#define B_32_R2_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt2Tm1814Method>
#define B_32_R3_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt3Tm1814Method>
#define B_32_R4_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt4Tm1814Method>
#define B_32_R5_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt5Tm1814Method>
#define B_32_R6_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt6Tm1814Method>
#define B_32_R7_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32Rmt7Tm1814Method>
#define B_32_I0_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32I2s0Tm1814Method>
#define B_32_I1_TM1_4 NeoPixelBrightnessBus<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method>
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
#endif
//APA102
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarSpiMethod> //hardware SPI
#define B_SS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarMethod> //soft SPI
//LPD8806
#define B_HS_LPD_3 NeoPixelBrightnessBus<Lpd8806GrbFeature, Lpd8806SpiMethod>
#define B_SS_LPD_3 NeoPixelBrightnessBus<Lpd8806GrbFeature, Lpd8806Method>
//WS2801
#define B_HS_WS1_3 NeoPixelBrightnessBus<NeoRbgFeature, NeoWs2801SpiMethod>
#define B_SS_WS1_3 NeoPixelBrightnessBus<NeoRbgFeature, NeoWs2801Method>
//P9813
#define B_HS_P98_3 NeoPixelBrightnessBus<P9813BgrFeature, P9813SpiMethod>
#define B_SS_P98_3 NeoPixelBrightnessBus<P9813BgrFeature, P9813Method>
//handles pointer type conversion for all possible bus types
class PolyBus {
public:
static void begin(void* busPtr, uint8_t busType, uint8_t* pins) {
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: (static_cast<B_8266_U0_NEO_3*>(busPtr))->Begin(); break;
case I_8266_U1_NEO_3: (static_cast<B_8266_U1_NEO_3*>(busPtr))->Begin(); break;
case I_8266_DM_NEO_3: (static_cast<B_8266_DM_NEO_3*>(busPtr))->Begin(); break;
case I_8266_BB_NEO_3: (static_cast<B_8266_BB_NEO_3*>(busPtr))->Begin(); break;
case I_8266_U0_NEO_4: (static_cast<B_8266_U0_NEO_4*>(busPtr))->Begin(); break;
case I_8266_U1_NEO_4: (static_cast<B_8266_U1_NEO_4*>(busPtr))->Begin(); break;
case I_8266_DM_NEO_4: (static_cast<B_8266_DM_NEO_4*>(busPtr))->Begin(); break;
case I_8266_BB_NEO_4: (static_cast<B_8266_BB_NEO_4*>(busPtr))->Begin(); break;
case I_8266_U0_400_3: (static_cast<B_8266_U0_400_3*>(busPtr))->Begin(); break;
case I_8266_U1_400_3: (static_cast<B_8266_U1_400_3*>(busPtr))->Begin(); break;
case I_8266_DM_400_3: (static_cast<B_8266_DM_400_3*>(busPtr))->Begin(); break;
case I_8266_BB_400_3: (static_cast<B_8266_BB_400_3*>(busPtr))->Begin(); break;
case I_8266_U0_TM1_4: (static_cast<B_8266_U0_TM1_4*>(busPtr))->Begin(); break;
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->Begin(); break;
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->Begin(); break;
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->Begin(); break;
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Begin(); break;
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->Begin(); break;
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->Begin(); break;
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->Begin(); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: (static_cast<B_32_R0_NEO_3*>(busPtr))->Begin(); break;
case I_32_R1_NEO_3: (static_cast<B_32_R1_NEO_3*>(busPtr))->Begin(); break;
case I_32_R2_NEO_3: (static_cast<B_32_R2_NEO_3*>(busPtr))->Begin(); break;
case I_32_R3_NEO_3: (static_cast<B_32_R3_NEO_3*>(busPtr))->Begin(); break;
case I_32_R4_NEO_3: (static_cast<B_32_R4_NEO_3*>(busPtr))->Begin(); break;
case I_32_R5_NEO_3: (static_cast<B_32_R5_NEO_3*>(busPtr))->Begin(); break;
case I_32_R6_NEO_3: (static_cast<B_32_R6_NEO_3*>(busPtr))->Begin(); break;
case I_32_R7_NEO_3: (static_cast<B_32_R7_NEO_3*>(busPtr))->Begin(); break;
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->Begin(); break;
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Begin(); break;
case I_32_R0_NEO_4: (static_cast<B_32_R0_NEO_4*>(busPtr))->Begin(); break;
case I_32_R1_NEO_4: (static_cast<B_32_R1_NEO_4*>(busPtr))->Begin(); break;
case I_32_R2_NEO_4: (static_cast<B_32_R2_NEO_4*>(busPtr))->Begin(); break;
case I_32_R3_NEO_4: (static_cast<B_32_R3_NEO_4*>(busPtr))->Begin(); break;
case I_32_R4_NEO_4: (static_cast<B_32_R4_NEO_4*>(busPtr))->Begin(); break;
case I_32_R5_NEO_4: (static_cast<B_32_R5_NEO_4*>(busPtr))->Begin(); break;
case I_32_R6_NEO_4: (static_cast<B_32_R6_NEO_4*>(busPtr))->Begin(); break;
case I_32_R7_NEO_4: (static_cast<B_32_R7_NEO_4*>(busPtr))->Begin(); break;
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Begin(); break;
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Begin(); break;
case I_32_R0_400_3: (static_cast<B_32_R0_400_3*>(busPtr))->Begin(); break;
case I_32_R1_400_3: (static_cast<B_32_R1_400_3*>(busPtr))->Begin(); break;
case I_32_R2_400_3: (static_cast<B_32_R2_400_3*>(busPtr))->Begin(); break;
case I_32_R3_400_3: (static_cast<B_32_R3_400_3*>(busPtr))->Begin(); break;
case I_32_R4_400_3: (static_cast<B_32_R4_400_3*>(busPtr))->Begin(); break;
case I_32_R5_400_3: (static_cast<B_32_R5_400_3*>(busPtr))->Begin(); break;
case I_32_R6_400_3: (static_cast<B_32_R6_400_3*>(busPtr))->Begin(); break;
case I_32_R7_400_3: (static_cast<B_32_R7_400_3*>(busPtr))->Begin(); break;
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Begin(); break;
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Begin(); break;
case I_32_R0_TM1_4: (static_cast<B_32_R0_TM1_4*>(busPtr))->Begin(); break;
case I_32_R1_TM1_4: (static_cast<B_32_R1_TM1_4*>(busPtr))->Begin(); break;
case I_32_R2_TM1_4: (static_cast<B_32_R2_TM1_4*>(busPtr))->Begin(); break;
case I_32_R3_TM1_4: (static_cast<B_32_R3_TM1_4*>(busPtr))->Begin(); break;
case I_32_R4_TM1_4: (static_cast<B_32_R4_TM1_4*>(busPtr))->Begin(); break;
case I_32_R5_TM1_4: (static_cast<B_32_R5_TM1_4*>(busPtr))->Begin(); break;
case I_32_R6_TM1_4: (static_cast<B_32_R6_TM1_4*>(busPtr))->Begin(); break;
case I_32_R7_TM1_4: (static_cast<B_32_R7_TM1_4*>(busPtr))->Begin(); break;
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->Begin(); break;
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->Begin(); break;
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->Begin(pins[1], -1, pins[0], -1); break;
#endif
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Begin(); break;
case I_SS_LPD_3: (static_cast<B_SS_LPD_3*>(busPtr))->Begin(); break;
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->Begin(); break;
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->Begin(); break;
}
};
static void* create(uint8_t busType, uint8_t* pins, uint16_t len) {
void* busPtr = nullptr;
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: busPtr = new B_8266_U0_NEO_3(len, pins[0]); break;
case I_8266_U1_NEO_3: busPtr = new B_8266_U1_NEO_3(len, pins[0]); break;
case I_8266_DM_NEO_3: busPtr = new B_8266_DM_NEO_3(len, pins[0]); break;
case I_8266_BB_NEO_3: busPtr = new B_8266_BB_NEO_3(len, pins[0]); break;
case I_8266_U0_NEO_4: busPtr = new B_8266_U0_NEO_4(len, pins[0]); break;
case I_8266_U1_NEO_4: busPtr = new B_8266_U1_NEO_4(len, pins[0]); break;
case I_8266_DM_NEO_4: busPtr = new B_8266_DM_NEO_4(len, pins[0]); break;
case I_8266_BB_NEO_4: busPtr = new B_8266_BB_NEO_4(len, pins[0]); break;
case I_8266_U0_400_3: busPtr = new B_8266_U0_400_3(len, pins[0]); break;
case I_8266_U1_400_3: busPtr = new B_8266_U1_400_3(len, pins[0]); break;
case I_8266_DM_400_3: busPtr = new B_8266_DM_400_3(len, pins[0]); break;
case I_8266_BB_400_3: busPtr = new B_8266_BB_400_3(len, pins[0]); break;
case I_8266_U0_TM1_4: busPtr = new B_8266_U0_TM1_4(len, pins[0]); break;
case I_8266_U1_TM1_4: busPtr = new B_8266_U1_TM1_4(len, pins[0]); break;
case I_8266_DM_TM1_4: busPtr = new B_8266_DM_TM1_4(len, pins[0]); break;
case I_8266_BB_TM1_4: busPtr = new B_8266_BB_TM1_4(len, pins[0]); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: busPtr = new B_32_R0_NEO_3(len, pins[0]); break;
case I_32_R1_NEO_3: busPtr = new B_32_R1_NEO_3(len, pins[0]); break;
case I_32_R2_NEO_3: busPtr = new B_32_R2_NEO_3(len, pins[0]); break;
case I_32_R3_NEO_3: busPtr = new B_32_R3_NEO_3(len, pins[0]); break;
case I_32_R4_NEO_3: busPtr = new B_32_R4_NEO_3(len, pins[0]); break;
case I_32_R5_NEO_3: busPtr = new B_32_R5_NEO_3(len, pins[0]); break;
case I_32_R6_NEO_3: busPtr = new B_32_R6_NEO_3(len, pins[0]); break;
case I_32_R7_NEO_3: busPtr = new B_32_R7_NEO_3(len, pins[0]); break;
case I_32_I0_NEO_3: busPtr = new B_32_I0_NEO_3(len, pins[0]); break;
case I_32_I1_NEO_3: busPtr = new B_32_I1_NEO_3(len, pins[0]); break;
case I_32_R0_NEO_4: busPtr = new B_32_R0_NEO_4(len, pins[0]); break;
case I_32_R1_NEO_4: busPtr = new B_32_R1_NEO_4(len, pins[0]); break;
case I_32_R2_NEO_4: busPtr = new B_32_R2_NEO_4(len, pins[0]); break;
case I_32_R3_NEO_4: busPtr = new B_32_R3_NEO_4(len, pins[0]); break;
case I_32_R4_NEO_4: busPtr = new B_32_R4_NEO_4(len, pins[0]); break;
case I_32_R5_NEO_4: busPtr = new B_32_R5_NEO_4(len, pins[0]); break;
case I_32_R6_NEO_4: busPtr = new B_32_R6_NEO_4(len, pins[0]); break;
case I_32_R7_NEO_4: busPtr = new B_32_R7_NEO_4(len, pins[0]); break;
case I_32_I0_NEO_4: busPtr = new B_32_I0_NEO_4(len, pins[0]); break;
case I_32_I1_NEO_4: busPtr = new B_32_I1_NEO_4(len, pins[0]); break;
case I_32_R0_400_3: busPtr = new B_32_R0_400_3(len, pins[0]); break;
case I_32_R1_400_3: busPtr = new B_32_R1_400_3(len, pins[0]); break;
case I_32_R2_400_3: busPtr = new B_32_R2_400_3(len, pins[0]); break;
case I_32_R3_400_3: busPtr = new B_32_R3_400_3(len, pins[0]); break;
case I_32_R4_400_3: busPtr = new B_32_R4_400_3(len, pins[0]); break;
case I_32_R5_400_3: busPtr = new B_32_R5_400_3(len, pins[0]); break;
case I_32_R6_400_3: busPtr = new B_32_R6_400_3(len, pins[0]); break;
case I_32_R7_400_3: busPtr = new B_32_R7_400_3(len, pins[0]); break;
case I_32_I0_400_3: busPtr = new B_32_I0_400_3(len, pins[0]); break;
case I_32_I1_400_3: busPtr = new B_32_I1_400_3(len, pins[0]); break;
case I_32_R0_TM1_4: busPtr = new B_32_R0_TM1_4(len, pins[0]); break;
case I_32_R1_TM1_4: busPtr = new B_32_R1_TM1_4(len, pins[0]); break;
case I_32_R2_TM1_4: busPtr = new B_32_R2_TM1_4(len, pins[0]); break;
case I_32_R3_TM1_4: busPtr = new B_32_R3_TM1_4(len, pins[0]); break;
case I_32_R4_TM1_4: busPtr = new B_32_R4_TM1_4(len, pins[0]); break;
case I_32_R5_TM1_4: busPtr = new B_32_R5_TM1_4(len, pins[0]); break;
case I_32_R6_TM1_4: busPtr = new B_32_R6_TM1_4(len, pins[0]); break;
case I_32_R7_TM1_4: busPtr = new B_32_R7_TM1_4(len, pins[0]); break;
case I_32_I0_TM1_4: busPtr = new B_32_I0_TM1_4(len, pins[0]); break;
case I_32_I1_TM1_4: busPtr = new B_32_I1_TM1_4(len, pins[0]); break;
#endif
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
case I_SS_DOT_3: busPtr = new B_SS_DOT_3(len, pins[1], pins[0]); break;
case I_HS_LPD_3: busPtr = new B_HS_LPD_3(len, pins[1], pins[0]); break;
case I_SS_LPD_3: busPtr = new B_SS_LPD_3(len, pins[1], pins[0]); break;
case I_HS_WS1_3: busPtr = new B_HS_WS1_3(len, pins[1], pins[0]); break;
case I_SS_WS1_3: busPtr = new B_SS_WS1_3(len, pins[1], pins[0]); break;
case I_HS_P98_3: busPtr = new B_HS_P98_3(len, pins[1], pins[0]); break;
case I_SS_P98_3: busPtr = new B_SS_P98_3(len, pins[1], pins[0]); break;
}
begin(busPtr, busType, pins);
return busPtr;
};
static void show(void* busPtr, uint8_t busType) {
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: (static_cast<B_8266_U0_NEO_3*>(busPtr))->Show(); break;
case I_8266_U1_NEO_3: (static_cast<B_8266_U1_NEO_3*>(busPtr))->Show(); break;
case I_8266_DM_NEO_3: (static_cast<B_8266_DM_NEO_3*>(busPtr))->Show(); break;
case I_8266_BB_NEO_3: (static_cast<B_8266_BB_NEO_3*>(busPtr))->Show(); break;
case I_8266_U0_NEO_4: (static_cast<B_8266_U0_NEO_4*>(busPtr))->Show(); break;
case I_8266_U1_NEO_4: (static_cast<B_8266_U1_NEO_4*>(busPtr))->Show(); break;
case I_8266_DM_NEO_4: (static_cast<B_8266_DM_NEO_4*>(busPtr))->Show(); break;
case I_8266_BB_NEO_4: (static_cast<B_8266_BB_NEO_4*>(busPtr))->Show(); break;
case I_8266_U0_400_3: (static_cast<B_8266_U0_400_3*>(busPtr))->Show(); break;
case I_8266_U1_400_3: (static_cast<B_8266_U1_400_3*>(busPtr))->Show(); break;
case I_8266_DM_400_3: (static_cast<B_8266_DM_400_3*>(busPtr))->Show(); break;
case I_8266_BB_400_3: (static_cast<B_8266_BB_400_3*>(busPtr))->Show(); break;
case I_8266_U0_TM1_4: (static_cast<B_8266_U0_TM1_4*>(busPtr))->Show(); break;
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->Show(); break;
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->Show(); break;
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->Show(); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: (static_cast<B_32_R0_NEO_3*>(busPtr))->Show(); break;
case I_32_R1_NEO_3: (static_cast<B_32_R1_NEO_3*>(busPtr))->Show(); break;
case I_32_R2_NEO_3: (static_cast<B_32_R2_NEO_3*>(busPtr))->Show(); break;
case I_32_R3_NEO_3: (static_cast<B_32_R3_NEO_3*>(busPtr))->Show(); break;
case I_32_R4_NEO_3: (static_cast<B_32_R4_NEO_3*>(busPtr))->Show(); break;
case I_32_R5_NEO_3: (static_cast<B_32_R5_NEO_3*>(busPtr))->Show(); break;
case I_32_R6_NEO_3: (static_cast<B_32_R6_NEO_3*>(busPtr))->Show(); break;
case I_32_R7_NEO_3: (static_cast<B_32_R7_NEO_3*>(busPtr))->Show(); break;
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->Show(); break;
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->Show(); break;
case I_32_R0_NEO_4: (static_cast<B_32_R0_NEO_4*>(busPtr))->Show(); break;
case I_32_R1_NEO_4: (static_cast<B_32_R1_NEO_4*>(busPtr))->Show(); break;
case I_32_R2_NEO_4: (static_cast<B_32_R2_NEO_4*>(busPtr))->Show(); break;
case I_32_R3_NEO_4: (static_cast<B_32_R3_NEO_4*>(busPtr))->Show(); break;
case I_32_R4_NEO_4: (static_cast<B_32_R4_NEO_4*>(busPtr))->Show(); break;
case I_32_R5_NEO_4: (static_cast<B_32_R5_NEO_4*>(busPtr))->Show(); break;
case I_32_R6_NEO_4: (static_cast<B_32_R6_NEO_4*>(busPtr))->Show(); break;
case I_32_R7_NEO_4: (static_cast<B_32_R7_NEO_4*>(busPtr))->Show(); break;
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->Show(); break;
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->Show(); break;
case I_32_R0_400_3: (static_cast<B_32_R0_400_3*>(busPtr))->Show(); break;
case I_32_R1_400_3: (static_cast<B_32_R1_400_3*>(busPtr))->Show(); break;
case I_32_R2_400_3: (static_cast<B_32_R2_400_3*>(busPtr))->Show(); break;
case I_32_R3_400_3: (static_cast<B_32_R3_400_3*>(busPtr))->Show(); break;
case I_32_R4_400_3: (static_cast<B_32_R4_400_3*>(busPtr))->Show(); break;
case I_32_R5_400_3: (static_cast<B_32_R5_400_3*>(busPtr))->Show(); break;
case I_32_R6_400_3: (static_cast<B_32_R6_400_3*>(busPtr))->Show(); break;
case I_32_R7_400_3: (static_cast<B_32_R7_400_3*>(busPtr))->Show(); break;
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->Show(); break;
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->Show(); break;
case I_32_R0_TM1_4: (static_cast<B_32_R0_TM1_4*>(busPtr))->Show(); break;
case I_32_R1_TM1_4: (static_cast<B_32_R1_TM1_4*>(busPtr))->Show(); break;
case I_32_R2_TM1_4: (static_cast<B_32_R2_TM1_4*>(busPtr))->Show(); break;
case I_32_R3_TM1_4: (static_cast<B_32_R3_TM1_4*>(busPtr))->Show(); break;
case I_32_R4_TM1_4: (static_cast<B_32_R4_TM1_4*>(busPtr))->Show(); break;
case I_32_R5_TM1_4: (static_cast<B_32_R5_TM1_4*>(busPtr))->Show(); break;
case I_32_R6_TM1_4: (static_cast<B_32_R6_TM1_4*>(busPtr))->Show(); break;
case I_32_R7_TM1_4: (static_cast<B_32_R7_TM1_4*>(busPtr))->Show(); break;
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->Show(); break;
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->Show(); break;
#endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(); break;
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->Show(); break;
case I_SS_LPD_3: (static_cast<B_SS_LPD_3*>(busPtr))->Show(); break;
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->Show(); break;
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->Show(); break;
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->Show(); break;
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->Show(); break;
}
};
static bool canShow(void* busPtr, uint8_t busType) {
switch (busType) {
case I_NONE: return true;
#ifdef ESP8266
case I_8266_U0_NEO_3: return (static_cast<B_8266_U0_NEO_3*>(busPtr))->CanShow(); break;
case I_8266_U1_NEO_3: return (static_cast<B_8266_U1_NEO_3*>(busPtr))->CanShow(); break;
case I_8266_DM_NEO_3: return (static_cast<B_8266_DM_NEO_3*>(busPtr))->CanShow(); break;
case I_8266_BB_NEO_3: return (static_cast<B_8266_BB_NEO_3*>(busPtr))->CanShow(); break;
case I_8266_U0_NEO_4: return (static_cast<B_8266_U0_NEO_4*>(busPtr))->CanShow(); break;
case I_8266_U1_NEO_4: return (static_cast<B_8266_U1_NEO_4*>(busPtr))->CanShow(); break;
case I_8266_DM_NEO_4: return (static_cast<B_8266_DM_NEO_4*>(busPtr))->CanShow(); break;
case I_8266_BB_NEO_4: return (static_cast<B_8266_BB_NEO_4*>(busPtr))->CanShow(); break;
case I_8266_U0_400_3: return (static_cast<B_8266_U0_400_3*>(busPtr))->CanShow(); break;
case I_8266_U1_400_3: return (static_cast<B_8266_U1_400_3*>(busPtr))->CanShow(); break;
case I_8266_DM_400_3: return (static_cast<B_8266_DM_400_3*>(busPtr))->CanShow(); break;
case I_8266_BB_400_3: return (static_cast<B_8266_BB_400_3*>(busPtr))->CanShow(); break;
case I_8266_U0_TM1_4: return (static_cast<B_8266_U0_TM1_4*>(busPtr))->CanShow(); break;
case I_8266_U1_TM1_4: return (static_cast<B_8266_U1_TM1_4*>(busPtr))->CanShow(); break;
case I_8266_DM_TM1_4: return (static_cast<B_8266_DM_TM1_4*>(busPtr))->CanShow(); break;
case I_8266_BB_TM1_4: return (static_cast<B_8266_BB_TM1_4*>(busPtr))->CanShow(); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: return (static_cast<B_32_R0_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R1_NEO_3: return (static_cast<B_32_R1_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R2_NEO_3: return (static_cast<B_32_R2_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R3_NEO_3: return (static_cast<B_32_R3_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R4_NEO_3: return (static_cast<B_32_R4_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R5_NEO_3: return (static_cast<B_32_R5_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R6_NEO_3: return (static_cast<B_32_R6_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R7_NEO_3: return (static_cast<B_32_R7_NEO_3*>(busPtr))->CanShow(); break;
case I_32_I0_NEO_3: return (static_cast<B_32_I0_NEO_3*>(busPtr))->CanShow(); break;
case I_32_I1_NEO_3: return (static_cast<B_32_I1_NEO_3*>(busPtr))->CanShow(); break;
case I_32_R0_NEO_4: return (static_cast<B_32_R0_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R1_NEO_4: return (static_cast<B_32_R1_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R2_NEO_4: return (static_cast<B_32_R2_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R3_NEO_4: return (static_cast<B_32_R3_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R4_NEO_4: return (static_cast<B_32_R4_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R5_NEO_4: return (static_cast<B_32_R5_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R6_NEO_4: return (static_cast<B_32_R6_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R7_NEO_4: return (static_cast<B_32_R7_NEO_4*>(busPtr))->CanShow(); break;
case I_32_I0_NEO_4: return (static_cast<B_32_I0_NEO_4*>(busPtr))->CanShow(); break;
case I_32_I1_NEO_4: return (static_cast<B_32_I1_NEO_4*>(busPtr))->CanShow(); break;
case I_32_R0_400_3: return (static_cast<B_32_R0_400_3*>(busPtr))->CanShow(); break;
case I_32_R1_400_3: return (static_cast<B_32_R1_400_3*>(busPtr))->CanShow(); break;
case I_32_R2_400_3: return (static_cast<B_32_R2_400_3*>(busPtr))->CanShow(); break;
case I_32_R3_400_3: return (static_cast<B_32_R3_400_3*>(busPtr))->CanShow(); break;
case I_32_R4_400_3: return (static_cast<B_32_R4_400_3*>(busPtr))->CanShow(); break;
case I_32_R5_400_3: return (static_cast<B_32_R5_400_3*>(busPtr))->CanShow(); break;
case I_32_R6_400_3: return (static_cast<B_32_R6_400_3*>(busPtr))->CanShow(); break;
case I_32_R7_400_3: return (static_cast<B_32_R7_400_3*>(busPtr))->CanShow(); break;
case I_32_I0_400_3: return (static_cast<B_32_I0_400_3*>(busPtr))->CanShow(); break;
case I_32_I1_400_3: return (static_cast<B_32_I1_400_3*>(busPtr))->CanShow(); break;
case I_32_R0_TM1_4: return (static_cast<B_32_R0_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R1_TM1_4: return (static_cast<B_32_R1_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R2_TM1_4: return (static_cast<B_32_R2_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R3_TM1_4: return (static_cast<B_32_R3_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R4_TM1_4: return (static_cast<B_32_R4_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R5_TM1_4: return (static_cast<B_32_R5_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R6_TM1_4: return (static_cast<B_32_R6_TM1_4*>(busPtr))->CanShow(); break;
case I_32_R7_TM1_4: return (static_cast<B_32_R7_TM1_4*>(busPtr))->CanShow(); break;
case I_32_I0_TM1_4: return (static_cast<B_32_I0_TM1_4*>(busPtr))->CanShow(); break;
case I_32_I1_TM1_4: return (static_cast<B_32_I1_TM1_4*>(busPtr))->CanShow(); break;
#endif
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
case I_HS_LPD_3: return (static_cast<B_HS_LPD_3*>(busPtr))->CanShow(); break;
case I_SS_LPD_3: return (static_cast<B_SS_LPD_3*>(busPtr))->CanShow(); break;
case I_HS_WS1_3: return (static_cast<B_HS_WS1_3*>(busPtr))->CanShow(); break;
case I_SS_WS1_3: return (static_cast<B_SS_WS1_3*>(busPtr))->CanShow(); break;
case I_HS_P98_3: return (static_cast<B_HS_P98_3*>(busPtr))->CanShow(); break;
case I_SS_P98_3: return (static_cast<B_SS_P98_3*>(busPtr))->CanShow(); break;
}
return true;
};
static void setPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint32_t c, uint8_t co) {
uint8_t r = c >> 16;
uint8_t g = c >> 8;
uint8_t b = c >> 0;
uint8_t w = c >> 24;
RgbwColor col;
//TODO make color order override possible on a per-strip basis
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
//reorder channels to selected order
switch (co)
{
case 0: col.G = g; col.R = r; col.B = b; break; //0 = GRB, default
case 1: col.G = r; col.R = g; col.B = b; break; //1 = RGB, common for WS2811
case 2: col.G = b; col.R = r; col.B = g; break; //2 = BRG
case 3: col.G = r; col.R = b; col.B = g; break; //3 = RBG
case 4: col.G = b; col.R = g; col.B = r; break; //4 = BGR
default: col.G = g; col.R = b; col.B = r; break; //5 = GBR
}
col.W = w;
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: (static_cast<B_8266_U0_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_U1_NEO_3: (static_cast<B_8266_U1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_DM_NEO_3: (static_cast<B_8266_DM_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_BB_NEO_3: (static_cast<B_8266_BB_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_U0_NEO_4: (static_cast<B_8266_U0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_U1_NEO_4: (static_cast<B_8266_U1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_DM_NEO_4: (static_cast<B_8266_DM_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_BB_NEO_4: (static_cast<B_8266_BB_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_U0_400_3: (static_cast<B_8266_U0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_U1_400_3: (static_cast<B_8266_U1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_DM_400_3: (static_cast<B_8266_DM_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_BB_400_3: (static_cast<B_8266_BB_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_8266_U0_TM1_4: (static_cast<B_8266_U0_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: (static_cast<B_32_R0_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R1_NEO_3: (static_cast<B_32_R1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R2_NEO_3: (static_cast<B_32_R2_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R3_NEO_3: (static_cast<B_32_R3_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R4_NEO_3: (static_cast<B_32_R4_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R5_NEO_3: (static_cast<B_32_R5_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R6_NEO_3: (static_cast<B_32_R6_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R7_NEO_3: (static_cast<B_32_R7_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R0_NEO_4: (static_cast<B_32_R0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R1_NEO_4: (static_cast<B_32_R1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R2_NEO_4: (static_cast<B_32_R2_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R3_NEO_4: (static_cast<B_32_R3_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R4_NEO_4: (static_cast<B_32_R4_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R5_NEO_4: (static_cast<B_32_R5_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R6_NEO_4: (static_cast<B_32_R6_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R7_NEO_4: (static_cast<B_32_R7_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R0_400_3: (static_cast<B_32_R0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R1_400_3: (static_cast<B_32_R1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R2_400_3: (static_cast<B_32_R2_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R3_400_3: (static_cast<B_32_R3_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R4_400_3: (static_cast<B_32_R4_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R5_400_3: (static_cast<B_32_R5_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R6_400_3: (static_cast<B_32_R6_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R7_400_3: (static_cast<B_32_R7_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_32_R0_TM1_4: (static_cast<B_32_R0_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R1_TM1_4: (static_cast<B_32_R1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R2_TM1_4: (static_cast<B_32_R2_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R3_TM1_4: (static_cast<B_32_R3_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R4_TM1_4: (static_cast<B_32_R4_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R5_TM1_4: (static_cast<B_32_R5_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R6_TM1_4: (static_cast<B_32_R6_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_R7_TM1_4: (static_cast<B_32_R7_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetPixelColor(pix, col); break;
#endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_SS_LPD_3: (static_cast<B_SS_LPD_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->SetPixelColor(pix, RgbColor(col.R,col.G,col.B)); break;
}
};
static void setBrightness(void* busPtr, uint8_t busType, uint8_t b) {
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: (static_cast<B_8266_U0_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_8266_U1_NEO_3: (static_cast<B_8266_U1_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_8266_DM_NEO_3: (static_cast<B_8266_DM_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_8266_BB_NEO_3: (static_cast<B_8266_BB_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_8266_U0_NEO_4: (static_cast<B_8266_U0_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_8266_U1_NEO_4: (static_cast<B_8266_U1_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_8266_DM_NEO_4: (static_cast<B_8266_DM_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_8266_BB_NEO_4: (static_cast<B_8266_BB_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_8266_U0_400_3: (static_cast<B_8266_U0_400_3*>(busPtr))->SetBrightness(b); break;
case I_8266_U1_400_3: (static_cast<B_8266_U1_400_3*>(busPtr))->SetBrightness(b); break;
case I_8266_DM_400_3: (static_cast<B_8266_DM_400_3*>(busPtr))->SetBrightness(b); break;
case I_8266_BB_400_3: (static_cast<B_8266_BB_400_3*>(busPtr))->SetBrightness(b); break;
case I_8266_U0_TM1_4: (static_cast<B_8266_U0_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_8266_U1_TM1_4: (static_cast<B_8266_U1_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_8266_DM_TM1_4: (static_cast<B_8266_DM_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_8266_BB_TM1_4: (static_cast<B_8266_BB_TM1_4*>(busPtr))->SetBrightness(b); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: (static_cast<B_32_R0_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R1_NEO_3: (static_cast<B_32_R1_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R2_NEO_3: (static_cast<B_32_R2_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R3_NEO_3: (static_cast<B_32_R3_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R4_NEO_3: (static_cast<B_32_R4_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R5_NEO_3: (static_cast<B_32_R5_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R6_NEO_3: (static_cast<B_32_R6_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R7_NEO_3: (static_cast<B_32_R7_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_I0_NEO_3: (static_cast<B_32_I0_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_I1_NEO_3: (static_cast<B_32_I1_NEO_3*>(busPtr))->SetBrightness(b); break;
case I_32_R0_NEO_4: (static_cast<B_32_R0_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R1_NEO_4: (static_cast<B_32_R1_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R2_NEO_4: (static_cast<B_32_R2_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R3_NEO_4: (static_cast<B_32_R3_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R4_NEO_4: (static_cast<B_32_R4_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R5_NEO_4: (static_cast<B_32_R5_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R6_NEO_4: (static_cast<B_32_R6_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R7_NEO_4: (static_cast<B_32_R7_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_I0_NEO_4: (static_cast<B_32_I0_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_I1_NEO_4: (static_cast<B_32_I1_NEO_4*>(busPtr))->SetBrightness(b); break;
case I_32_R0_400_3: (static_cast<B_32_R0_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R1_400_3: (static_cast<B_32_R1_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R2_400_3: (static_cast<B_32_R2_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R3_400_3: (static_cast<B_32_R3_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R4_400_3: (static_cast<B_32_R4_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R5_400_3: (static_cast<B_32_R5_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R6_400_3: (static_cast<B_32_R6_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R7_400_3: (static_cast<B_32_R7_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_I0_400_3: (static_cast<B_32_I0_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_I1_400_3: (static_cast<B_32_I1_400_3*>(busPtr))->SetBrightness(b); break;
case I_32_R0_TM1_4: (static_cast<B_32_R0_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R1_TM1_4: (static_cast<B_32_R1_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R2_TM1_4: (static_cast<B_32_R2_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R3_TM1_4: (static_cast<B_32_R3_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R4_TM1_4: (static_cast<B_32_R4_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R5_TM1_4: (static_cast<B_32_R5_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R6_TM1_4: (static_cast<B_32_R6_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_R7_TM1_4: (static_cast<B_32_R7_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_I0_TM1_4: (static_cast<B_32_I0_TM1_4*>(busPtr))->SetBrightness(b); break;
case I_32_I1_TM1_4: (static_cast<B_32_I1_TM1_4*>(busPtr))->SetBrightness(b); break;
#endif
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetBrightness(b); break;
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetBrightness(b); break;
case I_HS_LPD_3: (static_cast<B_HS_LPD_3*>(busPtr))->SetBrightness(b); break;
case I_SS_LPD_3: (static_cast<B_SS_LPD_3*>(busPtr))->SetBrightness(b); break;
case I_HS_WS1_3: (static_cast<B_HS_WS1_3*>(busPtr))->SetBrightness(b); break;
case I_SS_WS1_3: (static_cast<B_SS_WS1_3*>(busPtr))->SetBrightness(b); break;
case I_HS_P98_3: (static_cast<B_HS_P98_3*>(busPtr))->SetBrightness(b); break;
case I_SS_P98_3: (static_cast<B_SS_P98_3*>(busPtr))->SetBrightness(b); break;
}
};
static uint32_t getPixelColor(void* busPtr, uint8_t busType, uint16_t pix, uint8_t co) {
RgbwColor col(0,0,0,0);
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: col = (static_cast<B_8266_U0_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U1_NEO_3: col = (static_cast<B_8266_U1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_DM_NEO_3: col = (static_cast<B_8266_DM_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_BB_NEO_3: col = (static_cast<B_8266_BB_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U0_NEO_4: col = (static_cast<B_8266_U0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U1_NEO_4: col = (static_cast<B_8266_U1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_DM_NEO_4: col = (static_cast<B_8266_DM_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_BB_NEO_4: col = (static_cast<B_8266_BB_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U0_400_3: col = (static_cast<B_8266_U0_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U1_400_3: col = (static_cast<B_8266_U1_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_DM_400_3: col = (static_cast<B_8266_DM_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_BB_400_3: col = (static_cast<B_8266_BB_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U0_TM1_4: col = (static_cast<B_8266_U0_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_U1_TM1_4: col = (static_cast<B_8266_U1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_DM_TM1_4: col = (static_cast<B_8266_DM_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_8266_BB_TM1_4: col = (static_cast<B_8266_BB_TM1_4*>(busPtr))->GetPixelColor(pix); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: col = (static_cast<B_32_R0_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R1_NEO_3: col = (static_cast<B_32_R1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R2_NEO_3: col = (static_cast<B_32_R2_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R3_NEO_3: col = (static_cast<B_32_R3_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R4_NEO_3: col = (static_cast<B_32_R4_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R5_NEO_3: col = (static_cast<B_32_R5_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R6_NEO_3: col = (static_cast<B_32_R6_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R7_NEO_3: col = (static_cast<B_32_R7_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_I0_NEO_3: col = (static_cast<B_32_I0_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_I1_NEO_3: col = (static_cast<B_32_I1_NEO_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R0_NEO_4: col = (static_cast<B_32_R0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R1_NEO_4: col = (static_cast<B_32_R1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R2_NEO_4: col = (static_cast<B_32_R2_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R3_NEO_4: col = (static_cast<B_32_R3_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R4_NEO_4: col = (static_cast<B_32_R4_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R5_NEO_4: col = (static_cast<B_32_R5_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R6_NEO_4: col = (static_cast<B_32_R6_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R7_NEO_4: col = (static_cast<B_32_R7_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_I0_NEO_4: col = (static_cast<B_32_I0_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_I1_NEO_4: col = (static_cast<B_32_I1_NEO_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R0_400_3: col = (static_cast<B_32_R0_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R1_400_3: col = (static_cast<B_32_R1_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R2_400_3: col = (static_cast<B_32_R2_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R3_400_3: col = (static_cast<B_32_R3_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R4_400_3: col = (static_cast<B_32_R4_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R5_400_3: col = (static_cast<B_32_R5_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R6_400_3: col = (static_cast<B_32_R6_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R7_400_3: col = (static_cast<B_32_R7_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_I0_400_3: col = (static_cast<B_32_I0_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_I1_400_3: col = (static_cast<B_32_I1_400_3*>(busPtr))->GetPixelColor(pix); break;
case I_32_R0_TM1_4: col = (static_cast<B_32_R0_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R1_TM1_4: col = (static_cast<B_32_R1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R2_TM1_4: col = (static_cast<B_32_R2_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R3_TM1_4: col = (static_cast<B_32_R3_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R4_TM1_4: col = (static_cast<B_32_R4_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R5_TM1_4: col = (static_cast<B_32_R5_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R6_TM1_4: col = (static_cast<B_32_R6_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_R7_TM1_4: col = (static_cast<B_32_R7_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_I0_TM1_4: col = (static_cast<B_32_I0_TM1_4*>(busPtr))->GetPixelColor(pix); break;
case I_32_I1_TM1_4: col = (static_cast<B_32_I1_TM1_4*>(busPtr))->GetPixelColor(pix); break;
#endif
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
case I_HS_LPD_3: col = (static_cast<B_HS_LPD_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_LPD_3: col = (static_cast<B_SS_LPD_3*>(busPtr))->GetPixelColor(pix); break;
case I_HS_WS1_3: col = (static_cast<B_HS_WS1_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_WS1_3: col = (static_cast<B_SS_WS1_3*>(busPtr))->GetPixelColor(pix); break;
case I_HS_P98_3: col = (static_cast<B_HS_P98_3*>(busPtr))->GetPixelColor(pix); break;
case I_SS_P98_3: col = (static_cast<B_SS_P98_3*>(busPtr))->GetPixelColor(pix); break;
}
#ifdef COLOR_ORDER_OVERRIDE
if (indexPixel >= COO_MIN && indexPixel < COO_MAX) co = COO_ORDER;
#endif
switch (co)
{
// W G R B
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
}
return 0;
}
static void cleanup(void* busPtr, uint8_t busType) {
if (busPtr == nullptr) return;
switch (busType) {
case I_NONE: break;
#ifdef ESP8266
case I_8266_U0_NEO_3: delete (static_cast<B_8266_U0_NEO_3*>(busPtr)); break;
case I_8266_U1_NEO_3: delete (static_cast<B_8266_U1_NEO_3*>(busPtr)); break;
case I_8266_DM_NEO_3: delete (static_cast<B_8266_DM_NEO_3*>(busPtr)); break;
case I_8266_BB_NEO_3: delete (static_cast<B_8266_BB_NEO_3*>(busPtr)); break;
case I_8266_U0_NEO_4: delete (static_cast<B_8266_U0_NEO_4*>(busPtr)); break;
case I_8266_U1_NEO_4: delete (static_cast<B_8266_U1_NEO_4*>(busPtr)); break;
case I_8266_DM_NEO_4: delete (static_cast<B_8266_DM_NEO_4*>(busPtr)); break;
case I_8266_BB_NEO_4: delete (static_cast<B_8266_BB_NEO_4*>(busPtr)); break;
case I_8266_U0_400_3: delete (static_cast<B_8266_U0_400_3*>(busPtr)); break;
case I_8266_U1_400_3: delete (static_cast<B_8266_U1_400_3*>(busPtr)); break;
case I_8266_DM_400_3: delete (static_cast<B_8266_DM_400_3*>(busPtr)); break;
case I_8266_BB_400_3: delete (static_cast<B_8266_BB_400_3*>(busPtr)); break;
case I_8266_U0_TM1_4: delete (static_cast<B_8266_U0_TM1_4*>(busPtr)); break;
case I_8266_U1_TM1_4: delete (static_cast<B_8266_U1_TM1_4*>(busPtr)); break;
case I_8266_DM_TM1_4: delete (static_cast<B_8266_DM_TM1_4*>(busPtr)); break;
case I_8266_BB_TM1_4: delete (static_cast<B_8266_BB_TM1_4*>(busPtr)); break;
#endif
#ifdef ARDUINO_ARCH_ESP32
case I_32_R0_NEO_3: delete (static_cast<B_32_R0_NEO_3*>(busPtr)); break;
case I_32_R1_NEO_3: delete (static_cast<B_32_R1_NEO_3*>(busPtr)); break;
case I_32_R2_NEO_3: delete (static_cast<B_32_R2_NEO_3*>(busPtr)); break;
case I_32_R3_NEO_3: delete (static_cast<B_32_R3_NEO_3*>(busPtr)); break;
case I_32_R4_NEO_3: delete (static_cast<B_32_R4_NEO_3*>(busPtr)); break;
case I_32_R5_NEO_3: delete (static_cast<B_32_R5_NEO_3*>(busPtr)); break;
case I_32_R6_NEO_3: delete (static_cast<B_32_R6_NEO_3*>(busPtr)); break;
case I_32_R7_NEO_3: delete (static_cast<B_32_R7_NEO_3*>(busPtr)); break;
case I_32_I0_NEO_3: delete (static_cast<B_32_I0_NEO_3*>(busPtr)); break;
case I_32_I1_NEO_3: delete (static_cast<B_32_I1_NEO_3*>(busPtr)); break;
case I_32_R0_NEO_4: delete (static_cast<B_32_R0_NEO_4*>(busPtr)); break;
case I_32_R1_NEO_4: delete (static_cast<B_32_R1_NEO_4*>(busPtr)); break;
case I_32_R2_NEO_4: delete (static_cast<B_32_R2_NEO_4*>(busPtr)); break;
case I_32_R3_NEO_4: delete (static_cast<B_32_R3_NEO_4*>(busPtr)); break;
case I_32_R4_NEO_4: delete (static_cast<B_32_R4_NEO_4*>(busPtr)); break;
case I_32_R5_NEO_4: delete (static_cast<B_32_R5_NEO_4*>(busPtr)); break;
case I_32_R6_NEO_4: delete (static_cast<B_32_R6_NEO_4*>(busPtr)); break;
case I_32_R7_NEO_4: delete (static_cast<B_32_R7_NEO_4*>(busPtr)); break;
case I_32_I0_NEO_4: delete (static_cast<B_32_I0_NEO_4*>(busPtr)); break;
case I_32_I1_NEO_4: delete (static_cast<B_32_I1_NEO_4*>(busPtr)); break;
case I_32_R0_400_3: delete (static_cast<B_32_R0_400_3*>(busPtr)); break;
case I_32_R1_400_3: delete (static_cast<B_32_R1_400_3*>(busPtr)); break;
case I_32_R2_400_3: delete (static_cast<B_32_R2_400_3*>(busPtr)); break;
case I_32_R3_400_3: delete (static_cast<B_32_R3_400_3*>(busPtr)); break;
case I_32_R4_400_3: delete (static_cast<B_32_R4_400_3*>(busPtr)); break;
case I_32_R5_400_3: delete (static_cast<B_32_R5_400_3*>(busPtr)); break;
case I_32_R6_400_3: delete (static_cast<B_32_R6_400_3*>(busPtr)); break;
case I_32_R7_400_3: delete (static_cast<B_32_R7_400_3*>(busPtr)); break;
case I_32_I0_400_3: delete (static_cast<B_32_I0_400_3*>(busPtr)); break;
case I_32_I1_400_3: delete (static_cast<B_32_I1_400_3*>(busPtr)); break;
case I_32_R0_TM1_4: delete (static_cast<B_32_R0_TM1_4*>(busPtr)); break;
case I_32_R1_TM1_4: delete (static_cast<B_32_R1_TM1_4*>(busPtr)); break;
case I_32_R2_TM1_4: delete (static_cast<B_32_R2_TM1_4*>(busPtr)); break;
case I_32_R3_TM1_4: delete (static_cast<B_32_R3_TM1_4*>(busPtr)); break;
case I_32_R4_TM1_4: delete (static_cast<B_32_R4_TM1_4*>(busPtr)); break;
case I_32_R5_TM1_4: delete (static_cast<B_32_R5_TM1_4*>(busPtr)); break;
case I_32_R6_TM1_4: delete (static_cast<B_32_R6_TM1_4*>(busPtr)); break;
case I_32_R7_TM1_4: delete (static_cast<B_32_R7_TM1_4*>(busPtr)); break;
case I_32_I0_TM1_4: delete (static_cast<B_32_I0_TM1_4*>(busPtr)); break;
case I_32_I1_TM1_4: delete (static_cast<B_32_I1_TM1_4*>(busPtr)); break;
#endif
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
case I_HS_LPD_3: delete (static_cast<B_HS_LPD_3*>(busPtr)); break;
case I_SS_LPD_3: delete (static_cast<B_SS_LPD_3*>(busPtr)); break;
case I_HS_WS1_3: delete (static_cast<B_HS_WS1_3*>(busPtr)); break;
case I_SS_WS1_3: delete (static_cast<B_SS_WS1_3*>(busPtr)); break;
case I_HS_P98_3: delete (static_cast<B_HS_P98_3*>(busPtr)); break;
case I_SS_P98_3: delete (static_cast<B_SS_P98_3*>(busPtr)); break;
}
}
//gives back the internal type index (I_XX_XXX_X above) for the input
static uint8_t getI(uint8_t busType, uint8_t* pins, uint8_t num = 0) {
if (!IS_DIGITAL(busType)) return I_NONE;
if (IS_2PIN(busType)) { //SPI LED chips
bool isHSPI = false;
#ifdef ESP8266
if (pins[0] == P_8266_HS_MOSI && pins[1] == P_8266_HS_CLK) isHSPI = true;
#else
if(!num) isHSPI = true; // temporary hack to limit use of hardware SPI to a single SPI peripheral: only allow ESP32 hardware serial on segment 0
#endif
uint8_t t = I_NONE;
switch (busType) {
case TYPE_APA102: t = I_SS_DOT_3; break;
case TYPE_LPD8806: t = I_SS_LPD_3; break;
case TYPE_WS2801: t = I_SS_WS1_3; break;
case TYPE_P9813: t = I_SS_P98_3; break;
default: t=I_NONE;
}
if (t > I_NONE && isHSPI) t--; //hardware SPI has one smaller ID than software
return t;
} else {
#ifdef ESP8266
uint8_t offset = pins[0] -1; //for driver: 0 = uart0, 1 = uart1, 2 = dma, 3 = bitbang
if (offset > 3) offset = 3;
switch (busType) {
case TYPE_WS2812_RGB:
case TYPE_WS2812_WWA:
return I_8266_U0_NEO_3 + offset;
case TYPE_SK6812_RGBW:
return I_8266_U0_NEO_4 + offset;
case TYPE_WS2811_400KHZ:
return I_8266_U0_400_3 + offset;
}
#else //ESP32
uint8_t offset = num; //RMT bus # == bus index in BusManager
if (offset > 9) return I_NONE;
switch (busType) {
case TYPE_WS2812_RGB:
case TYPE_WS2812_WWA:
return I_32_R0_NEO_3 + offset;
case TYPE_SK6812_RGBW:
return I_32_R0_NEO_4 + offset;
case TYPE_WS2811_400KHZ:
return I_32_R0_400_3 + offset;
}
#endif
}
return I_NONE;
}
};
#endif

View File

@ -17,9 +17,7 @@ void shortPressAction()
bool isButtonPressed()
{
#if defined(BTNPIN) && BTNPIN > -1
if (digitalRead(BTNPIN) == LOW) return true;
#endif
if (btnPin>=0 && digitalRead(btnPin) == LOW) return true;
#ifdef TOUCHPIN
if (touchRead(TOUCHPIN) <= TOUCH_THRESHOLD) return true;
#endif
@ -29,8 +27,7 @@ bool isButtonPressed()
void handleButton()
{
#if (defined(BTNPIN) && BTNPIN > -1) || defined(TOUCHPIN)
if (!buttonEnabled) return;
if (btnPin<0 || !buttonEnabled) return;
if (isButtonPressed()) //pressed
{
@ -75,7 +72,6 @@ void handleButton()
buttonWaitTime = 0;
shortPressAction();
}
#endif
}
void handleIO()
@ -88,37 +84,39 @@ void handleIO()
lastOnTime = millis();
if (offMode)
{
#if RLYPIN >= 0
digitalWrite(RLYPIN, RLYMDE);
#endif
if (rlyPin>=0) {
pinMode(rlyPin, OUTPUT);
digitalWrite(rlyPin, rlyMde);
}
offMode = false;
}
} else if (millis() - lastOnTime > 600)
{
if (!offMode) {
#if LEDPIN == LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
if (!offMode) {
#ifdef ESP8266
//turn off built-in LED if strip is turned off
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
#endif
#if RLYPIN >= 0
digitalWrite(RLYPIN, !RLYMDE);
#endif
}
if (rlyPin>=0) {
pinMode(rlyPin, OUTPUT);
digitalWrite(rlyPin, !rlyMde);
}
}
offMode = true;
}
#if AUXPIN >= 0
//output
if (auxActive || auxActiveBefore)
if (auxPin>=1 && (auxActive || auxActiveBefore))
{
if (!auxActiveBefore)
{
auxActiveBefore = true;
switch (auxTriggeredState)
{
case 0: pinMode(AUXPIN, INPUT); break;
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
case 0: pinMode(auxPin, INPUT); break;
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
}
auxStartTime = millis();
}
@ -128,11 +126,10 @@ void handleIO()
auxActiveBefore = false;
switch (auxDefaultState)
{
case 0: pinMode(AUXPIN, INPUT); break;
case 1: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, HIGH); break;
case 2: pinMode(AUXPIN, OUTPUT); digitalWrite(AUXPIN, LOW); break;
case 0: pinMode(auxPin, INPUT); break;
case 1: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, HIGH); break;
case 2: pinMode(auxPin, OUTPUT); digitalWrite(auxPin, LOW); break;
}
}
}
#endif
}

View File

@ -30,8 +30,6 @@ void deserializeConfig() {
return;
}
//deserializeJson(doc, json);
//int rev_major = doc[F("rev")][0]; // 1
//int rev_minor = doc[F("rev")][1]; // 0
@ -89,7 +87,9 @@ void deserializeConfig() {
JsonObject hw = doc[F("hw")];
// initialize LED pins and lengths prior to other HW
JsonObject hw_led = hw[F("led")];
CJSON(ledCount, hw_led[F("total")]);
if (ledCount > MAX_LEDS) ledCount = MAX_LEDS;
@ -98,22 +98,51 @@ void deserializeConfig() {
CJSON(strip.reverseMode, hw_led[F("rev")]);
CJSON(strip.rgbwMode, hw_led[F("rgbwm")]);
JsonObject hw_led_ins_0 = hw_led[F("ins")][0];
//bool hw_led_ins_0_en = hw_led_ins_0[F("en")]; // true
//int hw_led_ins_0_start = hw_led_ins_0[F("start")]; // 0
//int hw_led_ins_0_len = hw_led_ins_0[F("len")]; // 1200
JsonArray ins = hw_led["ins"];
uint8_t s = 0;
useRGBW = false;
busses.removeAll();
for (JsonObject elm : ins) {
if (s >= WLED_MAX_BUSSES) break;
uint8_t pins[5] = {255, 255, 255, 255, 255};
JsonArray pinArr = elm[F("pin")];
if (pinArr.size() == 0) continue;
pins[0] = pinArr[0];
uint8_t i = 0;
for (int p : pinArr) {
pins[i] = p;
i++;
if (i>4) break;
}
//int hw_led_ins_0_pin_0 = hw_led_ins_0[F("pin")][0]; // 2
strip.setColorOrder(hw_led_ins_0[F("order")]);
//bool hw_led_ins_0_rev = hw_led_ins_0[F("rev")]; // false
skipFirstLed = hw_led_ins_0[F("skip")]; // 0
useRGBW = (hw_led_ins_0[F("type")] == TYPE_SK6812_RGBW);
uint16_t length = elm[F("len")];
if (length==0) continue;
uint8_t colorOrder = (int)elm[F("order")];
//only use skip from the first strip (this shouldn't have been in ins obj. but remains here for compatibility)
if (s==0) skipFirstLed = elm[F("skip")];
uint16_t start = elm[F("start")] | 0;
if (start >= ledCount) continue;
//limit length of strip if it would exceed total configured LEDs
if (start + length > ledCount) length = ledCount - start;
uint8_t ledType = elm[F("type")] | TYPE_WS2812_RGB;
bool reversed = elm[F("rev")];
//RGBW mode is enabled if at least one of the strips is RGBW
useRGBW = (useRGBW || BusManager::isRgbw(ledType));
s++;
BusConfig bc = BusConfig(ledType, pins, start, length, colorOrder, reversed);
busses.add(bc);
}
strip.finalizeInit(useRGBW, ledCount, skipFirstLed);
JsonObject hw_btn_ins_0 = hw[F("btn")][F("ins")][0];
buttonEnabled = hw_btn_ins_0[F("en")] | buttonEnabled;
//int hw_btn_ins_0_pin_0 = hw_btn_ins_0[F("pin")][0]; // 0
CJSON(buttonEnabled, hw_btn_ins_0[F("type")]);
int hw_btn_pin = hw_btn_ins_0[F("pin")][0];
if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP);
} else {
btnPin = -1;
}
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0[F("macros")];
CJSON(macroButton, hw_btn_ins_0_macros[0]);
@ -122,11 +151,24 @@ void deserializeConfig() {
//int hw_btn_ins_0_type = hw_btn_ins_0[F("type")]; // 0
//int hw_ir_pin = hw[F("ir")][F("pin")]; // 4
CJSON(irEnabled, hw[F("ir")][F("type")]); // 0
#ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = hw[F("ir")][F("pin")]; // 4
if (pinManager.allocatePin(hw_ir_pin,false)) {
irPin = hw_ir_pin;
} else {
irPin = -1;
}
#endif
CJSON(irEnabled, hw[F("ir")][F("type")]);
//int hw_relay_pin = hw[F("relay")][F("pin")]; // 12
//bool hw_relay_rev = hw[F("relay")][F("rev")]; // false
int hw_relay_pin = hw[F("relay")][F("pin")];
if (pinManager.allocatePin(hw_relay_pin,true)) {
rlyPin = hw_relay_pin;
pinMode(rlyPin, OUTPUT);
} else {
rlyPin = -1;
}
CJSON(rlyMde, hw[F("relay")][F("rev")]);
//int hw_status_pin = hw[F("status")][F("pin")]; // -1
@ -404,70 +446,57 @@ void serializeConfig() {
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
JsonObject hw_led_ins_0 = hw_led_ins.createNestedObject();
hw_led_ins_0[F("en")] = true;
hw_led_ins_0[F("start")] = 0;
hw_led_ins_0[F("len")] = ledCount;
JsonArray hw_led_ins_0_pin = hw_led_ins_0.createNestedArray("pin");
hw_led_ins_0_pin.add(LEDPIN);
#ifdef DATAPIN
hw_led_ins_0_pin.add(DATAPIN);
#endif
hw_led_ins_0[F("order")] = strip.getColorOrder();
hw_led_ins_0[F("rev")] = false;
hw_led_ins_0[F("skip")] = skipFirstLed ? 1 : 0;
//this is very crude and temporary
byte ledType = TYPE_WS2812_RGB;
if (useRGBW) ledType = TYPE_SK6812_RGBW;
#ifdef USE_WS2801
ledType = TYPE_WS2801;
#endif
#ifdef USE_APA102
ledType = TYPE_APA102;
#endif
#ifdef USE_LPD8806
ledType = TYPE_LPD8806;
#endif
#ifdef USE_P9813
ledType = TYPE_P9813;
#endif
#ifdef USE_TM1814
ledType = TYPE_TM1814;
#endif
hw_led_ins_0[F("type")] = ledType;
uint16_t start = 0;
for (uint8_t s = 0; s < busses.getNumBusses(); s++) {
Bus *bus = busses.getBus(s);
if (!bus || bus->getLength()==0) break;
JsonObject ins = hw_led_ins.createNestedObject();
ins[F("en")] = true;
ins[F("start")] = bus->getStart();
ins[F("len")] = bus->getLength();
JsonArray ins_pin = ins.createNestedArray("pin");
uint8_t pins[5];
uint8_t nPins = bus->getPins(pins);
for (uint8_t i = 0; i < nPins; i++) ins_pin.add(pins[i]);
ins[F("order")] = bus->getColorOrder();
ins[F("rev")] = bus->reversed;
ins[F("skip")] = (skipFirstLed && s == 0) ? 1 : 0;
ins[F("type")] = bus->getType();
}
JsonObject hw_btn = hw.createNestedObject("btn");
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
#if defined(BTNPIN) && BTNPIN > -1
// button BTNPIN
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
hw_btn_ins_0[F("type")] = (buttonEnabled) ? BTN_TYPE_PUSH : BTN_TYPE_NONE;
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
hw_btn_ins_0_pin.add(BTNPIN);
hw_btn_ins_0_pin.add(btnPin);
JsonArray hw_btn_ins_0_macros = hw_btn_ins_0.createNestedArray("macros");
hw_btn_ins_0_macros.add(macroButton);
hw_btn_ins_0_macros.add(macroLongPress);
hw_btn_ins_0_macros.add(macroDoublePress);
#ifndef WLED_DISABLE_INFRARED
if (irPin>=0) {
JsonObject hw_ir = hw.createNestedObject("ir");
hw_ir[F("pin")] = irPin;
hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled )
}
#endif
#if defined(IRPIN) && IRPIN > -1
JsonObject hw_ir = hw.createNestedObject("ir");
hw_ir[F("pin")] = IRPIN;
hw_ir[F("type")] = irEnabled; // the byte 'irEnabled' does contain the IR-Remote Type ( 0=disabled )
#endif
#if defined(RLYPIN) && RLYPIN > -1
JsonObject hw_relay = hw.createNestedObject("relay");
hw_relay[F("pin")] = RLYPIN;
hw_relay[F("rev")] = (RLYMDE) ? false : true;
JsonObject hw_status = hw.createNestedObject("status");
hw_status[F("pin")] = -1;
#endif
hw_relay[F("pin")] = rlyPin;
hw_relay[F("rev")] = rlyMde;
//JsonObject hw_status = hw.createNestedObject("status");
//hw_status[F("pin")] = -1;
JsonObject hw_aux = hw.createNestedObject("aux");
hw_aux[F("pin")] = auxPin;
JsonObject light = doc.createNestedObject("light");
light[F("scale-bri")] = briMultiplier;

View File

@ -13,6 +13,12 @@
//increase if you need more
#define WLED_MAX_USERMODS 4
#ifdef ESP8266
#define WLED_MAX_BUSSES 3
#else
#define WLED_MAX_BUSSES 10
#endif
//Usermod IDs
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
@ -95,6 +101,7 @@
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
#define TYPE_SK6812_RGBW 30
#define TYPE_TM1814 31
//"Analog" types (PWM) (32-47)
#define TYPE_ONOFF 40 //binary output (relays etc.)
#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel
@ -107,8 +114,11 @@
#define TYPE_APA102 51
#define TYPE_LPD8806 52
#define TYPE_P9813 53
#define TYPE_TM1814 54
#define IS_DIGITAL(t) (t & 0x10) //digital are 16-31 and 48-63
#define IS_PWM(t) (t > 40 && t < 46)
#define NUM_PWM_PINS(t) (t - 40) //for analog PWM 41-45 only
#define IS_2PIN(t) (t > 47)
//Color orders
#define COL_ORDER_GRB 0 //GRB(w),defaut
@ -159,6 +169,9 @@
#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached
#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist
#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occured
#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented)
#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented)
#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented)
//Timer mode types
#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness
@ -171,7 +184,11 @@
// maximum number of LEDs - more than 1500 LEDs (or 500 DMA "LEDPIN 3" driven ones) will cause a low memory condition on ESP8266
#ifndef MAX_LEDS
#define MAX_LEDS 1500
#ifdef ESP8266
#define MAX_LEDS 1536
#else
#define MAX_LEDS 8192
#endif
#endif
#define MAX_LEDS_DMA 500
@ -181,7 +198,11 @@
#define E131_MAX_UNIVERSE_COUNT 9
#define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
// PWM settings
#define WLED_PWM_FREQ_ESP8266 880 //PWM frequency proven as good for LEDs
#define WLED_PWM_FREQ_ESP32 5000
#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive
@ -193,4 +214,9 @@
#define JSON_BUFFER_SIZE 16384
#endif
//this is merely a default now and can be changed at runtime
#ifndef LEDPIN
#define LEDPIN 2
#endif
#endif

View File

@ -464,7 +464,7 @@ function populateInfo(i)
}
}
var vcn = "Kuuhaku";
if (i.ver.startsWith("0.11.")) vcn = "Mirai";
if (i.ver.startsWith("0.12.")) vcn = "Hikari";
if (i.cn) vcn = i.cn;
cn += `v${i.ver} "${vcn}"<br><br><table class="infot">
@ -473,7 +473,8 @@ function populateInfo(i)
${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")}
${inforow("Uptime",getRuntimeStr(i.uptime))}
${inforow("Free heap",heap," kB")}
${inforow("Estimated current",pwru)}
${inforow("Estimated current",pwru)}
${inforow("Frames / second",i.leds.fps)}
${inforow("MAC address",i.mac)}
${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.fs.t) + "%)")}
${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")}

View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta charset="utf-8">
<meta name="theme-color" content="#222222">
<title>WLED Live Preview</title>
<style>
body {
margin: 0;
}
#canv {
background: black;
filter: brightness(175%);
width: 100%;
height: 100%;
position: absolute;
}
</style>
</head>
<body>
<div id="canv" />
<script>
console.info("Live-Preview websocket opening");
var socket = new WebSocket("ws://"+document.location.host+"/ws");
socket.onopen = function () {
console.info("Live-Preview websocket is opened");
socket.send("{'lv':true}");
}
socket.onclose = function () { console.info("Live-Preview websocket is closing"); }
socket.onerror = function (event) { console.error("Live-Preview websocket error:", event); }
function updatePreview(leds) {
var str = "linear-gradient(90deg,";
var len = leds.length;
for (i = 0; i < len; i++) {
var leddata = leds[i];
if (leddata.length > 6) leddata = leddata.substring(2);
str += "#" + leddata;
if (i < len -1) str += ","
}
str += ")";
document.getElementById("canv").style.background = str;
}
socket.onmessage = function (event) {
try {
var json = JSON.parse(event.data);
if (json && json.leds) {
requestAnimationFrame(function () {updatePreview(json.leds);});
}
}
catch (err) {
console.error("Live-Preview websocket error:",err);
}
}
</script>
</body>
</html>

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=500">
<title>LED Settings</title>
<script>
var d=document,laprev=55;
var d=document,laprev=55,maxST=1,bmax=5000,bquot=0; //maximum bytes for LED allocation: 5kB for 8266, 32kB for 32
function H()
{
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");
@ -13,8 +13,29 @@
function B()
{
window.open("/settings","_self");
}
function S(){GetV();setABL();}
}
function trySubmit() {
var LCs = d.getElementsByTagName("input");
for (i=0; i<LCs.length; i++) {
var nm = LCs[i].name.substring(0,2);
//check for pin conflicts
if (nm=="L0" || nm=="L1" || nm=="RL" || nm=="BT" || nm=="IR" || nm=="AX")
if (LCs[i].value!="" && LCs[i].value!="-1") {
if (LCs[i].value > 5 && LCs[i].value < 12) {alert("Sorry, pins 6-11 can not be used.");LCs[i].focus();return;}
if (d.um_p && d.um_p.some((e)=>e==parseInt(LCs[i].value,10))) {alert("Usermod pin conflict!");LCs[i].focus();return;}
for (j=i+1; j<LCs.length; j++)
{
var n2 = LCs[j].name.substring(0,2);
if (n2=="L0" || n2=="L1" || n2=="RL" || n2=="BT" || n2=="IR" || n2=="AX")
if (LCs[j].value!="" && LCs[i].value==LCs[j].value) {alert("Pin conflict!");LCs[i].focus();return;}
}
}
}
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (bmax < 10000) msg += " Consider using an ESP32."; alert(msg); return;}
if (d.Sf.reportValidity()) d.Sf.submit();
}
function S(){GetV();setABL(); if (maxST>4) bmax=64000; d.getElementById('m1').innerHTML = bmax;}
function enABL()
{
var en = d.getElementById('able').checked;
@ -43,22 +64,95 @@
default: d.getElementById('LAdis').style.display = 'inline';
}
UI();
}
//returns mem usage
function getMem(type, len, p0) {
//len = parseInt(len);
if (type < 32) {
if (bmax < 10000 && p0 ==3) { //8266 DMA uses 5x the mem
if (type > 29) return len*20; //RGBW
return len*15;
} else if (bmax > 10000) //ESP32 RMT uses double buffer?
{
if (type > 29) return len*8; //RGBW
return len*6;
}
if (type > 29) return len*4; //RGBW
return len*3;
}
if (type > 31 && type < 48) return 5;
if (type == 44 || type == 45) return len*4; //RGBW
return len*3;
}
function UI()
{
var myC = d.querySelectorAll('.wc'),
l = myC.length;
for (i = 0; i < l; i++) {
myC[i].style.display = (d.getElementById('rgbw').checked) ? 'inline':'none';
}
var isRGBW = false, memu = 0;
d.getElementById('ledwarning').style.display = (d.Sf.LC.value > 1000) ? 'inline':'none';
d.getElementById('ampwarning').style.display = (d.Sf.MA.value > 7200) ? 'inline':'none';
if (d.Sf.LA.value == 255) laprev = 12;
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
if (d.Sf.LA.value == 255) laprev = 12;
else if (d.Sf.LA.value > 0) laprev = d.Sf.LA.value;
var s = d.getElementsByTagName("select");
for (i=0; i<s.length; i++) {
if (s[i].name.substring(0,2)=="LT") {
n=s[i].name.substring(2);
var type = s[i].value;
d.getElementById("p0d"+n).innerHTML = (type > 49) ? "Data pin:" : (type >41) ? "Pins:" : "Pin:";
d.getElementById("p1d"+n).innerHTML = (type > 49) ? "Clk:" : "";
var LK = d.getElementsByName("L1"+n)[0];
memu += getMem(type, d.getElementsByName("LC"+n)[0].value, d.getElementsByName("L0"+n)[0].value);
for (p=1; p<5; p++) {
var LK = d.getElementsByName("L"+p+n)[0];
if (!LK) continue;
if ((type>49 && p==1) || (type>41 && type < 50 && (p+40 < type))) // TYPE_xxxx values from const.h
{
LK.style.display = "inline";
LK.required = true;
} else {
LK.style.display = "none";
LK.required = false;
LK.value="";
}
}
if (type == 30 || type == 31 || type == 44 || type == 45) isRGBW = true;
d.getElementById("dig"+n).style.display = (type > 31 && type < 48) ? "none":"inline";
d.getElementById("psd"+n).innerHTML = (type > 31 && type < 48) ? "Index:":"Start:";
}
}
var myC = d.querySelectorAll('.wc'),
l = myC.length;
for (i = 0; i < l; i++) {
myC[i].style.display = (isRGBW) ? 'inline':'none';
}
if (d.activeElement == d.getElementsByName("LC")[0]) {
var o = d.getElementsByClassName("iST");
var i = o.length;
if (i == 1) d.getElementsByName("LC0")[0].value = d.getElementsByName("LC")[0].value;
}
var LCs = d.getElementsByTagName("input");
var sLC = 0, maxLC = 0;
for (i=0; i<LCs.length; i++) {
var nm = LCs[i].name.substring(0,2);
if (nm=="LC" && LCs[i].name != "LC") {var c = parseInt(LCs[i].value,10); if (c) {sLC+=c; if (c>maxLC) maxLC = c;} continue;}
}
d.getElementById('m0').innerHTML = memu;
bquot = memu / bmax * 100;
d.getElementById('dbar').style.background = `linear-gradient(90deg, ${bquot > 60 ? bquot > 90 ? "red":"orange":"#ccc"} 0 ${bquot}%%, #444 ${bquot}%% 100%%)`;
d.getElementById('ledwarning').style.display = (maxLC > 800 || bquot > 80) ? 'inline':'none';
//TODO add warning "Recommended pins on ESP8266 are 1 and 2 (3 only with low LED count)"
//TODO add overmemory warning
//TODO block disallowed pins 6-11
d.getElementById('wreason').innerHTML = (bquot > 80) ? "than 60%% of max. LED memory" : "800 LEDs per pin";
//var val = Math.ceil((100 + d.Sf.LC.value * laprev)/500)/2;
var val = Math.ceil((100 + sLC * laprev)/500)/2;
val = (val > 5) ? Math.ceil(val) : val;
var s = "";
var is12V = (d.Sf.LAsel.value == 30);
@ -72,18 +166,79 @@
s += val;
s += "A supply connected to LEDs";
}
var val2 = Math.ceil((100 + d.Sf.LC.value * laprev)/1500)/2;
var val2 = Math.ceil((100 + sLC * laprev)/1500)/2;
val2 = (val2 > 5) ? Math.ceil(val2) : val2;
var s2 = "(for most effects, ~";
s2 += val2;
s2 += "A is enough)<br>";
d.getElementById('psu').innerHTML = s;
d.getElementById('psu2').innerHTML = isWS2815 ? "" : s2;
}
}
function addLEDs(n)
{
if (n>1) {maxST=n; d.getElementById("+").style.display="inline"; return;}
var o = d.getElementsByClassName("iST");
var i = o.length;
if ((n==1 && i>=maxST) || (n==-1 && i==0)) return;
var f = d.getElementById("mLC");
if (n==1) {
var cn = `<div class="iST">
${i>0?'<hr style="width:260px">':''}
${i+1}:
<select name="LT${i}" onchange="UI()">
<option value="22">WS281x</option>
<option value="30">SK6812 RGBW</option>
<option value="31">TM1814</option>
<option value="24">400kHz</option>
<option value="50">WS2801</option>
<option value="51">APA102</option>
<option value="52">LPD8806</option>
<option value="53">P9813</option>
<option value="41">PWM White</option>
<option value="42">PWM WWCW</option>
<option value="43">PWM RGB</option>
<option value="44">PWM RGBW</option>
<option value="45">PWM RGBWC</option>
</select>&nbsp;
Color Order:
<select name="CO${i}">
<option value="0">GRB</option>
<option value="1">RGB</option>
<option value="2">BRG</option>
<option value="3">RBG</option>
<option value="4">BGR</option>
<option value="5">GBR</option>
</select><br>
<span id="p0d${i}">Pin:</span> <input type="number" name="L0${i}" min="0" max="40" required style="width:35px" oninput="UI()"/>
<span id="p1d${i}">Clock:</span> <input type="number" name="L1${i}" min="0" max="40" style="width:35px"/>
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="40" style="width:35px"/>
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="40" style="width:35px"/>
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="40" style="width:35px"/>
<br>
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" min="0" max="8191" value="0" required />&nbsp;
<div id="dig${i}" style="display:inline">
Count: <input type="number" name="LC${i}" min="0" max="2048" value="1" required oninput="UI()" /><br>
Reverse: <input type="checkbox" name="CV${i}"></div><br>
</div>`;
f.insertAdjacentHTML("beforeend", cn);
}
if (n==-1) {
o[--i].remove();--i;
}
d.getElementById("+").style.display = (i<maxST-1) ? "inline":"none";
d.getElementById("-").style.display = (i>0) ? "inline":"none";
UI();
}
function GetV()
{
//values injected by server while sending HTML
}
//values injected by server while sending HTML
//d.um_p=[];addLEDs(3);d.Sf.LC.value=250;addLEDs(1);d.Sf.L00.value=2;d.Sf.L10.value=0;d.Sf.LC0.value=250;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=0;d.Sf.LS0.checked=0;d.Sf.MA.value=5400;d.Sf.LA.value=55;d.getElementsByClassName("pow")[0].innerHTML="350mA";d.Sf.CA.value=40;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=3;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=64;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RV.checked=0;d.Sf.SL.checked=0;d.Sf.RL.value=12;d.Sf.RM.checked=0;d.Sf.BT.value=-1;d.Sf.IR.value=-1;d.Sf.AX.value=-1;
}
</script>
<style>
@import url("style.css");
@ -92,62 +247,51 @@
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>LED setup</h2>
LED count: <input name="LC" type="number" min="1" max="1500" oninput="UI()" required><br>
<div id="ledwarning" style="color: orange; display: none;">
&#9888; You might run into stability or lag issues.<br>
Use less than 1000 LEDs per ESP for the best experience!<br>
</div>
<i>Recommended power supply for brightest white:</i><br>
<b><span id="psu">?</span></b><br>
<span id="psu2"><br></span>
<br>
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
<div id="abl">
Maximum Current: <input name="MA" type="number" min="250" max="65000" oninput="UI()" required> mA<br>
<div id="ampwarning" style="color: orange; display: none;">
&#9888; Your power supply provides high current.<br>
To improve the safety of your setup,<br>
please use thick cables,<br>
multiple power injection points and a fuse!<br>
</div>
<i>Automatically limits brightness to stay close to the limit.<br>
Keep at &lt;1A if powering LEDs directly from the ESP 5V pin!<br>
If you are using an external power supply, enter its rating.<br>
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
LED voltage (Max. current for a single LED):<br>
<select name="LAsel" onchange="enLA()">
<option value="55" selected>5V default (55mA)</option>
<option value="35">5V efficient (35mA)</option>
<option value="30">12V (30mA)</option>
<option value="255">WS2815 (12mA)</option>
<option value="50">Custom</option>
</select><br>
<span id="LAdis" style="display: none;">Custom max. current per LED: <input name="LA" type="number" min="0" max="255" id="la" oninput="UI()" required> mA<br></span>
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
<button type="button" onclick="B()">Back</button><button type="button" onclick="trySubmit()">Save</button><hr>
<h2>LED &amp; Hardware setup</h2>
Total LED count: <input name="LC" type="number" min="1" max="8192" oninput="UI()" required><br>
<i>Recommended power supply for brightest white:</i><br>
<b><span id="psu">?</span></b><br>
<span id="psu2"><br></span>
<br>
Enable automatic brightness limiter: <input type="checkbox" name="ABen" onchange="enABL()" id="able"><br>
<div id="abl">
Maximum Current: <input name="MA" type="number" min="250" max="65000" oninput="UI()" required> mA<br>
<div id="ampwarning" style="color: orange; display: none;">
&#9888; Your power supply provides high current.<br>
To improve the safety of your setup,<br>
please use thick cables,<br>
multiple power injection points and a fuse!<br>
</div>
<br>
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW" onchange=UI() id="rgbw"><br>
<span class="wc">
Auto-calculate white channel from RGB:<br>
<select name=AW>
<option value=0>None</option>
<option value=1>Brighter</option>
<option value=2>Accurate</option>
<option value=3>Dual</option>
<option value=4>Legacy</option>
</select>
<br></span>
Color order:
<select name="CO">
<option value=0>GRB</option>
<option value=1>RGB</option>
<option value=2>BRG</option>
<option value=3>RBG</option>
<option value=4>BGR</option>
<option value=5>GBR</option>
</select>
<i>Automatically limits brightness to stay close to the limit.<br>
Keep at &lt;1A if powering LEDs directly from the ESP 5V pin!<br>
If you are using an external power supply, enter its rating.<br>
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
LED voltage (Max. current for a single LED):<br>
<select name="LAsel" onchange="enLA()">
<option value="55" selected>5V default (55mA)</option>
<option value="35">5V efficient (35mA)</option>
<option value="30">12V (30mA)</option>
<option value="255">WS2815 (12mA)</option>
<option value="50">Custom</option>
</select><br>
<span id="LAdis" style="display: none;">Custom max. current per LED: <input name="LA" type="number" min="0" max="255" id="la" oninput="UI()" required> mA<br></span>
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
</div>
<h3>Hardware setup</h3>
<div id="mLC">LED outputs:</div>
<button type="button" id="+" onclick="addLEDs(1)" style="display:none;border-radius:20px;height:36px;">+</button>
<button type="button" id="-" onclick="addLEDs(-1)" style="display:none;border-radius:20px;width:36px;height:36px;">-</button><br>
LED Memory Usage: <span id="m0">0</span> / <span id="m1">?</span> B<br>
<div id="dbar" style="display:inline-block; width: 100px; height: 10px; border-radius: 20px;"></div><br>
<div id="ledwarning" style="color: orange; display: none;">
&#9888; You might run into stability or lag issues.<br>
Use less than <span id="wreason">800 LEDs per pin</span> for the best experience!<br>
</div><br>
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()"> Active high <input type="checkbox" name="RM"><br>
Button pin: <input type="number" min="-1" max="40" name="BT" onchange="UI()"><br>
IR pin: <input type="number" min="-1" max="40" name="IR" onchange="UI()"><br>
AUX pin: <input type="number" min="-1" max="40" name="AX" onchange="UI()">
<h3>Defaults</h3>
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br><br>
@ -171,7 +315,7 @@
<option value="2">Fade Color</option>
<option value="3">Sunrise</option>
</select>
<h3>Advanced</h3>
<h3>Advanced</h3>
Palette blending:
<select name="PB">
<option value="0">Linear (wrap if moving)</option>
@ -180,8 +324,18 @@
<option value="3">None (not recommended)</option>
</select><br>
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
Skip first LED: <input type="checkbox" name="SL"><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
Skip first LED: <input type="checkbox" name="SL"><br>
<span class="wc">
Auto-calculate white channel from RGB:<br>
<select name="AW">
<option value=0>None</option>
<option value=1>Brighter</option>
<option value=2>Accurate</option>
<option value=3>Dual</option>
<option value=4>Legacy</option>
</select>
<br></span><hr>
<button type="button" onclick="B()">Back</button><button type="button" onclick="trySubmit()">Save</button>
</form>
</body>
</html>

View File

@ -76,7 +76,6 @@ bool decodeIRCustom(uint32_t code);
void applyRepeatActions();
void relativeChange(byte* property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
void changeEffectSpeed(int8_t amount);
void changeBrightness(int8_t amount);
void changeEffectIntensity(int8_t amount);
void decodeIR(uint32_t code);
void decodeIR24(uint32_t code);
@ -149,22 +148,6 @@ void setCronixie();
void _overlayCronixie();
void _drawOverlayCronixie();
//pin_manager.cpp
class PinManagerClass {
private:
#ifdef ESP8266
uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits
#else
uint8_t pinAlloc[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; //40bit, 1 bit per pin, we use all bits
#endif
public:
void deallocatePin(byte gpio);
bool allocatePin(byte gpio, bool output = true);
bool isPinAllocated(byte gpio);
bool isPinOk(byte gpio, bool output = true);
};
//playlist.cpp
void loadPlaylist(JsonObject playlistObject);
void handlePlaylist();

View File

@ -42,7 +42,7 @@ function B(){window.history.back()}function U(){document.getElementById("uf").st
.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}#msg{display:none}
</style></head><body><h2>WLED Software Update</h2><form method="POST"
action="/update" id="uf" enctype="multipart/form-data" onsubmit="U()">
Installed version: 0.11.1<br>Download the latest binary: <a
Installed version: 0.12.0-a0<br>Download the latest binary: <a
href="https://github.com/Aircoookie/WLED/releases" target="_blank"><img
src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square">
</a><br><input type="file" class="bt" name="update" accept=".bin" required><br>
@ -78,6 +78,17 @@ update();var tmout=null;function update(){if(document.hidden)return clearTimeout
</script></body></html>)=====";
// Autogenerated from wled00/data/liveviewws.htm, do not edit!!
const char PAGE_liveviewws[] PROGMEM = R"=====(<!DOCTYPE html><html><head><meta name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1"><meta
charset="utf-8"><meta name="theme-color" content="#222222"><title>
WLED Live Preview</title><style>
body{margin:0}#canv{background:#000;filter:brightness(175%);width:100%;height:100%;position:absolute}
</style></head><body><div id="canv"><script>
console.info("Live-Preview websocket opening");var socket=new WebSocket("ws://"+document.location.host+"/ws");function updatePreview(e){var o="linear-gradient(90deg,",n=e.length;for(i=0;i<n;i++){var t=e[i];t.length>6&&(t=t.substring(2)),o+="#"+t,i<n-1&&(o+=",")}o+=")",document.getElementById("canv").style.background=o}socket.onopen=function(){console.info("Live-Preview websocket is opened"),socket.send("{'lv':true}")},socket.onclose=function(){console.info("Live-Preview websocket is closing")},socket.onerror=function(e){console.error("Live-Preview websocket error:",e)},socket.onmessage=function(e){try{var o=JSON.parse(e.data);o&&o.leds&&requestAnimationFrame((function(){updatePreview(o.leds)}))}catch(e){console.error("Live-Preview websocket error:",e)}}
</script></body></html>)=====";
// Autogenerated from wled00/data/404.htm, do not edit!!
const char PAGE_404[] PROGMEM = R"=====(<!DOCTYPE html><html><head><meta charset="utf-8"><meta
content="width=device-width" name="viewport"><meta name="theme-color"

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,54 @@ uint16_t irTimesRepeated = 0;
uint8_t lastIR6ColourIdx = 0;
// brightnessSteps: a static array of brightness levels following a geometric
// progression. Can be generated from the following Python, adjusting the
// arbitrary 4.5 value to taste:
//
// def values(level):
// while level >= 5:
// yield int(level)
// level -= level / 4.5
// result = [v for v in reversed(list(values(255)))]
// print("%d values: %s" % (len(result), result))
//
// It would be hard to maintain repeatable steps if calculating this on the fly.
const byte brightnessSteps[] = {
5, 7, 9, 12, 16, 20, 26, 34, 43, 56, 72, 93, 119, 154, 198, 255
};
const size_t numBrightnessSteps = sizeof(brightnessSteps) / sizeof(uint8_t);
// increment `bri` to the next `brightnessSteps` value
void incBrightness()
{
// dumb incremental search is efficient enough for so few items
for (int index = 0; index < numBrightnessSteps; ++index)
{
if (brightnessSteps[index] > bri)
{
bri = brightnessSteps[index];
lastRepeatableAction = ACTION_BRIGHT_UP;
break;
}
}
}
// decrement `bri` to the next `brightnessSteps` value
void decBrightness()
{
// dumb incremental search is efficient enough for so few items
for (int index = numBrightnessSteps - 1; index >= 0; --index)
{
if (brightnessSteps[index] < bri)
{
bri = brightnessSteps[index];
lastRepeatableAction = ACTION_BRIGHT_DOWN;
break;
}
}
}
//Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control
//IR codes themselves can be defined directly after "case" or in "ir_codes.h"
bool decodeIRCustom(uint32_t code)
@ -47,16 +95,6 @@ void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte high
*property = (byte)constrain(new_val,0.1,255.1);
}
void changeBrightness(int8_t amount)
{
int16_t new_val = bri + amount;
if (new_val < 5) new_val = 5; //minimum brightness A=5
bri = (byte)constrain(new_val,0.1,255.1);
if(amount > 0) lastRepeatableAction = ACTION_BRIGHT_UP;
if(amount < 0) lastRepeatableAction = ACTION_BRIGHT_DOWN;
lastRepeatableValue = amount;
}
void changeEffectSpeed(int8_t amount)
{
if (effectCurrent != 0) {
@ -142,11 +180,11 @@ void applyRepeatActions(){
if (lastRepeatableAction == ACTION_BRIGHT_UP)
{
changeBrightness(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
incBrightness(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
else if (lastRepeatableAction == ACTION_BRIGHT_DOWN )
{
changeBrightness(lastRepeatableValue); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
decBrightness(); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
}
if (lastRepeatableAction == ACTION_SPEED_UP)
@ -187,8 +225,8 @@ void applyRepeatActions(){
void decodeIR24(uint32_t code)
{
switch (code) {
case IR24_BRIGHTER : changeBrightness(10); break;
case IR24_DARKER : changeBrightness(-10); break;
case IR24_BRIGHTER : incBrightness(); break;
case IR24_DARKER : decBrightness(); break;
case IR24_OFF : briLast = bri; bri = 0; break;
case IR24_ON : bri = briLast; break;
case IR24_RED : colorFromUint32(COLOR_RED); break;
@ -219,8 +257,8 @@ void decodeIR24(uint32_t code)
void decodeIR24OLD(uint32_t code)
{
switch (code) {
case IR24_OLD_BRIGHTER : changeBrightness(10); break;
case IR24_OLD_DARKER : changeBrightness(-10); break;
case IR24_OLD_BRIGHTER : incBrightness(); break;
case IR24_OLD_DARKER : decBrightness(); break;
case IR24_OLD_OFF : briLast = bri; bri = 0; break;
case IR24_OLD_ON : bri = briLast; break;
case IR24_OLD_RED : colorFromUint32(COLOR_RED); break;
@ -252,8 +290,8 @@ void decodeIR24OLD(uint32_t code)
void decodeIR24CT(uint32_t code)
{
switch (code) {
case IR24_CT_BRIGHTER : changeBrightness(10); break;
case IR24_CT_DARKER : changeBrightness(-10); break;
case IR24_CT_BRIGHTER : incBrightness(); break;
case IR24_CT_DARKER : decBrightness(); break;
case IR24_CT_OFF : briLast = bri; bri = 0; break;
case IR24_CT_ON : bri = briLast; break;
case IR24_CT_RED : colorFromUint32(COLOR_RED); break;
@ -287,8 +325,8 @@ void decodeIR24CT(uint32_t code)
void decodeIR40(uint32_t code)
{
switch (code) {
case IR40_BPLUS : changeBrightness(10); break;
case IR40_BMINUS : changeBrightness(-10); break;
case IR40_BPLUS : incBrightness(); break;
case IR40_BMINUS : decBrightness(); break;
case IR40_OFF : briLast = bri; bri = 0; break;
case IR40_ON : bri = briLast; break;
case IR40_RED : colorFromUint24(COLOR_RED); break;
@ -344,8 +382,8 @@ void decodeIR40(uint32_t code)
void decodeIR44(uint32_t code)
{
switch (code) {
case IR44_BPLUS : changeBrightness(10); break;
case IR44_BMINUS : changeBrightness(-10); break;
case IR44_BPLUS : incBrightness(); break;
case IR44_BMINUS : decBrightness(); break;
case IR44_OFF : briLast = bri; bri = 0; break;
case IR44_ON : bri = briLast; break;
case IR44_RED : colorFromUint24(COLOR_RED); break;
@ -407,8 +445,8 @@ void decodeIR44(uint32_t code)
void decodeIR21(uint32_t code)
{
switch (code) {
case IR21_BRIGHTER: changeBrightness(10); break;
case IR21_DARKER: changeBrightness(-10); break;
case IR21_BRIGHTER: incBrightness(); break;
case IR21_DARKER: decBrightness(); break;
case IR21_OFF: briLast = bri; bri = 0; break;
case IR21_ON: bri = briLast; break;
case IR21_RED: colorFromUint32(COLOR_RED); break;
@ -437,8 +475,8 @@ void decodeIR6(uint32_t code)
{
switch (code) {
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: changeBrightness(10); break;
case IR6_CHANNEL_DOWN: changeBrightness(-10); break;
case IR6_CHANNEL_UP: incBrightness(); break;
case IR6_CHANNEL_DOWN: decBrightness(); break;
case IR6_VOLUME_UP: relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break; // next effect
case IR6_VOLUME_DOWN: // next palette
relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1);
@ -472,8 +510,8 @@ void decodeIR9(uint32_t code)
case IR9_A : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
case IR9_B : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
case IR9_C : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
case IR9_UP : changeBrightness(16); break;
case IR9_DOWN : changeBrightness(-16); break;
case IR9_UP : incBrightness(); break;
case IR9_DOWN : decBrightness(); break;
//case IR9_UP : changeEffectIntensity(16); break;
//case IR9_DOWN : changeEffectIntensity(-16); break;
case IR9_LEFT : changeEffectSpeed(-16); break;
@ -488,7 +526,7 @@ void initIR()
{
if (irEnabled > 0)
{
irrecv = new IRrecv(IRPIN);
irrecv = new IRrecv(irPin);
irrecv->enableIRIn();
}
}

View File

@ -343,7 +343,6 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
if (errorFlag) root[F("error")] = errorFlag;
root[F("ps")] = currentPreset;
root[F("pss")] = savedPresets;
root[F("pl")] = (presetCyclingEnabled) ? 0: -1;
usermods.addToJsonState(root);
@ -424,6 +423,7 @@ void serializeInfo(JsonObject root)
leds_pin.add(LEDPIN);
leds[F("pwr")] = strip.currentMilliamps;
leds[F("fps")] = strip.getFps();
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
leds[F("maxseg")] = strip.getMaxSegments();
leds[F("seglock")] = false; //will be used in the future to prevent modifications to segment config
@ -588,7 +588,7 @@ void serveJson(AsyncWebServerRequest* request)
bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
{
AsyncWebSocketClient * wsc;
AsyncWebSocketClient * wsc = nullptr;
if (!request) { //not HTTP, use Websockets
#ifdef WLED_ENABLE_WEBSOCKETS
wsc = ws.client(wsClient);
@ -605,7 +605,7 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
for (uint16_t i= 0; i < used; i += n)
{
olen += sprintf(obuf + olen, "\"%06X\",", strip.getPixelColor(i));
olen += sprintf(obuf + olen, "\"%06X\",", strip.getPixelColor(i) & 0xFFFFFF);
}
olen -= 1;
oappend((const char*)F("],\"n\":"));

View File

@ -110,7 +110,7 @@ void publishMqtt()
char s[10];
char subuf[38];
sprintf(s, "%ld", bri);
sprintf(s, "%u", bri);
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/g");
mqtt->publish(subuf, 0, true, s);

View File

@ -1,9 +1,6 @@
#include "pin_manager.h"
#include "wled.h"
/*
* Registers pins so there is no attempt for two interfaces to use the same pin
*/
void PinManagerClass::deallocatePin(byte gpio)
{
if (!isPinOk(gpio, false)) return;
@ -51,4 +48,44 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
#endif
return false;
}
}
#ifdef ARDUINO_ARCH_ESP32
byte PinManagerClass::allocateLedc(byte channels)
{
if (channels > 16 || channels == 0) return 255;
byte ca = 0;
for (byte i = 0; i < 16; i++) {
byte by = i >> 3;
byte bi = i - 8*by;
if (bitRead(ledcAlloc[by], bi)) { //found occupied pin
ca = 0;
} else {
ca++;
}
if (ca >= channels) { //enough free channels
byte in = (i + 1) - ca;
for (byte j = 0; j < ca; j++) {
byte b = in + j;
byte by = b >> 3;
byte bi = b - 8*by;
bitWrite(ledcAlloc[by], bi, true);
}
return in;
}
}
return 255; //not enough consecutive free LEDC channels
}
void PinManagerClass::deallocateLedc(byte pos, byte channels)
{
for (byte j = pos; j < pos + channels; j++) {
if (j > 16) return;
byte by = j >> 3;
byte bi = j - 8*by;
bitWrite(ledcAlloc[by], bi, false);
}
}
#endif
PinManagerClass pinManager = PinManagerClass();

29
wled00/pin_manager.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef WLED_PIN_MANAGER_H
#define WLED_PIN_MANAGER_H
/*
* Registers pins so there is no attempt for two interfaces to use the same pin
*/
#include <Arduino.h>
class PinManagerClass {
private:
#ifdef ESP8266
uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits
#else
uint8_t pinAlloc[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; //40bit, 1 bit per pin, we use all bits
uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels
#endif
public:
void deallocatePin(byte gpio);
bool allocatePin(byte gpio, bool output = true);
bool isPinAllocated(byte gpio);
bool isPinOk(byte gpio, bool output = true);
#ifdef ARDUINO_ARCH_ESP32
byte allocateLedc(byte channels);
void deallocateLedc(byte pos, byte channels);
#endif
};
extern PinManagerClass pinManager;
#endif

View File

@ -75,18 +75,90 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
//LED SETTINGS
if (subPage == 2)
{
int t = request->arg(F("LC")).toInt();
int t = 0;
if (rlyPin>=0 && pinManager.isPinAllocated(rlyPin)) pinManager.deallocatePin(rlyPin);
#ifndef WLED_DISABLE_INFRARED
if (irPin>=0 && pinManager.isPinAllocated(irPin)) pinManager.deallocatePin(irPin);
#endif
if (btnPin>=0 && pinManager.isPinAllocated(btnPin)) pinManager.deallocatePin(btnPin);
//TODO remove all busses, but not in this system call
//busses->removeAll();
uint8_t colorOrder, type;
uint16_t length, start;
uint8_t pins[2] = {255, 255};
for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) {
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
char lk[4] = "L1"; lk[2] = 48+s; lk[3] = 0; //strip clock pin. 255 for none
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
char co[4] = "CO"; co[2] = 48+s; co[3] = 0; //strip color order
char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type
char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
if (!request->hasArg(lp)) {
DEBUG_PRINTLN("No data."); break;
}
pins[0] = request->arg(lp).toInt();
if (request->hasArg(lk)) {
pins[1] = (request->arg(lk).length() > 0) ? request->arg(lk).toInt() : 255;
}
type = request->arg(lt).toInt();
if (request->hasArg(lc) && request->arg(lc).toInt() > 0) {
length = request->arg(lc).toInt();
} else {
break; // no parameter
}
colorOrder = request->arg(co).toInt();
start = (request->hasArg(ls)) ? request->arg(ls).toInt() : 0;
if (busConfigs[s] != nullptr) delete busConfigs[s];
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder, request->hasArg(cv));
}
ledCount = request->arg(F("LC")).toInt();
if (t > 0 && t <= MAX_LEDS) ledCount = t;
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
#endif
//DMA method uses too much ram, TODO: limit!
// upate other pins
#ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = request->arg(F("IR")).toInt();
if (pinManager.isPinOk(hw_ir_pin) && pinManager.allocatePin(hw_ir_pin,false)) {
irPin = hw_ir_pin;
} else {
irPin = -1;
}
#endif
int hw_rly_pin = request->arg(F("RL")).toInt();
if (pinManager.allocatePin(hw_rly_pin,true)) {
rlyPin = hw_rly_pin;
} else {
rlyPin = -1;
}
rlyMde = (bool)request->hasArg(F("RM"));
int hw_btn_pin = request->arg(F("BT")).toInt();
if (pinManager.allocatePin(hw_btn_pin,false)) {
btnPin = hw_btn_pin;
pinMode(btnPin, INPUT_PULLUP);
} else {
btnPin = -1;
}
int hw_aux_pin = request->arg(F("AX")).toInt();
if (pinManager.allocatePin(hw_aux_pin,true)) {
auxPin = hw_aux_pin;
} else {
auxPin = -1;
}
strip.ablMilliampsMax = request->arg(F("MA")).toInt();
strip.milliampsPerLed = request->arg(F("LA")).toInt();
useRGBW = request->hasArg(F("EW"));
strip.setColorOrder(request->arg(F("CO")).toInt());
strip.rgbwMode = request->arg(F("AW")).toInt();
briS = request->arg(F("CA")).toInt();
@ -328,12 +400,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
DMXFixtureMap[i] = t;
}
}
#endif
if (subPage != 6 || !doReboot) serializeConfig(); //do not save if factory reset
if (subPage == 2) {
strip.init(useRGBW,ledCount,skipFirstLed);
}
if (subPage != 2 && (subPage != 6 || !doReboot)) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
if (subPage == 4) alexaInit();
}
@ -646,15 +715,15 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
if (nightlightMode > NL_MODE_SUN) nightlightMode = NL_MODE_SUN;
#if AUXPIN >= 0
//toggle general purpose output
pos = req.indexOf(F("AX="));
if (pos > 0) {
auxTime = getNumVal(&req, pos);
auxActive = true;
if (auxTime == 0) auxActive = false;
if (auxPin>=0) {
pos = req.indexOf(F("AX="));
if (pos > 0) {
auxTime = getNumVal(&req, pos);
auxActive = true;
if (auxTime == 0) auxActive = false;
}
}
#endif
pos = req.indexOf(F("TT="));
if (pos > 0) transitionDelay = getNumVal(&req, pos);

View File

@ -315,6 +315,15 @@ void handleNotifications()
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
id++;
}
} else if (udpIn[0] == 5) //dnrgbw
{
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
for (uint16_t i = 4; i < packetSize -2; i += 4)
{
if (id >= ledCount) break;
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
id++;
}
}
strip.show();
return;

View File

@ -13,7 +13,9 @@
#ifdef USERMOD_DALLASTEMPERATURE
#include "../usermods/Temperature/usermod_temperature.h"
#endif
//#include "usermod_v2_empty.h"
#ifdef USERMOD_BUZZER
#include "../usermods/buzzer/usermod_v2_buzzer.h"
#endif
@ -24,6 +26,11 @@
#ifdef USERMOD_MODE_SORT
#include "../usermods/usermod_v2_mode_sort/usermod_v2_mode_sort.h"
#endif
// BME280 v2 usermod. Define "USERMOD_BME280" in my_config.h
#ifdef USERMOD_BME280
#include "../usermods/BME280_v2/usermod_bme280.h"
#endif
#ifdef USERMOD_FOUR_LINE_DISLAY
#include "../usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h"
#endif
@ -45,14 +52,21 @@ void registerUsermods()
* || || ||
* \/ \/ \/
*/
//usermods.add(new MyExampleUsermod());
#ifdef USERMOD_DALLASTEMPERATURE
//usermods.add(new MyExampleUsermod());
#ifdef USERMOD_DALLASTEMPERATURE
usermods.add(new UsermodTemperature());
#endif
//usermods.add(new UsermodRenameMe());
#ifdef USERMOD_BUZZER
#endif
//usermods.add(new UsermodRenameMe());
#ifdef USERMOD_BUZZER
usermods.add(new BuzzerUsermod());
#endif
#endif
#ifdef USERMOD_BME280
usermods.add(new UsermodBME280());
#endif
#ifdef USERMOD_SENSORSTOMQTT
usermods.add(new UserMod_SensorsToMQTT());
#endif

View File

@ -205,10 +205,18 @@ void WLED::loop()
handleHue();
handleBlynk();
/*if (presetToApply) {
applyPreset(presetToApply);
presetToApply = 0;
}*/
//LED settings have been saved, re-init busses
if (busConfigs[0] != nullptr) {
busses.removeAll();
for (uint8_t i = 0; i < WLED_MAX_BUSSES; i++) {
if (busConfigs[i] == nullptr) break;
busses.add(*busConfigs[i]);
delete busConfigs[i]; busConfigs[i] = nullptr;
}
strip.finalizeInit(useRGBW, ledCount, skipFirstLed);
yield();
serializeConfig();
}
yield();
@ -277,13 +285,10 @@ void WLED::setup()
DEBUG_PRINTLN(ESP.getFreeHeap());
registerUsermods();
//strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
//strip.setBrightness(0);
//DEBUG_PRINT(F("LEDs inited. heap usage ~"));
//DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
bool fsinit = false;
DEBUGFS_PRINTLN(F("Mount FS"));
#ifdef ARDUINO_ARCH_ESP32
@ -298,8 +303,16 @@ void WLED::setup()
updateFSInfo();
deserializeConfig();
#if STATUSLED && STATUSLED != LEDPIN
pinMode(STATUSLED, OUTPUT);
#if STATUSLED
bool lStatusLed = false;
for (uint8_t i=0; i<strip.numStrips; i++) {
if (strip.getStripPin(i)==STATUSLED) {
lStatusLed = true;
break;
}
}
if (!lStatusLed)
pinMode(STATUSLED, OUTPUT);
#endif
//DEBUG_PRINTLN(F("Load EEPROM"));
@ -312,7 +325,8 @@ void WLED::setup()
WiFi.persistent(false);
WiFi.onEvent(WiFiEvent);
Serial.println(F("Ada"));
// Serial.println(F("Ada"));
DEBUG_PRINTLN(F("Ada"));
// generate module IDs
escapedMac = WiFi.macAddress();
@ -356,25 +370,14 @@ void WLED::setup()
void WLED::beginStrip()
{
// Initialize NeoPixel Strip and button
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA)
ledCount = MAX_LEDS_DMA; // DMA method uses too much ram
#endif
#endif
if (ledCount > MAX_LEDS || ledCount == 0)
ledCount = 30;
strip.init(useRGBW, ledCount, skipFirstLed);
strip.finalizeInit(useRGBW, ledCount, skipFirstLed);
strip.setBrightness(0);
strip.setShowCallback(handleOverlayDraw);
#if defined(BTNPIN) && BTNPIN > -1
pinManager.allocatePin(BTNPIN, false);
pinMode(BTNPIN, INPUT_PULLUP);
#endif
if (bootPreset > 0) applyPreset(bootPreset);
if (turnOnAtBoot) {
if (briS > 0) bri = briS;
@ -384,24 +387,13 @@ void WLED::beginStrip()
}
colorUpdated(NOTIFIER_CALL_MODE_INIT);
// init relay pin
#if RLYPIN >= 0
pinManager.allocatePin(RLYPIN);
pinMode(RLYPIN, OUTPUT);
#if RLYMDE
digitalWrite(RLYPIN, bri);
#else
digitalWrite(RLYPIN, !bri);
#endif
#endif
// init relay pin
if (rlyPin>=0)
digitalWrite(rlyPin, (rlyMde ? bri : !bri));
// disable button if it is "pressed" unintentionally
#if (defined(BTNPIN) && BTNPIN > -1) || defined(TOUCHPIN)
if (isButtonPressed())
if (btnPin>=0 && isButtonPressed())
buttonEnabled = false;
#else
buttonEnabled = false;
#endif
}
void WLED::initAP(bool resetAP)
@ -432,7 +424,7 @@ void WLED::initAP(bool resetAP)
udp2Connected = notifier2Udp.begin(udpPort2);
}
e131.begin(false, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", WiFi.softAPIP());
}
@ -496,7 +488,7 @@ void WLED::initConnection()
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
char hostname[25] = "wled-";
prepareHostname(hostname);
#ifdef ESP8266
WiFi.hostname(hostname);
#endif
@ -647,7 +639,13 @@ void WLED::handleConnection()
void WLED::handleStatusLED()
{
#if STATUSLED && STATUSLED != LEDPIN
#if STATUSLED
for (uint8_t s=0; s<strip.numStrips; s++) {
if (strip.getStripPin(s)==STATUSLED) {
return; // pin used for strip
}
}
ledStatusType = WLED_CONNECTED ? 0 : 2;
if (mqttEnabled && ledStatusType != 2) // Wi-Fi takes presendence over MQTT
ledStatusType = WLED_MQTT_CONNECTED ? 0 : 4;
@ -663,7 +661,7 @@ void WLED::handleStatusLED()
#else
digitalWrite(STATUSLED, LOW);
#endif
}
#endif
}
}

View File

@ -3,12 +3,12 @@
/*
Main sketch, global variable declarations
@title WLED project sketch
@version 0.11.1
@version 0.12.0-a0
@author Christian Schwinne
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2101130
#define VERSION 2102050
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -115,6 +115,8 @@
#include "FX.h"
#include "ir_codes.h"
#include "const.h"
#include "pin_manager.h"
#include "bus_manager.h"
#ifndef CLIENT_SSID
#define CLIENT_SSID DEFAULT_CLIENT_SSID
@ -130,7 +132,7 @@
Comment out this error message to build regardless.
#endif
#if IRPIN < 0
#if !defined(IRPIN) || IRPIN < 0
#ifndef WLED_DISABLE_INFRARED
#define WLED_DISABLE_INFRARED
#endif
@ -174,8 +176,8 @@
#endif
// Global Variable definitions
WLED_GLOBAL char versionString[] _INIT("0.11.1");
#define WLED_CODENAME "Mirai"
WLED_GLOBAL char versionString[] _INIT("0.12.0-a0");
#define WLED_CODENAME "Hikari"
// AP and OTA default passwords (for maximum security change them!)
WLED_GLOBAL char apPass[65] _INIT(DEFAULT_AP_PASS);
@ -183,13 +185,29 @@ WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
// Hardware CONFIG (only changeble HERE, not at runtime)
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
#ifndef BTNPIN
WLED_GLOBAL int8_t btnPin _INIT(-1);
#else
WLED_GLOBAL int8_t btnPin _INIT(BTNPIN);
#endif
#ifndef RLYPIN
WLED_GLOBAL int8_t rlyPin _INIT(-1);
#else
WLED_GLOBAL int8_t rlyPin _INIT(RLYPIN);
#endif
#ifndef RLYMDE
WLED_GLOBAL bool rlyMde _INIT(1);
#else
WLED_GLOBAL bool rlyMde _INIT(RLYMDE);
#endif
#ifndef IRPIN
WLED_GLOBAL int8_t irPin _INIT(-1);
#else
WLED_GLOBAL int8_t irPin _INIT(IRPIN);
#endif
//WLED_GLOBAL byte presetToApply _INIT(0);
#if AUXPIN >= 0
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
#endif
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
@ -466,12 +484,18 @@ WLED_GLOBAL long lastInterfaceUpdate _INIT(0);
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
#if AUXPIN >= 0
// auxiliary debug pin
WLED_GLOBAL byte auxTime _INIT(0);
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
WLED_GLOBAL bool auxActive _INIT(false, auxActiveBefore _INIT(false);
// auxiliary debug pin
#ifndef AUXPIN
WLED_GLOBAL int8_t auxPin _INIT(-1);
#else
WLED_GLOBAL int8_t auxPin _INIT(AUXPIN);
#endif
WLED_GLOBAL byte auxTime _INIT(0);
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
WLED_GLOBAL bool auxActive _INIT(false);
WLED_GLOBAL bool auxActiveBefore _INIT(false);
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
// alexa udp
WLED_GLOBAL String escapedMac;
@ -504,7 +528,6 @@ WLED_GLOBAL JsonDocument* fileDoc;
WLED_GLOBAL bool doCloseFile _INIT(false);
// presets
WLED_GLOBAL uint16_t savedPresets _INIT(0);
WLED_GLOBAL int16_t currentPreset _INIT(-1);
WLED_GLOBAL bool isPreset _INIT(false);
@ -531,15 +554,15 @@ WLED_GLOBAL ESPAsyncE131 e131 _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]; //temporary, to remember values from network callback until after
// Usermod manager
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
WLED_GLOBAL PinManagerClass pinManager _INIT(PinManagerClass());
// Status LED
#if STATUSLED && STATUSLED != LEDPIN
#if STATUSLED
WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0);
WLED_GLOBAL unsigned short ledStatusType _INIT(0); // current status type - corresponds to number of blinks per second
WLED_GLOBAL bool ledStatusState _INIT(0); // the current LED state

View File

@ -39,9 +39,15 @@ void initServer()
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*");
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*");
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveview);
});
#ifdef WLED_ENABLE_WEBSOCKETS
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveviewws);
});
#else
server.on("/liveview", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_liveview);
});
#endif
//settings page
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest *request){

View File

@ -254,14 +254,60 @@ void getSettingsJS(byte subPage, char* dest)
}
if (subPage == 2) {
#ifdef ESP8266
#if LEDPIN == 3
oappend(SET_F("d.Sf.LC.max=500;"));
char nS[3];
// add usermod pins as d.um_p array (TODO: usermod config shouldn't use state. instead we should load "um" object from cfg.json)
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
JsonObject mods = doc.createNestedObject(F("mods"));
usermods.addToJsonState(mods);
if (!mods.isNull()) {
uint8_t i=0;
oappend(SET_F("d.um_p=["));
for (JsonPair kv : mods) {
if (strncmp_P(kv.key().c_str(),PSTR("pin_"),4) == 0) {
if (i++) oappend(SET_F(","));
oappend(itoa((int)kv.value(),nS,10));
}
}
oappend(SET_F("];"));
}
#if defined(WLED_MAX_BUSSES) && WLED_MAX_BUSSES>1
oappend(SET_F("addLEDs("));
oappend(itoa(WLED_MAX_BUSSES,nS,10));
oappend(SET_F(");"));
#endif
oappend(SET_F("d.Sf.LC.max=")); //TODO Formula for max LEDs on ESP8266 depending on types. 500 DMA or 1500 UART (about 4kB mem usage)
#if defined(ESP8266) && LEDPIN == 3
oappendi(MAX_LEDS_DMA);
#else
oappend(SET_F("d.Sf.LC.max=1500;"));
#endif
oappendi(MAX_LEDS);
#endif
oappend(";");
sappend('v',SET_F("LC"),ledCount);
for (uint8_t s=0; s < busses.getNumBusses(); s++){
Bus* bus = busses.getBus(s);
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
char lk[4] = "L1"; lk[2] = 48+s; lk[3] = 0; //strip clock pin. 255 for none
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
char co[4] = "CO"; co[2] = 48+s; co[3] = 0; //strip color order
char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type
char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED
char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse
oappend(SET_F("addLEDs(1);"));
uint8_t pins[5];
uint8_t nPins = bus->getPins(pins);
sappend('v', lp, pins[0]);
if (pinManager.isPinOk(pins[1])) sappend('v', lk, pins[1]);
sappend('v', lc, bus->getLength());
sappend('v',lt,bus->getType());
sappend('v',co,bus->getColorOrder());
sappend('v',ls,bus->getStart());
sappend('c',cv,bus->reversed);
}
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed);
if (strip.currentMilliamps)
@ -273,8 +319,8 @@ void getSettingsJS(byte subPage, char* dest)
}
sappend('v',SET_F("CA"),briS);
sappend('c',SET_F("EW"),useRGBW);
sappend('i',SET_F("CO"),strip.getColorOrder());
//sappend('c',SET_F("EW"),useRGBW);
//sappend('i',SET_F("CO"),strip.getColorOrder());
sappend('v',SET_F("AW"),strip.rgbwMode);
sappend('c',SET_F("BO"),turnOnAtBoot);
@ -292,6 +338,11 @@ void getSettingsJS(byte subPage, char* dest)
sappend('i',SET_F("PB"),strip.paletteBlend);
sappend('c',SET_F("RV"),strip.reverseMode);
sappend('c',SET_F("SL"),skipFirstLed);
sappend('v',SET_F("RL"),rlyPin);
sappend('c',SET_F("RM"),rlyMde);
sappend('v',SET_F("BT"),btnPin);
sappend('v',SET_F("IR"),irPin);
sappend('v',SET_F("AX"),auxPin);
}
if (subPage == 3)