mirror of https://github.com/meshcore-dev/MeshCore
2 changed files with 166 additions and 171 deletions
@ -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; |
|
||||
} |
|
||||
} |
} |
||||
Loading…
Reference in new issue