Compare commits

..

2 Commits

Author SHA1 Message Date
Blaž Kristan
acfb8b24ab Address issues 2025-12-20 20:18:37 +01:00
Blaž Kristan
97d3792a77 Fix for #5201
- use constants instead of magic numbers
2025-12-20 11:15:36 +01:00
8 changed files with 47 additions and 74 deletions

View File

@@ -20,19 +20,17 @@ float UsermodTemperature::readDallas() {
}
#endif
switch(sensorFound) {
case 0x10: // DS18S20 has 9-bit precision - 1-bit fraction part
case 0x10: // DS18S20 has 9-bit precision
result = (data[1] << 8) | data[0];
retVal = float(result) * 0.5f;
break;
case 0x22: // DS1822
case 0x28: // DS18B20
case 0x22: // DS18B20
case 0x28: // DS1822
case 0x3B: // DS1825
case 0x42: // DS28EA00
// 12-bit precision - 4-bit fraction part
result = (data[1] << 8) | data[0];
// Clear LSBs to match desired precision (9/10/11-bit) rounding towards negative infinity
result &= 0xFFFF << (3 - (resolution & 3));
retVal = float(result) * 0.0625f; // 2^(-4)
result = (data[1]<<4) | (data[0]>>4); // we only need whole part, we will add fraction when returning
if (data[1] & 0x80) result |= 0xF000; // fix negative value
retVal = float(result) + ((data[0] & 0x08) ? 0.5f : 0.0f);
break;
}
}
@@ -71,8 +69,8 @@ bool UsermodTemperature::findSensor() {
if (oneWire->crc8(deviceAddress, 7) == deviceAddress[7]) {
switch (deviceAddress[0]) {
case 0x10: // DS18S20
case 0x22: // DS1822
case 0x28: // DS18B20
case 0x22: // DS18B20
case 0x28: // DS1822
case 0x3B: // DS1825
case 0x42: // DS28EA00
DEBUG_PRINTLN(F("Sensor found."));
@@ -279,7 +277,6 @@ void UsermodTemperature::addToConfig(JsonObject &root) {
top[FPSTR(_parasite)] = parasite;
top[FPSTR(_parasitePin)] = parasitePin;
top[FPSTR(_domoticzIDX)] = idx;
top[FPSTR(_resolution)] = resolution;
DEBUG_PRINTLN(F("Temperature config saved."));
}
@@ -307,7 +304,6 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
parasite = top[FPSTR(_parasite)] | parasite;
parasitePin = top[FPSTR(_parasitePin)] | parasitePin;
idx = top[FPSTR(_domoticzIDX)] | idx;
resolution = top[FPSTR(_resolution)] | resolution;
if (!initDone) {
// first run: reading from cfg.json
@@ -328,7 +324,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
}
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return !top[FPSTR(_resolution)].isNull();
return !top[FPSTR(_domoticzIDX)].isNull();
}
void UsermodTemperature::appendConfigData() {
@@ -336,14 +332,6 @@ void UsermodTemperature::appendConfigData() {
oappend(F("',1,'<i>(if no Vcc connected)</i>');")); // 0 is field type, 1 is actual field
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
oappend(F("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field
oappend(F("dd=addDD('")); oappend(String(FPSTR(_name)).c_str());
oappend(F("','")); oappend(String(FPSTR(_resolution)).c_str()); oappend(F("');"));
oappend(F("addO(dd,'0.5 °C (9-bit)',0);"));
oappend(F("addO(dd,'0.25°C (10-bit)',1);"));
oappend(F("addO(dd,'0.125°C (11-bit)',2);"));
oappend(F("addO(dd,'0.0625°C (12-bit)',3);"));
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_resolution)).c_str());
oappend(F("',1,'<i>(ignored on DS18S20)</i>');")); // 0 is field type, 1 is actual field
}
float UsermodTemperature::getTemperature() {
@@ -363,7 +351,6 @@ const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr";
const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin";
const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx";
const char UsermodTemperature::_resolution[] PROGMEM = "resolution";
const char UsermodTemperature::_sensor[] PROGMEM = "sensor";
const char UsermodTemperature::_temperature[] PROGMEM = "temperature";
const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature";

View File

@@ -48,7 +48,6 @@ class UsermodTemperature : public Usermod {
bool HApublished = false;
int16_t idx = -1; // Domoticz virtual sensor idx
uint8_t resolution = 0; // 9bits=0, 10bits=1, 11bits=2, 12bits=3
// strings to reduce flash memory usage (used more than twice)
static const char _name[];
@@ -57,7 +56,6 @@ class UsermodTemperature : public Usermod {
static const char _parasite[];
static const char _parasitePin[];
static const char _domoticzIDX[];
static const char _resolution[];
static const char _sensor[];
static const char _temperature[];
static const char _Temperature[];

View File

@@ -401,19 +401,19 @@ void RotaryEncoderUIUsermod::sortModesAndPalettes() {
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
DEBUG_PRINT(F("Sorting palettes: ")); DEBUG_PRINT(getPaletteCount()); DEBUG_PRINT('/'); DEBUG_PRINTLN(customPalettes.size());
palettes_qstrings = re_findModeStrings(JSON_palette_names, getPaletteCount() + 1); // +1 for default palette
palettes_alpha_indexes = re_initIndexArray(getPaletteCount());
palettes_qstrings = re_findModeStrings(JSON_palette_names, getPaletteCount()); // allocates memory for all palette names
palettes_alpha_indexes = re_initIndexArray(getPaletteCount()); // allocates memory for all palette indexes
if (customPalettes.size()) {
for (int i=0; i<customPalettes.size(); i++) {
palettes_alpha_indexes[getPaletteCount()-customPalettes.size()+i] = 255-i;
palettes_qstrings[getPaletteCount()-customPalettes.size()+i] = PSTR("~Custom~");
palettes_alpha_indexes[FIXED_PALETTE_COUNT+i] = 255-i;
palettes_qstrings[FIXED_PALETTE_COUNT+i] = PSTR("~Custom~");
}
}
// How many palette names start with '*' and should not be sorted?
// (Also skipping the first one, 'Default').
int skipPaletteCount = 1;
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++;
re_sortModes(palettes_qstrings, palettes_alpha_indexes, getPaletteCount()-customPalettes.size(), skipPaletteCount);
int skipPaletteCount = 1; // could use DYNAMIC_PALETTE_COUNT instead
while (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') skipPaletteCount++; // legacy code
re_sortModes(palettes_qstrings, palettes_alpha_indexes, FIXED_PALETTE_COUNT, skipPaletteCount); // only sort fixed palettes (skip dynamic)
}
byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) {

View File

@@ -230,7 +230,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
// then come the custom palettes (255,254,...) growing downwards from 255 (255 being 1st custom palette)
// palette 0 is a varying palette depending on effect and may be replaced by segment's color if so
// instructed in color_from_palette()
if (pal > FIXED_PALETTE_COUNT && pal <= 255-customPalettes.size()) pal = 0; // out of bounds palette
if (pal >= FIXED_PALETTE_COUNT && pal <= 255-customPalettes.size()) pal = 0; // out of bounds palette
//default palette. Differs depending on effect
if (pal == 0) pal = _default_palette; // _default_palette is set in setMode()
switch (pal) {
@@ -268,11 +268,11 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
default: //progmem palettes
if (pal > 255 - customPalettes.size()) {
targetPalette = customPalettes[255-pal]; // we checked bounds above
} else if (pal < DYNAMIC_PALETTE_COUNT+FASTLED_PALETTE_COUNT+1) { // palette 6 - 12, fastled palettes
targetPalette = *fastledPalettes[pal-DYNAMIC_PALETTE_COUNT-1];
} else if (pal < DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT) { // palette 6 - 12, fastled palettes
targetPalette = *fastledPalettes[pal - DYNAMIC_PALETTE_COUNT];
} else {
byte tcp[72];
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal-(DYNAMIC_PALETTE_COUNT+FASTLED_PALETTE_COUNT)-1])), 72);
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[pal - (DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT)])), sizeof(tcp));
targetPalette.loadDynamicGradientPalette(tcp);
}
break;

View File

@@ -156,7 +156,7 @@ void ParticleSystem2D::setParticleSize(uint8_t size) {
particleHardRadius = PS_P_MINHARDRADIUS + ((particlesize * 52) >> 6); // use 1 pixel + 80% of size for hard radius (slight overlap with boarders so they do not "float" and nicer stacking)
}
else if (particlesize == 0)
particleHardRadius = PS_P_MINHARDRADIUS >> 1; // single pixel particles have half the radius (i.e. 1/2 pixel)
particleHardRadius = particleHardRadius >> 1; // single pixel particles have half the radius (i.e. 1/2 pixel)
}
// enable/disable gravity, optionally, set the force (force=8 is default) can be -127 to +127, 0 is disable
@@ -595,7 +595,7 @@ void ParticleSystem2D::render() {
if (fireIntesity) { // fire mode
brightness = (uint32_t)particles[i].ttl * (3 + (fireIntesity >> 5)) + 5;
brightness = min(brightness, (uint32_t)255);
baseRGB = ColorFromPaletteWLED(SEGPALETTE, brightness, 255, LINEARBLEND_NOWRAP); // map hue to brightness for fire effect
baseRGB = ColorFromPaletteWLED(SEGPALETTE, brightness, 255, LINEARBLEND_NOWRAP);
}
else {
brightness = min((particles[i].ttl << 1), (int)255);
@@ -842,7 +842,7 @@ void ParticleSystem2D::handleCollisions() {
for (uint32_t bin = 0; bin < numBins; bin++) {
binParticleCount = 0; // reset for this bin
int32_t binStart = bin * binWidth - overlap; // note: first bin will extend to negative, but that is ok as out of bounds particles are ignored
int32_t binEnd = binStart + binWidth + (overlap << 1); // add twice the overlap as start is start-overlap, note: last bin can be out of bounds, see above;
int32_t binEnd = binStart + binWidth + overlap; // note: last bin can be out of bounds, see above;
// fill the binIndices array for this bin
for (uint32_t i = 0; i < usedParticles; i++) {
@@ -879,7 +879,7 @@ void ParticleSystem2D::handleCollisions() {
massratio1 = (mass2 << 8) / totalmass; // massratio 1 depends on mass of particle 2, i.e. if 2 is heavier -> higher velocity impact on 1
massratio2 = (mass1 << 8) / totalmass;
}
// note: using the same logic as in 1D is much slower though it would be more accurate but it is not really needed in 2D: particles slipping through each other is much less visible
// note: using the same logic as in 1D is much slower though it would be more accurate but it is not really needed in 2D
int32_t dx = (particles[idx_j].x + particles[idx_j].vx) - (particles[idx_i].x + particles[idx_i].vx); // distance with lookahead
if (dx * dx < collDistSq) { // check x direction, if close, check y direction (squaring is faster than abs() or dual compare)
int32_t dy = (particles[idx_j].y + particles[idx_j].vy) - (particles[idx_i].y + particles[idx_i].vy); // distance with lookahead
@@ -1247,7 +1247,7 @@ void ParticleSystem1D::setParticleSize(const uint8_t size) {
particleHardRadius = PS_P_MINHARDRADIUS_1D + ((particlesize * 52) >> 6); // use 1 pixel + 80% of size for hard radius (slight overlap with boarders so they do not "float" and nicer stacking)
}
else if (particlesize == 0)
particleHardRadius = PS_P_MINHARDRADIUS_1D >> 1; // single pixel particles have half the radius (i.e. 1/2 pixel)
particleHardRadius = particleHardRadius >> 1; // single pixel particles have half the radius (i.e. 1/2 pixel)
}
// enable/disable gravity, optionally, set the force (force=8 is default) can be -127 to +127, 0 is disable
@@ -1632,7 +1632,7 @@ void ParticleSystem1D::handleCollisions() {
for (uint32_t bin = 0; bin < numBins; bin++) {
binParticleCount = 0; // reset for this bin
int32_t binStart = bin * binWidth - overlap; // note: first bin will extend to negative, but that is ok as out of bounds particles are ignored
int32_t binEnd = binStart + binWidth + (overlap << 1); // add twice the overlap as start is start-overlap, note: last bin can be out of bounds, see above
int32_t binEnd = binStart + binWidth + overlap; // note: last bin can be out of bounds, see above
// fill the binIndices array for this bin
for (uint32_t i = 0; i < usedParticles; i++) {

View File

@@ -6,9 +6,9 @@
* Readability defines and their associated numerical values + compile-time constants
*/
constexpr size_t FASTLED_PALETTE_COUNT = 7; // = sizeof(fastledPalettes) / sizeof(fastledPalettes[0]);
constexpr size_t GRADIENT_PALETTE_COUNT = 59; // = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]);
constexpr size_t DYNAMIC_PALETTE_COUNT = 5; // 1-5 are dynamic palettes (1=random,2=primary,3=primary+secondary,4=primary+secondary+tertiary,5=primary+secondary(+tertiary if not black)
constexpr size_t FASTLED_PALETTE_COUNT = 7; // 6-12 = sizeof(fastledPalettes) / sizeof(fastledPalettes[0]);
constexpr size_t GRADIENT_PALETTE_COUNT = 59; // 13-72 = sizeof(gGradientPalettes) / sizeof(gGradientPalettes[0]);
constexpr size_t DYNAMIC_PALETTE_COUNT = 6; // 0- 5 = dynamic palettes (0=default(virtual),1=random,2=primary,3=primary+secondary,4=primary+secondary+tertiary,5=primary+secondary(+tertiary if not black)
constexpr size_t FIXED_PALETTE_COUNT = DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT + GRADIENT_PALETTE_COUNT; // total number of fixed palettes
#ifndef ESP8266
#define WLED_MAX_CUSTOM_PALETTES (255 - FIXED_PALETTE_COUNT) // allow up to 255 total palettes, user is warned about stability issues when adding more than 10

View File

@@ -397,19 +397,11 @@ button, .btn {
</div>
</div>
<hr>
<div class="ed active">
<div>
<h3>Video Lab</h3>
<div><small>Stream video and generate animated GIFs (beta)</small></div>
<button class="btn" id="t2" style="display:none"></button>
</div>
</div>
<hr>
<div class="ed active">
<div>
<h3>PIXEL MAGIC Tool</h3>
<div><small>Legacy pixel art editor</small></div>
<button class="btn" id="t3" style="display:none"></button>
<button class="btn" id="t2" style="display:none"></button>
</div>
</div>
<hr>
@@ -424,8 +416,6 @@ button, .btn {
<script>
const d=document,gId=i=>d.getElementById(i),cE=t=>d.createElement(t);
const imgageFX = 53; // image effect number
const txtFX = 122; // scrolling text effect number
/* canvases */
const cv=gId('cv'),cx=cv.getContext('2d',{willReadFrequently:true});
@@ -447,8 +437,7 @@ let fL; // file list
await segLoad(); // load available segments
await flU(); // update file list
toolChk('pixelpaint.htm','t1'); // update buttons of additional tools
toolChk('videolab.htm','t2');
toolChk('pxmagic.htm','t3');
toolChk('pxmagic.htm','t2');
await fsMem(); // show file system memory info
})();
@@ -478,7 +467,7 @@ function segLoad(){
if(j.seg&&j.seg.length){
j.seg.forEach(({id,n,start,stop,startY,stopY,fx})=>{
const w=stop-start,h=(stopY-startY)||1;
const t = (n || `Segment ${id}`) + (h>1 ? ` (${w}x${h})` : ` (${w}px)`) + (fx===imgageFX ? ' [Image]' : (fx===txtFX ? ' [Scrolling Text]' : ''));
const t = (n || `Segment ${id}`) + (h>1 ? ` (${w}x${h})` : ` (${w}px)`) + (fx===53 ? ' [Image]' : (fx===122 ? ' [Scrolling Text]' : ''));
const o=new Option(t,id);
o.dataset.w=w; o.dataset.h=h; o.dataset.fx=fx||0;
s1.add(o); // gif tool
@@ -499,7 +488,7 @@ function segLoad(){
function curImgSeg(){
const sel=gId('seg');
for(let i=0;i<sel.options.length;i++){
if(parseInt(sel.options[i].dataset.fx)===imgageFX) return parseInt(sel.options[i].value);
if(parseInt(sel.options[i].dataset.fx)===53) return parseInt(sel.options[i].value);
}
return null;
}

View File

@@ -945,26 +945,25 @@ void serializePalettes(JsonObject root, int page)
{
byte tcp[72];
#ifdef ESP8266
int itemPerPage = 5;
constexpr int itemPerPage = 5;
#else
int itemPerPage = 8;
constexpr int itemPerPage = 8;
#endif
int customPalettesCount = customPalettes.size();
int palettesCount = getPaletteCount() - customPalettesCount; // palettesCount is number of palettes, not palette index
const int customPalettesCount = customPalettes.size();
const int palettesCount = FIXED_PALETTE_COUNT; // palettesCount is number of palettes, not palette index
int maxPage = (palettesCount + customPalettesCount -1) / itemPerPage;
const int maxPage = (palettesCount + customPalettesCount) / itemPerPage;
if (page > maxPage) page = maxPage;
int start = itemPerPage * page;
int end = start + itemPerPage;
if (end > palettesCount + customPalettesCount) end = palettesCount + customPalettesCount;
const int start = itemPerPage * page;
int end = min(start + itemPerPage, palettesCount + customPalettesCount);
root[F("m")] = maxPage; // inform caller how many pages there are
JsonObject palettes = root.createNestedObject("p");
for (int i = start; i <= end; i++) {
JsonArray curPalette = palettes.createNestedArray(String(i<=palettesCount ? i : 255 - (i - (palettesCount + 1))));
for (int i = start; i < end; i++) {
JsonArray curPalette = palettes.createNestedArray(String(i >= palettesCount ? 255 - i + palettesCount : i));
switch (i) {
case 0: //default palette
setPaletteColors(curPalette, PartyColors_p);
@@ -993,12 +992,12 @@ void serializePalettes(JsonObject root, int page)
curPalette.add("c1");
break;
default:
if (i > palettesCount)
setPaletteColors(curPalette, customPalettes[i - (palettesCount + 1)]);
else if (i < 13) // palette 6 - 12, fastled palettes
setPaletteColors(curPalette, *fastledPalettes[i-6]);
if (i >= palettesCount) // custom palettes
setPaletteColors(curPalette, customPalettes[i - palettesCount]);
else if (i < DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT) // palette 6 - 12, fastled palettes
setPaletteColors(curPalette, *fastledPalettes[i - DYNAMIC_PALETTE_COUNT]);
else {
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - 13])), 72);
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i - (DYNAMIC_PALETTE_COUNT + FASTLED_PALETTE_COUNT)])), sizeof(tcp));
setPaletteColors(curPalette, tcp);
}
break;