mirror of
https://github.com/wled/WLED.git
synced 2025-07-08 19:36:33 +00:00
Merge branch '0_15' into 0_15_battery_usermod_readme
This commit is contained in:
commit
19ccff9ff1
@ -7,6 +7,7 @@ This Usermod is designed to read a `BME280` or `BMP280` sensor and output the fo
|
||||
- Dew Point (`BME280` only)
|
||||
|
||||
Configuration is performed via the Usermod menu. There are no parameters to set in code! The following settings can be configured in the Usermod Menu:
|
||||
- The i2c address in decimal. Set it to either 118 (0x76, the default) or 119 (0x77).
|
||||
- Temperature Decimals (number of decimal places to output)
|
||||
- Humidity Decimals
|
||||
- Pressure Decimals
|
||||
|
@ -24,6 +24,7 @@ private:
|
||||
uint8_t PressureDecimals = 0; // Number of decimal places in published pressure values
|
||||
uint16_t TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
|
||||
uint16_t PressureInterval = 300; // Interval to measure pressure in seconds
|
||||
BME280I2C::I2CAddr I2CAddress = BME280I2C::I2CAddr_0x76; // i2c address, defaults to 0x76
|
||||
bool PublishAlways = false; // Publish values even when they have not changed
|
||||
bool UseCelsius = true; // Use Celsius for Reporting
|
||||
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
|
||||
@ -35,20 +36,7 @@ private:
|
||||
#endif
|
||||
bool initDone = false;
|
||||
|
||||
// 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};
|
||||
BME280I2C bme;
|
||||
|
||||
uint8_t sensorType;
|
||||
|
||||
@ -181,34 +169,52 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void initializeBmeComms()
|
||||
{
|
||||
BME280I2C::Settings settings{
|
||||
BME280::OSR_X16, // Temperature oversampling x16
|
||||
BME280::OSR_X16, // Humidity oversampling x16
|
||||
BME280::OSR_X16, // Pressure oversampling x16
|
||||
BME280::Mode_Forced,
|
||||
BME280::StandbyTime_1000ms,
|
||||
BME280::Filter_Off,
|
||||
BME280::SpiEnable_False,
|
||||
I2CAddress
|
||||
};
|
||||
|
||||
bme.setSettings(settings);
|
||||
|
||||
if (!bme.begin())
|
||||
{
|
||||
sensorType = 0;
|
||||
DEBUG_PRINTLN(F("Could not find BME280 I2C sensor!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
sensorType = 1;
|
||||
DEBUG_PRINTLN(F("Found BME280 sensor! Success."));
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
sensorType = 2;
|
||||
DEBUG_PRINTLN(F("Found BMP280 sensor! No Humidity available."));
|
||||
break;
|
||||
default:
|
||||
sensorType = 0;
|
||||
DEBUG_PRINTLN(F("Found UNKNOWN sensor! Error!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
if (i2c_scl<0 || i2c_sda<0) { enabled = false; sensorType = 0; return; }
|
||||
|
||||
if (!bme.begin())
|
||||
{
|
||||
sensorType = 0;
|
||||
DEBUG_PRINTLN(F("Could not find BME280 I2C sensor!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
sensorType = 1;
|
||||
DEBUG_PRINTLN(F("Found BME280 sensor! Success."));
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
sensorType = 2;
|
||||
DEBUG_PRINTLN(F("Found BMP280 sensor! No Humidity available."));
|
||||
break;
|
||||
default:
|
||||
sensorType = 0;
|
||||
DEBUG_PRINTLN(F("Found UNKNOWN sensor! Error!"));
|
||||
}
|
||||
}
|
||||
initDone=true;
|
||||
initializeBmeComms();
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -365,7 +371,6 @@ public:
|
||||
}
|
||||
else if (sensorType==2) //BMP280
|
||||
{
|
||||
|
||||
JsonArray temperature_json = user.createNestedArray(F("Temperature"));
|
||||
JsonArray pressure_json = user.createNestedArray(F("Pressure"));
|
||||
temperature_json.add(roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals));
|
||||
@ -399,6 +404,7 @@ public:
|
||||
{
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
top[F("I2CAddress")] = static_cast<uint8_t>(I2CAddress);
|
||||
top[F("TemperatureDecimals")] = TemperatureDecimals;
|
||||
top[F("HumidityDecimals")] = HumidityDecimals;
|
||||
top[F("PressureDecimals")] = PressureDecimals;
|
||||
@ -426,6 +432,10 @@ public:
|
||||
|
||||
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
|
||||
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
|
||||
uint8_t tmpI2cAddress;
|
||||
configComplete &= getJsonValue(top[F("I2CAddress")], tmpI2cAddress, 0x76);
|
||||
I2CAddress = static_cast<BME280I2C::I2CAddr>(tmpI2cAddress);
|
||||
|
||||
configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1);
|
||||
configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0);
|
||||
configComplete &= getJsonValue(top[F("PressureDecimals")], PressureDecimals, 0);
|
||||
@ -440,8 +450,23 @@ public:
|
||||
// first run: reading from cfg.json
|
||||
DEBUG_PRINTLN(F(" config loaded."));
|
||||
} else {
|
||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||
// changing parameters from settings page
|
||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||
|
||||
// Reset all known values
|
||||
sensorType = 0;
|
||||
sensorTemperature = 0;
|
||||
sensorHumidity = 0;
|
||||
sensorHeatIndex = 0;
|
||||
sensorDewPoint = 0;
|
||||
sensorPressure = 0;
|
||||
lastTemperature = 0;
|
||||
lastHumidity = 0;
|
||||
lastHeatIndex = 0;
|
||||
lastDewPoint = 0;
|
||||
lastPressure = 0;
|
||||
|
||||
initializeBmeComms();
|
||||
}
|
||||
|
||||
return configComplete;
|
||||
|
@ -14,6 +14,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The initial delay before the first battery voltage reading after power-on.
|
||||
// This allows the voltage to stabilize before readings are taken, improving accuracy of initial reading.
|
||||
#ifndef USERMOD_BATTERY_INITIAL_DELAY
|
||||
#define USERMOD_BATTERY_INITIAL_DELAY 10000 // (milliseconds)
|
||||
#endif
|
||||
|
||||
// the frequency to check the battery, 30 sec
|
||||
#ifndef USERMOD_BATTERY_MEASUREMENT_INTERVAL
|
||||
#define USERMOD_BATTERY_MEASUREMENT_INTERVAL 30000
|
||||
|
@ -61,6 +61,7 @@ Enables battery level monitoring of your project.
|
||||
| `USERMOD_BATTERY` | | Define this (in `my_config.h`) to have this usermod included wled00\usermods_list.cpp |
|
||||
| `USERMOD_BATTERY_MEASUREMENT_PIN` | | Defaults to A0 on ESP8266 and GPIO35 on ESP32 |
|
||||
| `USERMOD_BATTERY_MEASUREMENT_INTERVAL` | ms | Battery check interval. defaults to 30 seconds |
|
||||
| `USERMOD_BATTERY_INITIAL_DELAY` | ms | Delay before initial reading. defaults to 10 seconds to allow voltage stabilization |
|
||||
| `USERMOD_BATTERY_{TYPE}_MIN_VOLTAGE` | v | Minimum battery voltage. default is 2.6 (18650 battery standard) |
|
||||
| `USERMOD_BATTERY_{TYPE}_MAX_VOLTAGE` | v | Maximum battery voltage. default is 4.2 (18650 battery standard) |
|
||||
| `USERMOD_BATTERY_{TYPE}_TOTAL_CAPACITY` | mAh | The capacity of all cells in parallel summed up |
|
||||
@ -138,6 +139,7 @@ Specification from: [Molicel INR18650-M35A, 3500mAh 10A Lithium-ion battery, 3.6
|
||||
|
||||
- Integrate factory pattern to make it easier to add other / custom battery types
|
||||
- Update readme
|
||||
- Improved initial reading accuracy by delaying initial measurement to allow voltage to stabilize at power-on
|
||||
|
||||
2023-01-04
|
||||
|
||||
|
@ -22,6 +22,10 @@ class UsermodBattery : public Usermod
|
||||
UMBattery* bat = new UnkownUMBattery();
|
||||
batteryConfig cfg;
|
||||
|
||||
// Initial delay before first reading to allow voltage stabilization
|
||||
unsigned long initialDelay = USERMOD_BATTERY_INITIAL_DELAY;
|
||||
bool initialDelayComplete = false;
|
||||
bool isFirstVoltageReading = true;
|
||||
// how often to read the battery voltage
|
||||
unsigned long readingInterval = USERMOD_BATTERY_MEASUREMENT_INTERVAL;
|
||||
unsigned long nextReadTime = 0;
|
||||
@ -137,7 +141,6 @@ class UsermodBattery : public Usermod
|
||||
if (pinManager.allocatePin(batteryPin, false, PinOwner::UM_Battery)) {
|
||||
DEBUG_PRINTLN(F("Battery pin allocation succeeded."));
|
||||
success = true;
|
||||
bat->setVoltage(readVoltage());
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
@ -148,10 +151,10 @@ class UsermodBattery : public Usermod
|
||||
}
|
||||
#else //ESP8266 boards have only one analog input pin A0
|
||||
pinMode(batteryPin, INPUT);
|
||||
bat->setVoltage(readVoltage());
|
||||
#endif
|
||||
|
||||
nextReadTime = millis() + readingInterval;
|
||||
// First voltage reading is delayed to allow voltage stabilization after powering up
|
||||
nextReadTime = millis() + initialDelay;
|
||||
lastReadTime = millis();
|
||||
|
||||
initDone = true;
|
||||
@ -178,6 +181,25 @@ class UsermodBattery : public Usermod
|
||||
|
||||
lowPowerIndicator();
|
||||
|
||||
// Handling the initial delay
|
||||
if (!initialDelayComplete && millis() < nextReadTime)
|
||||
return; // Continue to return until the initial delay is over
|
||||
|
||||
// Once the initial delay is over, set it as complete
|
||||
if (!initialDelayComplete)
|
||||
{
|
||||
initialDelayComplete = true;
|
||||
// Set the regular interval after initial delay
|
||||
nextReadTime = millis() + readingInterval;
|
||||
}
|
||||
|
||||
// Make the first voltage reading after the initial delay has elapsed
|
||||
if (isFirstVoltageReading)
|
||||
{
|
||||
bat->setVoltage(readVoltage());
|
||||
isFirstVoltageReading = false;
|
||||
}
|
||||
|
||||
// check the battery level every USERMOD_BATTERY_MEASUREMENT_INTERVAL (ms)
|
||||
if (millis() < nextReadTime) return;
|
||||
|
||||
|
@ -5054,25 +5054,25 @@ uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline
|
||||
SEGMENT.fill(BLACK);
|
||||
}
|
||||
|
||||
uint16_t xscale = SEGMENT.intensity*4;
|
||||
uint32_t yscale = SEGMENT.speed*8;
|
||||
uint8_t indexx = 0;
|
||||
unsigned xscale = SEGMENT.intensity*4;
|
||||
unsigned yscale = SEGMENT.speed*8;
|
||||
unsigned indexx = 0;
|
||||
|
||||
SEGPALETTE = CRGBPalette16( CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0), CRGB(0,0,0),
|
||||
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange,
|
||||
CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
|
||||
CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow);
|
||||
CRGBPalette16 pal = SEGMENT.check1 ? SEGPALETTE : CRGBPalette16(CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black,
|
||||
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::DarkOrange,
|
||||
CRGB::DarkOrange,CRGB::DarkOrange, CRGB::Orange, CRGB::Orange,
|
||||
CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow);
|
||||
|
||||
for (int j=0; j < cols; j++) {
|
||||
for (int i=0; i < rows; i++) {
|
||||
indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map.
|
||||
SEGMENT.setPixelColorXY(j, i, ColorFromPalette(SEGPALETTE, min(i*(indexx)>>4, 255), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
|
||||
indexx = inoise8(j*yscale*rows/255, i*xscale+strip.now/4); // We're moving along our Perlin map.
|
||||
SEGMENT.setPixelColorXY(j, i, ColorFromPalette(pal, min(i*(indexx)>>4, 255U), i*255/cols, LINEARBLEND)); // With that value, look up the 8 bit colour palette value and assign it to the current LED.
|
||||
} // for i
|
||||
} // for j
|
||||
|
||||
return FRAMETIME;
|
||||
} // mode_2Dfirenoise()
|
||||
static const char _data_FX_MODE_2DFIRENOISE[] PROGMEM = "Firenoise@X scale,Y scale;;!;2";
|
||||
static const char _data_FX_MODE_2DFIRENOISE[] PROGMEM = "Firenoise@X scale,Y scale,,,,Palette;;!;2;pal=66";
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
|
11
wled00/FX.h
11
wled00/FX.h
@ -90,7 +90,7 @@
|
||||
//#define SEGCOLOR(x) strip._segments[strip.getCurrSegmentId()].currentColor(x, strip._segments[strip.getCurrSegmentId()].colors[x])
|
||||
//#define SEGLEN strip._segments[strip.getCurrSegmentId()].virtualLength()
|
||||
#define SEGCOLOR(x) strip.segColor(x) /* saves us a few kbytes of code */
|
||||
#define SEGPALETTE strip._currentPalette
|
||||
#define SEGPALETTE Segment::getCurrentPalette()
|
||||
#define SEGLEN strip._virtualSegmentLength /* saves us a few kbytes of code */
|
||||
#define SPEED_FORMULA_L (5U + (50U*(255U - SEGMENT.speed))/SEGLEN)
|
||||
|
||||
@ -324,7 +324,8 @@ typedef enum mapping1D2D {
|
||||
M12_Pixels = 0,
|
||||
M12_pBar = 1,
|
||||
M12_pArc = 2,
|
||||
M12_pCorner = 3
|
||||
M12_pCorner = 3,
|
||||
M12_sPinwheel = 4
|
||||
} mapping1D2D_t;
|
||||
|
||||
// segment, 80 bytes
|
||||
@ -417,6 +418,7 @@ typedef struct Segment {
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
// perhaps this should be per segment, not static
|
||||
static CRGBPalette16 _currentPalette; // palette used for current effect (includes transition, used in color_from_palette())
|
||||
static CRGBPalette16 _randomPalette; // actual random palette
|
||||
static CRGBPalette16 _newRandomPalette; // target random palette
|
||||
static uint16_t _lastPaletteChange; // last random palette change time in millis()/1000
|
||||
@ -534,6 +536,7 @@ typedef struct Segment {
|
||||
static void modeBlend(bool blend) { _modeBlend = blend; }
|
||||
#endif
|
||||
static void handleRandomPalette();
|
||||
inline static const CRGBPalette16 &getCurrentPalette(void) { return Segment::_currentPalette; }
|
||||
|
||||
void setUp(uint16_t i1, uint16_t i2, uint8_t grp=1, uint8_t spc=0, uint16_t ofs=UINT16_MAX, uint16_t i1Y=0, uint16_t i2Y=1);
|
||||
bool setColor(uint8_t slot, uint32_t c); //returns true if changed
|
||||
@ -571,7 +574,7 @@ typedef struct Segment {
|
||||
uint8_t currentMode(void); // currently active effect/mode (while in transition)
|
||||
uint32_t currentColor(uint8_t slot); // currently active segment color (blended while in transition)
|
||||
CRGBPalette16 &loadPalette(CRGBPalette16 &tgt, uint8_t pal);
|
||||
CRGBPalette16 ¤tPalette(CRGBPalette16 &tgt, uint8_t paletteID);
|
||||
void setCurrentPalette(void);
|
||||
|
||||
// 1D strip
|
||||
uint16_t virtualLength(void) const;
|
||||
@ -706,7 +709,6 @@ class WS2812FX { // 96 bytes
|
||||
panels(1),
|
||||
#endif
|
||||
// semi-private (just obscured) used in effect functions through macros
|
||||
_currentPalette(CRGBPalette16(CRGB::Black)),
|
||||
_colors_t{0,0,0},
|
||||
_virtualSegmentLength(0),
|
||||
// true private variables
|
||||
@ -901,7 +903,6 @@ class WS2812FX { // 96 bytes
|
||||
// end 2D support
|
||||
|
||||
void loadCustomPalettes(void); // loads custom palettes from JSON
|
||||
CRGBPalette16 _currentPalette; // palette used for current effect (includes transition)
|
||||
std::vector<CRGBPalette16> customPalettes; // TODO: move custom palettes out of WS2812FX class
|
||||
|
||||
// using public variables to reduce code size increase due to inline function getSegment() (with bounds checking)
|
||||
|
@ -77,6 +77,7 @@ uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for t
|
||||
uint16_t Segment::maxWidth = DEFAULT_LED_COUNT;
|
||||
uint16_t Segment::maxHeight = 1;
|
||||
|
||||
CRGBPalette16 Segment::_currentPalette = CRGBPalette16(CRGB::Black);
|
||||
CRGBPalette16 Segment::_randomPalette = generateRandomPalette(); // was CRGBPalette16(DEFAULT_COLOR);
|
||||
CRGBPalette16 Segment::_newRandomPalette = generateRandomPalette(); // was CRGBPalette16(DEFAULT_COLOR);
|
||||
uint16_t Segment::_lastPaletteChange = 0; // perhaps it should be per segment
|
||||
@ -203,7 +204,7 @@ void Segment::resetIfRequired() {
|
||||
|
||||
CRGBPalette16 IRAM_ATTR &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
if (pal < 245 && pal > GRADIENT_PALETTE_COUNT+13) pal = 0;
|
||||
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0;
|
||||
if (pal > 245 && (strip.customPalettes.size() == 0 || 255U-pal > strip.customPalettes.size()-1)) pal = 0; // TODO remove strip dependency by moving customPalettes out of strip
|
||||
//default palette. Differs depending on effect
|
||||
if (pal == 0) switch (mode) {
|
||||
case FX_MODE_FIRE_2012 : pal = 35; break; // heat palette
|
||||
@ -334,8 +335,8 @@ void Segment::handleTransition() {
|
||||
// transition progression between 0-65535
|
||||
uint16_t IRAM_ATTR Segment::progress() {
|
||||
if (isInTransition()) {
|
||||
unsigned long timeNow = millis();
|
||||
if (_t->_dur > 0 && timeNow - _t->_start < _t->_dur) return (timeNow - _t->_start) * 0xFFFFU / _t->_dur;
|
||||
unsigned diff = millis() - _t->_start;
|
||||
if (_t->_dur > 0 && diff < _t->_dur) return diff * 0xFFFFU / _t->_dur;
|
||||
}
|
||||
return 0xFFFFU;
|
||||
}
|
||||
@ -438,18 +439,17 @@ uint32_t IRAM_ATTR Segment::currentColor(uint8_t slot) {
|
||||
#endif
|
||||
}
|
||||
|
||||
CRGBPalette16 IRAM_ATTR &Segment::currentPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
loadPalette(targetPalette, pal);
|
||||
void Segment::setCurrentPalette() {
|
||||
loadPalette(_currentPalette, palette);
|
||||
unsigned prog = progress();
|
||||
if (strip.paletteFade && prog < 0xFFFFU) {
|
||||
// blend palettes
|
||||
// there are about 255 blend passes of 48 "blends" to completely blend two palettes (in _dur time)
|
||||
// minimum blend time is 100ms maximum is 65535ms
|
||||
unsigned noOfBlends = ((255U * prog) / 0xFFFFU) - _t->_prevPaletteBlends;
|
||||
for (unsigned i=0; i<noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, targetPalette, 48);
|
||||
targetPalette = _t->_palT; // copy transitioning/temporary palette
|
||||
for (unsigned i = 0; i < noOfBlends; i++, _t->_prevPaletteBlends++) nblendPaletteTowardPalette(_t->_palT, _currentPalette, 48);
|
||||
_currentPalette = _t->_palT; // copy transitioning/temporary palette
|
||||
}
|
||||
return targetPalette;
|
||||
}
|
||||
|
||||
// relies on WS2812FX::service() to call it for each frame
|
||||
@ -637,6 +637,42 @@ uint16_t IRAM_ATTR Segment::nrOfVStrips() const {
|
||||
return vLen;
|
||||
}
|
||||
|
||||
// Constants for mapping mode "Pinwheel"
|
||||
#ifndef WLED_DISABLE_2D
|
||||
constexpr int Pinwheel_Steps_Small = 72; // no holes up to 16x16
|
||||
constexpr int Pinwheel_Size_Small = 16; // larger than this -> use "Medium"
|
||||
constexpr int Pinwheel_Steps_Medium = 192; // no holes up to 32x32
|
||||
constexpr int Pinwheel_Size_Medium = 32; // larger than this -> use "Big"
|
||||
constexpr int Pinwheel_Steps_Big = 304; // no holes up to 50x50
|
||||
constexpr int Pinwheel_Size_Big = 50; // larger than this -> use "XL"
|
||||
constexpr int Pinwheel_Steps_XL = 368;
|
||||
constexpr float Int_to_Rad_Small = (DEG_TO_RAD * 360) / Pinwheel_Steps_Small; // conversion: from 0...72 to Radians
|
||||
constexpr float Int_to_Rad_Med = (DEG_TO_RAD * 360) / Pinwheel_Steps_Medium; // conversion: from 0...192 to Radians
|
||||
constexpr float Int_to_Rad_Big = (DEG_TO_RAD * 360) / Pinwheel_Steps_Big; // conversion: from 0...304 to Radians
|
||||
constexpr float Int_to_Rad_XL = (DEG_TO_RAD * 360) / Pinwheel_Steps_XL; // conversion: from 0...368 to Radians
|
||||
|
||||
constexpr int Fixed_Scale = 512; // fixpoint scaling factor (9bit for fraction)
|
||||
|
||||
// Pinwheel helper function: pixel index to radians
|
||||
static float getPinwheelAngle(int i, int vW, int vH) {
|
||||
int maxXY = max(vW, vH);
|
||||
if (maxXY <= Pinwheel_Size_Small) return float(i) * Int_to_Rad_Small;
|
||||
if (maxXY <= Pinwheel_Size_Medium) return float(i) * Int_to_Rad_Med;
|
||||
if (maxXY <= Pinwheel_Size_Big) return float(i) * Int_to_Rad_Big;
|
||||
// else
|
||||
return float(i) * Int_to_Rad_XL;
|
||||
}
|
||||
// Pinwheel helper function: matrix dimensions to number of rays
|
||||
static int getPinwheelLength(int vW, int vH) {
|
||||
int maxXY = max(vW, vH);
|
||||
if (maxXY <= Pinwheel_Size_Small) return Pinwheel_Steps_Small;
|
||||
if (maxXY <= Pinwheel_Size_Medium) return Pinwheel_Steps_Medium;
|
||||
if (maxXY <= Pinwheel_Size_Big) return Pinwheel_Steps_Big;
|
||||
// else
|
||||
return Pinwheel_Steps_XL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 1D strip
|
||||
uint16_t IRAM_ATTR Segment::virtualLength() const {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@ -652,6 +688,9 @@ uint16_t IRAM_ATTR Segment::virtualLength() const {
|
||||
case M12_pArc:
|
||||
vLen = max(vW,vH); // get the longest dimension
|
||||
break;
|
||||
case M12_sPinwheel:
|
||||
vLen = getPinwheelLength(vW, vH);
|
||||
break;
|
||||
}
|
||||
return vLen;
|
||||
}
|
||||
@ -718,6 +757,52 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
for (int x = 0; x <= i; x++) setPixelColorXY(x, i, col);
|
||||
for (int y = 0; y < i; y++) setPixelColorXY(i, y, col);
|
||||
break;
|
||||
case M12_sPinwheel: {
|
||||
// i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small)
|
||||
float centerX = roundf((vW-1) / 2.0f);
|
||||
float centerY = roundf((vH-1) / 2.0f);
|
||||
float angleRad = getPinwheelAngle(i, vW, vH); // angle in radians
|
||||
float cosVal = cos_t(angleRad);
|
||||
float sinVal = sin_t(angleRad);
|
||||
|
||||
// avoid re-painting the same pixel
|
||||
int lastX = INT_MIN; // impossible position
|
||||
int lastY = INT_MIN; // impossible position
|
||||
// draw line at angle, starting at center and ending at the segment edge
|
||||
// we use fixed point math for better speed. Starting distance is 0.5 for better rounding
|
||||
// int_fast16_t and int_fast32_t types changed to int, minimum bits commented
|
||||
int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit
|
||||
int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit
|
||||
int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit
|
||||
int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit
|
||||
|
||||
int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint
|
||||
int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint
|
||||
|
||||
// Odd rays start further from center if prevRay started at center.
|
||||
static int prevRay = INT_MIN; // previous ray number
|
||||
if ((i % 2 == 1) && (i - 1 == prevRay || i + 1 == prevRay)) {
|
||||
int jump = min(vW/3, vH/3); // can add 2 if using medium pinwheel
|
||||
posx += inc_x * jump;
|
||||
posy += inc_y * jump;
|
||||
}
|
||||
prevRay = i;
|
||||
|
||||
// draw ray until we hit any edge
|
||||
while ((posx >= 0) && (posy >= 0) && (posx < maxX) && (posy < maxY)) {
|
||||
// scale down to integer (compiler will replace division with appropriate bitshift)
|
||||
int x = posx / Fixed_Scale;
|
||||
int y = posy / Fixed_Scale;
|
||||
// set pixel
|
||||
if (x != lastX || y != lastY) setPixelColorXY(x, y, col); // only paint if pixel position is different
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
// advance to next position
|
||||
posx += inc_x;
|
||||
posy += inc_y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) {
|
||||
@ -833,7 +918,36 @@ uint32_t IRAM_ATTR Segment::getPixelColor(int i)
|
||||
// use longest dimension
|
||||
return vW>vH ? getPixelColorXY(i, 0) : getPixelColorXY(0, i);
|
||||
break;
|
||||
}
|
||||
case M12_sPinwheel:
|
||||
// not 100% accurate, returns pixel at outer edge
|
||||
// i = angle --> 0 - 296 (Big), 0 - 192 (Medium), 0 - 72 (Small)
|
||||
float centerX = roundf((vW-1) / 2.0f);
|
||||
float centerY = roundf((vH-1) / 2.0f);
|
||||
float angleRad = getPinwheelAngle(i, vW, vH); // angle in radians
|
||||
float cosVal = cos_t(angleRad);
|
||||
float sinVal = sin_t(angleRad);
|
||||
|
||||
int posx = (centerX + 0.5f * cosVal) * Fixed_Scale; // X starting position in fixed point 18 bit
|
||||
int posy = (centerY + 0.5f * sinVal) * Fixed_Scale; // Y starting position in fixed point 18 bit
|
||||
int inc_x = cosVal * Fixed_Scale; // X increment per step (fixed point) 10 bit
|
||||
int inc_y = sinVal * Fixed_Scale; // Y increment per step (fixed point) 10 bit
|
||||
int32_t maxX = vW * Fixed_Scale; // X edge in fixedpoint
|
||||
int32_t maxY = vH * Fixed_Scale; // Y edge in fixedpoint
|
||||
|
||||
// trace ray from center until we hit any edge - to avoid rounding problems, we use the same method as in setPixelColor
|
||||
int x = INT_MIN;
|
||||
int y = INT_MIN;
|
||||
while ((posx >= 0) && (posy >= 0) && (posx < maxX) && (posy < maxY)) {
|
||||
// scale down to integer (compiler will replace division with appropriate bitshift)
|
||||
x = posx / Fixed_Scale;
|
||||
y = posy / Fixed_Scale;
|
||||
// advance to next position
|
||||
posx += inc_x;
|
||||
posy += inc_y;
|
||||
}
|
||||
return getPixelColorXY(x, y);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -1069,9 +1183,7 @@ uint32_t Segment::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8_
|
||||
if (mapping && virtualLength() > 1) paletteIndex = (i*255)/(virtualLength() -1);
|
||||
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
|
||||
if (!wrap && strip.paletteBlend != 3) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||
CRGBPalette16 curPal;
|
||||
curPal = currentPalette(curPal, palette);
|
||||
CRGB fastled_col = ColorFromPalette(curPal, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global
|
||||
CRGB fastled_col = ColorFromPalette(_currentPalette, paletteIndex, pbri, (strip.paletteBlend == 3)? NOBLEND:LINEARBLEND); // NOTE: paletteBlend should be global
|
||||
|
||||
return RGBW32(fastled_col.r, fastled_col.g, fastled_col.b, W(color));
|
||||
}
|
||||
@ -1184,7 +1296,7 @@ void WS2812FX::service() {
|
||||
_colors_t[0] = gamma32(seg.currentColor(0));
|
||||
_colors_t[1] = gamma32(seg.currentColor(1));
|
||||
_colors_t[2] = gamma32(seg.currentColor(2));
|
||||
seg.currentPalette(_currentPalette, seg.palette); // we need to pass reference
|
||||
seg.setCurrentPalette(); // load actual palette
|
||||
// when correctWB is true we need to correct/adjust RGB value according to desired CCT value, but it will also affect actual WW/CW ratio
|
||||
// when cctFromRgb is true we implicitly calculate WW and CW from RGB values
|
||||
if (cctFromRgb) BusManager::setSegmentCCT(-1);
|
||||
|
@ -17,6 +17,11 @@
|
||||
#if !defined(WLED_NO_I2S1_PIXELBUS) && (defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2))
|
||||
#define WLED_NO_I2S1_PIXELBUS
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifdef WLED_USE_PARALLEL_I2S
|
||||
#warning Use less than 300 pixels per bus.
|
||||
#endif
|
||||
#endif
|
||||
// temporary end
|
||||
|
||||
//Hardware SPI Pins
|
||||
@ -224,8 +229,11 @@
|
||||
//#define B_32_I0_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Ws2812xMethod, NeoGammaNullMethod>
|
||||
//#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_NEO_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Ws2812xMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//RGBW
|
||||
#define B_32_RN_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32RmtNSk6812Method, NeoGammaNullMethod>
|
||||
@ -234,8 +242,11 @@
|
||||
//#define B_32_I0_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s0X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1Sk6812Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_NEO_4 NeoPixelBusLg<NeoGrbwFeature, NeoEsp32I2s1X8Sk6812Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//400Kbps
|
||||
#define B_32_RN_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtN400KbpsMethod, NeoGammaNullMethod>
|
||||
@ -244,8 +255,11 @@
|
||||
//#define B_32_I0_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1400KbpsMethod, NeoGammaNullMethod>
|
||||
//#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_400_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8400KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//TM1814 (RGBW)
|
||||
#define B_32_RN_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32RmtNTm1814Method, NeoGammaNullMethod>
|
||||
@ -254,8 +268,11 @@
|
||||
//#define B_32_I0_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s0X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1Tm1814Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_TM1_4 NeoPixelBusLg<NeoWrgbTm1814Feature, NeoEsp32I2s1X8Tm1814Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//TM1829 (RGB)
|
||||
#define B_32_RN_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32RmtNTm1829Method, NeoGammaNullMethod>
|
||||
@ -264,8 +281,11 @@
|
||||
//#define B_32_I0_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s0X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1Tm1829Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_TM2_3 NeoPixelBusLg<NeoBrgFeature, NeoEsp32I2s1X8Tm1829Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//UCS8903
|
||||
#define B_32_RN_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||
@ -274,8 +294,11 @@
|
||||
//#define B_32_I0_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||
//#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_UCS_3 NeoPixelBusLg<NeoRgbUcs8903Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//UCS8904
|
||||
#define B_32_RN_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||
@ -284,8 +307,11 @@
|
||||
//#define B_32_I0_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||
//#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
|
||||
#else
|
||||
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod>// parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
|
||||
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||
@ -293,8 +319,11 @@
|
||||
//#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0X8Apa106Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Apa106Method, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1X8Apa106Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//FW1906 GRBCW
|
||||
#define B_32_RN_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32RmtNWs2812xMethod, NeoGammaNullMethod>
|
||||
@ -303,8 +332,11 @@
|
||||
//#define B_32_I0_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s0X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||
//#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_FW6_5 NeoPixelBusLg<NeoGrbcwxFeature, NeoEsp32I2s1X8800KbpsMethod, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//WS2805 RGBWC
|
||||
#define B_32_RN_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32RmtNWs2805Method, NeoGammaNullMethod>
|
||||
@ -313,8 +345,11 @@
|
||||
//#define B_32_I0_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s0X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1Ws2805Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
|
||||
#else
|
||||
#define B_32_I1_2805_5 NeoPixelBusLg<NeoGrbwwFeature, NeoEsp32I2s1X8Ws2805Method, NeoGammaNullMethod> // parallel I2S
|
||||
#endif
|
||||
#endif
|
||||
//TM1914 (RGB)
|
||||
#define B_32_RN_TM1914_3 NeoPixelBusLg<NeoGrbTm1914Feature, NeoEsp32RmtNTm1914Method, NeoGammaNullMethod>
|
||||
@ -323,8 +358,11 @@
|
||||
//#define B_32_I0_TM1914_3 NeoPixelBusLg<NeoGrbTm1914Feature, NeoEsp32I2s0X8Tm1914Method, NeoGammaNullMethod>
|
||||
#endif
|
||||
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define B_32_I1_TM1914_3 NeoPixelBusLg<NeoGrbTm1914Feature, NeoEsp32I2s1Tm1914Method, NeoGammaNullMethod>
|
||||
//#define B_32_I1_TM1914_3 NeoPixelBusLg<NeoGrbTm1914Feature, NeoEsp32I2s1X8Tm1914Method, NeoGammaNullMethod>
|
||||
#else
|
||||
#define B_32_I1_TM1914_3 NeoPixelBusLg<NeoGrbTm1914Feature, NeoEsp32I2s1X8Tm1914Method, NeoGammaNullMethod>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -541,7 +579,11 @@ class PolyBus {
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3))
|
||||
// NOTE: "channel" is only used on ESP32 (and its variants) for RMT channel allocation
|
||||
// since 0.15.0-b3 I2S1 is favoured for classic ESP32 and moved to position 0 (channel 0) so we need to subtract 1 for correct RMT allocation
|
||||
#ifdef WLED_USE_PARALLEL_I2S
|
||||
if (channel > 7) channel -= 8; // accommodate parallel I2S1 which is used 1st on classic ESP32
|
||||
#else
|
||||
if (channel > 0) channel--; // accommodate I2S1 which is used as 1st bus on classic ESP32
|
||||
#endif
|
||||
#endif
|
||||
void* busPtr = nullptr;
|
||||
switch (busType) {
|
||||
@ -1619,9 +1661,15 @@ class PolyBus {
|
||||
//if (num > 3) offset = num -4; // I2S not supported yet
|
||||
#else
|
||||
// standard ESP32 has 8 RMT and 2 I2S channels
|
||||
#ifdef WLED_USE_PARALLEL_I2S
|
||||
if (num > 16) return I_NONE;
|
||||
if (num < 8) offset = 2; // prefer 8 parallel I2S1 channels
|
||||
if (num == 16) offset = 1;
|
||||
#else
|
||||
if (num > 9) return I_NONE;
|
||||
if (num > 8) offset = 1;
|
||||
if (num == 0) offset = 2; // prefer I2S1 for 1st bus (less flickering but more RAM needed)
|
||||
#endif
|
||||
#endif
|
||||
switch (busType) {
|
||||
case TYPE_WS2812_1CH_X3:
|
||||
|
@ -124,7 +124,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(strip.panels, matrix[F("mpc")]);
|
||||
strip.panel.clear();
|
||||
JsonArray panels = matrix[F("panels")];
|
||||
uint8_t s = 0;
|
||||
int s = 0;
|
||||
if (!panels.isNull()) {
|
||||
strip.panel.reserve(max(1U,min((size_t)strip.panels,(size_t)WLED_MAX_PANELS))); // pre-allocate memory for panels
|
||||
for (JsonObject pnl : panels) {
|
||||
@ -156,7 +156,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonArray ins = hw_led["ins"];
|
||||
|
||||
if (fromFS || !ins.isNull()) {
|
||||
uint8_t s = 0; // bus iterator
|
||||
int s = 0; // bus iterator
|
||||
if (fromFS) BusManager::removeAll(); // can't safely manipulate busses directly in network callback
|
||||
uint32_t mem = 0, globalBufMem = 0;
|
||||
uint16_t maxlen = 0;
|
||||
@ -790,7 +790,7 @@ void serializeConfig() {
|
||||
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
||||
matrix[F("mpc")] = strip.panels;
|
||||
JsonArray panels = matrix.createNestedArray(F("panels"));
|
||||
for (uint8_t i=0; i<strip.panel.size(); i++) {
|
||||
for (size_t i = 0; i < strip.panel.size(); i++) {
|
||||
JsonObject pnl = panels.createNestedObject();
|
||||
pnl["b"] = strip.panel[i].bottomStart;
|
||||
pnl["r"] = strip.panel[i].rightStart;
|
||||
@ -806,7 +806,7 @@ void serializeConfig() {
|
||||
|
||||
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
||||
|
||||
for (uint8_t s = 0; s < BusManager::getNumBusses(); s++) {
|
||||
for (size_t s = 0; s < BusManager::getNumBusses(); s++) {
|
||||
Bus *bus = BusManager::getBus(s);
|
||||
if (!bus || bus->getLength()==0) break;
|
||||
JsonObject ins = hw_led_ins.createNestedObject();
|
||||
@ -815,7 +815,7 @@ void serializeConfig() {
|
||||
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]);
|
||||
for (int i = 0; i < nPins; i++) ins_pin.add(pins[i]);
|
||||
ins[F("order")] = bus->getColorOrder();
|
||||
ins["rev"] = bus->isReversed();
|
||||
ins[F("skip")] = bus->skippedLeds();
|
||||
@ -829,7 +829,7 @@ void serializeConfig() {
|
||||
|
||||
JsonArray hw_com = hw.createNestedArray(F("com"));
|
||||
const ColorOrderMap& com = BusManager::getColorOrderMap();
|
||||
for (uint8_t s = 0; s < com.count(); s++) {
|
||||
for (size_t s = 0; s < com.count(); s++) {
|
||||
const ColorOrderMapEntry *entry = com.get(s);
|
||||
if (!entry) break;
|
||||
|
||||
@ -846,7 +846,7 @@ void serializeConfig() {
|
||||
JsonArray hw_btn_ins = hw_btn.createNestedArray("ins");
|
||||
|
||||
// configuration for all buttons
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
for (int i = 0; i < WLED_MAX_BUTTONS; i++) {
|
||||
JsonObject hw_btn_ins_0 = hw_btn_ins.createNestedObject();
|
||||
hw_btn_ins_0["type"] = buttonType[i];
|
||||
JsonArray hw_btn_ins_0_pin = hw_btn_ins_0.createNestedArray("pin");
|
||||
|
@ -60,8 +60,12 @@
|
||||
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
|
||||
#define WLED_MIN_VIRTUAL_BUSSES 4
|
||||
#else
|
||||
// the 10th digital bus (I2S0) will prevent Audioreactive usermod from functioning (it is last used though)
|
||||
// the last digital bus (I2S0) will prevent Audioreactive usermod from functioning
|
||||
#ifndef WLED_USE_PARALLEL_I2S
|
||||
#define WLED_MAX_BUSSES 10
|
||||
#else
|
||||
#define WLED_MAX_BUSSES 17
|
||||
#endif
|
||||
#define WLED_MIN_VIRTUAL_BUSSES 0
|
||||
#endif
|
||||
#endif
|
||||
|
@ -801,6 +801,7 @@ function populateSegments(s)
|
||||
`<option value="1" ${inst.m12==1?' selected':''}>Bar</option>`+
|
||||
`<option value="2" ${inst.m12==2?' selected':''}>Arc</option>`+
|
||||
`<option value="3" ${inst.m12==3?' selected':''}>Corner</option>`+
|
||||
`<option value="4" ${inst.m12==4?' selected':''}>Pinwheel</option>`+
|
||||
`</select></div>`+
|
||||
`</div>`;
|
||||
let sndSim = `<div data-snd="si" class="lbl-s hide">Sound sim<br>`+
|
||||
|
@ -5,12 +5,12 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
|
||||
<title>LED Settings</title>
|
||||
<script>
|
||||
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxCO=10,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||
d.um_p = [];
|
||||
d.rsvd = [];
|
||||
d.ro_gpio = [];
|
||||
d.max_gpio = 50;
|
||||
var customStarts=false,startsDirty=[],maxCOOverrides=5;
|
||||
var customStarts=false,startsDirty=[];
|
||||
var loc = false, locip, locproto = "http:";
|
||||
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
|
||||
function B(){window.open(getURL("/settings"),"_self");}
|
||||
@ -57,8 +57,8 @@
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}
|
||||
function bLimits(b,v,p,m,l) {
|
||||
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l;
|
||||
function bLimits(b,v,p,m,l,o) {
|
||||
maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
|
||||
}
|
||||
function pinsOK() {
|
||||
var ok = true;
|
||||
@ -138,7 +138,8 @@
|
||||
gId("psuMA").style.display = ppl ? 'none' : 'inline';
|
||||
gId("ppldis").style.display = ppl ? 'inline' : 'none';
|
||||
// set PPL minimum value and clear actual PPL limit if ABL disabled
|
||||
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,n)=>{
|
||||
d.Sf.querySelectorAll("#mLC input[name^=MA]").forEach((i,x)=>{
|
||||
var n = String.fromCharCode((x<10?48:55)+x);
|
||||
gId("PSU"+n).style.display = ppl ? "inline" : "none";
|
||||
const t = parseInt(d.Sf["LT"+n].value); // LED type SELECT
|
||||
const c = parseInt(d.Sf["LC"+n].value); //get LED count
|
||||
@ -164,8 +165,9 @@
|
||||
if (parseInt(i.value) > 0) d.Sf.ABL.checked = true;
|
||||
});
|
||||
// select appropriate LED current
|
||||
d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,n)=>{
|
||||
d.Sf.querySelectorAll("#mLC select[name^=LAsel]").forEach((sel,x)=>{
|
||||
sel.value = 0; // set custom
|
||||
var n = String.fromCharCode((x<10?48:55)+x);
|
||||
switch (parseInt(d.Sf["LA"+n].value)) {
|
||||
case 0: break; // disable ABL
|
||||
case 15: sel.value = 15; break;
|
||||
@ -358,10 +360,11 @@
|
||||
gId("json").style.display = d.Sf.IT.value==8 ? "" : "none";
|
||||
}
|
||||
function lastEnd(i) {
|
||||
if (i<1) return 0;
|
||||
v = parseInt(d.getElementsByName("LS"+(i-1))[0].value) + parseInt(d.getElementsByName("LC"+(i-1))[0].value);
|
||||
var t = parseInt(d.getElementsByName("LT"+(i-1))[0].value);
|
||||
if (t > 31 && t < 48) v = 1; //PWM busses
|
||||
if (i-- < 1) return 0;
|
||||
var s = String.fromCharCode((i<10?48:55)+i);
|
||||
v = parseInt(d.getElementsByName("LS"+s)[0].value) + parseInt(d.getElementsByName("LC"+s)[0].value);
|
||||
var t = parseInt(d.getElementsByName("LT"+s)[0].value);
|
||||
if (isPWM(t)) v = 1; //PWM busses
|
||||
if (isNaN(v)) return 0;
|
||||
return v;
|
||||
}
|
||||
@ -371,6 +374,7 @@
|
||||
var i = o.length;
|
||||
|
||||
if ((n==1 && i>=maxB+maxV) || (n==-1 && i==0)) return;
|
||||
var s = String.fromCharCode((i<10?48:55)+i);
|
||||
|
||||
var f = gId("mLC");
|
||||
if (n==1) {
|
||||
@ -378,7 +382,7 @@
|
||||
var cn = `<div class="iST">
|
||||
<hr class="sml">
|
||||
${i+1}:
|
||||
<select name="LT${i}" onchange="UI(true)">${i>=maxB ? '' :
|
||||
<select name="LT${s}" onchange="UI(true)">${i>=maxB ? '' :
|
||||
'<option value="22" selected>WS281x</option>\
|
||||
<option value="30">SK6812/WS2814 RGBW</option>\
|
||||
<option value="31">TM1814</option>\
|
||||
@ -409,8 +413,8 @@ ${i+1}:
|
||||
<option value="88">DDP RGBW (network)</option>
|
||||
<option value="89">Art-Net RGBW (network)</option>
|
||||
</select><br>
|
||||
<div id="abl${i}">
|
||||
mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
||||
<div id="abl${s}">
|
||||
mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
|
||||
<option value="55" selected>55mA (typ. 5V WS281x)</option>
|
||||
<option value="35">35mA (eco WS2812)</option>
|
||||
<option value="30">30mA (typ. 12V)</option>
|
||||
@ -418,11 +422,11 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
||||
<option value="15">15mA (seed/fairy pixels)</option>
|
||||
<option value="0">Custom</option>
|
||||
</select><br>
|
||||
<div id="LAdis${i}" style="display: none;">max. mA/LED: <input name="LA${i}" type="number" min="1" max="255" oninput="UI()"> mA<br></div>
|
||||
<div id="PSU${i}">PSU: <input name="MA${i}" type="number" class="xl" min="250" max="65000" oninput="UI()" value="250"> mA<br></div>
|
||||
<div id="LAdis${s}" style="display: none;">max. mA/LED: <input name="LA${s}" type="number" min="1" max="255" oninput="UI()"> mA<br></div>
|
||||
<div id="PSU${s}">PSU: <input name="MA${s}" type="number" class="xl" min="250" max="65000" oninput="UI()" value="250"> mA<br></div>
|
||||
</div>
|
||||
<div id="co${i}" style="display:inline">Color Order:
|
||||
<select name="CO${i}">
|
||||
<div id="co${s}" style="display:inline">Color Order:
|
||||
<select name="CO${s}">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
@ -430,21 +434,21 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
||||
<option value="4">BGR</option>
|
||||
<option value="5">GBR</option>
|
||||
</select></div>
|
||||
<div id="dig${i}w" style="display:none">Swap: <select name="WO${i}"><option value="0">None</option><option value="1">W & B</option><option value="2">W & G</option><option value="3">W & R</option></select></div>
|
||||
<div id="dig${i}l" style="display:none">Clock: <select name="SP${i}"><option value="0">Slowest</option><option value="1">Slow</option><option value="2">Normal</option><option value="3">Fast</option><option value="4">Fastest</option></select></div>
|
||||
<div id="dig${s}w" style="display:none">Swap: <select name="WO${s}"><option value="0">None</option><option value="1">W & B</option><option value="2">W & G</option><option value="3">W & R</option></select></div>
|
||||
<div id="dig${s}l" style="display:none">Clock: <select name="SP${s}"><option value="0">Slowest</option><option value="1">Slow</option><option value="2">Normal</option><option value="3">Fast</option><option value="4">Fastest</option></select></div>
|
||||
<div>
|
||||
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />
|
||||
<div id="dig${i}c" style="display:inline">Length: <input type="number" name="LC${i}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br>
|
||||
<span id="psd${s}">Start:</span> <input type="number" name="LS${s}" id="ls${s}" class="l starts" min="0" max="8191" value="${lastEnd(i)}" oninput="startsDirty[${i}]=true;UI();" required />
|
||||
<div id="dig${s}c" style="display:inline">Length: <input type="number" name="LC${s}" class="l" min="1" max="${maxPB}" value="1" required oninput="UI()" /></div><br>
|
||||
</div>
|
||||
<span id="p0d${i}">GPIO:</span><input type="number" name="L0${i}" required class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p1d${i}"></span><input type="number" name="L1${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p2d${i}"></span><input type="number" name="L2${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p3d${i}"></span><input type="number" name="L3${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p4d${i}"></span><input type="number" name="L4${i}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<div id="dig${i}r" style="display:inline"><br><span id="rev${i}">Reversed</span>: <input type="checkbox" name="CV${i}"></div>
|
||||
<div id="dig${i}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${i}" min="0" max="255" value="0" oninput="UI()"></div>
|
||||
<div id="dig${i}f" style="display:inline"><br>Off Refresh: <input id="rf${i}" type="checkbox" name="RF${i}"></div>
|
||||
<div id="dig${i}a" style="display:inline"><br>Auto-calculate white channel from RGB:<br><select name="AW${i}"><option value=0>None</option><option value=1>Brighter</option><option value=2>Accurate</option><option value=3>Dual</option><option value=4>Max</option></select> </div>
|
||||
<span id="p0d${s}">GPIO:</span><input type="number" name="L0${s}" required class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p1d${s}"></span><input type="number" name="L1${s}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p2d${s}"></span><input type="number" name="L2${s}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p3d${s}"></span><input type="number" name="L3${s}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<span id="p4d${s}"></span><input type="number" name="L4${s}" class="s" onchange="UI();pinUpd(this);"/>
|
||||
<div id="dig${s}r" style="display:inline"><br><span id="rev${s}">Reversed</span>: <input type="checkbox" name="CV${s}"></div>
|
||||
<div id="dig${s}s" style="display:inline"><br>Skip first LEDs: <input type="number" name="SL${s}" min="0" max="255" value="0" oninput="UI()"></div>
|
||||
<div id="dig${s}f" style="display:inline"><br>Off Refresh: <input id="rf${s}" type="checkbox" name="RF${s}"></div>
|
||||
<div id="dig${s}a" style="display:inline"><br>Auto-calculate white channel from RGB:<br><select name="AW${s}"><option value=0>None</option><option value=1>Brighter</option><option value=2>Accurate</option><option value=3>Dual</option><option value=4>Max</option></select> </div>
|
||||
</div>`;
|
||||
f.insertAdjacentHTML("beforeend", cn);
|
||||
}
|
||||
@ -462,14 +466,14 @@ mA/LED: <select name="LAsel${i}" onchange="enLA(this,${i});UI();">
|
||||
|
||||
function addCOM(start=0,len=1,co=0) {
|
||||
var i = d.getElementsByClassName("com_entry").length;
|
||||
if (i >= 10) return;
|
||||
|
||||
if (i >= maxCO) return;
|
||||
var s = String.fromCharCode((i<10?48:55)+i);
|
||||
var b = `<div class="com_entry">
|
||||
<hr class="sml">
|
||||
${i+1}: Start: <input type="number" name="XS${i}" id="xs${i}" class="l starts" min="0" max="65535" value="${start}" oninput="UI();" required="">
|
||||
Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65535" value="${len}" required="" oninput="UI()">
|
||||
${i+1}: Start: <input type="number" name="XS${s}" id="xs${s}" class="l starts" min="0" max="65535" value="${start}" oninput="UI();" required="">
|
||||
Length: <input type="number" name="XC${s}" id="xc${s}" class="l" min="1" max="65535" value="${len}" required="" oninput="UI()">
|
||||
<div>Color Order:
|
||||
<select id="xo${i}" name="XO${i}">
|
||||
<select id="xo${s}" name="XO${s}">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
@ -477,7 +481,7 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
||||
<option value="4">BGR</option>
|
||||
<option value="5">GBR</option>
|
||||
</select>
|
||||
Swap: <select id="xw${i}" name="XW${i}">
|
||||
Swap: <select id="xw${s}" name="XW${s}">
|
||||
<option value="0">Use global</option>
|
||||
<option value="1">W & B</option>
|
||||
<option value="2">W & G</option>
|
||||
@ -485,8 +489,8 @@ Swap: <select id="xw${i}" name="XW${i}">
|
||||
</select>
|
||||
</div></div>`;
|
||||
gId("com_entries").insertAdjacentHTML("beforeend", b);
|
||||
gId("xo"+i).value = co & 0x0F;
|
||||
gId("xw"+i).value = co >> 4;
|
||||
gId("xo"+s).value = co & 0x0F;
|
||||
gId("xw"+s).value = co >> 4;
|
||||
btnCOM(i+1);
|
||||
UI();
|
||||
}
|
||||
@ -502,7 +506,7 @@ Swap: <select id="xw${i}" name="XW${i}">
|
||||
|
||||
function resetCOM(_newMaxCOOverrides=undefined) {
|
||||
if (_newMaxCOOverrides) {
|
||||
maxCOOverrides = _newMaxCOOverrides;
|
||||
maxCO = _newMaxCOOverrides;
|
||||
}
|
||||
for (let e of d.getElementsByClassName("com_entry")) {
|
||||
e.remove();
|
||||
@ -511,16 +515,15 @@ Swap: <select id="xw${i}" name="XW${i}">
|
||||
}
|
||||
|
||||
function btnCOM(i) {
|
||||
gId("com_add").style.display = (i<maxCOOverrides) ? "inline":"none";
|
||||
gId("com_add").style.display = (i<maxCO) ? "inline":"none";
|
||||
gId("com_rem").style.display = (i>0) ? "inline":"none";
|
||||
}
|
||||
|
||||
function addBtn(i,p,t) {
|
||||
var c = gId("btns").innerHTML;
|
||||
var bt = "BT" + String.fromCharCode((i<10?48:55)+i);
|
||||
var be = "BE" + String.fromCharCode((i<10?48:55)+i);
|
||||
c += `Button ${i} GPIO: <input type="number" name="${bt}" onchange="UI()" class="xs" value="${p}">`;
|
||||
c += ` <select name="${be}">`
|
||||
var s = String.fromCharCode((i<10?48:55)+i);
|
||||
c += `Button ${i} GPIO: <input type="number" name="BT${s}" onchange="UI()" class="xs" value="${p}">`;
|
||||
c += ` <select name="BE${s}">`
|
||||
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
|
||||
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
|
||||
c += `<option value="3" ${t==3?"selected":""}>Push inverted</option>`;
|
||||
@ -531,7 +534,7 @@ Swap: <select id="xw${i}" name="XW${i}">
|
||||
c += `<option value="8" ${t==8?"selected":""}>Analog inverted</option>`;
|
||||
c += `<option value="9" ${t==9?"selected":""}>Touch (switch)</option>`;
|
||||
c += `</select>`;
|
||||
c += `<span style="cursor: pointer;" onclick="off('${bt}')"> ✕</span><br>`;
|
||||
c += `<span style="cursor: pointer;" onclick="off('BT${s}')"> ✕</span><br>`;
|
||||
gId("btns").innerHTML = c;
|
||||
}
|
||||
function tglSi(cs) {
|
||||
|
@ -136,27 +136,28 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
useGlobalLedBuffer = request->hasArg(F("LD"));
|
||||
|
||||
bool busesChanged = false;
|
||||
for (uint8_t s = 0; s < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; s++) {
|
||||
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||
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
|
||||
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip first N LEDs
|
||||
char rf[4] = "RF"; rf[2] = 48+s; rf[3] = 0; //refresh required
|
||||
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
|
||||
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //channel swap
|
||||
char sp[4] = "SP"; sp[2] = 48+s; sp[3] = 0; //bus clock speed (DotStar & PWM)
|
||||
char la[4] = "LA"; la[2] = 48+s; la[3] = 0; //LED mA
|
||||
char ma[4] = "MA"; ma[2] = 48+s; ma[3] = 0; //max mA
|
||||
for (int s = 0; s < WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES; s++) {
|
||||
int offset = s < 10 ? 48 : 55;
|
||||
char lp[4] = "L0"; lp[2] = offset+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||
char lc[4] = "LC"; lc[2] = offset+s; lc[3] = 0; //strip length
|
||||
char co[4] = "CO"; co[2] = offset+s; co[3] = 0; //strip color order
|
||||
char lt[4] = "LT"; lt[2] = offset+s; lt[3] = 0; //strip type
|
||||
char ls[4] = "LS"; ls[2] = offset+s; ls[3] = 0; //strip start LED
|
||||
char cv[4] = "CV"; cv[2] = offset+s; cv[3] = 0; //strip reverse
|
||||
char sl[4] = "SL"; sl[2] = offset+s; sl[3] = 0; //skip first N LEDs
|
||||
char rf[4] = "RF"; rf[2] = offset+s; rf[3] = 0; //refresh required
|
||||
char aw[4] = "AW"; aw[2] = offset+s; aw[3] = 0; //auto white mode
|
||||
char wo[4] = "WO"; wo[2] = offset+s; wo[3] = 0; //channel swap
|
||||
char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed (DotStar & PWM)
|
||||
char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED mA
|
||||
char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max mA
|
||||
if (!request->hasArg(lp)) {
|
||||
DEBUG_PRINT(F("No data for "));
|
||||
DEBUG_PRINTLN(s);
|
||||
break;
|
||||
}
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
lp[1] = 48+i;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
lp[1] = offset+i;
|
||||
if (!request->hasArg(lp)) break;
|
||||
pins[i] = (request->arg(lp).length() > 0) ? request->arg(lp).toInt() : 255;
|
||||
}
|
||||
@ -210,11 +211,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed
|
||||
|
||||
ColorOrderMap com = {};
|
||||
for (uint8_t s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) {
|
||||
char xs[4] = "XS"; xs[2] = 48+s; xs[3] = 0; //start LED
|
||||
char xc[4] = "XC"; xc[2] = 48+s; xc[3] = 0; //strip length
|
||||
char xo[4] = "XO"; xo[2] = 48+s; xo[3] = 0; //color order
|
||||
char xw[4] = "XW"; xw[2] = 48+s; xw[3] = 0; //W swap
|
||||
for (int s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) {
|
||||
int offset = s < 10 ? 48 : 55;
|
||||
char xs[4] = "XS"; xs[2] = offset+s; xs[3] = 0; //start LED
|
||||
char xc[4] = "XC"; xc[2] = offset+s; xc[3] = 0; //strip length
|
||||
char xo[4] = "XO"; xo[2] = offset+s; xo[3] = 0; //color order
|
||||
char xw[4] = "XW"; xw[2] = offset+s; xw[3] = 0; //W swap
|
||||
if (request->hasArg(xs)) {
|
||||
start = request->arg(xs).toInt();
|
||||
length = request->arg(xc).toInt();
|
||||
@ -249,9 +251,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
disablePullUp = (bool)request->hasArg(F("IP"));
|
||||
touchThreshold = request->arg(F("TT")).toInt();
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
char bt[4] = "BT"; bt[2] = (i<10?48:55)+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
char be[4] = "BE"; be[2] = (i<10?48:55)+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
for (int i = 0; i < WLED_MAX_BUTTONS; i++) {
|
||||
int offset = i < 10 ? 48 : 55;
|
||||
char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
char be[4] = "BE"; be[2] = offset+i; be[3] = 0; // button type (use A,B,C,... if WLED_MAX_BUTTONS>10)
|
||||
int hw_btn_pin = request->arg(bt).toInt();
|
||||
if (hw_btn_pin >= 0 && pinManager.allocatePin(hw_btn_pin,false,PinOwner::Button)) {
|
||||
btnPin[i] = hw_btn_pin;
|
||||
|
@ -350,7 +350,8 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(itoa(WLED_MIN_VIRTUAL_BUSSES,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
|
||||
oappend(itoa(MAX_LEDS,nS,10));
|
||||
oappend(itoa(MAX_LEDS,nS,10)); oappend(",");
|
||||
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
|
||||
oappend(SET_F(");"));
|
||||
|
||||
sappend('c',SET_F("MS"),autoSegments);
|
||||
@ -362,28 +363,29 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("AW"),Bus::getGlobalAWMode());
|
||||
sappend('c',SET_F("LD"),useGlobalLedBuffer);
|
||||
|
||||
uint16_t sumMa = 0;
|
||||
for (uint8_t s=0; s < BusManager::getNumBusses(); s++) {
|
||||
unsigned sumMa = 0;
|
||||
for (int s = 0; s < BusManager::getNumBusses(); s++) {
|
||||
Bus* bus = BusManager::getBus(s);
|
||||
if (bus == nullptr) continue;
|
||||
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||
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
|
||||
char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED
|
||||
char rf[4] = "RF"; rf[2] = 48+s; rf[3] = 0; //off refresh
|
||||
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
|
||||
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //swap channels
|
||||
char sp[4] = "SP"; sp[2] = 48+s; sp[3] = 0; //bus clock speed
|
||||
char la[4] = "LA"; la[2] = 48+s; la[3] = 0; //LED current
|
||||
char ma[4] = "MA"; ma[2] = 48+s; ma[3] = 0; //max per-port PSU current
|
||||
int offset = s < 10 ? 48 : 55;
|
||||
char lp[4] = "L0"; lp[2] = offset+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||
char lc[4] = "LC"; lc[2] = offset+s; lc[3] = 0; //strip length
|
||||
char co[4] = "CO"; co[2] = offset+s; co[3] = 0; //strip color order
|
||||
char lt[4] = "LT"; lt[2] = offset+s; lt[3] = 0; //strip type
|
||||
char ls[4] = "LS"; ls[2] = offset+s; ls[3] = 0; //strip start LED
|
||||
char cv[4] = "CV"; cv[2] = offset+s; cv[3] = 0; //strip reverse
|
||||
char sl[4] = "SL"; sl[2] = offset+s; sl[3] = 0; //skip 1st LED
|
||||
char rf[4] = "RF"; rf[2] = offset+s; rf[3] = 0; //off refresh
|
||||
char aw[4] = "AW"; aw[2] = offset+s; aw[3] = 0; //auto white mode
|
||||
char wo[4] = "WO"; wo[2] = offset+s; wo[3] = 0; //swap channels
|
||||
char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed
|
||||
char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED current
|
||||
char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max per-port PSU current
|
||||
oappend(SET_F("addLEDs(1);"));
|
||||
uint8_t pins[5];
|
||||
uint8_t nPins = bus->getPins(pins);
|
||||
for (uint8_t i = 0; i < nPins; i++) {
|
||||
lp[1] = 48+i;
|
||||
int nPins = bus->getPins(pins);
|
||||
for (int i = 0; i < nPins; i++) {
|
||||
lp[1] = offset+i;
|
||||
if (pinManager.isPinOk(pins[i]) || IS_VIRTUAL(bus->getType())) sappend('v',lp,pins[i]);
|
||||
}
|
||||
sappend('v',lc,bus->getLength());
|
||||
@ -395,7 +397,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',rf,bus->isOffRefreshRequired());
|
||||
sappend('v',aw,bus->getAutoWhiteMode());
|
||||
sappend('v',wo,bus->getColorOrder() >> 4);
|
||||
uint16_t speed = bus->getFrequency();
|
||||
unsigned speed = bus->getFrequency();
|
||||
if (IS_PWM(bus->getType())) {
|
||||
switch (speed) {
|
||||
case WLED_PWM_FREQ/2 : speed = 0; break;
|
||||
@ -428,7 +430,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
|
||||
oappend(SET_F(");"));
|
||||
const ColorOrderMap& com = BusManager::getColorOrderMap();
|
||||
for (uint8_t s=0; s < com.count(); s++) {
|
||||
for (int s = 0; s < com.count(); s++) {
|
||||
const ColorOrderMapEntry* entry = com.get(s);
|
||||
if (entry == nullptr) break;
|
||||
oappend(SET_F("addCOM("));
|
||||
@ -459,7 +461,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("RL"),rlyPin);
|
||||
sappend('c',SET_F("RM"),rlyMde);
|
||||
sappend('c',SET_F("RO"),rlyOpenDrain);
|
||||
for (uint8_t i=0; i<WLED_MAX_BUTTONS; i++) {
|
||||
for (int i = 0; i < WLED_MAX_BUTTONS; i++) {
|
||||
oappend(SET_F("addBtn("));
|
||||
oappend(itoa(i,nS,10)); oappend(",");
|
||||
oappend(itoa(btnPin[i],nS,10)); oappend(",");
|
||||
|
Loading…
x
Reference in New Issue
Block a user