refactor button.h to support long press and handle callback functions inside Process().

This commit is contained in:
2025-05-23 17:11:36 -07:00
parent b847515f32
commit 9ed9e01966

View File

@ -16,11 +16,11 @@
#include <Arduino.h> #include <Arduino.h>
const uint8_t DEBOUNCE_MS = 10; const uint8_t DEBOUNCE_MS = 10;
const uint16_t LONG_PRESS_DURATION_MS = 750;
class Button { class Button {
protected: protected:
typedef void (*CallbackFunction)(void); typedef void (*CallbackFunction)(void);
CallbackFunction on_press;
public: public:
// Enum constants for active change in button state. // Enum constants for active change in button state.
@ -28,6 +28,7 @@ class Button {
CHANGE_UNCHANGED, CHANGE_UNCHANGED,
CHANGE_PRESSED, CHANGE_PRESSED,
CHANGE_RELEASED, CHANGE_RELEASED,
CHANGE_RELEASED_LONG,
}; };
Button() {} Button() {}
@ -42,6 +43,7 @@ class Button {
void Init(uint8_t pin) { void Init(uint8_t pin) {
pinMode(pin, INPUT_PULLUP); pinMode(pin, INPUT_PULLUP);
pin_ = pin; pin_ = pin;
old_read_ = digitalRead(pin_);
} }
/** /**
@ -50,14 +52,15 @@ class Button {
* @param f Callback function to attach push behavior to this button. * @param f Callback function to attach push behavior to this button.
*/ */
void AttachPressHandler(CallbackFunction f) { void AttachPressHandler(CallbackFunction f) {
on_press = f; on_press_ = f;
}
// Execute the press callback.
void OnPress() {
if (on_press != NULL) {
on_press();
} }
/**
* Provide a handler function for executing when button is pressed.
*
* @param f Callback function to attach push behavior to this button.
*/
void AttachLongPressHandler(CallbackFunction f) {
on_long_press_ = f;
} }
/** /**
@ -65,10 +68,10 @@ class Button {
*/ */
void Process() { void Process() {
int read = digitalRead(pin_); int read = digitalRead(pin_);
bool debounced = (millis() - last_press_) > DEBOUNCE_MS; bool debounced = (millis() - last_press_) > DEBOUNCE_MS;
bool pressed = read == 0 && old_read_ == 1 && debounced; bool pressed = read == 0 && old_read_ == 1 && debounced;
bool released = read == 1 && old_read_ == 0 && debounced; bool released = read == 1 && old_read_ == 0 && debounced;
// Update variables for next loop // Update variables for next loop
last_press_ = (pressed || released) ? millis() : last_press_; last_press_ = (pressed || released) ? millis() : last_press_;
@ -76,10 +79,15 @@ class Button {
change_ = CHANGE_UNCHANGED; change_ = CHANGE_UNCHANGED;
if (pressed) { if (pressed) {
change_ = CHANGE_PRESSED; change_ = CHANGE_PRESSED;
on_ = true;
} else if (released) { } else if (released) {
// Call appropriate button press handler upon release.
if (last_press_ + LONG_PRESS_DURATION_MS > millis()) {
change_ = CHANGE_RELEASED; change_ = CHANGE_RELEASED;
on_ = false; if (on_press_ != NULL) on_press_();
} else {
change_ = CHANGE_RELEASED_LONG;
if (on_long_press_ != NULL) on_long_press_();
}
} }
old_read_ = read; old_read_ = read;
} }
@ -96,14 +104,15 @@ class Button {
* *
* @return true if cv signal is high, false if cv signal is low * @return true if cv signal is high, false if cv signal is low
*/ */
inline bool On() { return on_; } inline bool On() { return digitalRead(pin_) == 0; }
private: private:
uint8_t pin_; uint8_t pin_;
uint8_t old_read_; uint8_t old_read_ = 1;
unsigned long last_press_; unsigned long last_press_;
ButtonChange change_ = CHANGE_UNCHANGED; ButtonChange change_ = CHANGE_UNCHANGED;
bool on_; CallbackFunction on_press_;
CallbackFunction on_long_press_;
}; };
#endif #endif