Button pin provider & runtime settings (#2162)
* wip
* cleanup buttons-through-serial code, remove hw mention from button module
* remove wip
* implement mqtt settings
* fixup struct members, dual no longer allocates debouncer
* add missing debounceevent lib
* fix missing event_handler, update names
* fix namespace
* drop lib
* fix int<->bool comparison
* Move gpio16 handling from DigitalPin to EventHandler
* Cleanup debounceevent headers
* Don't expect system headers to be included
* re 70b54c489f - no allocation, for real
* Adjust settings names
* dont retain by default
* unused
* typo
* Fix length type (ref 6017ad9474c5ea2f77fbca5f3c19b6cef058b2e9)
* Move pin class outside of debounce lib, lowercase ns
* move event handling inside of button_t
* refactor config. ..._MODE -> _CONFIG, ..._MODE_... -> ..._ACTION_...
* fix test
* naming
* move indexed value to header
* refactor actions into direct opts
* fix webui, fix buttons not respecting old user setting
* change button config format from bitmask to a struct, adjust settings conversion
* proxy some more header defautls, fix web kv
* gpiopin
* adjust webui func to support every setting
* clarify single-return event->string
* fix dual setting
* fix dual packet condition, de-duplicate funcs
* fix bogus warning 4 years ago |
|
- /*
-
- Original code:
-
- Debounce buttons and trigger events
- Copyright (C) 2015-2018 by Xose Pérez <xose dot perez at gmail dot com>
-
- The DebounceEvent library is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- The DebounceEvent library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with the DebounceEvent library. If not, see <http://www.gnu.org/licenses/>.
-
- ----------------------------------------------------------------------------------
-
- Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
-
- Modified to include generic INPUT / OUTPUT pin support through a custom interface.
- Definitions are incompatible with DebounceEvent, you should not include it's headers.
-
- */
-
- #include <functional>
- #include <memory>
-
- #include "libs/DebounceEvent.h"
-
- namespace debounce_event {
-
- EventEmitter::EventEmitter(types::Pin pin, types::EventHandler callback, const types::Config& config, unsigned long debounce_delay, unsigned long repeat) :
- _pin(pin),
- _callback(callback),
- _config(config),
- _is_switch(config.mode == types::Mode::Switch),
- _default_status(config.default_state == types::DefaultState::High),
- _delay(debounce_delay),
- _repeat(repeat),
- _status(false),
- _ready(false),
- _reset_count(true),
- _event_start(0),
- _event_length(0),
- _event_count(0)
- {
- if (!pin) return;
-
- if (_config.pin_mode == types::PinMode::InputPullup) {
- _pin->pinMode(INPUT_PULLUP);
- } else if (_config.pin_mode == types::PinMode::InputPulldown) {
- // ESP8266 does not have INPUT_PULLDOWN definition, and instead
- // has a GPIO16-specific INPUT_PULLDOWN_16:
- // - https://github.com/esp8266/Arduino/issues/478
- // - https://github.com/esp8266/Arduino/commit/1b3581d55ebf0f8c91e081f9af4cf7433d492ec9
- #ifdef ESP8266
- if (_pin->pin == 16) {
- _pin->pinMode(_default_status ? INPUT : INPUT_PULLDOWN_16);
- } else {
- _pin->pinMode(INPUT);
- }
- #else
- _pin->pinMode(INPUT_PULLDOWN);
- #endif
- } else {
- _pin->pinMode(INPUT);
- }
-
- _status = _is_switch ? (_pin->digitalRead() == (HIGH)) : _default_status;
- }
-
- EventEmitter::EventEmitter(types::Pin pin, const types::Config& config, unsigned long delay, unsigned long repeat) :
- EventEmitter(pin, nullptr, config, delay, repeat)
- {}
-
- bool EventEmitter::isPressed() {
- return (_status != _default_status);
- }
-
- const types::Pin EventEmitter::getPin() const {
- return _pin;
- }
-
- const types::Config EventEmitter::getConfig() const {
- return _config;
- }
-
- unsigned long EventEmitter::getEventLength() {
- return _event_length;
- }
- unsigned long EventEmitter::getEventCount() {
- return _event_count;
- }
-
- // TODO: current implementation allows pin == nullptr
-
- types::Event EventEmitter::loop() {
-
- static_assert((HIGH) == 1, "Arduino API HIGH is not 1");
- static_assert((LOW) == 0, "Arduino API LOW is not 0");
-
- auto event = types::EventNone;
- bool status = _pin->digitalRead() == (HIGH);
-
- if (status != _status) {
-
- // TODO: check each loop instead of blocking?
- auto start = millis();
- while (millis() - start < _delay) delay(1);
-
- status = _pin->digitalRead() == (HIGH);
- if (status != _status) {
-
- _status = !_status;
-
- if (_is_switch) {
- event = types::EventChanged;
- } else {
- if (_status == _default_status) {
- _event_length = millis() - _event_start;
- _ready = true;
- } else {
- event = types::EventPressed;
- _event_start = millis();
- _event_length = 0;
- if (_reset_count) {
- _event_count = 1;
- _reset_count = false;
- } else {
- ++_event_count;
- }
- _ready = false;
- }
- }
- }
- }
-
- if (_ready && (millis() - _event_start > _repeat)) {
- _ready = false;
- _reset_count = true;
- event = types::EventReleased;
- }
-
- if (_callback && (event != types::EventNone)) {
- _callback(*this, event, _event_count, _event_length);
- }
-
- return event;
-
- }
-
- } // namespace debounce_event
|