Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for an immediate "press" event callback #141

Merged
merged 5 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ Here's a full list of events handled by this library:

| Attach Function | Description |
| ----------------------- | ------------------------------------------------------------- |
| `attachClick` | Fires as soon as a single click is detected. |
| `attachPress` | Fires as soon as a press is detected. |
| `attachClick` | Fires as soon as a single click press and release is detected.|
| `attachDoubleClick` | Fires as soon as a double click is detected. |
| `attachMultiClick` | Fires as soon as multiple clicks have been detected. |
| `attachLongPressStart` | Fires as soon as the button is held down for 800 milliseconds.|
Expand All @@ -175,12 +176,16 @@ This is because a single click callback must not to be triggered in case of a do
| `setPressMs(int)` | `800 msec` | Duration to hold a button to trigger a long press. |

You may change these default values but be aware that when you specify too short times
it is hard to click twice or you will create a press instead of a click.
it is hard to click twice or you will create a long press instead of a click.

The former functions `setDebounceTicks`, `setClickTicks` and `setPressTicks` are marked deprecated.
The term `Ticks` in these functions where confusing. Replace them with the ...Ms function calls.
There is no functional change on them.

Set debounce ms to a negative value to only debounce on release. `setDebounceMs(-25);` will immediately
update to a pressed state, and will debounce for 25ms going into the released state. This will expidite
the `attachPress` callback function to run instantly.


### Additional Functions

Expand Down
40 changes: 31 additions & 9 deletions src/OneButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ OneButton::OneButton(const int pin, const bool activeLow, const bool pullupActiv


// explicitly set the number of millisec that have to pass by before a click is assumed stable.
void OneButton::setDebounceMs(const unsigned int ms)
void OneButton::setDebounceMs(const int ms)
{
_debounce_ms = ms;
} // setDebounceMs
Expand All @@ -84,6 +84,20 @@ void OneButton::setIdleMs(const unsigned int ms)
_idle_ms = ms;
} // setIdleMs

// save function for click event
void OneButton::attachPress(callbackFunction newFunction)
{
_pressFunc = newFunction;
} // attachPress


// save function for parameterized click event
void OneButton::attachPress(parameterizedCallbackFunction newFunction, void *parameter)
{
_paramPressFunc = newFunction;
_pressFuncParam = parameter;
} // attachPress

// save function for click event
void OneButton::attachClick(callbackFunction newFunction)
{
Expand Down Expand Up @@ -204,28 +218,33 @@ int OneButton::getNumberClicks(void)
/**
* @brief Debounce input pin level for use in SpesialInput.
*/
int OneButton::debounce(const int value) {
bool OneButton::debounce(const bool value) {
now = millis(); // current (relative) time in msecs.
if (_lastDebouncePinLevel == value) {
if (now - _lastDebounceTime >= _debounce_ms)
debouncedPinLevel = value;

// Don't debounce going into active state, if _debounce_ms is negative
if(value && _debounce_ms < 0)
debouncedLevel = value;

if (_lastDebounceLevel == value) {
if (now - _lastDebounceTime >= abs(_debounce_ms))
debouncedLevel = value;
} else {
_lastDebounceTime = now;
_lastDebouncePinLevel = value;
_lastDebounceLevel = value;
}
return debouncedPinLevel;
return debouncedLevel;
};


/**
* @brief Check input of the configured pin,
* debounce input pin level and then
* debounce button state and then
* advance the finite state machine (FSM).
*/
void OneButton::tick(void)
{
if (_pin >= 0) {
_fsm(debounce(digitalRead(_pin)) == _buttonPressed);
_fsm(debounce(digitalRead(_pin) == _buttonPressed));
}
} // tick()

Expand Down Expand Up @@ -267,6 +286,9 @@ void OneButton::_fsm(bool activeLevel)
_newState(OneButton::OCS_DOWN);
_startTime = now; // remember starting time
_nClicks = 0;

if (_pressFunc) _pressFunc();
if (_paramPressFunc) _paramPressFunc(_pressFuncParam);
} // if
break;

Expand Down
23 changes: 17 additions & 6 deletions src/OneButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class OneButton
*/
[[deprecated("Use setDebounceMs() instead.")]]
void setDebounceTicks(const unsigned int ms) { setDebounceMs(ms); }; // deprecated
void setDebounceMs(const unsigned int ms);
void setDebounceMs(const int ms);

/**
* set # millisec after single click is assumed.
Expand Down Expand Up @@ -85,6 +85,13 @@ class OneButton

// ----- Attach events functions -----

/**
* Attach an event to be called immediately when a depress is detected.
* @param newFunction This function will be called when the event has been detected.
*/
void attachPress(callbackFunction newFunction);
void attachPress(parameterizedCallbackFunction newFunction, void *parameter);

/**
* Attach an event to be called when a single click is detected.
* @param newFunction This function will be called when the event has been detected.
Expand Down Expand Up @@ -177,7 +184,7 @@ class OneButton

private:
int _pin = -1; // hardware pin number.
unsigned int _debounce_ms = 50; // number of msecs for debounce times.
int _debounce_ms = 50; // number of msecs for debounce times.
unsigned int _click_ms = 400; // number of msecs before a click is detected.
unsigned int _press_ms = 800; // number of msecs before a long button press is detected
unsigned int _idle_ms = 1000; // number of msecs before idle is detected
Expand All @@ -187,6 +194,10 @@ class OneButton
// HIGH if the button connects the input pin to VCC when pressed.

// These variables will hold functions acting as event source.
callbackFunction _pressFunc = NULL;
parameterizedCallbackFunction _paramPressFunc = NULL;
void *_pressFuncParam = NULL;

callbackFunction _clickFunc = NULL;
parameterizedCallbackFunction _paramClickFunc = NULL;
void *_clickFuncParam = NULL;
Expand Down Expand Up @@ -241,8 +252,8 @@ class OneButton

bool _idleState = false;

int debouncedPinLevel = -1;
int _lastDebouncePinLevel = -1; // used for pin debouncing
bool debouncedLevel = false;
bool _lastDebounceLevel = false; // used for pin debouncing
unsigned long _lastDebounceTime = 0; // millis()
unsigned long now = 0; // millis()

Expand All @@ -256,8 +267,8 @@ class OneButton
public:
int pin() const { return _pin; };
stateMachine_t state() const { return _state; };
int debounce(const int value);
int debouncedValue() const { return debouncedPinLevel; };
bool debounce(const bool value);
int debouncedValue() const { return debouncedLevel; };

/**
* @brief Use this function in the DuringLongPress and LongPressStop events to get the time since the button was pressed.
Expand Down
Loading