From 02b6d53544a15fd4a514f66af9c34acf38a2d688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Tue, 20 Jul 2021 13:41:30 +0200 Subject: [PATCH] Rotary Encoder Compilation fix. (#2085) * Compilation fix. * Make rotary encoder usermod runtime configurable. --- .../usermod_v2_four_line_display.h | 22 ++- .../usermod_v2_rotary_encoder_ui.h | 125 +++++++++++++++--- 2 files changed, 123 insertions(+), 24 deletions(-) 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 0e21f085..b56afc08 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 @@ -133,6 +133,7 @@ class FourLineDisplayUsermod : public Usermod { if (type == NONE) return; if (!pinManager.allocatePin(sclPin)) { sclPin = -1; type = NONE; return;} if (!pinManager.allocatePin(sdaPin)) { pinManager.deallocatePin(sclPin); sclPin = sdaPin = -1; type = NONE; return; } + DEBUG_PRINTLN(F("Allocating display.")); switch (type) { case SSD1306: #ifdef ESP8266 @@ -184,12 +185,19 @@ class FourLineDisplayUsermod : public Usermod { type = NONE; return; } - (static_cast(u8x8))->begin(); + initDone = true; + if (u8x8 != nullptr) { + DEBUG_PRINTLN(F("Starting display.")); + (static_cast(u8x8))->begin(); + } else { + DEBUG_PRINTLN(F("Display init failed.")); + type = NONE; + return; + } setFlipMode(flip); setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 setPowerSave(0); drawString(0, 0, "Loading..."); - initDone = true; } // gets called every time WiFi is (re-)connected. Initialize own network @@ -388,10 +396,8 @@ class FourLineDisplayUsermod : public Usermod { showCurrentEffectOrPalette(knownPalette, JSON_palette_names, line); break; case FLD_LINE_TIME: - showTime(false); - break; default: - // unknown type, do nothing + showTime(false); break; } } @@ -466,6 +472,10 @@ class FourLineDisplayUsermod : public Usermod { overlayUntil = millis() + showHowLong; } + void setLineType(byte lT) { + lineType = (Line4Type) lT; + } + /** * Line 3 or 4 (last two lines) can be marked with an * arrow in the first column. Pass 2 or 3 to this to @@ -648,6 +658,7 @@ class FourLineDisplayUsermod : public Usermod { type = newType; DEBUG_PRINTLN(F(" config loaded.")); } else { + DEBUG_PRINTLN(F(" config (re)loaded.")); // changing parameters from settings page if (sclPin!=newScl || sdaPin!=newSda || type!=newType) { if (type != NONE) delete (static_cast(u8x8)); @@ -665,7 +676,6 @@ class FourLineDisplayUsermod : public Usermod { setContrast(contrast); setFlipMode(flip); if (needsRedraw && !wakeDisplay()) redraw(true); - DEBUG_PRINTLN(F(" config (re)loaded.")); } // use "return !top["newestParameter"].isNull();" when updating Usermod with new features return true; diff --git a/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h b/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h index 424bb67a..5c8dd70e 100644 --- a/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h +++ b/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h @@ -39,10 +39,11 @@ #ifndef USERMOD_FOUR_LINE_DISPLAY // These constants won't be defined if we aren't using FourLineDisplay. -#define FLD_LINE_3_BRIGHTNESS 0 -#define FLD_LINE_3_EFFECT_SPEED 0 -#define FLD_LINE_3_EFFECT_INTENSITY 0 -#define FLD_LINE_3_PALETTE 0 +#define FLD_LINE_BRIGHTNESS 0 +#define FLD_LINE_MODE 0 +#define FLD_LINE_EFFECT_SPEED 0 +#define FLD_LINE_EFFECT_INTENSITY 0 +#define FLD_LINE_PALETTE 0 #endif @@ -55,10 +56,10 @@ private: int fadeAmount = 10; // Amount to change every step (brightness) unsigned long currentTime; unsigned long loopTime; - const int pinA = ENCODER_DT_PIN; // DT from encoder - const int pinB = ENCODER_CLK_PIN; // CLK from encoder - const int pinC = ENCODER_SW_PIN; // SW from encoder - unsigned char select_state = 0; // 0: brightness, 1: effect, 2: effect speed + int8_t pinA = ENCODER_DT_PIN; // DT from encoder + int8_t pinB = ENCODER_CLK_PIN; // CLK from encoder + int8_t pinC = ENCODER_SW_PIN; // SW from encoder + unsigned char select_state = 0; // 0: brightness, 1: effect, 2: effect speed unsigned char button_state = HIGH; unsigned char prev_button_state = HIGH; @@ -79,6 +80,16 @@ private: uint8_t effectCurrentIndex = 0; uint8_t effectPaletteIndex = 0; + bool initDone = false; + bool enabled = true; + + // strings to reduce flash memory usage (used more than twice) + static const char _name[]; + static const char _enabled[]; + static const char _DT_pin[]; + static const char _CLK_pin[]; + static const char _SW_pin[]; + public: /* * setup() is called once at boot. WiFi is not yet connected at this point. @@ -86,6 +97,10 @@ public: */ void setup() { + if (!pinManager.allocatePin(pinA)) { enabled = false; return;} + if (!pinManager.allocatePin(pinB)) { pinManager.deallocatePin(pinA); enabled = false; return; } + if (!pinManager.allocatePin(pinC)) { pinManager.deallocatePin(pinA); pinManager.deallocatePin(pinB); enabled = false; return; } + pinMode(pinA, INPUT_PULLUP); pinMode(pinB, INPUT_PULLUP); pinMode(pinC, INPUT_PULLUP); @@ -101,10 +116,12 @@ public: // But it's optional. But you want it. display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP); if (display != nullptr) { - display->setLineThreeType(FLD_LINE_3_BRIGHTNESS); + display->setLineType(FLD_LINE_BRIGHTNESS); display->setMarkLine(3); } #endif + + initDone = true; } /* @@ -128,6 +145,8 @@ public: */ void loop() { + if (!enabled) return; + currentTime = millis(); // get the current elapsed time // Initialize effectCurrentIndex and effectPaletteIndex to @@ -153,19 +172,19 @@ public: if (display != nullptr) { switch(newState) { case 0: - changedState = changeState("Brightness", FLD_LINE_3_BRIGHTNESS, 3); + changedState = changeState("Brightness", FLD_LINE_BRIGHTNESS, 3); break; case 1: - changedState = changeState("Select FX", FLD_LINE_3_EFFECT_SPEED, 2); + changedState = changeState("Select FX", FLD_LINE_MODE, 2); break; case 2: - changedState = changeState("FX Speed", FLD_LINE_3_EFFECT_SPEED, 3); + changedState = changeState("FX Speed", FLD_LINE_EFFECT_SPEED, 3); break; case 3: - changedState = changeState("FX Intensity", FLD_LINE_3_EFFECT_INTENSITY, 3); + changedState = changeState("FX Intensity", FLD_LINE_EFFECT_INTENSITY, 3); break; case 4: - changedState = changeState("Palette", FLD_LINE_3_PALETTE, 3); + changedState = changeState("Palette", FLD_LINE_PALETTE, 3); break; } } @@ -231,7 +250,7 @@ public: void findCurrentEffectAndPalette() { currentEffectAndPaleeteInitialized = true; for (uint8_t i = 0; i < strip.getModeCount(); i++) { - byte value = modes_alpha_indexes[i]; + //byte value = modes_alpha_indexes[i]; if (modes_alpha_indexes[i] == effectCurrent) { effectCurrentIndex = i; break; @@ -239,7 +258,7 @@ public: } for (uint8_t i = 0; i < strip.getPaletteCount(); i++) { - byte value = palettes_alpha_indexes[i]; + //byte value = palettes_alpha_indexes[i]; if (palettes_alpha_indexes[i] == strip.getSegment(0).palette) { effectPaletteIndex = i; break; @@ -255,7 +274,7 @@ public: return false; } display->overlay("Mode change", stateName, 1500); - display->setLineThreeType(lineThreeMode); + display->setLineType(lineThreeMode); display->setMarkLine(markedLine); } #endif @@ -386,10 +405,73 @@ public: */ void readFromJsonState(JsonObject &root) { - userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value + //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) { + // we add JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}} + JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname + top[FPSTR(_enabled)] = enabled; + top[FPSTR(_DT_pin)] = pinA; + top[FPSTR(_CLK_pin)] = pinB; + top[FPSTR(_SW_pin)] = pinC; + DEBUG_PRINTLN(F("Rotary Encoder config saved.")); + } + + /** + * 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) { + // we look for JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}} + JsonObject top = root[FPSTR(_name)]; + if (top.isNull()) { + DEBUG_PRINT(FPSTR(_name)); + DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); + return false; + } + int8_t newDTpin = pinA; + int8_t newCLKpin = pinB; + int8_t newSWpin = pinC; + + enabled = top[FPSTR(_enabled)] | enabled; + newDTpin = top[FPSTR(_DT_pin)] | newDTpin; + newCLKpin = top[FPSTR(_CLK_pin)] | newCLKpin; + newSWpin = top[FPSTR(_SW_pin)] | newSWpin; + + DEBUG_PRINT(FPSTR(_name)); + if (!initDone) { + // first run: reading from cfg.json + pinA = newDTpin; + pinB = newCLKpin; + pinC = newSWpin; + DEBUG_PRINTLN(F(" config loaded.")); + } else { + DEBUG_PRINTLN(F(" config (re)loaded.")); + // changing parameters from settings page + if (pinA!=newDTpin || pinB!=newCLKpin || pinC!=newSWpin) { + pinManager.deallocatePin(pinA); + pinManager.deallocatePin(pinB); + pinManager.deallocatePin(pinC); + pinA = newDTpin; + pinB = newCLKpin; + pinC = newSWpin; + if (pinA<0 || pinB<0 || pinC<0) { + enabled = false; + return true; + } + setup(); + } + } + // use "return !top["newestParameter"].isNull();" when updating Usermod with new features + return !top[FPSTR(_enabled)].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. @@ -399,3 +481,10 @@ public: 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";