mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-03-30 21:25:46 +00:00
128 lines
3.4 KiB
C++
128 lines
3.4 KiB
C++
#include "Button.h"
|
|
|
|
Button::Button(uint8_t pin, bool activeState)
|
|
: _pin(pin), _activeState(activeState), _isAnalog(false), _analogThreshold(20) {
|
|
_currentState = false; // Initialize as not pressed
|
|
_lastState = _currentState;
|
|
}
|
|
|
|
Button::Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold)
|
|
: _pin(pin), _activeState(activeState), _isAnalog(isAnalog), _analogThreshold(analogThreshold) {
|
|
_currentState = false; // Initialize as not pressed
|
|
_lastState = _currentState;
|
|
}
|
|
|
|
void Button::begin() {
|
|
if (!_isAnalog) {
|
|
pinMode(_pin, INPUT_PULLUP);
|
|
}
|
|
_currentState = readButton();
|
|
_lastState = _currentState;
|
|
}
|
|
|
|
void Button::update() {
|
|
uint32_t now = millis();
|
|
|
|
// Read button at specified interval
|
|
if (now - _lastReadTime < BUTTON_READ_INTERVAL_MS) {
|
|
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();
|
|
}
|
|
}
|
|
|
|
_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;
|
|
}
|
|
}
|
|
|
|
bool Button::readButton() {
|
|
if (_isAnalog) {
|
|
return (analogRead(_pin) < _analogThreshold);
|
|
} else {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
} |