Reverting changes to Button code
This commit is contained in:
@@ -1,142 +1,125 @@
|
|||||||
#include "Button.h"
|
#include "Button.h"
|
||||||
|
|
||||||
Button::Button(uint8_t pin, bool activeState)
|
Button::Button(uint8_t pin, bool activeState)
|
||||||
: _pin(pin), _activeState(activeState), _isAnalog(false), _analogThreshold(20)
|
: _pin(pin), _activeState(activeState), _isAnalog(false), _analogThreshold(20) {
|
||||||
{
|
_currentState = false; // Initialize as not pressed
|
||||||
_currentState = false; // Initialize as not pressed
|
_lastState = _currentState;
|
||||||
_lastState = _currentState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Button::Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold)
|
Button::Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold)
|
||||||
: _pin(pin), _activeState(activeState), _isAnalog(isAnalog), _analogThreshold(analogThreshold)
|
: _pin(pin), _activeState(activeState), _isAnalog(isAnalog), _analogThreshold(analogThreshold) {
|
||||||
{
|
_currentState = false; // Initialize as not pressed
|
||||||
_currentState = false; // Initialize as not pressed
|
_lastState = _currentState;
|
||||||
_lastState = _currentState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::begin()
|
void Button::begin() {
|
||||||
{
|
_currentState = readButton();
|
||||||
_currentState = readButton();
|
_lastState = _currentState;
|
||||||
_lastState = _currentState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::update()
|
void Button::update() {
|
||||||
{
|
uint32_t now = millis();
|
||||||
uint32_t now = millis();
|
|
||||||
|
// Read button at specified interval
|
||||||
// Read button at specified interval
|
if (now - _lastReadTime < BUTTON_READ_INTERVAL_MS) {
|
||||||
if (now - _lastReadTime < BUTTON_READ_INTERVAL_MS) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
_lastReadTime = now;
|
|
||||||
|
|
||||||
bool newState = readButton();
|
|
||||||
|
|
||||||
// Check if state has changed
|
|
||||||
if (newState != _lastState) {
|
|
||||||
_stateChangeTime = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debounce check
|
|
||||||
if ((now - _stateChangeTime) > BUTTON_DEBOUNCE_TIME_MS) {
|
|
||||||
if (newState != _currentState) {
|
|
||||||
_currentState = newState;
|
|
||||||
handleStateChange();
|
|
||||||
}
|
}
|
||||||
}
|
_lastReadTime = now;
|
||||||
|
|
||||||
_lastState = newState;
|
bool newState = readButton();
|
||||||
|
|
||||||
// Handle multi-click timeout
|
// Check if state has changed
|
||||||
if (_state == WAITING_FOR_MULTI_CLICK && (now - _releaseTime) > BUTTON_CLICK_TIMEOUT_MS) {
|
if (newState != _lastState) {
|
||||||
// Timeout reached, process the clicks
|
_stateChangeTime = now;
|
||||||
if (_clickCount == 1) {
|
|
||||||
triggerEvent(SHORT_PRESS);
|
|
||||||
}
|
}
|
||||||
else if (_clickCount == 2) {
|
|
||||||
triggerEvent(DOUBLE_PRESS);
|
// Debounce check
|
||||||
|
if ((now - _stateChangeTime) > BUTTON_DEBOUNCE_TIME_MS) {
|
||||||
|
if (newState != _currentState) {
|
||||||
|
_currentState = newState;
|
||||||
|
handleStateChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_clickCount >= 3) {
|
|
||||||
triggerEvent(TRIPLE_PRESS);
|
_lastState = newState;
|
||||||
}
|
|
||||||
_clickCount = 0;
|
// Handle multi-click timeout
|
||||||
_state = IDLE;
|
if (_state == WAITING_FOR_MULTI_CLICK && (now - _releaseTime) > BUTTON_CLICK_TIMEOUT_MS) {
|
||||||
}
|
// Timeout reached, process the clicks
|
||||||
|
if (_clickCount == 1) {
|
||||||
// Handle long press while button is held
|
triggerEvent(SHORT_PRESS);
|
||||||
if (_state == PRESSED && (now - _pressTime) > BUTTON_LONG_PRESS_TIME_MS) {
|
} else if (_clickCount == 2) {
|
||||||
triggerEvent(LONG_PRESS);
|
triggerEvent(DOUBLE_PRESS);
|
||||||
_state = IDLE; // Prevent multiple press events
|
} else if (_clickCount >= 3) {
|
||||||
_clickCount = 0;
|
triggerEvent(TRIPLE_PRESS);
|
||||||
}
|
}
|
||||||
}
|
_clickCount = 0;
|
||||||
|
_state = IDLE;
|
||||||
bool Button::readButton()
|
}
|
||||||
{
|
|
||||||
if (_isAnalog) {
|
// Handle long press while button is held
|
||||||
return (analogRead(_pin) < _analogThreshold);
|
if (_state == PRESSED && (now - _pressTime) > BUTTON_LONG_PRESS_TIME_MS) {
|
||||||
}
|
triggerEvent(LONG_PRESS);
|
||||||
else {
|
_state = IDLE; // Prevent multiple press events
|
||||||
return (digitalRead(_pin) == _activeState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::handleStateChange()
|
|
||||||
{
|
|
||||||
uint32_t now = millis();
|
|
||||||
|
|
||||||
if (_currentState) {
|
|
||||||
// Button pressed
|
|
||||||
_pressTime = now;
|
|
||||||
_state = PRESSED;
|
|
||||||
triggerEvent(ANY_PRESS);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Button released
|
|
||||||
if (_state == PRESSED) {
|
|
||||||
uint32_t pressDuration = now - _pressTime;
|
|
||||||
|
|
||||||
if (pressDuration < BUTTON_LONG_PRESS_TIME_MS) {
|
|
||||||
// Short press detected
|
|
||||||
_clickCount++;
|
|
||||||
_releaseTime = now;
|
|
||||||
_state = WAITING_FOR_MULTI_CLICK;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Long press already handled in update()
|
|
||||||
_state = IDLE;
|
|
||||||
_clickCount = 0;
|
_clickCount = 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::triggerEvent(EventType event)
|
bool Button::readButton() {
|
||||||
{
|
if (_isAnalog) {
|
||||||
_lastEvent = event;
|
return (analogRead(_pin) < _analogThreshold);
|
||||||
|
} else {
|
||||||
|
return (digitalRead(_pin) == _activeState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (event) {
|
void Button::handleStateChange() {
|
||||||
case ANY_PRESS:
|
uint32_t now = millis();
|
||||||
if (_onAnyPress)
|
|
||||||
_onAnyPress();
|
if (_currentState) {
|
||||||
break;
|
// Button pressed
|
||||||
case SHORT_PRESS:
|
_pressTime = now;
|
||||||
if (_onShortPress)
|
_state = PRESSED;
|
||||||
_onShortPress();
|
triggerEvent(ANY_PRESS);
|
||||||
break;
|
} else {
|
||||||
case DOUBLE_PRESS:
|
// Button released
|
||||||
if (_onDoublePress)
|
if (_state == PRESSED) {
|
||||||
_onDoublePress();
|
uint32_t pressDuration = now - _pressTime;
|
||||||
break;
|
|
||||||
case TRIPLE_PRESS:
|
if (pressDuration < BUTTON_LONG_PRESS_TIME_MS) {
|
||||||
if (_onTriplePress)
|
// Short press detected
|
||||||
_onTriplePress();
|
_clickCount++;
|
||||||
break;
|
_releaseTime = now;
|
||||||
case LONG_PRESS:
|
_state = WAITING_FOR_MULTI_CLICK;
|
||||||
if (_onLongPress)
|
} else {
|
||||||
_onLongPress();
|
// Long press already handled in update()
|
||||||
break;
|
_state = IDLE;
|
||||||
default:
|
_clickCount = 0;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::triggerEvent(EventType event) {
|
||||||
|
_lastEvent = event;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case ANY_PRESS:
|
||||||
|
if (_onAnyPress) _onAnyPress();
|
||||||
|
break;
|
||||||
|
case SHORT_PRESS:
|
||||||
|
if (_onShortPress) _onShortPress();
|
||||||
|
break;
|
||||||
|
case DOUBLE_PRESS:
|
||||||
|
if (_onDoublePress) _onDoublePress();
|
||||||
|
break;
|
||||||
|
case TRIPLE_PRESS:
|
||||||
|
if (_onTriplePress) _onTriplePress();
|
||||||
|
break;
|
||||||
|
case LONG_PRESS:
|
||||||
|
if (_onLongPress) _onLongPress();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,62 +4,74 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
// Button timing configuration
|
// Button timing configuration
|
||||||
#define BUTTON_DEBOUNCE_TIME_MS 50 // Debounce time in ms
|
#define BUTTON_DEBOUNCE_TIME_MS 50 // Debounce time in ms
|
||||||
#define BUTTON_CLICK_TIMEOUT_MS 500 // Max time between clicks for multi-click
|
#define BUTTON_CLICK_TIMEOUT_MS 500 // Max time between clicks for multi-click
|
||||||
#define BUTTON_LONG_PRESS_TIME_MS 3000 // Time to trigger long press (3 seconds)
|
#define BUTTON_LONG_PRESS_TIME_MS 3000 // Time to trigger long press (3 seconds)
|
||||||
#define BUTTON_READ_INTERVAL_MS 10 // How often to read the button
|
#define BUTTON_READ_INTERVAL_MS 10 // How often to read the button
|
||||||
|
|
||||||
class Button {
|
class Button {
|
||||||
public:
|
public:
|
||||||
enum EventType { NONE, SHORT_PRESS, DOUBLE_PRESS, TRIPLE_PRESS, LONG_PRESS, ANY_PRESS };
|
enum EventType {
|
||||||
|
NONE,
|
||||||
|
SHORT_PRESS,
|
||||||
|
DOUBLE_PRESS,
|
||||||
|
TRIPLE_PRESS,
|
||||||
|
LONG_PRESS,
|
||||||
|
ANY_PRESS
|
||||||
|
};
|
||||||
|
|
||||||
using EventCallback = std::function<void()>;
|
using EventCallback = std::function<void()>;
|
||||||
|
|
||||||
Button(uint8_t pin, bool activeState = LOW);
|
Button(uint8_t pin, bool activeState = LOW);
|
||||||
Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold = 20);
|
Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold = 20);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
// Set callbacks for different events
|
// Set callbacks for different events
|
||||||
void onShortPress(EventCallback callback) { _onShortPress = callback; }
|
void onShortPress(EventCallback callback) { _onShortPress = callback; }
|
||||||
void onDoublePress(EventCallback callback) { _onDoublePress = callback; }
|
void onDoublePress(EventCallback callback) { _onDoublePress = callback; }
|
||||||
void onTriplePress(EventCallback callback) { _onTriplePress = callback; }
|
void onTriplePress(EventCallback callback) { _onTriplePress = callback; }
|
||||||
void onLongPress(EventCallback callback) { _onLongPress = callback; }
|
void onLongPress(EventCallback callback) { _onLongPress = callback; }
|
||||||
void onAnyPress(EventCallback callback) { _onAnyPress = callback; }
|
void onAnyPress(EventCallback callback) { _onAnyPress = callback; }
|
||||||
|
|
||||||
// State getters
|
// State getters
|
||||||
bool isPressed() const { return _currentState; }
|
bool isPressed() const { return _currentState; }
|
||||||
EventType getLastEvent() const { return _lastEvent; }
|
EventType getLastEvent() const { return _lastEvent; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum State { IDLE, PRESSED, RELEASED, WAITING_FOR_MULTI_CLICK };
|
enum State {
|
||||||
|
IDLE,
|
||||||
|
PRESSED,
|
||||||
|
RELEASED,
|
||||||
|
WAITING_FOR_MULTI_CLICK
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t _pin;
|
uint8_t _pin;
|
||||||
bool _activeState;
|
bool _activeState;
|
||||||
bool _isAnalog;
|
bool _isAnalog;
|
||||||
uint16_t _analogThreshold;
|
uint16_t _analogThreshold;
|
||||||
|
|
||||||
State _state = IDLE;
|
State _state = IDLE;
|
||||||
bool _currentState;
|
bool _currentState;
|
||||||
bool _lastState;
|
bool _lastState;
|
||||||
|
|
||||||
uint32_t _stateChangeTime = 0;
|
uint32_t _stateChangeTime = 0;
|
||||||
uint32_t _pressTime = 0;
|
uint32_t _pressTime = 0;
|
||||||
uint32_t _releaseTime = 0;
|
uint32_t _releaseTime = 0;
|
||||||
uint32_t _lastReadTime = 0;
|
uint32_t _lastReadTime = 0;
|
||||||
|
|
||||||
uint8_t _clickCount = 0;
|
uint8_t _clickCount = 0;
|
||||||
EventType _lastEvent = NONE;
|
EventType _lastEvent = NONE;
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
EventCallback _onShortPress = nullptr;
|
EventCallback _onShortPress = nullptr;
|
||||||
EventCallback _onDoublePress = nullptr;
|
EventCallback _onDoublePress = nullptr;
|
||||||
EventCallback _onTriplePress = nullptr;
|
EventCallback _onTriplePress = nullptr;
|
||||||
EventCallback _onLongPress = nullptr;
|
EventCallback _onLongPress = nullptr;
|
||||||
EventCallback _onAnyPress = nullptr;
|
EventCallback _onAnyPress = nullptr;
|
||||||
|
|
||||||
bool readButton();
|
bool readButton();
|
||||||
void handleStateChange();
|
void handleStateChange();
|
||||||
void triggerEvent(EventType event);
|
void triggerEvent(EventType event);
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user