diff --git a/firmware/platformio.ini b/firmware/platformio.ini index ed0723a5..d0ac0afc 100644 --- a/firmware/platformio.ini +++ b/firmware/platformio.ini @@ -23,10 +23,11 @@ lib_deps = mathieucarbou/ESPAsyncWebServer@3.1.5 wollewald/BH1750_WE@1.1.10 denyschuhlib/NTPtime@1.2.1 - fastled/FastLED@3.9.8 + fastled/FastLED@3.9.9 tzapu/WiFiManager@2.0.17 sensirion/arduino-sht@1.2.6 soylentorange/forcedBMX280@1.1.1 dawidchyrzynski/home-assistant-integration@2.1.0 https://github.com/J-A-A-M/melody-player.git@2.4.0 yasheena/TelnetSpy@1.4 + mathertel/OneButton@2.6.1 diff --git a/firmware/src/JaamButton.cpp b/firmware/src/JaamButton.cpp new file mode 100644 index 00000000..caa9c258 --- /dev/null +++ b/firmware/src/JaamButton.cpp @@ -0,0 +1,66 @@ +#include "JaamButton.h" +#include + + +int button1Pin = -1; +int button2Pin = -1; +OneButton button1; +OneButton button2; + +JaamButton::JaamButton() { +} + +void JaamButton::tick() { + if (isButton1Enabled()) button1.tick(); + if (isButton2Enabled()) button2.tick(); +} + +void JaamButton::setButton1Pin(int pin) { + button1Pin = pin; + if (isButton1Enabled()) { + button1.setup(button1Pin); + } +} + +void JaamButton::setButton2Pin(int pin) { + button2Pin = pin; + if (isButton1Enabled()) { + button2.setup(button2Pin); + } +} + +void JaamButton::setButton1ClickListener(void (*listener)(void)) { + if (isButton1Enabled()) { + button1.attachClick(listener); + } +} + +void JaamButton::setButton2ClickListener(void (*listener)(void)) { + if (isButton2Enabled()) { + button2.attachClick(listener); + } +} + +void JaamButton::setButton1LongClickListener(void (*listener)(void)) { + if (isButton1Enabled()) { + button1.attachLongPressStart(listener); + } +} + +void JaamButton::setButton2LongClickListener(void (*listener)(void)) { + if (isButton2Enabled()) { + button2.attachLongPressStart(listener); + } +} + +bool JaamButton::isButton1Enabled() { + return button1Pin >= 0; +} + +bool JaamButton::isButton2Enabled() { + return button2Pin >= 0; +} + +bool JaamButton::isAnyButtonEnabled() { + return isButton1Enabled() || isButton2Enabled(); +} diff --git a/firmware/src/JaamButton.h b/firmware/src/JaamButton.h new file mode 100644 index 00000000..3231c267 --- /dev/null +++ b/firmware/src/JaamButton.h @@ -0,0 +1,14 @@ +class JaamButton { +public: + JaamButton(); + void tick(); + void setButton1Pin(int pin); + void setButton2Pin(int pin); + void setButton1ClickListener(void (*listener)(void)); + void setButton2ClickListener(void (*listener)(void)); + void setButton1LongClickListener(void (*listener)(void)); + void setButton2LongClickListener(void (*listener)(void)); + bool isButton1Enabled(); + bool isButton2Enabled(); + bool isAnyButtonEnabled(); +}; diff --git a/firmware/src/JaamFirmware.cpp b/firmware/src/JaamFirmware.cpp index 4d094b19..ef3c7067 100644 --- a/firmware/src/JaamFirmware.cpp +++ b/firmware/src/JaamFirmware.cpp @@ -24,6 +24,7 @@ #include #include "JaamLightSensor.h" #include "JaamClimateSensor.h" +#include "JaamButton.h" #if BUZZER_ENABLED #include #include @@ -284,20 +285,8 @@ int wifiSignal; int ledsBrightnessLevels[BR_LEVELS_COUNT]; // Array containing LEDs brightness values int currentDimDisplay = 0; -// Button variables -#define SHORT_PRESS_TIME 500 // 500 milliseconds -#define LONG_PRESS_TIME 500 // 500 milliseconds -struct ButtonState { - const char* name; - int lastState = LOW; // the previous state from the input pin - int currentState; // the current reading from the input pin - unsigned long pressedTime = 0; - unsigned long releasedTime = 0; - bool isPressing = false; - bool isLongDetected = false; -}; -ButtonState button1; -ButtonState button2; +JaamButton buttons; + #define NIGHT_BRIGHTNESS_LEVEL 2 int binsCount = 0; @@ -321,14 +310,6 @@ bool isServiceStripEnabled() { return settings.service_ledpin > -1; } -bool isButton1Enabled() { - return settings.buttonpin > -1; -} - -bool isButton2Enabled() { - return settings.button2pin > -1; -} - bool isAlertPinEnabled() { return settings.alertpin > -1; } @@ -1013,6 +994,7 @@ bool saveNightMode(bool newState) { return true; } +//--Button start void handleClick(int event, SoundType soundType) { if (event != 0 && needToPlaySound(soundType)) playMelody(soundType); switch (event) { @@ -1079,47 +1061,40 @@ void longClick(int modeLong) { handleClick(modeLong, LONG_CLICK); } -// for display chars testing purposes -// int startSymbol = 0; -//--Button start -void buttonUpdate(ButtonState &button, uint8_t pin, int mode, int modeLong) { - // read the state of the switch/button: - button.currentState = digitalRead(pin); - - if (button.lastState == HIGH && button.currentState == LOW) { // button is pressed - button.pressedTime = millis(); - button.isPressing = true; - button.isLongDetected = false; - } else if (button.lastState == LOW && button.currentState == HIGH) { // button is released - button.isPressing = false; - button.releasedTime = millis(); - - long pressDuration = button.releasedTime - button.pressedTime; - - if (pressDuration < SHORT_PRESS_TIME) { +void buttonClick(const char* buttonName, int mode) { #if TEST_MODE - displayMessage("Single click!", button.name); + displayMessage("Single click!", buttonName); #else - singleClick(mode); + singleClick(mode); #endif - } - } - - if (button.isPressing == true && button.isLongDetected == false) { - long pressDuration = millis() - button.pressedTime; +} - if (pressDuration > LONG_PRESS_TIME) { +void buttonLongClick(const char* buttonName, int modeLong) { #if TEST_MODE - displayMessage("Long click!", button.name); + displayMessage("Long click!", buttonName); #else - longClick(modeLong); + longClick(modeLong); #endif - button.isLongDetected = true; - } - } +} + +void button1Click() { + LOG.println("Button 1 click"); + buttonClick("Button 1", settings.button_mode); +} + +void button2Click() { + LOG.println("Button 2 click"); + buttonClick("Button 2", settings.button2_mode); +} + +void button1LongClick() { + LOG.println("Button 1 long click"); + buttonLongClick("Button 1", settings.button_mode_long); +} - // save the the last state - button.lastState = button.currentState; +void button2LongClick() { + LOG.println("Button 2 long click"); + buttonLongClick("Button 2", settings.button2_mode_long); } void distributeBrightnessLevels() { @@ -2087,11 +2062,11 @@ void handleModes(AsyncWebServerRequest* request) { } addSlider(response, "weather_min_temp", "Нижній рівень температури (режим 'Погода')", settings.weather_min_temp, -20, 10, 1, "°C"); addSlider(response, "weather_max_temp", "Верхній рівень температури (режим 'Погода')", settings.weather_max_temp, 11, 40, 1, "°C"); - if (isButton1Enabled()) { + if (buttons.isButton1Enabled()) { addSelectBox(response, "button_mode", "Режим кнопки (Single Click)", settings.button_mode, SINGLE_CLICK_OPTIONS, SINGLE_CLICK_OPTIONS_MAX, NULL, false, ignoreSingleClickOptions); addSelectBox(response, "button_mode_long", "Режим кнопки (Long Click)", settings.button_mode_long, LONG_CLICK_OPTIONS, LONG_CLICK_OPTIONS_MAX, NULL, false, ignoreLongClickOptions); } - if (isButton2Enabled()) { + if (buttons.isButton2Enabled()) { addSelectBox(response, "button2_mode", "Режим кнопки 2 (Single Click)", settings.button2_mode, SINGLE_CLICK_OPTIONS, SINGLE_CLICK_OPTIONS_MAX, NULL, false, ignoreSingleClickOptions); addSelectBox(response, "button2_mode_long", "Режим кнопки 2 (Long Click)", settings.button2_mode_long, LONG_CLICK_OPTIONS, LONG_CLICK_OPTIONS_MAX, NULL, false, ignoreLongClickOptions); } @@ -3422,10 +3397,11 @@ void initLegacy() { settings.kyiv_district_mode = 3; settings.pixelpin = 13; - settings.bg_pixelpin = 0; + settings.bg_pixelpin = -1; settings.bg_pixelcount = 0; - settings.service_ledpin = 0; + settings.service_ledpin = -1; settings.buttonpin = 35; + settings.button2pin = -1; settings.display_model = 1; settings.display_height = 64; break; @@ -3465,17 +3441,21 @@ void initLegacy() { minBlinkBrightness = 0.07f; break; } - if (isButton1Enabled()) { - pinMode(settings.buttonpin, INPUT_PULLUP); - button1.name = "Button 1"; - } - if (isButton2Enabled()) { - pinMode(settings.button2pin, INPUT_PULLUP); - button2.name = "Button 2"; - } LOG.printf("Offset: %d\n", offset); } +void initButtons() { + LOG.println("Init buttons"); + + buttons.setButton1Pin(settings.buttonpin); + buttons.setButton1ClickListener(button1Click); + buttons.setButton1LongClickListener(button1LongClick); + + buttons.setButton2Pin(settings.button2pin); + buttons.setButton2ClickListener(button2Click); + buttons.setButton2LongClickListener(button2LongClick); +} + void initBuzzer() { #if BUZZER_ENABLED if (isBuzzerEnabled()) { @@ -3809,6 +3789,7 @@ void setup() { initChipID(); initSettings(); initLegacy(); + initButtons(); initBuzzer(); initAlertPin(); initClearPin(); @@ -3863,10 +3844,5 @@ void loop() { mapCycle(); } #endif - if (isButton1Enabled()) { - buttonUpdate(button1, settings.buttonpin, settings.button_mode, settings.button_mode_long); - } - if (isButton2Enabled()) { - buttonUpdate(button2, settings.button2pin, settings.button2_mode, settings.button2_mode_long); - } + buttons.tick(); }