|
|
@ -1,230 +0,0 @@ |
|
|
|
/* |
|
|
|
|
|
|
|
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 |