Browse Source

Reverting changes to Button code

pull/353/head
hank 1 year ago
parent
commit
40bf7bbb9f
  1. 225
      examples/companion_radio/Button.cpp
  2. 112
      examples/companion_radio/Button.h

225
examples/companion_radio/Button.cpp

@ -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;
// Handle multi-click timeout
if (_state == WAITING_FOR_MULTI_CLICK && (now - _releaseTime) > BUTTON_CLICK_TIMEOUT_MS) {
// Timeout reached, process the clicks
if (_clickCount == 1) {
triggerEvent(SHORT_PRESS);
} else if (_clickCount == 2) {
triggerEvent(DOUBLE_PRESS);
} else if (_clickCount >= 3) {
triggerEvent(TRIPLE_PRESS);
}
_clickCount = 0;
_state = IDLE;
}
// Handle long press while button is held
if (_state == PRESSED && (now - _pressTime) > BUTTON_LONG_PRESS_TIME_MS) {
triggerEvent(LONG_PRESS);
_state = IDLE; // Prevent multiple press events
_clickCount = 0;
} }
_clickCount = 0;
_state = IDLE;
}
// Handle long press while button is held
if (_state == PRESSED && (now - _pressTime) > BUTTON_LONG_PRESS_TIME_MS) {
triggerEvent(LONG_PRESS);
_state = IDLE; // Prevent multiple press events
_clickCount = 0;
}
} }
bool Button::readButton() bool Button::readButton() {
{ if (_isAnalog) {
if (_isAnalog) { return (analogRead(_pin) < _analogThreshold);
return (analogRead(_pin) < _analogThreshold); } else {
} return (digitalRead(_pin) == _activeState);
else { }
return (digitalRead(_pin) == _activeState);
}
} }
void Button::handleStateChange() void Button::handleStateChange() {
{ uint32_t now = millis();
uint32_t now = millis();
if (_currentState) {
if (_currentState) { // Button pressed
// Button pressed _pressTime = now;
_pressTime = now; _state = PRESSED;
_state = PRESSED; triggerEvent(ANY_PRESS);
triggerEvent(ANY_PRESS); } else {
} // Button released
else { if (_state == PRESSED) {
// Button released uint32_t pressDuration = now - _pressTime;
if (_state == PRESSED) {
uint32_t pressDuration = now - _pressTime; if (pressDuration < BUTTON_LONG_PRESS_TIME_MS) {
// Short press detected
if (pressDuration < BUTTON_LONG_PRESS_TIME_MS) { _clickCount++;
// Short press detected _releaseTime = now;
_clickCount++; _state = WAITING_FOR_MULTI_CLICK;
_releaseTime = now; } else {
_state = WAITING_FOR_MULTI_CLICK; // Long press already handled in update()
} _state = IDLE;
else { _clickCount = 0;
// Long press already handled in update() }
_state = IDLE; }
_clickCount = 0;
}
} }
}
} }
void Button::triggerEvent(EventType event) void Button::triggerEvent(EventType event) {
{ _lastEvent = event;
_lastEvent = event;
switch (event) {
switch (event) { case ANY_PRESS:
case ANY_PRESS: if (_onAnyPress) _onAnyPress();
if (_onAnyPress) break;
_onAnyPress(); case SHORT_PRESS:
break; if (_onShortPress) _onShortPress();
case SHORT_PRESS: break;
if (_onShortPress) case DOUBLE_PRESS:
_onShortPress(); if (_onDoublePress) _onDoublePress();
break; break;
case DOUBLE_PRESS: case TRIPLE_PRESS:
if (_onDoublePress) if (_onTriplePress) _onTriplePress();
_onDoublePress(); break;
break; case LONG_PRESS:
case TRIPLE_PRESS: if (_onLongPress) _onLongPress();
if (_onTriplePress) break;
_onTriplePress(); default:
break; break;
case LONG_PRESS: }
if (_onLongPress)
_onLongPress();
break;
default:
break;
}
} }

112
examples/companion_radio/Button.h

@ -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,
uint8_t _pin; PRESSED,
bool _activeState; RELEASED,
bool _isAnalog; WAITING_FOR_MULTI_CLICK
uint16_t _analogThreshold; };
State _state = IDLE;
bool _currentState;
bool _lastState;
uint32_t _stateChangeTime = 0;
uint32_t _pressTime = 0;
uint32_t _releaseTime = 0;
uint32_t _lastReadTime = 0;
uint8_t _clickCount = 0;
EventType _lastEvent = NONE;
// Callbacks
EventCallback _onShortPress = nullptr;
EventCallback _onDoublePress = nullptr;
EventCallback _onTriplePress = nullptr;
EventCallback _onLongPress = nullptr;
EventCallback _onAnyPress = nullptr;
bool readButton(); uint8_t _pin;
void handleStateChange(); bool _activeState;
void triggerEvent(EventType event); bool _isAnalog;
uint16_t _analogThreshold;
State _state = IDLE;
bool _currentState;
bool _lastState;
uint32_t _stateChangeTime = 0;
uint32_t _pressTime = 0;
uint32_t _releaseTime = 0;
uint32_t _lastReadTime = 0;
uint8_t _clickCount = 0;
EventType _lastEvent = NONE;
// Callbacks
EventCallback _onShortPress = nullptr;
EventCallback _onDoublePress = nullptr;
EventCallback _onTriplePress = nullptr;
EventCallback _onLongPress = nullptr;
EventCallback _onAnyPress = nullptr;
bool readButton();
void handleStateChange();
void triggerEvent(EventType event);
}; };
Loading…
Cancel
Save