Skip to content

Commit

Permalink
Merge pull request #141 from mattallen37/master
Browse files Browse the repository at this point in the history
Add support for an immediate "press" event callback 
and minor changes in debounce behavior.
  • Loading branch information
mathertel authored May 27, 2024
2 parents 54c81d0 + 2251f1a commit 05242ac
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 17 deletions.
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

0 comments on commit 05242ac

Please sign in to comment.