From 7ee14724fca66ed8bc80a247cb5c93c51cdfce82 Mon Sep 17 00:00:00 2001 From: bole5 Date: Tue, 8 Feb 2022 00:03:20 +0100 Subject: [PATCH 1/7] Improve Pin Manager Debugging (#2532) --- wled00/pin_manager.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 2b908557..07db3f76 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -132,6 +132,13 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by byte bi = gpio - 8*by; bitWrite(pinAlloc[by], bi, true); ownerTag[gpio] = tag; + #ifdef WLED_DEBUG + DEBUG_PRINT(F("PIN ALLOC: Pin ")); + DEBUG_PRINT(gpio); + DEBUG_PRINT(F(" allocated by ")); + DebugPrintOwnerTag(tag); + DEBUG_PRINTLN(F("")); + #endif } return true; } @@ -155,7 +162,14 @@ bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag) byte bi = gpio - 8*by; bitWrite(pinAlloc[by], bi, true); ownerTag[gpio] = tag; - + #ifdef WLED_DEBUG + DEBUG_PRINT(F("PIN ALLOC: Pin ")); + DEBUG_PRINT(gpio); + DEBUG_PRINT(F(" allocated by ")); + DebugPrintOwnerTag(tag); + DEBUG_PRINTLN(F("")); + #endif + return true; } From f9bce5410433feb27fb6b9495d5360b68e850f0d Mon Sep 17 00:00:00 2001 From: bole5 Date: Tue, 8 Feb 2022 00:15:24 +0100 Subject: [PATCH 2/7] Change Default Relay Pin to -1 (#2531) --- wled00/wled.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled.h b/wled00/wled.h index 17eaaa7a..3f151280 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -225,7 +225,7 @@ WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({0}); WLED_GLOBAL int8_t btnPin[WLED_MAX_BUTTONS] _INIT({BTNPIN}); #endif #ifndef RLYPIN -WLED_GLOBAL int8_t rlyPin _INIT(12); +WLED_GLOBAL int8_t rlyPin _INIT(-1); #else WLED_GLOBAL int8_t rlyPin _INIT(RLYPIN); #endif From 00b0193a432da98840108a29494c7da8ef886a5d Mon Sep 17 00:00:00 2001 From: Christian Schwinne Date: Wed, 9 Feb 2022 08:43:35 +0100 Subject: [PATCH 3/7] Fix re-init segment data leak (fixes #2535 ) (#2536) --- wled00/FX.h | 4 ++-- wled00/FX_fcn.cpp | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index c186fdeb..30cd5a48 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -81,7 +81,6 @@ #define SEGLEN _virtualSegmentLength #define SEGACT SEGMENT.stop #define SPEED_FORMULA_L 5U + (50U*(255U - SEGMENT.speed))/SEGLEN -#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes)) // some common colors #define RED (uint32_t)0xFF0000 @@ -409,8 +408,9 @@ class WS2812FX { * Flags that before the next effect is calculated, * the internal segment state should be reset. * Call resetIfRequired before calling the next effect function. + * Safe to call from interrupts and network requests. */ - inline void reset() { _requiresReset = true; } + inline void markForReset() { _requiresReset = true; } private: uint16_t _dataLen = 0; bool _requiresReset = false; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 42a183a7..302464b6 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -67,7 +67,12 @@ //do not call this method from system context (network callback) void WS2812FX::finalizeInit(void) { - RESET_RUNTIME; + //reset segment runtimes + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { + _segment_runtimes[i].markForReset(); + _segment_runtimes[i].resetIfRequired(); + } + _hasWhiteChannel = _isOffRefreshRequired = false; //if busses failed to load, add default (fresh install, FS issue, ...) @@ -373,7 +378,7 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) { if (_segments[segid].mode != m) { - _segment_runtimes[segid].reset(); + _segment_runtimes[segid].markForReset(); _segments[segid].mode = m; } } @@ -612,12 +617,12 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, seg.spacing = spacing; } if (offset < UINT16_MAX) seg.offset = offset; - _segment_runtimes[n].reset(); + _segment_runtimes[n].markForReset(); } void WS2812FX::restartRuntime() { for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) { - _segment_runtimes[i].reset(); + _segment_runtimes[i].markForReset(); } } @@ -648,9 +653,9 @@ void WS2812FX::resetSegments() { _segments[i].cct = 127; _segments[i].speed = DEFAULT_SPEED; _segments[i].intensity = DEFAULT_INTENSITY; - _segment_runtimes[i].reset(); + _segment_runtimes[i].markForReset(); } - _segment_runtimes[0].reset(); + _segment_runtimes[0].markForReset(); } void WS2812FX::makeAutoSegments() { From 38bc618ee5263f964ec00ed504d0fed6fc1bec57 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Wed, 9 Feb 2022 00:46:54 -0800 Subject: [PATCH 4/7] Float and better 3rd party library compatibility (#2534) * define as float (not double) * Avoid #define of 1 or 2 char symbols Having this file define 'A' and 'C' pollutes the global namespace, and causes conflicts with other libraries that also pollute the global namespace with short #defines. It's easier to fix this header. * unused variable warning --- .../usermod_sn_photoresistor.h | 4 +- .../usermod_v2_battery_status_basic.h | 8 ++-- wled00/wled_math.h | 41 +++++++++++-------- wled00/wled_serial.cpp | 2 - 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h b/usermods/SN_Photoresistor/usermod_sn_photoresistor.h index 6a7e9f5a..9c3be7cc 100644 --- a/usermods/SN_Photoresistor/usermod_sn_photoresistor.h +++ b/usermods/SN_Photoresistor/usermod_sn_photoresistor.h @@ -22,12 +22,12 @@ // 10 bits #ifndef USERMOD_SN_PHOTORESISTOR_ADC_PRECISION -#define USERMOD_SN_PHOTORESISTOR_ADC_PRECISION 1024.0 +#define USERMOD_SN_PHOTORESISTOR_ADC_PRECISION 1024.0f #endif // resistor size 10K hms #ifndef USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE -#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0 +#define USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE 10000.0f #endif // only report if differance grater than offset value diff --git a/usermods/battery_status_basic/usermod_v2_battery_status_basic.h b/usermods/battery_status_basic/usermod_v2_battery_status_basic.h index ab9cba3b..cb3c0867 100644 --- a/usermods/battery_status_basic/usermod_v2_battery_status_basic.h +++ b/usermods/battery_status_basic/usermod_v2_battery_status_basic.h @@ -21,10 +21,10 @@ #ifndef USERMOD_BATTERY_ADC_PRECISION #ifdef ARDUINO_ARCH_ESP32 // 12 bits - #define USERMOD_BATTERY_ADC_PRECISION 4095.0 + #define USERMOD_BATTERY_ADC_PRECISION 4095.0f #else // 10 bits - #define USERMOD_BATTERY_ADC_PRECISION 1024.0 + #define USERMOD_BATTERY_ADC_PRECISION 1024.0f #endif #endif @@ -39,11 +39,11 @@ // https://batterybro.com/blogs/18650-wholesale-battery-reviews/18852515-when-to-recycle-18650-batteries-and-how-to-start-a-collection-center-in-your-vape-shop // Discharge voltage: 2.5 volt + .1 for personal safety #ifndef USERMOD_BATTERY_MIN_VOLTAGE - #define USERMOD_BATTERY_MIN_VOLTAGE 2.6 + #define USERMOD_BATTERY_MIN_VOLTAGE 2.6f #endif #ifndef USERMOD_BATTERY_MAX_VOLTAGE - #define USERMOD_BATTERY_MAX_VOLTAGE 4.2 + #define USERMOD_BATTERY_MAX_VOLTAGE 4.2f #endif class UsermodBatteryBasic : public Usermod diff --git a/wled00/wled_math.h b/wled00/wled_math.h index a13c95d5..bfaff06a 100644 --- a/wled00/wled_math.h +++ b/wled00/wled_math.h @@ -80,36 +80,41 @@ float asin_t(float x) { return res; } -//https://stackoverflow.com/a/42542593 -#define A 0.0776509570923569 -#define B -0.287434475393028 -#define C ((HALF_PI/2) - A - B) - -//polynominal factors for approximation between 1 and 5 -#define C0 0.089494f -#define C1 0.974207f -#define C2 -0.326175f -#define C3 0.05375f -#define C4 -0.003445f - +// declare a template with no implementation, and only one specialization +// this allows hiding the constants, while ensuring ODR causes optimizations +// to still apply. (Fixes issues with conflicting 3rd party #define's) +template T atan_t(T x); +template<> float atan_t(float x) { - bool neg = (x < 0); + //For A/B/C, see https://stackoverflow.com/a/42542593 + static const double A { 0.0776509570923569 }; + static const double B { -0.287434475393028 }; + static const double C { ((HALF_PI/2) - A - B) }; + // polynominal factors for approximation between 1 and 5 + static const float C0 { 0.089494f }; + static const float C1 { 0.974207f }; + static const float C2 { -0.326175f }; + static const float C3 { 0.05375f }; + static const float C4 { -0.003445f }; + #ifdef WLED_DEBUG_MATH float xinput = x; #endif + bool neg = (x < 0); x = std::abs(x); float res; - if (x > 5.0f) { //atan(x) converges to pi/2 - (1/x) for large values + if (x > 5.0f) { // atan(x) converges to pi/2 - (1/x) for large values res = HALF_PI - (1.0f/x); - } - else if (x > 1.0f) { //1 < x < 5 + } else if (x > 1.0f) { //1 < x < 5 float xx = x * x; res = (C4*xx*xx)+(C3*xx*x)+(C2*xx)+(C1*x)+C0; - } else { //this approximation is only for x <= 1 + } else { // this approximation is only for x <= 1 float xx = x * x; res = ((A*xx + B)*xx + C)*x; } - if (neg) res = -res; + if (neg) { + res = -res; + } #ifdef WLED_DEBUG_MATH Serial.printf("atan,%f,%f,%f\n",xinput,res,atan(xinput)); #endif diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index 11a3bb00..4f71721d 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -46,8 +46,6 @@ void handleSerial() static byte red = 0x00; static byte green = 0x00; - uint16_t nBytes = 0; - while (Serial.available() > 0) { yield(); From 4cdb18907f16f6d58525404ec7339cb0a4335e4f Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Wed, 9 Feb 2022 19:27:52 +0100 Subject: [PATCH 5/7] Fix for Four Line Display usermod. --- .../usermod_v2_four_line_display/readme.md | 26 ++- .../usermod_v2_four_line_display.h | 187 ++++++++---------- 2 files changed, 111 insertions(+), 102 deletions(-) diff --git a/usermods/usermod_v2_four_line_display/readme.md b/usermods/usermod_v2_four_line_display/readme.md index 367f3d7a..47518be9 100644 --- a/usermods/usermod_v2_four_line_display/readme.md +++ b/usermods/usermod_v2_four_line_display/readme.md @@ -31,9 +31,33 @@ This usermod requires the `U8g2` and `Wire` libraries. See the `platformio_override.ini.sample` found in the Rotary Encoder UI usermod folder for how to include these using `platformio_override.ini`. +## Configuration + +* `enabled` - enable/disable usermod +* `pin` - GPIO pins used for display; I2C displays use Clk & Data; SPI displays can use SCK, MOSI, CS, DC & RST +* `type` - display type in numeric format + * 1 = I2C SSD1306 128x32 + * 2 = I2C SH1106 128x32 + * 3 = I2C SSD1306 128x64 (4 double-height lines) + * 4 = I2C SSD1305 128x32 + * 5 = I2C SSD1305 128x64 (4 double-height lines) + * 6 = SPI SSD1306 128x32 + * 7 = SPI SSD1306 128x64 (4 double-height lines) +* `contrast` - set display contrast (higher contrast may reduce display lifetime) +* `refreshRateSec` - time in seconds for display refresh +* `screenTimeOutSec` - screen saver time-out in seconds +* `flip` - flip/rotate display 180° +* `sleepMode` - enable/disable screen saver +* `clockMode` - enable/disable clock display in screen saver mode +* `i2c-freq-kHz` - I2C clock frequency in kHz (may help reduce dropped frames, range: 400-3400) + ## Change Log 2021-02 * First public release + 2021-04 -* Adaptation for runtime configuration. \ No newline at end of file +* Adaptation for runtime configuration. + +2021-11 +* Added configuration option description. \ No newline at end of file diff --git a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h index aaa96764..c5251cba 100644 --- a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h +++ b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h @@ -25,6 +25,10 @@ //The SCL and SDA pins are defined here. #ifdef ARDUINO_ARCH_ESP32 + #define HW_PIN_SCL 22 + #define HW_PIN_SDA 21 + #define HW_PIN_CLOCKSPI 18 + #define HW_PIN_DATASPI 23 #ifndef FLD_PIN_SCL #define FLD_PIN_SCL 22 #endif @@ -47,6 +51,10 @@ #define FLD_PIN_RESET 26 #endif #else + #define HW_PIN_SCL 5 + #define HW_PIN_SDA 4 + #define HW_PIN_CLOCKSPI 14 + #define HW_PIN_DATASPI 13 #ifndef FLD_PIN_SCL #define FLD_PIN_SCL 5 #endif @@ -70,6 +78,14 @@ #endif #endif +#ifndef FLD_TYPE + #ifndef FLD_SPI_DEFAULT + #define FLD_TYPE SSD1306 + #else + #define FLD_TYPE SSD1306_SPI + #endif +#endif + // When to time out to the clock or blank the screen // if SLEEP_MODE_ENABLED. #define SCREEN_TIMEOUT_MS 60*1000 // 1 min @@ -115,11 +131,11 @@ class FourLineDisplayUsermod : public Usermod { #ifndef FLD_SPI_DEFAULT int8_t ioPin[5] = {FLD_PIN_SCL, FLD_PIN_SDA, -1, -1, -1}; // I2C pins: SCL, SDA uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000) - DisplayType type = SSD1306; // display type #else int8_t ioPin[5] = {FLD_PIN_CLOCKSPI, FLD_PIN_DATASPI, FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET}; // SPI pins: CLK, MOSI, CS, DC, RST - DisplayType type = SSD1306_SPI; // display type + uint32_t ioFrequency = 1000000; // in Hz (minimum is 500kHz, baseline is 1MHz and maximum should be 20MHz) #endif + DisplayType type = FLD_TYPE; // display type bool flip = false; // flip display 180° uint8_t contrast = 10; // screen contrast uint8_t lineHeight = 1; // 1 row or 2 rows @@ -127,6 +143,7 @@ class FourLineDisplayUsermod : public Usermod { uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms bool sleepMode = true; // allow screen sleep? bool clockMode = false; // display clock + bool enabled = true; // Next variables hold the previous known values to determine if redraw is // required. @@ -150,6 +167,7 @@ class FourLineDisplayUsermod : public Usermod { // strings to reduce flash memory usage (used more than twice) static const char _name[]; + static const char _enabled[]; static const char _contrast[]; static const char _refreshRate[]; static const char _screenTimeOut[]; @@ -169,88 +187,72 @@ class FourLineDisplayUsermod : public Usermod { // gets called once at boot. Do all initialization that doesn't depend on // network here void setup() { - if (type == NONE) return; + if (type == NONE || !enabled) return; + + bool isHW; + PinOwner po = PinOwner::UM_FourLineDisplay; if (type == SSD1306_SPI || type == SSD1306_SPI64) { - PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true}, { ioPin[2], true }, { ioPin[3], true}, { ioPin[4], true }}; - if (!pinManager.allocateMultiplePins(pins, 5, PinOwner::UM_FourLineDisplay)) { type=NONE; return; } + isHW = (ioPin[0]==HW_PIN_CLOCKSPI && ioPin[1]==HW_PIN_DATASPI); + PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }}; + if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; } } else { - PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true} }; - if (!pinManager.allocateMultiplePins(pins, 2, PinOwner::UM_FourLineDisplay)) { type=NONE; return; } + isHW = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA); + PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } }; + if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins + if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; } } + DEBUG_PRINTLN(F("Allocating display.")); switch (type) { case SSD1306: - #ifdef ESP8266 - if (!(ioPin[0]==5 && ioPin[1]==4)) - u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset - else - #endif - u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset + else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA lineHeight = 1; break; case SH1106: - #ifdef ESP8266 - if (!(ioPin[0]==5 && ioPin[1]==4)) - u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset - else - #endif - u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA + if (!isHW) u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset + else u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA lineHeight = 2; break; case SSD1306_64: - #ifdef ESP8266 - if (!(ioPin[0]==5 && ioPin[1]==4)) - u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset - else - #endif - u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset + else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA lineHeight = 2; break; case SSD1305: - #ifdef ESP8266 - if (!(ioPin[0]==5 && ioPin[1]==4)) - u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset - else - #endif - u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset + else u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA lineHeight = 1; break; case SSD1305_64: - #ifdef ESP8266 - if (!(ioPin[0]==5 && ioPin[1]==4)) - u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset - else - #endif - u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset + else u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA lineHeight = 2; break; case SSD1306_SPI: - if (!(ioPin[0]==FLD_PIN_CLOCKSPI && ioPin[1]==FLD_PIN_DATASPI)) // if not overridden these sould be HW accellerated - u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); - else - u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); + else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset lineHeight = 1; break; case SSD1306_SPI64: - if (!(ioPin[0]==FLD_PIN_CLOCKSPI && ioPin[1]==FLD_PIN_DATASPI)) // if not overridden these sould be HW accellerated - u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); - else - u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); + else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset lineHeight = 2; break; default: u8x8 = nullptr; } + if (nullptr == u8x8) { DEBUG_PRINTLN(F("Display init failed.")); - for (byte i=0; i<5 && ioPin[i]>=0; i++) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay); + pinManager.deallocateMultiplePins((const uint8_t*)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po); type = NONE; return; } initDone = true; DEBUG_PRINTLN(F("Starting display.")); - if (!(type == SSD1306_SPI || type == SSD1306_SPI64)) u8x8->setBusClock(ioFrequency); // can be used for SPI too + /*if (!(type == SSD1306_SPI || type == SSD1306_SPI64))*/ u8x8->setBusClock(ioFrequency); // can be used for SPI too u8x8->begin(); setFlipMode(flip); setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 @@ -266,7 +268,7 @@ class FourLineDisplayUsermod : public Usermod { * Da loop. */ void loop() { - if (millis() - lastUpdate < (clockMode?1000:refreshRate) || strip.isUpdating()) return; + if (!enabled || millis() - lastUpdate < (clockMode?1000:refreshRate) || strip.isUpdating()) return; lastUpdate = millis(); redraw(false); @@ -276,40 +278,40 @@ class FourLineDisplayUsermod : public Usermod { * Wrappers for screen drawing */ void setFlipMode(uint8_t mode) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setFlipMode(mode); } void setContrast(uint8_t contrast) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setContrast(contrast); } void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setFont(u8x8_font_chroma48medium8_r); if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string); else u8x8->drawString(col, row, string); } void draw2x2String(uint8_t col, uint8_t row, const char *string) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setFont(u8x8_font_chroma48medium8_r); u8x8->draw2x2String(col, row, string); } void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setFont(font); if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph); else u8x8->drawGlyph(col, row, glyph); } uint8_t getCols() { - if (type==NONE) return 0; + if (type==NONE || !enabled) return 0; return u8x8->getCols(); } void clear() { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->clear(); } void setPowerSave(uint8_t save) { - if (type==NONE) return; + if (type == NONE || !enabled) return; u8x8->setPowerSave(save); } @@ -327,7 +329,7 @@ class FourLineDisplayUsermod : public Usermod { static bool showName = false; unsigned long now = millis(); - if (type==NONE) return; + if (type == NONE || !enabled) return; if (overlayUntil > 0) { if (now >= overlayUntil) { // Time to display the overlay has elapsed. @@ -438,6 +440,7 @@ class FourLineDisplayUsermod : public Usermod { void drawLine(uint8_t line, Line4Type lineType) { char lineBuffer[LINE_BUFFER_SIZE]; + uint8_t printedChars; switch(lineType) { case FLD_LINE_BRIGHTNESS: sprintf_P(lineBuffer, PSTR("Brightness %3d"), bri); @@ -452,10 +455,16 @@ class FourLineDisplayUsermod : public Usermod { drawString(2, line*lineHeight, lineBuffer); break; case FLD_LINE_MODE: - showCurrentEffectOrPalette(knownMode, JSON_mode_names, line); + printedChars = extractModeName(knownMode, JSON_mode_names, lineBuffer, LINE_BUFFER_SIZE-1); + for (;printedChars < getCols()-2 && printedChars < LINE_BUFFER_SIZE-3; printedChars++) lineBuffer[printedChars]=' '; + lineBuffer[printedChars] = 0; + drawString(2, line*lineHeight, lineBuffer); break; case FLD_LINE_PALETTE: - showCurrentEffectOrPalette(knownPalette, JSON_palette_names, line); + printedChars = extractModeName(knownPalette, JSON_palette_names, lineBuffer, LINE_BUFFER_SIZE-1); + for (;printedChars < getCols()-2 && printedChars < LINE_BUFFER_SIZE-3; printedChars++) lineBuffer[printedChars]=' '; + lineBuffer[printedChars] = 0; + drawString(2, line*lineHeight, lineBuffer); break; case FLD_LINE_TIME: default: @@ -464,41 +473,6 @@ class FourLineDisplayUsermod : public Usermod { } } - /** - * Display the current effect or palette (desiredEntry) - * on the appropriate line (row). - */ - void showCurrentEffectOrPalette(int knownMode, const char *qstring, uint8_t row) { - char lineBuffer[LINE_BUFFER_SIZE]; - uint8_t qComma = 0; - bool insideQuotes = false; - uint8_t printedChars = 0; - char singleJsonSymbol; - - // Find the mode name in JSON - for (size_t i = 0; i < strlen_P(qstring); i++) { - singleJsonSymbol = pgm_read_byte_near(qstring + i); - if (singleJsonSymbol == '\0') break; - switch (singleJsonSymbol) { - case '"': - insideQuotes = !insideQuotes; - break; - case '[': - case ']': - break; - case ',': - qComma++; - default: - if (!insideQuotes || (qComma != knownMode)) break; - lineBuffer[printedChars++] = singleJsonSymbol; - } - if ((qComma > knownMode) || (printedChars >= getCols()-2) || printedChars >= sizeof(lineBuffer)-2) break; - } - for (;printedChars < getCols()-2 && printedChars < sizeof(lineBuffer)-2; printedChars++) lineBuffer[printedChars]=' '; - lineBuffer[printedChars] = 0; - drawString(2, row*lineHeight, lineBuffer); - } - /** * If there screen is off or in clock is displayed, * this will return true. This allows us to throw away @@ -506,6 +480,7 @@ class FourLineDisplayUsermod : public Usermod { * to wake up the screen. */ bool wakeDisplay() { + if (type == NONE || !enabled) return false; knownHour = 99; if (displayTurnedOff) { // Turn the display back on @@ -522,6 +497,8 @@ class FourLineDisplayUsermod : public Usermod { * Clears the screen and prints on the middle two lines. */ void overlay(const char* line1, const char *line2, long showHowLong) { + if (type == NONE || !enabled) return; + if (displayTurnedOff) { // Turn the display back on (includes clear()) sleepOrClock(false); @@ -583,6 +560,7 @@ class FourLineDisplayUsermod : public Usermod { * the useAMPM configuration. */ void showTime(bool fullScreen = true) { + if (type == NONE || !enabled) return; char lineBuffer[LINE_BUFFER_SIZE]; updateLocalTime(); @@ -676,10 +654,12 @@ class FourLineDisplayUsermod : public Usermod { */ void addToConfig(JsonObject& root) { JsonObject top = root.createNestedObject(FPSTR(_name)); + top[FPSTR(_enabled)] = enabled; JsonArray io_pin = top.createNestedArray("pin"); for (byte i=0; i<5; i++) io_pin.add(ioPin[i]); - top["help4PinTypes"] = F("Clk,Data,CS,DC,RST"); // help for Settings page + top["help4Pins"] = F("Clk,Data,CS,DC,RST"); // help for Settings page top["type"] = type; + top["help4Type"] = F("1=SSD1306,2=SH1106,3=SSD1306_128x64,4=SSD1305,5=SSD1305_128x64,6=SSD1306_SPI,7=SSD1306_SPI_128x64"); // help for Settings page top[FPSTR(_flip)] = (bool) flip; top[FPSTR(_contrast)] = contrast; top[FPSTR(_refreshRate)] = refreshRate/1000; @@ -710,6 +690,7 @@ class FourLineDisplayUsermod : public Usermod { return false; } + enabled = top[FPSTR(_enabled)] | enabled; newType = top["type"] | newType; for (byte i=0; i<5; i++) newPin[i] = top["pin"][i] | ioPin[i]; flip = top[FPSTR(_flip)] | flip; @@ -718,7 +699,10 @@ class FourLineDisplayUsermod : public Usermod { screenTimeout = (top[FPSTR(_screenTimeOut)] | screenTimeout/1000) * 1000; sleepMode = top[FPSTR(_sleepMode)] | sleepMode; clockMode = top[FPSTR(_clockMode)] | clockMode; - ioFrequency = min(3400, max(100, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency + if (newType == SSD1306_SPI || newType == SSD1306_SPI64) + ioFrequency = min(20000, max(500, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency + else + ioFrequency = min(3400, max(100, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency DEBUG_PRINT(FPSTR(_name)); if (!initDone) { @@ -733,10 +717,10 @@ class FourLineDisplayUsermod : public Usermod { for (byte i=0; i<5; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; } if (pinsChanged || type!=newType) { if (type != NONE) delete u8x8; - for (byte i=0; i<5; i++) { - if (ioPin[i]>=0) pinManager.deallocatePin(ioPin[i], PinOwner::UM_FourLineDisplay); - ioPin[i] = newPin[i]; - } + PinOwner po = PinOwner::UM_FourLineDisplay; + if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins + pinManager.deallocateMultiplePins((const uint8_t *)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po); + for (byte i=0; i<5; i++) ioPin[i] = newPin[i]; if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1 type = NONE; return true; @@ -750,7 +734,7 @@ class FourLineDisplayUsermod : public Usermod { if (needsRedraw && !wakeDisplay()) redraw(true); } // use "return !top["newestParameter"].isNull();" when updating Usermod with new features - return !(top[_busClkFrequency]).isNull(); + return !top[FPSTR(_enabled)].isNull(); } /* @@ -764,6 +748,7 @@ class FourLineDisplayUsermod : public Usermod { // strings to reduce flash memory usage (used more than twice) const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay"; +const char FourLineDisplayUsermod::_enabled[] PROGMEM = "enabled"; const char FourLineDisplayUsermod::_contrast[] PROGMEM = "contrast"; const char FourLineDisplayUsermod::_refreshRate[] PROGMEM = "refreshRateSec"; const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOutSec"; From 930ded676788bfb888c7952ea7423111d4527192 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Wed, 9 Feb 2022 19:59:17 +0100 Subject: [PATCH 6/7] Fix touch pin --- wled00/button.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wled00/button.cpp b/wled00/button.cpp index b55df8d0..8472d392 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -72,21 +72,23 @@ void doublePressAction(uint8_t b) bool isButtonPressed(uint8_t i) { if (btnPin[i]<0) return false; + uint8_t pin = btnPin[i]; + switch (buttonType[i]) { case BTN_TYPE_NONE: case BTN_TYPE_RESERVED: break; case BTN_TYPE_PUSH: case BTN_TYPE_SWITCH: - if (digitalRead(btnPin[i]) == LOW) return true; + if (digitalRead(pin) == LOW) return true; break; case BTN_TYPE_PUSH_ACT_HIGH: case BTN_TYPE_PIR_SENSOR: - if (digitalRead(btnPin[i]) == HIGH) return true; + if (digitalRead(pin) == HIGH) return true; break; case BTN_TYPE_TOUCH: #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) - if (touchRead(btnPin[i]) <= touchThreshold) return true; + if (touchRead(pin) <= touchThreshold) return true; #endif break; } @@ -314,4 +316,4 @@ void handleIO() } offMode = true; } -} +} \ No newline at end of file From 4d714cf9a4aa89a41461a5e4d2c50afe3a0ae0f6 Mon Sep 17 00:00:00 2001 From: ulrich Date: Wed, 9 Feb 2022 23:08:42 +0100 Subject: [PATCH 7/7] Fixed buffer overflow in HA autodiscovery. #2538 --- usermods/multi_relay/usermod_multi_relay.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index 23dcc1e2..6143a6b9 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -272,7 +272,7 @@ class MultiRelay : public Usermod { void publishHomeAssistantAutodiscovery() { for (uint8_t i = 0; i < MULTI_RELAY_MAX_RELAYS; i++) { - char uid[16], json_str[1024], buf[128]; + char uid[24], json_str[1024], buf[128]; size_t payload_size; sprintf_P(uid, PSTR("%s_sw%d"), escapedMac.c_str(), i);