Maxim Prokhorov 4 years ago
parent
commit
95e31e02ad
6 changed files with 515 additions and 64 deletions
  1. +19
    -12
      code/espurna/button.h
  2. +90
    -23
      code/espurna/button.ino
  3. +51
    -20
      code/espurna/button_config.h
  4. +125
    -0
      code/espurna/config/defaults.h
  5. +0
    -9
      code/espurna/config/types.h
  6. +230
    -0
      code/espurna/debounce.h

+ 19
- 12
code/espurna/button.h View File

@ -8,25 +8,32 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#pragma once #pragma once
#include <DebounceEvent.h>
#include "debounce.h"
struct button_t {
#include <memory>
struct button_event_delays_t {
button_event_delays_t();
button_event_delays_t(unsigned long debounce, unsigned long dblclick, unsigned long lngclick, unsigned long lnglngclick);
// TODO: dblclick and debounce delays - right now a global setting, independent of ID
static unsigned long DebounceDelay;
static unsigned long DblclickDelay;
const unsigned long debounce;
const unsigned long dblclick;
const unsigned long lngclick;
const unsigned long lnglngclick;
};
// Use built-in indexed definitions to configure DebounceEvent
button_t(unsigned char index);
struct button_t {
// Provide custom DebounceEvent parameters instead
button_t(unsigned char pin, unsigned char mode, unsigned long actions, unsigned char relayID);
button_t(std::shared_ptr<DebounceEvent::PinBase> pin, int mode, unsigned long actions, unsigned char relayID, button_event_delays_t delays);
bool state(); bool state();
std::unique_ptr<DebounceEvent> event;
unsigned long actions;
unsigned char relayID;
std::unique_ptr<DebounceEvent::DebounceEvent> event_handler;
button_event_delays_t event_delays;
const unsigned long actions;
const unsigned char relayID;
}; };
bool buttonState(unsigned char id); bool buttonState(unsigned char id);


+ 90
- 23
code/espurna/button.ino View File

@ -8,7 +8,6 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#if BUTTON_SUPPORT #if BUTTON_SUPPORT
#include <DebounceEvent.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -19,28 +18,72 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include "button.h" #include "button.h"
#include "button_config.h" #include "button_config.h"
#include "debounce.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// TODO: dblclick and debounce delays - right now a global setting, independent of ID
unsigned long button_t::DebounceDelay = BUTTON_DEBOUNCE_DELAY;
unsigned long button_t::DblclickDelay = BUTTON_DBLCLICK_DELAY;
button_event_delays_t::button_event_delays_t() :
debounce(BUTTON_DEBOUNCE_DELAY),
dblclick(BUTTON_DBLCLICK_DELAY),
lngclick(BUTTON_LNGCLICK_DELAY),
lnglngclick(BUTTON_LNGLNGCLICK_DELAY)
{}
button_t::button_t(unsigned char pin, unsigned char mode, unsigned long actions, unsigned char relayID) :
event(new DebounceEvent(pin, mode, DebounceDelay, DblclickDelay)),
actions(actions),
relayID(relayID)
button_event_delays_t::button_event_delays_t(unsigned long debounce, unsigned long dblclick, unsigned long lngclick, unsigned long lnglngclick) :
debounce(debounce),
dblclick(dblclick),
lngclick(lngclick),
lnglngclick(lnglngclick)
{} {}
button_t::button_t(unsigned char index) :
button_t(_buttonPin(index), _buttonMode(index), _buttonConstructActions(index), _buttonRelay(index))
button_t::button_t(std::shared_ptr<DebounceEvent::PinBase> pin, int mode, unsigned long actions, unsigned char relayID, button_event_delays_t delays) :
event_handler(new DebounceEvent::DebounceEvent(pin, mode, delays.debounce, delays.dblclick)),
event_delays(delays),
actions(actions),
relayID(relayID)
{} {}
bool button_t::state() { bool button_t::state() {
return event->pressed();
return event_handler->pressed();
} }
std::vector<button_t> _buttons; std::vector<button_t> _buttons;
// -----------------------------------------------------------------------------
constexpr const uint8_t _buttonMapReleased(uint8_t count, uint8_t length, unsigned long lngclick_delay, unsigned long lnglngclick_delay) {
return (
(1 == count) ? (
(length > lnglngclick_delay) ? BUTTON_EVENT_LNGLNGCLICK :
(length > lngclick_delay) ? BUTTON_EVENT_LNGCLICK : BUTTON_EVENT_CLICK
) :
(2 == count) ? BUTTON_EVENT_DBLCLICK :
(3 == count) ? BUTTON_EVENT_TRIPLECLICK :
BUTTON_EVENT_NONE
);
}
const uint8_t _buttonMapEvent(button_t& button, DebounceEvent::Types::event_t event) {
using namespace DebounceEvent;
switch (event) {
case Types::EventPressed:
return BUTTON_EVENT_PRESSED;
case Types::EventChanged:
return BUTTON_EVENT_CLICK;
case Types::EventReleased: {
return _buttonMapReleased(
button.event_handler->getEventCount(),
button.event_handler->getEventLength(),
button.event_delays.lngclick,
button.event_delays.lnglngclick
);
}
case Types::EventNone:
default:
return BUTTON_EVENT_NONE;
}
}
unsigned char buttonCount() { unsigned char buttonCount() {
return _buttons.size(); return _buttons.size();
} }
@ -148,8 +191,22 @@ void buttonEvent(unsigned char id, unsigned char event) {
} }
struct DummyPin : virtual public DebounceEvent::PinBase {
DummyPin(unsigned char pin) : DebounceEvent::PinBase(pin) {}
void digitalWrite(int8_t val) {}
void pinMode(int8_t mode) {}
int digitalRead() { return 0; }
};
unsigned char buttonAdd(unsigned char pin, unsigned char mode, unsigned long actions, unsigned char relayID) { unsigned char buttonAdd(unsigned char pin, unsigned char mode, unsigned long actions, unsigned char relayID) {
_buttons.emplace_back(pin, mode, actions, relayID);
const unsigned char index = _buttons.size();
button_event_delays_t delays {
getSetting({"btnDebDelay", index}, _buttonDebounceDelay(index)),
getSetting({"btnDblCDelay", index}, _buttonDoubleClickDelay(index)),
getSetting({"btnLngCDelay", index}, _buttonLongClickDelay(index)),
getSetting({"btnLngLngCDelay", index}, _buttonLongLongClickDelay(index))
};
_buttons.emplace_back(std::make_shared<DummyPin>(GPIO_NONE), BUTTON_PUSHBUTTON, actions, relayID, delays);
return _buttons.size() - 1; return _buttons.size() - 1;
} }
@ -214,12 +271,26 @@ void buttonSetup() {
_buttons.reserve(buttons); _buttons.reserve(buttons);
// TODO: load based on index
button_t::DebounceDelay = getSetting("btnDebounce", BUTTON_DEBOUNCE_DELAY);
button_t::DblclickDelay = getSetting("btnDelay", BUTTON_DBLCLICK_DELAY);
for (unsigned char index = 0; index < buttons; ++index) {
const auto pin = getSetting({"btnGPIO", index}, _buttonPin(index));
if (!gpioValid(pin)) {
break;
}
for (unsigned char id = 0; id < buttons; ++id) {
_buttons.emplace_back(id);
button_event_delays_t delays {
getSetting({"btnDebDelay", index}, _buttonDebounceDelay(index)),
getSetting({"btnDblCDelay", index}, _buttonDoubleClickDelay(index)),
getSetting({"btnLngCDelay", index}, _buttonLongClickDelay(index)),
getSetting({"btnLngLngCDelay", index}, _buttonLongLongClickDelay(index))
};
_buttons.emplace_back(
std::make_shared<DebounceEvent::DigitalPin>(pin),
getSetting({"btnMode", index}, _buttonMode(index)),
getSetting({"btnActions", index}, _buttonConstructActions(index)),
getSetting({"btnRelay", index}, _buttonRelay(index)),
delays
);
} }
#endif #endif
@ -307,12 +378,8 @@ void buttonLoop() {
for (size_t id = 0; id < _buttons.size(); ++id) { for (size_t id = 0; id < _buttons.size(); ++id) {
auto& button = _buttons[id]; auto& button = _buttons[id];
if (auto event = button.event->loop()) {
buttonEvent(id, _buttonMapEvent(
event,
button.event->getEventCount(),
button.event->getEventLength()
));
if (auto event = button.event_handler->loop()) {
buttonEvent(id, _buttonMapEvent(button, event));
} }
} }


+ 51
- 20
code/espurna/button_config.h View File

@ -123,35 +123,66 @@ constexpr const unsigned char _buttonRelay(unsigned char index) {
); );
} }
constexpr const unsigned char _buttonDecodeEventAction(unsigned long actions, unsigned char event) {
constexpr const unsigned long _buttonDebounceDelay(unsigned char index) {
return ( return (
(event == BUTTON_EVENT_PRESSED) ? ((actions) & 0x0F) :
(event == BUTTON_EVENT_CLICK) ? ((actions >> 4) & 0x0F) :
(event == BUTTON_EVENT_DBLCLICK) ? ((actions >> 8) & 0x0F) :
(event == BUTTON_EVENT_LNGCLICK) ? ((actions >> 12) & 0x0F) :
(event == BUTTON_EVENT_LNGLNGCLICK) ? ((actions >> 16) & 0x0F) :
(event == BUTTON_EVENT_TRIPLECLICK) ? ((actions >> 20) & 0x0F) : BUTTON_MODE_NONE
(index == 0) ? BUTTON1_DEBOUNCE_DELAY :
(index == 1) ? BUTTON2_DEBOUNCE_DELAY :
(index == 2) ? BUTTON3_DEBOUNCE_DELAY :
(index == 3) ? BUTTON4_DEBOUNCE_DELAY :
(index == 4) ? BUTTON5_DEBOUNCE_DELAY :
(index == 5) ? BUTTON6_DEBOUNCE_DELAY :
(index == 6) ? BUTTON7_DEBOUNCE_DELAY :
(index == 7) ? BUTTON8_DEBOUNCE_DELAY : BUTTON_DEBOUNCE_DELAY
);
}
constexpr const unsigned long _buttonDoubleClickDelay(unsigned char index) {
return (
(index == 0) ? BUTTON1_DBLCLICK_DELAY :
(index == 1) ? BUTTON2_DBLCLICK_DELAY :
(index == 2) ? BUTTON3_DBLCLICK_DELAY :
(index == 3) ? BUTTON4_DBLCLICK_DELAY :
(index == 4) ? BUTTON5_DBLCLICK_DELAY :
(index == 5) ? BUTTON6_DBLCLICK_DELAY :
(index == 6) ? BUTTON7_DBLCLICK_DELAY :
(index == 7) ? BUTTON8_DBLCLICK_DELAY : BUTTON_DBLCLICK_DELAY
); );
} }
constexpr const uint8_t _buttonMapReleased(uint8_t count, uint8_t length) {
constexpr const unsigned long _buttonLongClickDelay(unsigned char index) {
return ( return (
(1 == count) ? (
(length > BUTTON_LNGLNGCLICK_DELAY) ? BUTTON_EVENT_LNGLNGCLICK :
(length > BUTTON_LNGCLICK_DELAY) ? BUTTON_EVENT_LNGCLICK : BUTTON_EVENT_CLICK
) :
(2 == count) ? BUTTON_EVENT_DBLCLICK :
(3 == count) ? BUTTON_EVENT_TRIPLECLICK :
BUTTON_EVENT_NONE
(index == 0) ? BUTTON1_LNGCLICK_DELAY :
(index == 1) ? BUTTON2_LNGCLICK_DELAY :
(index == 2) ? BUTTON3_LNGCLICK_DELAY :
(index == 3) ? BUTTON4_LNGCLICK_DELAY :
(index == 4) ? BUTTON5_LNGCLICK_DELAY :
(index == 5) ? BUTTON6_LNGCLICK_DELAY :
(index == 6) ? BUTTON7_LNGCLICK_DELAY :
(index == 7) ? BUTTON8_LNGCLICK_DELAY : BUTTON_LNGCLICK_DELAY
); );
} }
constexpr const uint8_t _buttonMapEvent(uint8_t event, uint8_t count, uint16_t length) {
constexpr const unsigned long _buttonLongLongClickDelay(unsigned char index) {
return ( return (
(event == EVENT_PRESSED) ? BUTTON_EVENT_PRESSED :
(event == EVENT_CHANGED) ? BUTTON_EVENT_CLICK :
(event == EVENT_RELEASED) ? _buttonMapReleased(count, length) :
BUTTON_EVENT_NONE
(index == 0) ? BUTTON1_LNGLNGCLICK_DELAY :
(index == 1) ? BUTTON2_LNGLNGCLICK_DELAY :
(index == 2) ? BUTTON3_LNGLNGCLICK_DELAY :
(index == 3) ? BUTTON4_LNGLNGCLICK_DELAY :
(index == 4) ? BUTTON5_LNGLNGCLICK_DELAY :
(index == 5) ? BUTTON6_LNGLNGCLICK_DELAY :
(index == 6) ? BUTTON7_LNGLNGCLICK_DELAY :
(index == 7) ? BUTTON8_LNGLNGCLICK_DELAY : BUTTON_LNGLNGCLICK_DELAY
);
}
constexpr const unsigned char _buttonDecodeEventAction(unsigned long actions, unsigned char event) {
return (
(event == BUTTON_EVENT_PRESSED) ? ((actions) & 0x0F) :
(event == BUTTON_EVENT_CLICK) ? ((actions >> 4) & 0x0F) :
(event == BUTTON_EVENT_DBLCLICK) ? ((actions >> 8) & 0x0F) :
(event == BUTTON_EVENT_LNGCLICK) ? ((actions >> 12) & 0x0F) :
(event == BUTTON_EVENT_LNGLNGCLICK) ? ((actions >> 16) & 0x0F) :
(event == BUTTON_EVENT_TRIPLECLICK) ? ((actions >> 20) & 0x0F) : BUTTON_MODE_NONE
); );
} }


+ 125
- 0
code/espurna/config/defaults.h View File

@ -233,6 +233,131 @@
#define BUTTON8_RELAY RELAY_NONE #define BUTTON8_RELAY RELAY_NONE
#endif #endif
#ifndef BUTTON1_EVENT_SOURCE
#define BUTTON1_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON2_EVENT_SOURCE
#define BUTTON2_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON3_EVENT_SOURCE
#define BUTTON3_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON4_EVENT_SOURCE
#define BUTTON4_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON5_EVENT_SOURCE
#define BUTTON5_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON6_EVENT_SOURCE
#define BUTTON6_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON7_EVENT_SOURCE
#define BUTTON7_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON8_EVENT_SOURCE
#define BUTTON8_EVENT_SOURCE DigitalPin
#endif
#ifndef BUTTON1_DEBOUNCE_DELAY
#define BUTTON1_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON2_DEBOUNCE_DELAY
#define BUTTON2_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON3_DEBOUNCE_DELAY
#define BUTTON3_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON4_DEBOUNCE_DELAY
#define BUTTON4_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON5_DEBOUNCE_DELAY
#define BUTTON5_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON6_DEBOUNCE_DELAY
#define BUTTON6_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON7_DEBOUNCE_DELAY
#define BUTTON7_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON8_DEBOUNCE_DELAY
#define BUTTON8_DEBOUNCE_DELAY BUTTON_DEBOUNCE_DELAY
#endif
#ifndef BUTTON1_DBLCLICK_DELAY
#define BUTTON1_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON2_DBLCLICK_DELAY
#define BUTTON2_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON3_DBLCLICK_DELAY
#define BUTTON3_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON4_DBLCLICK_DELAY
#define BUTTON4_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON5_DBLCLICK_DELAY
#define BUTTON5_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON6_DBLCLICK_DELAY
#define BUTTON6_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON7_DBLCLICK_DELAY
#define BUTTON7_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON8_DBLCLICK_DELAY
#define BUTTON8_DBLCLICK_DELAY BUTTON_DBLCLICK_DELAY
#endif
#ifndef BUTTON1_LNGCLICK_DELAY
#define BUTTON1_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON2_LNGCLICK_DELAY
#define BUTTON2_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON3_LNGCLICK_DELAY
#define BUTTON3_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON4_LNGCLICK_DELAY
#define BUTTON4_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON5_LNGCLICK_DELAY
#define BUTTON5_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON6_LNGCLICK_DELAY
#define BUTTON6_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON7_LNGCLICK_DELAY
#define BUTTON7_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON8_LNGCLICK_DELAY
#define BUTTON8_LNGCLICK_DELAY BUTTON_LNGCLICK_DELAY
#endif
#ifndef BUTTON1_LNGLNGCLICK_DELAY
#define BUTTON1_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON2_LNGLNGCLICK_DELAY
#define BUTTON2_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON3_LNGLNGCLICK_DELAY
#define BUTTON3_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON4_LNGLNGCLICK_DELAY
#define BUTTON4_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON5_LNGLNGCLICK_DELAY
#define BUTTON5_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON6_LNGLNGCLICK_DELAY
#define BUTTON6_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON7_LNGLNGCLICK_DELAY
#define BUTTON7_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
#ifndef BUTTON8_LNGLNGCLICK_DELAY
#define BUTTON8_LNGLNGCLICK_DELAY BUTTON_LNGLNGCLICK_DELAY
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Encoders // Encoders
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 0
- 9
code/espurna/config/types.h View File

@ -44,15 +44,6 @@
#define BUTTON_MODE_DIM_UP 10 #define BUTTON_MODE_DIM_UP 10
#define BUTTON_MODE_DIM_DOWN 11 #define BUTTON_MODE_DIM_DOWN 11
// Needed for ESP8285 boards under Windows using PlatformIO (?)
#ifndef BUTTON_PUSHBUTTON
#define BUTTON_PUSHBUTTON 0
#define BUTTON_SWITCH 1
#define BUTTON_DEFAULT_HIGH 2
#define BUTTON_SET_PULLUP 4
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// ENCODER // ENCODER
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------


+ 230
- 0
code/espurna/debounce.h View File

@ -0,0 +1,230 @@
/*
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/>.
----------------------------------------------------------------------------------
Modified to include generic INPUT / OUTPUT pin support through a custom interface.
Definitions are incompatible with DebounceEvent, you should not include it's headers.
*/
#pragma once
#include <Arduino.h>
namespace DebounceEvent {
#include <functional>
#include <memory>
namespace Types {
enum event_t {
EventNone,
EventChanged,
EventPressed,
EventReleased
};
enum mode_t {
ModePushbutton = 1 << 0,
ModeSwitch = 1 << 1,
ModeDefaultHigh = 1 << 2,
ModeSetPullup = 1 << 3
};
}
constexpr const unsigned long DebounceDelay = 50UL;
constexpr const unsigned long RepeatDelay = 500UL;
// base interface for generic pin handler.
class PinBase {
public:
PinBase(unsigned char pin) :
pin(pin)
{}
virtual void pinMode(int8_t mode) = 0;
virtual void digitalWrite(int8_t val) = 0;
virtual int digitalRead() = 0;
const unsigned char pin;
};
// real hardware pin
class DigitalPin : public PinBase {
public:
DigitalPin(unsigned char pin) :
PinBase(pin)
{}
void pinMode(int8_t mode) {
// Note: proxy for pinMode so it doesn't ignore INPUT_PULLUP with GPIO16
if (((mode == INPUT) || (mode == INPUT_PULLUP)) && this->pin == 16) {
::pinMode(this->pin, ((mode == INPUT_PULLUP) ? INPUT : INPUT_PULLDOWN_16));
return;
}
::pinMode(this->pin, mode);
}
void digitalWrite(int8_t val) {
::digitalWrite(this->pin, val);
}
int digitalRead() {
return ::digitalRead(this->pin);
}
};
class DebounceEvent {
public:
// TODO: not used in espurna buttons node
using callback_f = std::function<void(DebounceEvent* self, uint8_t event, uint8_t count, uint16_t length)>;
DebounceEvent(std::shared_ptr<PinBase> pin, int mode = Types::ModePushbutton | Types::ModeDefaultHigh, unsigned long delay = DebounceDelay, unsigned long repeat = RepeatDelay);
DebounceEvent(std::shared_ptr<PinBase> pin, callback_f callback, int mode = Types::ModePushbutton | Types::ModeDefaultHigh, unsigned long delay = DebounceDelay, unsigned long repeat = RepeatDelay);
Types::event_t loop();
bool pressed();
unsigned long getEventLength();
unsigned long getEventCount();
std::shared_ptr<PinBase> pin;
callback_f callback;
const int mode;
private:
const bool _is_switch;
const bool _default_status;
const unsigned long _delay;
const unsigned long _repeat;
bool _status;
bool _ready;
bool _reset_count;
unsigned long _event_start;
unsigned long _event_length;
unsigned char _event_count;
};
DebounceEvent::DebounceEvent(std::shared_ptr<PinBase> pin, DebounceEvent::callback_f callback, int mode, unsigned long debounce_delay, unsigned long repeat) :
pin(pin),
callback(callback),
mode(mode),
_is_switch(mode & Types::ModeSwitch),
_default_status(mode & Types::ModeDefaultHigh),
_delay(debounce_delay),
_repeat(repeat),
_status(false),
_ready(false),
_reset_count(true),
_event_start(0),
_event_length(0),
_event_count(0)
{
pin->pinMode((mode & Types::ModeSetPullup) ? INPUT_PULLUP : INPUT);
_status = (mode & Types::ModeSwitch) ? pin->digitalRead() : _default_status;
}
DebounceEvent::DebounceEvent(std::shared_ptr<PinBase> pin, int mode, unsigned long delay, unsigned long repeat) :
DebounceEvent(pin, nullptr, mode, delay, repeat)
{}
bool DebounceEvent::pressed() {
return (_status != _default_status);
}
unsigned long DebounceEvent::getEventLength() {
return _event_length;
}
unsigned long DebounceEvent::getEventCount() {
return _event_count;
}
Types::event_t DebounceEvent::loop() {
auto event = Types::EventNone;
if (pin->digitalRead() != _status) {
// TODO: check each loop instead of blocking?
auto start = millis();
while (millis() - start < _delay) delay(1);
if (pin->digitalRead() != _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;
}
// compat definitions from the original lib
#define BUTTON_PUSHBUTTON DebounceEvent::Types::ModePushbutton
#define BUTTON_SWITCH DebounceEvent::Types::ModeSwitch
#define BUTTON_DEFAULT_HIGH DebounceEvent::Types::ModeDefaultHigh
#define BUTTON_SET_PULLUP DebounceEvent::Types::ModeSetPullup
#define EVENT_NONE DebounceEvent::Types::EventNone
#define EVENT_CHANGED DebounceEvent::Types::EventChanged
#define EVENT_PRESSED DebounceEvent::Types::EventPressed
#define EVENT_RELEASED DebounceEvent::Types::EventReleased
} // namespace DebounceEvent

Loading…
Cancel
Save