Merge branch 'mdev' into audio_fastpath

This commit is contained in:
Frank
2023-07-08 19:23:36 +02:00
12 changed files with 4607 additions and 4223 deletions

View File

@@ -912,12 +912,6 @@ build_flags_M =
-D USE_ALT_DISPLAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI -D USE_ALT_DISPLAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI
-D USERMOD_FOUR_LINE_DISPLAY -D USERMOD_FOUR_LINE_DISPLAY
-D USERMOD_ROTARY_ENCODER_UI -D USERMOD_ROTARY_ENCODER_UI
-D USERMOD_AUTO_SAVE
-D USERMOD_WEATHER ; WLEDMM usermod
-D USERMOD_MPU6050_IMU ; gyro/accelero for USERMOD_GAMES (ONLY WORKS IF USERMOD_FOUR_LINE_DISPLAY NOT INCLUDED - I2C SHARING BUG)
-D USERMOD_GAMES ; WLEDMM usermod
-D USERMOD_BATTERY ;; enable Battery usermod
-D USERMOD_BATTERY_USE_LIPO ;; use new "decharging curve" for LiPo cells
-D USERMOD_ANIMARTRIX ; WLEDMM usermod: CC BY-NC 3.0 licensed effects by Stefan Petrick -D USERMOD_ANIMARTRIX ; WLEDMM usermod: CC BY-NC 3.0 licensed effects by Stefan Petrick
;WLEDMM: only setting WLED_DEBUG_HOST is enough, ip and port can be defined in sync settings as well ;WLEDMM: only setting WLED_DEBUG_HOST is enough, ip and port can be defined in sync settings as well
-D WLED_DEBUG_HOST='"192.168.x.x"' ;; to send debug messages over network to host 192.168.x.y - FQDN is also possible -D WLED_DEBUG_HOST='"192.168.x.x"' ;; to send debug messages over network to host 192.168.x.y - FQDN is also possible
@@ -927,17 +921,21 @@ lib_deps_M =
;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings ;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings
OneWire@~2.3.5 ; used for USERMOD_FOUR_LINE_DISPLAY and USERMOD_DALLASTEMPERATURE OneWire@~2.3.5 ; used for USERMOD_FOUR_LINE_DISPLAY and USERMOD_DALLASTEMPERATURE
olikraus/U8g2 @ ^2.28.8 ; used for USERMOD_FOUR_LINE_DISPLAY olikraus/U8g2 @ ^2.28.8 ; used for USERMOD_FOUR_LINE_DISPLAY
ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU https://github.com/netmindz/animartrix.git#f070fefc42febe2de3a2ab5d6d39e78bbc539702
https://github.com/netmindz/animartrix.git#d7c1896166f13fec2917c305222a77e3b504d060
lib_deps_V4_M = lib_deps_V4_M =
;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings ;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings
paulstoffregen/OneWire@ ^2.3.7 ; used for USERMOD_DALLASTEMPERATURE -> need newer release with bugfixes for -S3; still requires TEMPERATURE_PIN < 46 paulstoffregen/OneWire@ ^2.3.7 ; used for USERMOD_DALLASTEMPERATURE -> need newer release with bugfixes for -S3; still requires TEMPERATURE_PIN < 46
olikraus/U8g2@ ^2.34.5 ; used for USERMOD_FOUR_LINE_DISPLAY -> need newer version with bugfixes for arduino-esp32 v2.0.4 (Wire inititialization) olikraus/U8g2@ ^2.34.5 ; used for USERMOD_FOUR_LINE_DISPLAY -> need newer version with bugfixes for arduino-esp32 v2.0.4 (Wire inititialization)
ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU https://github.com/netmindz/animartrix.git#f070fefc42febe2de3a2ab5d6d39e78bbc539702
https://github.com/netmindz/animartrix.git#d7c1896166f13fec2917c305222a77e3b504d060
build_flags_XL = build_flags_XL =
-D USERMOD_AUTO_SAVE
-D USERMOD_WEATHER ; WLEDMM usermod
-D USERMOD_MPU6050_IMU ; gyro/accelero for USERMOD_GAMES (ONLY WORKS IF USERMOD_FOUR_LINE_DISPLAY NOT INCLUDED - I2C SHARING BUG)
-D USERMOD_GAMES ; WLEDMM usermod
-D USERMOD_BATTERY ;; enable Battery usermod
-D USERMOD_BATTERY_USE_LIPO ;; use new "decharging curve" for LiPo cells
-D USERMOD_BH1750 -D USERMOD_BH1750
-D USERMOD_ANIMATED_STAIRCASE -D USERMOD_ANIMATED_STAIRCASE
-D USERMOD_RTC ;; experimental -D USERMOD_RTC ;; experimental
@@ -957,6 +955,7 @@ build_flags_XL =
-D USERMOD_ANIMARTRIX ; WLEDMM usermod: CC BY-NC 3.0 licensed effects by Stefan Petrick -D USERMOD_ANIMARTRIX ; WLEDMM usermod: CC BY-NC 3.0 licensed effects by Stefan Petrick
lib_deps_XL = lib_deps_XL =
ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU
claws/BH1750 @^1.2.0 ; used for USERMOD_BH1750 claws/BH1750 @^1.2.0 ; used for USERMOD_BH1750
; adafruit/Adafruit BMP280 Library @ 2.1.0 ;; experimental for usermod USERMOD_SENSORSTOMQTT ; adafruit/Adafruit BMP280 Library @ 2.1.0 ;; experimental for usermod USERMOD_SENSORSTOMQTT
; adafruit/Adafruit CCS811 Library @ 1.0.4 ;; experimental for usermod USERMOD_SENSORSTOMQTT ; adafruit/Adafruit CCS811 Library @ 1.0.4 ;; experimental for usermod USERMOD_SENSORSTOMQTT
@@ -1090,6 +1089,9 @@ build_unflags =
-D USERMOD_ANIMARTRIX ;; Tips our memory usage over the limit -D USERMOD_ANIMARTRIX ;; Tips our memory usage over the limit
; RAM: [== ] 24.4% (used 80060 bytes from 327680 bytes) ; RAM: [== ] 24.4% (used 80060 bytes from 327680 bytes)
; Flash: [==========] 95.3% (used 1499037 bytes from 1572864 bytes) ; Flash: [==========] 95.3% (used 1499037 bytes from 1572864 bytes)
; HELP !!!!! :
; RAM: [== ] 24.5% (used 80356 bytes from 327680 bytes)
; Flash: [==========] 99.9% (used 1571053 bytes from 1572864 bytes)
[env:esp32_16MB_M] [env:esp32_16MB_M]
extends = esp32_4MB_M_base extends = esp32_4MB_M_base

View File

@@ -7,58 +7,58 @@
//======================================================================================================================== //========================================================================================================================
static const char _data_FX_mode_Module_Experiment10[] PROGMEM = "Z💡Module_Experiment10 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment10[] PROGMEM = "Y💡Module_Experiment10 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment9[] PROGMEM = "Z💡Module_Experiment9 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment9[] PROGMEM = "Y💡Module_Experiment9 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment8[] PROGMEM = "Z💡Module_Experiment8 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment8[] PROGMEM = "Y💡Module_Experiment8 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment7[] PROGMEM = "Z💡Module_Experiment7 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment7[] PROGMEM = "Y💡Module_Experiment7 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment6[] PROGMEM = "Z💡Module_Experiment6 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment6[] PROGMEM = "Y💡Module_Experiment6 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment5[] PROGMEM = "Z💡Module_Experiment5 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment5[] PROGMEM = "Y💡Module_Experiment5 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment4[] PROGMEM = "Z💡Module_Experiment4 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment4[] PROGMEM = "Y💡Module_Experiment4 ☾@Speed;;1;2";
static const char _data_FX_mode_Zoom2[] PROGMEM = "Z💡Zoom2 ☾@;;1;2"; static const char _data_FX_mode_Zoom2[] PROGMEM = "Y💡Zoom2 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment3[] PROGMEM = "Z💡Module_Experiment3 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment3[] PROGMEM = "Y💡Module_Experiment3 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment2[] PROGMEM = "Z💡Module_Experiment2 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment2[] PROGMEM = "Y💡Module_Experiment2 ☾@Speed;;1;2";
static const char _data_FX_mode_Module_Experiment1[] PROGMEM = "Z💡Module_Experiment1 ☾@;;1;2"; static const char _data_FX_mode_Module_Experiment1[] PROGMEM = "Y💡Module_Experiment1 ☾@Speed;;1;2";
static const char _data_FX_mode_Parametric_Water[] PROGMEM = "Z💡Parametric_Water ☾@;;1;2"; static const char _data_FX_mode_Parametric_Water[] PROGMEM = "Y💡Parametric_Water ☾@Speed;;1;2";
static const char _data_FX_mode_Water[] PROGMEM = "Z💡Water ☾@;;1;2"; static const char _data_FX_mode_Water[] PROGMEM = "Y💡Water ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido_6[] PROGMEM = "Z💡Complex_Kaleido_6 ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido_6[] PROGMEM = "Y💡Complex_Kaleido_6 ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido_5[] PROGMEM = "Z💡Complex_Kaleido_5 ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido_5[] PROGMEM = "Y💡Complex_Kaleido_5 ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido_4[] PROGMEM = "Z💡Complex_Kaleido_4 ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido_4[] PROGMEM = "Y💡Complex_Kaleido_4 ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido_3[] PROGMEM = "Z💡Complex_Kaleido_3 ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido_3[] PROGMEM = "Y💡Complex_Kaleido_3 ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido_2[] PROGMEM = "Z💡Complex_Kaleido_2 ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido_2[] PROGMEM = "Y💡Complex_Kaleido_2 ☾@Speed;;1;2";
static const char _data_FX_mode_Complex_Kaleido[] PROGMEM = "Z💡Complex_Kaleido ☾@;;1;2"; static const char _data_FX_mode_Complex_Kaleido[] PROGMEM = "Y💡Complex_Kaleido ☾@Speed;;1;2";
static const char _data_FX_mode_SM10[] PROGMEM = "Z💡SM10 ☾@;;1;2"; static const char _data_FX_mode_SM10[] PROGMEM = "Y💡SM10 ☾@Speed;;1;2";
static const char _data_FX_mode_SM9[] PROGMEM = "Z💡SM9 ☾@;;1;2"; static const char _data_FX_mode_SM9[] PROGMEM = "Y💡SM9 ☾@Speed;;1;2";
static const char _data_FX_mode_SM8[] PROGMEM = "Z💡SM8 ☾@;;1;2"; static const char _data_FX_mode_SM8[] PROGMEM = "Y💡SM8 ☾@Speed;;1;2";
static const char _data_FX_mode_SM7[] PROGMEM = "Z💡SM7 ☾@;;1;2"; static const char _data_FX_mode_SM7[] PROGMEM = "Y💡SM7 ☾@Speed;;1;2";
static const char _data_FX_mode_SM6[] PROGMEM = "Z💡SM6 ☾@;;1;2"; static const char _data_FX_mode_SM6[] PROGMEM = "Y💡SM6 ☾@Speed;;1;2";
static const char _data_FX_mode_SM5[] PROGMEM = "Z💡SM5 ☾@;;1;2"; static const char _data_FX_mode_SM5[] PROGMEM = "Y💡SM5 ☾@Speed;;1;2";
static const char _data_FX_mode_SM4[] PROGMEM = "Z💡SM4 ☾@;;1;2"; static const char _data_FX_mode_SM4[] PROGMEM = "Y💡SM4 ☾@Speed;;1;2";
static const char _data_FX_mode_SM3[] PROGMEM = "Z💡SM3 ☾@;;1;2"; static const char _data_FX_mode_SM3[] PROGMEM = "Y💡SM3 ☾@Speed;;1;2";
static const char _data_FX_mode_SM2[] PROGMEM = "Z💡SM2 ☾@;;1;2"; static const char _data_FX_mode_SM2[] PROGMEM = "Y💡SM2 ☾@Speed;;1;2";
static const char _data_FX_mode_SM1[] PROGMEM = "Z💡SM1 ☾@;;1;2"; static const char _data_FX_mode_SM1[] PROGMEM = "Y💡SM1 ☾@Speed;;1;2";
static const char _data_FX_mode_Big_Caleido[] PROGMEM = "Z💡Big_Caleido ☾@;;1;2"; static const char _data_FX_mode_Big_Caleido[] PROGMEM = "Y💡Big_Caleido ☾@Speed;;1;2";
static const char _data_FX_mode_RGB_Blobs5[] PROGMEM = "Z💡RGB_Blobs5 ☾@;;1;2"; static const char _data_FX_mode_RGB_Blobs5[] PROGMEM = "Y💡RGB_Blobs5 ☾@Speed;;1;2";
static const char _data_FX_mode_RGB_Blobs4[] PROGMEM = "Z💡RGB_Blobs4 ☾@;;1;2"; static const char _data_FX_mode_RGB_Blobs4[] PROGMEM = "Y💡RGB_Blobs4 ☾@Speed;;1;2";
static const char _data_FX_mode_RGB_Blobs3[] PROGMEM = "Z💡RGB_Blobs3 ☾@;;1;2"; static const char _data_FX_mode_RGB_Blobs3[] PROGMEM = "Y💡RGB_Blobs3 ☾@Speed;;1;2";
static const char _data_FX_mode_RGB_Blobs2[] PROGMEM = "Z💡RGB_Blobs2 ☾@;;1;2"; static const char _data_FX_mode_RGB_Blobs2[] PROGMEM = "Y💡RGB_Blobs2 ☾@Speed;;1;2";
static const char _data_FX_mode_RGB_Blobs[] PROGMEM = "Z💡RGB_Blobs ☾@;;1;2"; static const char _data_FX_mode_RGB_Blobs[] PROGMEM = "Y💡RGB_Blobs ☾@Speed;;1;2";
static const char _data_FX_mode_Polar_Waves[] PROGMEM = "Z💡Polar_Waves ☾@;;1;2"; static const char _data_FX_mode_Polar_Waves[] PROGMEM = "Y💡Polar_Waves ☾@Speed;;1;2";
static const char _data_FX_mode_Slow_Fade[] PROGMEM = "Z💡Slow_Fade ☾@;;1;2"; static const char _data_FX_mode_Slow_Fade[] PROGMEM = "Y💡Slow_Fade ☾@Speed;;1;2";
static const char _data_FX_mode_Zoom[] PROGMEM = "Z💡Zoom ☾@;;1;2"; static const char _data_FX_mode_Zoom[] PROGMEM = "Y💡Zoom ☾@Speed;;1;2";
static const char _data_FX_mode_Hot_Blob[] PROGMEM = "Z💡Hot_Blob ☾@;;1;2"; static const char _data_FX_mode_Hot_Blob[] PROGMEM = "Y💡Hot_Blob ☾@Speed;;1;2";
static const char _data_FX_mode_Spiralus2[] PROGMEM = "Z💡Spiralus2 ☾@;;1;2"; static const char _data_FX_mode_Spiralus2[] PROGMEM = "Y💡Spiralus2 ☾@Speed;;1;2";
static const char _data_FX_mode_Spiralus[] PROGMEM = "Z💡Spiralus ☾@;;1;2"; static const char _data_FX_mode_Spiralus[] PROGMEM = "Y💡Spiralus ☾@Speed;;1;2";
static const char _data_FX_mode_Yves[] PROGMEM = "Z💡Yves ☾@;;1;2"; static const char _data_FX_mode_Yves[] PROGMEM = "Y💡Yves ☾@Speed;;1;2";
static const char _data_FX_mode_Scaledemo1[] PROGMEM = "Z💡Scaledemo1 ☾@;;1;2"; static const char _data_FX_mode_Scaledemo1[] PROGMEM = "Y💡Scaledemo1 ☾@Speed;;1;2";
static const char _data_FX_mode_Lava1[] PROGMEM = "Z💡Lava1 ☾@;;1;2"; static const char _data_FX_mode_Lava1[] PROGMEM = "Y💡Lava1 ☾@Speed;;1;2";
static const char _data_FX_mode_Caleido3[] PROGMEM = "Z💡Caleido3 ☾@;;1;2"; static const char _data_FX_mode_Caleido3[] PROGMEM = "Y💡Caleido3 ☾@Speed;;1;2";
static const char _data_FX_mode_Caleido2[] PROGMEM = "Z💡Caleido2 ☾@;;1;2"; static const char _data_FX_mode_Caleido2[] PROGMEM = "Y💡Caleido2 ☾@Speed;;1;2";
static const char _data_FX_mode_Caleido1[] PROGMEM = "Z💡Caleido1 ☾@;;1;2"; static const char _data_FX_mode_Caleido1[] PROGMEM = "Y💡Caleido1 ☾@Speed;;1;2";
static const char _data_FX_mode_Distance_Experiment[] PROGMEM = "Z💡Distance_Experiment ☾@;;1;2"; static const char _data_FX_mode_Distance_Experiment[] PROGMEM = "Y💡Distance_Experiment ☾@Speed;;1;2";
static const char _data_FX_mode_Center_Field[] PROGMEM = "Z💡Center_Field ☾@;;1;2"; static const char _data_FX_mode_Center_Field[] PROGMEM = "Y💡Center_Field ☾@Speed;;1;2";
static const char _data_FX_mode_Waves[] PROGMEM = "Z💡Waves ☾@;;1;2"; static const char _data_FX_mode_Waves[] PROGMEM = "Y💡Waves ☾@Speed;;1;2";
static const char _data_FX_mode_Chasing_Spirals[] PROGMEM = "Z💡Chasing_Spirals ☾@;;1;2"; static const char _data_FX_mode_Chasing_Spirals[] PROGMEM = "Y💡Chasing_Spirals ☾@Speed;;1;2";
static const char _data_FX_mode_Rotating_Blob[] PROGMEM = "Z💡Rotating_Blob ☾@;;1;2"; static const char _data_FX_mode_Rotating_Blob[] PROGMEM = "Y💡Rotating_Blob ☾@Speed;;1;2";
class ANIMartRIXMod:public ANIMartRIX { class ANIMartRIXMod:public ANIMartRIX {
@@ -67,6 +67,14 @@ class ANIMartRIXMod:public ANIMartRIX {
if (SEGENV.call == 0) { if (SEGENV.call == 0) {
init(SEGMENT.virtualWidth(), SEGMENT.virtualHeight(), false); init(SEGMENT.virtualWidth(), SEGMENT.virtualHeight(), false);
} }
float speedFactor = 1.0;
if (SEGMENT.speed < 128) {
speedFactor = (float) map(SEGMENT.speed, 0, 127, 1, 10) / 10.0f;
}
else{
speedFactor = map(SEGMENT.speed, 128, 255, 10, 100) / 10;
}
setSpeedFactor(speedFactor);
} }
void setPixelColor(int x, int y, rgb pixel) { void setPixelColor(int x, int y, rgb pixel) {
SEGMENT.setPixelColorXY(x, y, CRGB(pixel.red, pixel.green, pixel.blue)); SEGMENT.setPixelColorXY(x, y, CRGB(pixel.red, pixel.green, pixel.blue));
@@ -231,6 +239,7 @@ uint16_t mode_Big_Caleido() {
return FRAMETIME; return FRAMETIME;
} }
uint16_t mode_RGB_Blobs5() { uint16_t mode_RGB_Blobs5() {
anim.initEffect();
anim.RGB_Blobs5(); anim.RGB_Blobs5();
return FRAMETIME; return FRAMETIME;
} }
@@ -350,6 +359,8 @@ class AnimartrixUsermod : public Usermod {
void setup() { void setup() {
if(!enabled) return;
strip.addEffect(255, &mode_Module_Experiment10, _data_FX_mode_Module_Experiment10); strip.addEffect(255, &mode_Module_Experiment10, _data_FX_mode_Module_Experiment10);
strip.addEffect(255, &mode_Module_Experiment9, _data_FX_mode_Module_Experiment9); strip.addEffect(255, &mode_Module_Experiment9, _data_FX_mode_Module_Experiment9);
strip.addEffect(255, &mode_Module_Experiment8, _data_FX_mode_Module_Experiment8); strip.addEffect(255, &mode_Module_Experiment8, _data_FX_mode_Module_Experiment8);
@@ -418,6 +429,7 @@ class AnimartrixUsermod : public Usermod {
void addToJsonInfo(JsonObject& root) void addToJsonInfo(JsonObject& root)
{ {
if(!enabled) return;
char myStringBuffer[16]; // buffer for snprintf() char myStringBuffer[16]; // buffer for snprintf()
JsonObject user = root["u"]; JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u"); if (user.isNull()) user = root.createNestedObject("u");

View File

@@ -120,23 +120,6 @@ class FourLineDisplayUsermod : public Usermod {
// HW interface & configuration // HW interface & configuration
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
// semaphores - needed on ESP32 only, as we use a separate task to update the display
SemaphoreHandle_t drawMux = xSemaphoreCreateBinary(); // for drawstring and drawglyph functions (to prevent concurrent access to HW)
SemaphoreHandle_t drawMuxBig = xSemaphoreCreateBinary(); // for draw2x2GlyphIcons() and showCurrentEffectOrPalette() - more complex and not thread-safe
const TickType_t maxWait = 300 * portTICK_PERIOD_MS; // wait max. 300ms (drawstring semaphore)
const TickType_t maxWaitLong = 800 * portTICK_PERIOD_MS; // wait max. 800ms (big drawing semaphore)
#define FLD_SemaphoreTake(x,t) xSemaphoreTake((x),(t))
#define FLD_SemaphoreGive(x) xSemaphoreGive(x)
#else
// 8266 or no tasks - no semaphores
#define FLD_SemaphoreTake(x,t) pdTRUE
#define FLD_SemaphoreGive(x)
#if !defined(ARDUINO_ARCH_ESP32) && !defined(pdTRUE)
#define pdTRUE true
#endif
#endif
#ifndef FLD_SPI_DEFAULT #ifndef FLD_SPI_DEFAULT
int8_t ioPin[5] = {FLD_PIN_SCL, FLD_PIN_SDA, -1, -1, -1}; // I2C pins: SCL, SDA 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) uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000)
@@ -214,7 +197,7 @@ class FourLineDisplayUsermod : public Usermod {
// or check the gallery: // or check the gallery:
// https://github.com/olikraus/u8g2/wiki/gallery // https://github.com/olikraus/u8g2/wiki/gallery
// is this display using SPI? // WLEDMM is this display using SPI?
bool displayIsSPI(DisplayType disp) { bool displayIsSPI(DisplayType disp) {
switch(disp) { switch(disp) {
case SSD1306_SPI: // falls thru case SSD1306_SPI: // falls thru
@@ -229,7 +212,231 @@ class FourLineDisplayUsermod : public Usermod {
} }
// some displays need this to properly apply contrast // some displays need this to properly apply contrast
void setVcomh(bool highContrast) { void setVcomh(bool highContrast);
/**
* Wrappers for screen drawing
*/
void setFlipMode(uint8_t mode);
void setContrast(uint8_t contrast);
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false);
void draw2x2String(uint8_t col, uint8_t row, const char *string);
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false);
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font);
uint8_t getCols();
void clear();
void setPowerSave(uint8_t save);
void center(String &line, uint8_t width);
void draw2x2GlyphIcons();
/**
* Display the current date and time in large characters
* on the middle rows. Based 24 or 12 hour depending on
* the useAMPM configuration.
*/
void showTime();
public:
// gets called once at boot. Do all initialization that doesn't depend on
// network here
void setup();
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void connected();
/**
* Da loop.
*/
void loop();
//function to update lastredraw
inline void updateRedrawTime() {lastRedraw = millis(); }
//function to to check if a redraw or overlay draw is active. Needed for UM Rotary, to avoid random/concurrent drawing
bool canDraw(void);
/**
* Redraw the screen (but only if things have changed
* or if forceRedraw).
*/
void redraw(bool forceRedraw);
void redraw_core(bool forceRedraw);
void updateBrightness();
void updateSpeed();
void updateIntensity();
void drawStatusIcons();
/**
* marks the position of the arrow showing
* the current setting being changed
* pass line and colum info
*/
void setMarkLine(byte newMarkLineNum, byte newMarkColNum);
//Draw the arrow for the current setting being changed
void drawArrow();
//Display the current effect or palette (desiredEntry)
// on the appropriate line (row).
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row);
/**
* If there screen is off or in clock is displayed,
* this will return true. This allows us to throw away
* the first input from the rotary encoder but
* to wake up the screen.
*/
bool wakeDisplay();
/**
* Allows you to show one line and a glyph as overlay for a period of time.
* Clears the screen and prints.
* Used in Rotary Encoder usermod.
*/
void overlay(const char* line1, long showHowLong, byte glyphType);
/**
* Allows you to show Akemi WLED logo overlay for a period of time.
* Clears the screen and prints.
*/
void overlayLogo(long showHowLong);
/**
* Allows you to show two lines as overlay for a period of time.
* Clears the screen and prints.
* Used in Auto Save usermod
*/
void overlay(const char* line1, const char* line2, long showHowLong);
void networkOverlay(const char* line1, long showHowLong);
/**
* Enable sleep (turn the display off) or clock mode.
*/
void sleepOrClock(bool sleepEnable);
/**
* handleButton() can be used to override default button behaviour. Returning true
* will prevent button working in a default way.
* Replicating button.cpp
*/
bool handleButton(uint8_t b);
void onUpdateBegin(bool init);
/*
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
//void addToJsonInfo(JsonObject& root) {
//JsonObject user = root["u"];
//if (user.isNull()) user = root.createNestedObject("u");
//JsonArray data = user.createNestedArray(F("4LineDisplay"));
//data.add(F("Loaded."));
//}
/*
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void addToJsonState(JsonObject& root) {
//}
/*
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
//void readFromJsonState(JsonObject& root) {
// if (!initDone) return; // prevent crash on boot applyPreset()
//}
void appendConfigData();
/*
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
* If you want to force saving the current state, use serializeConfig() in your loop().
*
* CAUTION: serializeConfig() will initiate a filesystem write operation.
* It might cause the LEDs to stutter and will cause flash wear if called too often.
* Use it sparingly and always in the loop, never in network callbacks!
*
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root);
/*
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
*
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/
bool readFromConfig(JsonObject& root);
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() {
return USERMOD_ID_FOUR_LINE_DISP;
}
};
// 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 = "refreshRate-ms";
const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOutSec";
const char FourLineDisplayUsermod::_flip[] PROGMEM = "flip";
const char FourLineDisplayUsermod::_sleepMode[] PROGMEM = "sleepMode";
const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode";
const char FourLineDisplayUsermod::_showSeconds[] PROGMEM = "showSeconds";
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix";
#ifdef ARDUINO_ARCH_ESP32
FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr;
#endif
//WLEDMM
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
// semaphores - needed on ESP32 only, as we use a separate task to update the display
SemaphoreHandle_t drawMux = xSemaphoreCreateBinary(); // for drawstring and drawglyph functions (to prevent concurrent access to HW)
SemaphoreHandle_t drawMuxBig = xSemaphoreCreateBinary(); // for draw2x2GlyphIcons() and showCurrentEffectOrPalette() - more complex and not thread-safe
const TickType_t maxWait = 300 * portTICK_PERIOD_MS; // wait max. 300ms (drawstring semaphore)
const TickType_t maxWaitLong = 800 * portTICK_PERIOD_MS; // wait max. 800ms (big drawing semaphore)
#define FLD_SemaphoreTake(x,t) xSemaphoreTake((x),(t))
#define FLD_SemaphoreGive(x) xSemaphoreGive(x)
#else
// 8266 or no tasks - no semaphores
#define FLD_SemaphoreTake(x,t) pdTRUE
#define FLD_SemaphoreGive(x)
#if !defined(ARDUINO_ARCH_ESP32) && !defined(pdTRUE)
#define pdTRUE true
#endif
#endif
// some displays need this to properly apply contrast
void FourLineDisplayUsermod::setVcomh(bool highContrast) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
@@ -243,17 +450,17 @@ class FourLineDisplayUsermod : public Usermod {
/** /**
* Wrappers for screen drawing * Wrappers for screen drawing
*/ */
void setFlipMode(uint8_t mode) { void FourLineDisplayUsermod::setFlipMode(uint8_t mode) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
u8x8->setFlipMode(mode); u8x8->setFlipMode(mode);
} }
void setContrast(uint8_t contrast) { void FourLineDisplayUsermod::setContrast(uint8_t contrast) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
u8x8->setContrast(contrast); u8x8->setContrast(contrast);
} }
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) { void FourLineDisplayUsermod::drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex
@@ -277,7 +484,7 @@ class FourLineDisplayUsermod : public Usermod {
#endif #endif
FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex
} }
void draw2x2String(uint8_t col, uint8_t row, const char *string) { void FourLineDisplayUsermod::draw2x2String(uint8_t col, uint8_t row, const char *string) {
if (!typeOK || !enabled) return; if (!typeOK || !enabled) return;
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex
@@ -302,7 +509,7 @@ class FourLineDisplayUsermod : public Usermod {
#endif #endif
FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex
} }
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) { void FourLineDisplayUsermod::drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH) {
if (!typeOK || !enabled) return; if (!typeOK || !enabled) return;
if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex
u8x8->setFont(font); u8x8->setFont(font);
@@ -310,37 +517,37 @@ class FourLineDisplayUsermod : public Usermod {
else u8x8->drawGlyph(col, row, glyph); else u8x8->drawGlyph(col, row, glyph);
FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex
} }
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) { void FourLineDisplayUsermod::draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
if (!typeOK || !enabled) return; if (!typeOK || !enabled) return;
if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex
u8x8->setFont(font); u8x8->setFont(font);
u8x8->draw2x2Glyph(col, row, glyph); u8x8->draw2x2Glyph(col, row, glyph);
FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex
} }
uint8_t getCols() { uint8_t FourLineDisplayUsermod::getCols() {
if (!typeOK || !enabled) return 0; if (!typeOK || !enabled) return 0;
return u8x8->getCols(); return u8x8->getCols();
} }
void clear() { void FourLineDisplayUsermod::clear() {
if (!typeOK || !enabled) return; if (!typeOK || !enabled) return;
if (nullptr == u8x8) return; // prevents some crashes if (nullptr == u8x8) return; // prevents some crashes
if (FLD_SemaphoreTake(drawMux, maxWaitLong ) != pdTRUE) return; // WLEDMM acquire draw mutex - clear() can take very long in software I2C mode if (FLD_SemaphoreTake(drawMux, maxWaitLong ) != pdTRUE) return; // WLEDMM acquire draw mutex - clear() can take very long in software I2C mode
u8x8->clear(); // crashes randomly on ESP32 u8x8->clear(); // crashes randomly on ESP32
FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex
} }
void setPowerSave(uint8_t save) { void FourLineDisplayUsermod::setPowerSave(uint8_t save) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (u8x8 == nullptr) return; if (u8x8 == nullptr) return;
u8x8->setPowerSave(save); u8x8->setPowerSave(save);
} }
void center(String &line, uint8_t width) { void FourLineDisplayUsermod::center(String &line, uint8_t width) {
int len = line.length(); int len = line.length();
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line; if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
for (byte i=line.length(); i<width; i++) line += ' '; for (byte i=line.length(); i<width; i++) line += ' ';
} }
void draw2x2GlyphIcons() { void FourLineDisplayUsermod::draw2x2GlyphIcons() {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex
if (lineHeight > 1) { if (lineHeight > 1) {
@@ -364,7 +571,7 @@ class FourLineDisplayUsermod : public Usermod {
* on the middle rows. Based 24 or 12 hour depending on * on the middle rows. Based 24 or 12 hour depending on
* the useAMPM configuration. * the useAMPM configuration.
*/ */
void showTime() { void FourLineDisplayUsermod::showTime() {
if (!typeOK || !enabled || !displayTurnedOff) return; if (!typeOK || !enabled || !displayTurnedOff) return;
unsigned long now = millis(); unsigned long now = millis();
@@ -426,11 +633,11 @@ class FourLineDisplayUsermod : public Usermod {
drawing = false; drawing = false;
} }
public: // public:
// gets called once at boot. Do all initialization that doesn't depend on // gets called once at boot. Do all initialization that doesn't depend on
// network here // network here
void setup() { void FourLineDisplayUsermod::setup() {
if (!enabled) return; // typeOK = true will be set after successful setup if (!enabled) return; // typeOK = true will be set after successful setup
bool isHW = false; bool isHW = false;
@@ -623,7 +830,7 @@ class FourLineDisplayUsermod : public Usermod {
// gets called every time WiFi is (re-)connected. Initialize own network // gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here // interfaces here
void connected() { void FourLineDisplayUsermod::connected() {
knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() : knownSsid = WiFi.SSID(); //apActive ? apSSID : WiFi.SSID(); //apActive ? WiFi.softAPSSID() :
knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP(); knownIp = Network.localIP(); //apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
networkOverlay(PSTR("NETWORK INFO"),7000); networkOverlay(PSTR("NETWORK INFO"),7000);
@@ -632,7 +839,7 @@ class FourLineDisplayUsermod : public Usermod {
/** /**
* Da loop. * Da loop.
*/ */
void loop() { void FourLineDisplayUsermod::loop() {
#if !defined(ARDUINO_ARCH_ESP32) || !defined(FLD_ESP32_USE_THREADS) #if !defined(ARDUINO_ARCH_ESP32) || !defined(FLD_ESP32_USE_THREADS)
static unsigned long lastRunTime = 0; static unsigned long lastRunTime = 0;
unsigned long now = millis(); unsigned long now = millis();
@@ -647,13 +854,8 @@ class FourLineDisplayUsermod : public Usermod {
#endif #endif
} }
//function to update lastredraw
void updateRedrawTime() {
lastRedraw = millis();
}
//function to to check if a redraw or overlay draw is active. Needed for UM Rotary, to avoid random/concurrent drawing //function to to check if a redraw or overlay draw is active. Needed for UM Rotary, to avoid random/concurrent drawing
bool canDraw(void) { bool FourLineDisplayUsermod::canDraw(void) {
if (!typeOK || !enabled || !initDone) return(false); // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled || !initDone) return(false); // WLEDMM make sure the display is initialized before we try to draw on it
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) // only necessary on ESP32 #if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) // only necessary on ESP32
if (drawing) return(false); // overlay draws someting if (drawing) return(false); // overlay draws someting
@@ -666,7 +868,7 @@ class FourLineDisplayUsermod : public Usermod {
* Redraw the screen (but only if things have changed * Redraw the screen (but only if things have changed
* or if forceRedraw). * or if forceRedraw).
*/ */
void redraw(bool forceRedraw) { void FourLineDisplayUsermod::redraw(bool forceRedraw) {
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) #if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
// use a wrapper onESP32, to ensure the functions is not running several times in parallel ! // use a wrapper onESP32, to ensure the functions is not running several times in parallel !
static bool doForceRedraw = false; // for delaying "force redraw" static bool doForceRedraw = false; // for delaying "force redraw"
@@ -686,7 +888,7 @@ class FourLineDisplayUsermod : public Usermod {
reDrawing = false; // reset activity flag, as redraw has too many early returns that don't take care of this reDrawing = false; // reset activity flag, as redraw has too many early returns that don't take care of this
} }
void redraw_core(bool forceRedraw) { void FourLineDisplayUsermod::redraw_core(bool forceRedraw) {
#endif #endif
bool needRedraw = false; bool needRedraw = false;
unsigned long now = millis(); unsigned long now = millis();
@@ -802,7 +1004,7 @@ class FourLineDisplayUsermod : public Usermod {
showCurrentEffectOrPalette(knownMode, JSON_mode_names, 3); //Effect Mode info showCurrentEffectOrPalette(knownMode, JSON_mode_names, 3); //Effect Mode info
} }
void updateBrightness() { void FourLineDisplayUsermod::updateBrightness() {
knownBrightness = bri; knownBrightness = bri;
if (overlayUntil == 0) { if (overlayUntil == 0) {
brightness100 = ((uint16_t)bri*100)/255; brightness100 = ((uint16_t)bri*100)/255;
@@ -813,7 +1015,7 @@ class FourLineDisplayUsermod : public Usermod {
} }
} }
void updateSpeed() { void FourLineDisplayUsermod::updateSpeed() {
knownEffectSpeed = effectSpeed; knownEffectSpeed = effectSpeed;
if (overlayUntil == 0) { if (overlayUntil == 0) {
fxspeed100 = ((uint16_t)effectSpeed*100)/255; fxspeed100 = ((uint16_t)effectSpeed*100)/255;
@@ -824,7 +1026,7 @@ class FourLineDisplayUsermod : public Usermod {
} }
} }
void updateIntensity() { void FourLineDisplayUsermod::updateIntensity() {
knownEffectIntensity = effectIntensity; knownEffectIntensity = effectIntensity;
if (overlayUntil == 0) { if (overlayUntil == 0) {
fxintensity100 = ((uint16_t)effectIntensity*100)/255; fxintensity100 = ((uint16_t)effectIntensity*100)/255;
@@ -835,7 +1037,7 @@ class FourLineDisplayUsermod : public Usermod {
} }
} }
void drawStatusIcons() { void FourLineDisplayUsermod::drawStatusIcons() {
uint8_t col = 15; uint8_t col = 15;
uint8_t row = 0; uint8_t row = 0;
drawGlyph(col, row, (wificonnected ? 20 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // wifi icon drawGlyph(col, row, (wificonnected ? 20 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // wifi icon
@@ -850,19 +1052,19 @@ class FourLineDisplayUsermod : public Usermod {
* the current setting being changed * the current setting being changed
* pass line and colum info * pass line and colum info
*/ */
void setMarkLine(byte newMarkLineNum, byte newMarkColNum) { void FourLineDisplayUsermod::setMarkLine(byte newMarkLineNum, byte newMarkColNum) {
markLineNum = newMarkLineNum; markLineNum = newMarkLineNum;
markColNum = newMarkColNum; markColNum = newMarkColNum;
} }
//Draw the arrow for the current setting being changed //Draw the arrow for the current setting being changed
void drawArrow() { void FourLineDisplayUsermod::drawArrow() {
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1); if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
} }
//Display the current effect or palette (desiredEntry) //Display the current effect or palette (desiredEntry)
// on the appropriate line (row). // on the appropriate line (row).
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) { void FourLineDisplayUsermod::showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
char lineBuffer[MAX_JSON_CHARS] = { '\0' }; char lineBuffer[MAX_JSON_CHARS] = { '\0' };
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex
@@ -934,7 +1136,7 @@ class FourLineDisplayUsermod : public Usermod {
* the first input from the rotary encoder but * the first input from the rotary encoder but
* to wake up the screen. * to wake up the screen.
*/ */
bool wakeDisplay() { bool FourLineDisplayUsermod::wakeDisplay() {
if (!typeOK || !enabled) return false; if (!typeOK || !enabled) return false;
if (!initDone) return false; if (!initDone) return false;
if (displayTurnedOff) { if (displayTurnedOff) {
@@ -956,7 +1158,7 @@ class FourLineDisplayUsermod : public Usermod {
* Clears the screen and prints. * Clears the screen and prints.
* Used in Rotary Encoder usermod. * Used in Rotary Encoder usermod.
*/ */
void overlay(const char* line1, long showHowLong, byte glyphType) { void FourLineDisplayUsermod::overlay(const char* line1, long showHowLong, byte glyphType) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (!initDone) return; // WLEDMM bugfix if (!initDone) return; // WLEDMM bugfix
unsigned long now = millis(); unsigned long now = millis();
@@ -983,7 +1185,7 @@ class FourLineDisplayUsermod : public Usermod {
* Allows you to show Akemi WLED logo overlay for a period of time. * Allows you to show Akemi WLED logo overlay for a period of time.
* Clears the screen and prints. * Clears the screen and prints.
*/ */
void overlayLogo(long showHowLong) { void FourLineDisplayUsermod::overlayLogo(long showHowLong) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
unsigned long now = millis(); unsigned long now = millis();
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
@@ -1045,7 +1247,7 @@ class FourLineDisplayUsermod : public Usermod {
* Clears the screen and prints. * Clears the screen and prints.
* Used in Auto Save usermod * Used in Auto Save usermod
*/ */
void overlay(const char* line1, const char* line2, long showHowLong) { void FourLineDisplayUsermod::overlay(const char* line1, const char* line2, long showHowLong) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (!initDone) return; // WLEDMM bugfix if (!initDone) return; // WLEDMM bugfix
unsigned long now = millis(); unsigned long now = millis();
@@ -1069,7 +1271,7 @@ class FourLineDisplayUsermod : public Usermod {
drawing = false; drawing = false;
} }
void networkOverlay(const char* line1, long showHowLong) { void FourLineDisplayUsermod::networkOverlay(const char* line1, long showHowLong) {
if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it
if (!initDone) return; // WLEDMM bugfix if (!initDone) return; // WLEDMM bugfix
unsigned long now = millis(); unsigned long now = millis();
@@ -1113,7 +1315,7 @@ class FourLineDisplayUsermod : public Usermod {
/** /**
* Enable sleep (turn the display off) or clock mode. * Enable sleep (turn the display off) or clock mode.
*/ */
void sleepOrClock(bool sleepEnable) { void FourLineDisplayUsermod::sleepOrClock(bool sleepEnable) {
if (sleepEnable) { if (sleepEnable) {
displayTurnedOff = true; displayTurnedOff = true;
//setContrast(contrastFix? 2+ contrast/4 : 0); // un-comment to dim display in "clock mode" //setContrast(contrastFix? 2+ contrast/4 : 0); // un-comment to dim display in "clock mode"
@@ -1134,7 +1336,7 @@ class FourLineDisplayUsermod : public Usermod {
* will prevent button working in a default way. * will prevent button working in a default way.
* Replicating button.cpp * Replicating button.cpp
*/ */
bool handleButton(uint8_t b) { bool FourLineDisplayUsermod::handleButton(uint8_t b) {
yield(); yield();
if (!enabled if (!enabled
|| b // butto 0 only || b // butto 0 only
@@ -1210,7 +1412,7 @@ class FourLineDisplayUsermod : public Usermod {
#define ARDUINO_RUNNING_CORE 1 #define ARDUINO_RUNNING_CORE 1
#endif #endif
#endif #endif
void onUpdateBegin(bool init) { void FourLineDisplayUsermod::onUpdateBegin(bool init) {
#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) #if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS)
if (init && Display_Task) { if (init && Display_Task) {
vTaskSuspend(Display_Task); // update is about to begin, disable task to prevent crash vTaskSuspend(Display_Task); // update is about to begin, disable task to prevent crash
@@ -1271,7 +1473,7 @@ class FourLineDisplayUsermod : public Usermod {
// if (!initDone) return; // prevent crash on boot applyPreset() // if (!initDone) return; // prevent crash on boot applyPreset()
//} //}
void appendConfigData() { void FourLineDisplayUsermod::appendConfigData() {
oappend(SET_F("addHB('4LineDisplay');")); oappend(SET_F("addHB('4LineDisplay');"));
oappend(SET_F("dd=addDropdown('4LineDisplay','type');")); oappend(SET_F("dd=addDropdown('4LineDisplay','type');"));
@@ -1346,7 +1548,7 @@ class FourLineDisplayUsermod : public Usermod {
* *
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/ */
void addToConfig(JsonObject& root) { void FourLineDisplayUsermod::addToConfig(JsonObject& root) {
// determine if we are using global HW pins (data & clock) // determine if we are using global HW pins (data & clock)
int8_t hw_dta, hw_clk; int8_t hw_dta, hw_clk;
if (displayIsSPI(type)) { if (displayIsSPI(type)) {
@@ -1389,7 +1591,7 @@ class FourLineDisplayUsermod : public Usermod {
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup. * but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :) * If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/ */
bool readFromConfig(JsonObject& root) { bool FourLineDisplayUsermod::readFromConfig(JsonObject& root) {
bool needsRedraw = false; bool needsRedraw = false;
DisplayType newType = type; DisplayType newType = type;
int8_t oldPin[5]; for (byte i=0; i<5; i++) oldPin[i] = ioPin[i]; int8_t oldPin[5]; for (byte i=0; i<5; i++) oldPin[i] = ioPin[i];
@@ -1477,33 +1679,6 @@ class FourLineDisplayUsermod : public Usermod {
return !top[FPSTR(_contrastFix)].isNull(); return !top[FPSTR(_contrastFix)].isNull();
} }
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId() {
return USERMOD_ID_FOUR_LINE_DISP;
}
};
// 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 = "refreshRate-ms";
const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOutSec";
const char FourLineDisplayUsermod::_flip[] PROGMEM = "flip";
const char FourLineDisplayUsermod::_sleepMode[] PROGMEM = "sleepMode";
const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode";
const char FourLineDisplayUsermod::_showSeconds[] PROGMEM = "showSeconds";
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix";
#ifdef ARDUINO_ARCH_ESP32
FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr;
#endif
// WLEDMM clean up some macros, so they don't cause problems in other usermods // WLEDMM clean up some macros, so they don't cause problems in other usermods
#undef FLD_SemaphoreTake #undef FLD_SemaphoreTake
#undef FLD_SemaphoreGive #undef FLD_SemaphoreGive

View File

@@ -184,7 +184,162 @@ private:
* Sort the modes and palettes to the index arrays * Sort the modes and palettes to the index arrays
* modes_alpha_indexes and palettes_alpha_indexes. * modes_alpha_indexes and palettes_alpha_indexes.
*/ */
void sortModesAndPalettes() { void sortModesAndPalettes();
byte *re_initIndexArray(int numModes);
/**
* Return an array of mode or palette names from the JSON string.
* They don't end in '\0', they end in '"'.
*/
const char **re_findModeStrings(const char json[], int numModes);
/**
* Sort either the modes or the palettes using quicksort.
*/
void re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip);
public:
/*
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup();
/*
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
void connected();
/*
* loop() is called continuously. Here you can check for events, read sensors, etc.
*
* Tips:
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
*
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
void loop();
void displayNetworkInfo();
void findCurrentEffectAndPalette();
boolean changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph);
void lampUdated();
void changeBrightness(bool increase);
void changeEffect(bool increase);
void changeEffectSpeed(bool increase);
void changeEffectIntensity(bool increase);
void changeCustom(uint8_t par, bool increase);
void changePalette(bool increase);
void changeHue(bool increase);
void changeSat(bool increase);
void changePreset(bool increase) ;
void changeCCT(bool increase);
/*
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
/*
void addToJsonInfo(JsonObject& root)
{
int reading = 20;
//this code adds "u":{"Light":[20," lux"]} to the info object
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonArray lightArr = user.createNestedArray("Light"); //name
lightArr.add(reading); //value
lightArr.add(" lux"); //unit
}
*/
/*
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
/*
void addToJsonState(JsonObject &root)
{
//root["user0"] = userVar0;
}
*/
/*
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
/*
void readFromJsonState(JsonObject &root)
{
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
}
*/
/**
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
*/
void addToConfig(JsonObject &root);
//WLEDMM: add appendConfigData
void appendConfigData();
/**
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
*
* The function should return true if configuration was successfully loaded or false if there was no configuration.
*/
bool readFromConfig(JsonObject &root);
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
{
return USERMOD_ID_ROTARY_ENC_UI;
}
};
// strings to reduce flash memory usage (used more than twice)
const char RotaryEncoderUIUsermod::_name[] PROGMEM = "Rotary-Encoder";
const char RotaryEncoderUIUsermod::_enabled[] PROGMEM = "enabled";
const char RotaryEncoderUIUsermod::_DT_pin[] PROGMEM = "DT-pin";
const char RotaryEncoderUIUsermod::_CLK_pin[] PROGMEM = "CLK-pin";
const char RotaryEncoderUIUsermod::_SW_pin[] PROGMEM = "SW-pin";
const char RotaryEncoderUIUsermod::_presetHigh[] PROGMEM = "preset-high";
const char RotaryEncoderUIUsermod::_presetLow[] PROGMEM = "preset-low";
const char RotaryEncoderUIUsermod::_applyToAll[] PROGMEM = "apply-2-all-seg";
/**
* Sort the modes and palettes to the index arrays
* modes_alpha_indexes and palettes_alpha_indexes.
*/
void RotaryEncoderUIUsermod::sortModesAndPalettes() {
//modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount()); //modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
modes_qstrings = strip.getModeDataSrc(); modes_qstrings = strip.getModeDataSrc();
modes_alpha_indexes = re_initIndexArray(strip.getModeCount()); modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
@@ -200,7 +355,7 @@ private:
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount); re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount);
} }
byte *re_initIndexArray(int numModes) { byte *RotaryEncoderUIUsermod::re_initIndexArray(int numModes) {
byte *indexes = (byte *)malloc(sizeof(byte) * numModes); byte *indexes = (byte *)malloc(sizeof(byte) * numModes);
for (byte i = 0; i < numModes; i++) { for (byte i = 0; i < numModes; i++) {
indexes[i] = i; indexes[i] = i;
@@ -212,7 +367,7 @@ private:
* Return an array of mode or palette names from the JSON string. * Return an array of mode or palette names from the JSON string.
* They don't end in '\0', they end in '"'. * They don't end in '\0', they end in '"'.
*/ */
const char **re_findModeStrings(const char json[], int numModes) { const char **RotaryEncoderUIUsermod::re_findModeStrings(const char json[], int numModes) {
const char **modeStrings = (const char **)malloc(sizeof(const char *) * numModes); const char **modeStrings = (const char **)malloc(sizeof(const char *) * numModes);
uint8_t modeIndex = 0; uint8_t modeIndex = 0;
bool insideQuotes = false; bool insideQuotes = false;
@@ -250,7 +405,7 @@ private:
/** /**
* Sort either the modes or the palettes using quicksort. * Sort either the modes or the palettes using quicksort.
*/ */
void re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip) { void RotaryEncoderUIUsermod::re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip) {
if (!modeNames) return; if (!modeNames) return;
listBeingSorted = modeNames; listBeingSorted = modeNames;
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp); qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
@@ -258,12 +413,12 @@ private:
} }
public: // public:
/* /*
* setup() is called once at boot. WiFi is not yet connected at this point. * setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar. * You can use it to initialize variables, sensors or similar.
*/ */
void setup() void RotaryEncoderUIUsermod::setup()
{ {
DEBUG_PRINTLN(F("Usermod Rotary Encoder init.")); DEBUG_PRINTLN(F("Usermod Rotary Encoder init."));
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } }; PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
@@ -318,7 +473,7 @@ public:
* connected() is called every time the WiFi is (re)connected * connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces * Use it to initialize network interfaces
*/ */
void connected() void RotaryEncoderUIUsermod::connected()
{ {
//Serial.println("Connected to WiFi!"); //Serial.println("Connected to WiFi!");
} }
@@ -333,7 +488,7 @@ public:
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds. * 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here. * Instead, use a timer check as shown here.
*/ */
void loop() void RotaryEncoderUIUsermod::loop()
{ {
if (!enabled) return; if (!enabled) return;
unsigned long currentTime = millis(); // get the current elapsed time unsigned long currentTime = millis(); // get the current elapsed time
@@ -469,14 +624,14 @@ public:
} }
} }
void displayNetworkInfo() { void RotaryEncoderUIUsermod::displayNetworkInfo() {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display != nullptr) if (display != nullptr)
display->networkOverlay(PSTR("NETWORK INFO"), 10000); display->networkOverlay(PSTR("NETWORK INFO"), 10000);
#endif #endif
} }
void findCurrentEffectAndPalette() { void RotaryEncoderUIUsermod::findCurrentEffectAndPalette() {
if (modes_alpha_indexes == nullptr) return; // WLEDMM bugfix if (modes_alpha_indexes == nullptr) return; // WLEDMM bugfix
currentEffectAndPaletteInitialized = true; currentEffectAndPaletteInitialized = true;
for (uint8_t i = 0; i < strip.getModeCount(); i++) { for (uint8_t i = 0; i < strip.getModeCount(); i++) {
@@ -494,7 +649,7 @@ public:
} }
} }
boolean changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph) { boolean RotaryEncoderUIUsermod::changeState(const char *stateName, byte markedLine, byte markedCol, byte glyph) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display != nullptr) { if (display != nullptr) {
if (display->wakeDisplay()) { if (display->wakeDisplay()) {
@@ -509,7 +664,7 @@ public:
return true; return true;
} }
void lampUdated() { void RotaryEncoderUIUsermod::lampUdated() {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
//setValuesFromFirstSelectedSeg(); //to make transition work on main segment (should no longer be required) //setValuesFromFirstSelectedSeg(); //to make transition work on main segment (should no longer be required)
@@ -518,7 +673,7 @@ public:
updateInterfaces(CALL_MODE_BUTTON); updateInterfaces(CALL_MODE_BUTTON);
} }
void changeBrightness(bool increase) { void RotaryEncoderUIUsermod::changeBrightness(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -539,7 +694,7 @@ public:
} }
void changeEffect(bool increase) { void RotaryEncoderUIUsermod::changeEffect(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -569,7 +724,7 @@ public:
} }
void changeEffectSpeed(bool increase) { void RotaryEncoderUIUsermod::changeEffectSpeed(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -598,7 +753,7 @@ public:
} }
void changeEffectIntensity(bool increase) { void RotaryEncoderUIUsermod::changeEffectIntensity(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -627,7 +782,7 @@ public:
} }
void changeCustom(uint8_t par, bool increase) { void RotaryEncoderUIUsermod::changeCustom(uint8_t par, bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
uint8_t val = 0; uint8_t val = 0;
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
@@ -676,7 +831,7 @@ public:
} }
void changePalette(bool increase) { void RotaryEncoderUIUsermod::changePalette(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -706,7 +861,7 @@ public:
} }
void changeHue(bool increase){ void RotaryEncoderUIUsermod::changeHue(bool increase){
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -736,7 +891,7 @@ public:
#endif #endif
} }
void changeSat(bool increase){ void RotaryEncoderUIUsermod::changeSat(bool increase){
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -765,7 +920,7 @@ public:
#endif #endif
} }
void changePreset(bool increase) { void RotaryEncoderUIUsermod::changePreset(bool increase) {
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -797,7 +952,7 @@ public:
} }
} }
void changeCCT(bool increase){ void RotaryEncoderUIUsermod::changeCCT(bool increase){
#ifdef USERMOD_FOUR_LINE_DISPLAY #ifdef USERMOD_FOUR_LINE_DISPLAY
if (display && display->wakeDisplay()) { if (display && display->wakeDisplay()) {
display->redraw(true); display->redraw(true);
@@ -869,7 +1024,7 @@ public:
/** /**
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json * addToConfig() (called from set.cpp) stores persistent properties to cfg.json
*/ */
void addToConfig(JsonObject &root) { void RotaryEncoderUIUsermod::addToConfig(JsonObject &root) {
// we add JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}} // we add JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}}
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
top[FPSTR(_enabled)] = enabled; top[FPSTR(_enabled)] = enabled;
@@ -883,7 +1038,7 @@ public:
} }
//WLEDMM: add appendConfigData //WLEDMM: add appendConfigData
void appendConfigData() void RotaryEncoderUIUsermod::appendConfigData()
{ {
oappend(SET_F("addHB('Rotary-Encoder');")); oappend(SET_F("addHB('Rotary-Encoder');"));
@@ -903,7 +1058,7 @@ public:
* *
* The function should return true if configuration was successfully loaded or false if there was no configuration. * The function should return true if configuration was successfully loaded or false if there was no configuration.
*/ */
bool readFromConfig(JsonObject &root) { bool RotaryEncoderUIUsermod::readFromConfig(JsonObject &root) {
// we look for JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}} // we look for JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}}
JsonObject top = root[FPSTR(_name)]; JsonObject top = root[FPSTR(_name)];
if (top.isNull()) { if (top.isNull()) {
@@ -950,23 +1105,3 @@ public:
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features // use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return !top[FPSTR(_applyToAll)].isNull(); return !top[FPSTR(_applyToAll)].isNull();
} }
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
{
return USERMOD_ID_ROTARY_ENC_UI;
}
};
// strings to reduce flash memory usage (used more than twice)
const char RotaryEncoderUIUsermod::_name[] PROGMEM = "Rotary-Encoder";
const char RotaryEncoderUIUsermod::_enabled[] PROGMEM = "enabled";
const char RotaryEncoderUIUsermod::_DT_pin[] PROGMEM = "DT-pin";
const char RotaryEncoderUIUsermod::_CLK_pin[] PROGMEM = "CLK-pin";
const char RotaryEncoderUIUsermod::_SW_pin[] PROGMEM = "SW-pin";
const char RotaryEncoderUIUsermod::_presetHigh[] PROGMEM = "preset-high";
const char RotaryEncoderUIUsermod::_presetLow[] PROGMEM = "preset-low";
const char RotaryEncoderUIUsermod::_applyToAll[] PROGMEM = "apply-2-all-seg";

View File

@@ -5285,7 +5285,7 @@ uint16_t mode_2DPlasmaball(void) { // By: Stepko https://edito
SEGMENT.fadeToBlackBy(SEGMENT.custom1>>2); SEGMENT.fadeToBlackBy(SEGMENT.custom1>>2);
float t = millis() / (33 - SEGMENT.speed/8); uint_fast32_t t = (millis() * 8) / (256 - SEGMENT.speed); // optimized to avoid float
for (int i = 0; i < cols; i++) { for (int i = 0; i < cols; i++) {
uint16_t thisVal = inoise8(i * 30, t, t); uint16_t thisVal = inoise8(i * 30, t, t);
uint16_t thisMax = map(thisVal, 0, 255, 0, cols-1); uint16_t thisMax = map(thisVal, 0, 255, 0, cols-1);
@@ -6058,7 +6058,8 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli
SEGMENT.custom2 = *maxVol * 2; SEGMENT.custom2 = *maxVol * 2;
} }
if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin
if (SEGMENT.custom2 < 48) SEGMENT.custom2 = 48; // WLEDMM prevent stupid settings for maxVol (below 24 = noise)
if (SEGMENT.custom2 < 24) SEGMENT.custom2 = 24; // WLEDMM prevent stupid settings for maxVol (below 24 = noise)
*binNum = SEGMENT.custom1; // Select a bin. *binNum = SEGMENT.custom1; // Select a bin.
*maxVol = SEGMENT.custom2 / 2; // Our volume comparator. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator.
@@ -6690,7 +6691,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
SEGMENT.custom2 = *maxVol * 2; SEGMENT.custom2 = *maxVol * 2;
} }
if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin
if (SEGMENT.custom2 < 48) SEGMENT.custom2 = 48; // WLEDMM prevent stupid settings for maxVol (below 24 = noise) if (SEGMENT.custom2 < 24) SEGMENT.custom2 = 24; // WLEDMM prevent stupid settings for maxVol (below 24 = noise)
*binNum = SEGMENT.custom1; // Select a bin. *binNum = SEGMENT.custom1; // Select a bin.
*maxVol = SEGMENT.custom2 / 2; // Our volume comparator. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator.
@@ -7297,7 +7298,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
} }
if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin if (SEGMENT.custom1 < 1) SEGMENT.custom1 = 1; // WLEDMM prevent stupid settings for bin
if (SEGMENT.custom2 < 48) SEGMENT.custom2 = 48; // WLEDMM prevent stupid settings for maxVol (below 24 = noise) if (SEGMENT.custom2 < 24) SEGMENT.custom2 = 24; // WLEDMM prevent stupid settings for maxVol (below 24 = noise)
*binNum = SEGMENT.custom1; // Select a bin. *binNum = SEGMENT.custom1; // Select a bin.
*maxVol = SEGMENT.custom2 / 2; // Our volume comparator. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator.

View File

@@ -1709,7 +1709,8 @@ void WS2812FX::estimateCurrentAndLimitBri() {
} }
uint32_t powerSum0 = powerSum; uint32_t powerSum0 = powerSum;
powerSum *= _brightness; //powerSum *= _brightness; // for NPBrightnessBus
powerSum *= 255; // no need to scale down powerSum - NPB-LG getPixelColor returns colors scaled down by brightness
if (powerSum > powerBudget) //scale brightness down to stay in current limit if (powerSum > powerBudget) //scale brightness down to stay in current limit
{ {
@@ -1718,9 +1719,10 @@ void WS2812FX::estimateCurrentAndLimitBri() {
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI; uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
uint8_t newBri = scale8(_brightness, scaleB); uint8_t newBri = scale8(_brightness, scaleB);
// to keep brightness uniform, sets virtual busses too - softhack007: apply reductions immediately // to keep brightness uniform, sets virtual busses too - softhack007: apply reductions immediately
if (scaleB < 255) busses.setBrightness(scaleB, true); // NPB-LG has already applied brightness, so its suffifient to post-apply scaling if (scaleB < 255) busses.setBrightness(scaleB, true); // NPB-LG has already applied brightness, so its suffifient to post-apply scaling ==> use scaleB instead of newBri
busses.setBrightness(newBri, false); // set new brightness for next frame busses.setBrightness(newBri, false); // set new brightness for next frame
currentMilliamps = (powerSum0 * newBri) / puPerMilliamp; //currentMilliamps = (powerSum0 * newBri) / puPerMilliamp; // for NPBrightnessBus
currentMilliamps = (powerSum0 * scaleB) / puPerMilliamp; // for NPBus-LG
} else { } else {
currentMilliamps = powerSum / puPerMilliamp; currentMilliamps = powerSum / puPerMilliamp;
busses.setBrightness(_brightness, false); // set new brightness for next frame busses.setBrightness(_brightness, false); // set new brightness for next frame

View File

@@ -412,6 +412,13 @@ button {
bottom: 0; bottom: 0;
} }
/* WLEDMM */
#effectGFX, #segGFX {
position: -webkit-sticky;
position: sticky;
top: 0;
}
#sliders .labels { #sliders .labels {
padding-top: 3px; padding-top: 3px;
font-size: small; font-size: small;

View File

@@ -9,7 +9,7 @@
// Autogenerated from wled00/data/cpal/cpal.htm, do not edit!! // Autogenerated from wled00/data/cpal/cpal.htm, do not edit!!
const uint16_t PAGE_cpal_L = 4721; const uint16_t PAGE_cpal_L = 4721;
const uint8_t PAGE_cpal[] PROGMEM = { const uint8_t PAGE_cpal[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xbd, 0x3b, 0x7f, 0x73, 0xdb, 0xb6,
0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2, 0x92, 0xff, 0xe7, 0x53, 0x20, 0x4c, 0x5f, 0x42, 0xd6, 0x14, 0x45, 0xd2, 0xb6, 0x64, 0x4b, 0xa2,
0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d, 0x3b, 0xa9, 0x93, 0x77, 0xce, 0x8d, 0xdd, 0x64, 0x5e, 0x7c, 0x6e, 0x7b, 0x3e, 0xbf, 0x31, 0x4d,
0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91, 0x42, 0x12, 0x1b, 0x8a, 0xe0, 0x03, 0x21, 0xd9, 0xae, 0xac, 0xef, 0x7e, 0xbb, 0x00, 0x48, 0x91,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -403,6 +403,6 @@ void registerUsermods()
usermods.add(new GamesUsermod()); usermods.add(new GamesUsermod());
#endif #endif
#ifdef USERMOD_ANIMARTRIX #ifdef USERMOD_ANIMARTRIX
usermods.add(new AnimartrixUsermod("Animartrix", true)); usermods.add(new AnimartrixUsermod("Animartrix", false));
#endif #endif
} }