Skip to content

Commit

Permalink
fix: 🐛 made it possible to change long_press_threshold and `repeat_…
Browse files Browse the repository at this point in the history
…cooldown`
  • Loading branch information
PA055 committed Oct 6, 2024
1 parent 7c5845f commit 510b151
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 17 deletions.
65 changes: 51 additions & 14 deletions include/gamepad/button.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,43 @@ class Button {
uint32_t time_released = 0;
/// How many times the button has been repeat-pressed
uint32_t repeat_iterations = 0;
/// How long the threshold should be for the longPress and shortRelease events
uint32_t long_press_threshold = 500;
/// How often repeatPress is called
uint32_t repeat_cooldown = 50;
/**
* @brief Set the time for a press to be considered a long press for the button
*
* @note this is likely to be used with the onLongPress(), onShortRelease(), onLongRelease(), or onRepeatPress()
* events
*
* @param threshold the time in ms that would be considered a long press
*
* @b Example:
* @code {.cpp}
* // change the threshold
* gamepad::master.Left.set_long_press_threshold(5000);
* // then call the function
* gamepad::master.Left.onLongPress("longPress1", []() {
* std::cout << "I was held for 5000ms instead of the 500ms default!" << std::endl;
* });
* @endcode
*/
void set_long_press_threshold(uint32_t threshold) const;
/**
* @brief Set the interval for the repeatPress event to repeat
*
* @note this is likely to be used with the onRepeatPress() event
*
* @param cooldown the interval in ms
*
* @b Example:
* @code {.cpp}
* // change the threshold
* gamepad::master.Up.set_repeat_cooldown(100);
* // then call the function
* gamepad::master.Up.onRepeatPress("repeatPress1", []() {
* std::cout << "I'm being repeated every 100ms instead of the 50ms default!" << std::endl;
* });
* @endcode
*/
void set_repeat_cooldown(uint32_t cooldown) const;
/**
* @brief Register a function to run when the button is pressed.
*
Expand All @@ -56,7 +89,7 @@ class Button {
* @brief Register a function to run when the button is long pressed.
*
* By default, onLongPress will fire when the button has been held down for
* 500ms or more, this threshold can be adjusted by changing long_press_threshold.
* 500ms or more, this threshold can be adjusted via the set_long_press_threshold() method.
*
* @warning When using this event along with onPress, both the onPress
* and onlongPress listeners may fire together.
Expand Down Expand Up @@ -97,7 +130,7 @@ class Button {
* @brief Register a function to run when the button is short released.
*
* By default, shortRelease will fire when the button has been released before 500ms, this threshold can be
* adjusted by changing long_press_threshold.
* adjusted via the set_long_press_threshold() method.
*
* @note This event will most likely be used along with the longPress event.
*
Expand All @@ -119,7 +152,7 @@ class Button {
* @brief Register a function to run when the button is long released.
*
* By default, longRelease will fire when the button has been released after 500ms, this threshold can be
* adjusted by changing long_press_threshold.
* adjusted via the set_long_press_threshold() method.
*
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run when the button is long released, the function MUST NOT block
Expand All @@ -129,18 +162,18 @@ class Button {
* @b Example:
* @code {.cpp}
* // Use a function...
* gamepad::master.A.onLongRelease("moveLiftToGround", moveLiftToGround);
* gamepad::master.Up.onLongRelease("moveLiftToGround", moveLiftToGround);
* // ...or a lambda
* gamepad::master.B.onLongRelease("spinIntake", []() { intake.move(127); });
* gamepad::master.Left.onLongRelease("spinIntake", []() { intake.move(127); });
* @endcode
*
*/
bool onLongRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run periodically after its been held
*
* By default repeatPress will start repeating after 500ms and repeat every 50ms, this can be changed by
* adjusting long_press_threshold and repeat_cooldown respectively
* By default repeatPress will start repeating after 500ms and repeat every 50ms, this can be adjusted via the
* set_long_press_threshold() and set_repeat_cooldown() methods respectively
*
* @param listenerName The name of the listener, this must be a unique name
* @param func the function to run periodically when the button is held, the function MUST NOT block
Expand All @@ -150,9 +183,9 @@ class Button {
* @b Example:
* @code {.cpp}
* // Use a function...
* gamepad::master.A.onRepeatPress("shootDisk", shootOneDisk);
* gamepad::master.X.onRepeatPress("shootDisk", shootOneDisk);
* // ...or a lambda
* gamepad::master.B.onRepeatPress("scoreOneRing", []() { intake.move_relative(200, 100); });
* gamepad::master.A.onRepeatPress("scoreOneRing", []() { intake.move_relative(200, 100); });
* @endcode
*
*/
Expand Down Expand Up @@ -207,11 +240,15 @@ class Button {
* @param is_held Whether or not the button is currently held down
*/
void update(bool is_held);
/// How long the threshold should be for the longPress and shortRelease events
mutable uint32_t long_press_threshold = 500;
/// How often repeatPress is called
mutable uint32_t repeat_cooldown = 50;
/// The last time the update function was called
uint32_t last_update_time = pros::millis();
/// The last time the long press event was fired
uint32_t last_long_press_time = 0;
// The last time the repeat event was called
/// The last time the repeat event was called
uint32_t last_repeat_time = 0;
mutable _impl::EventHandler<std::string> onPressEvent {};
mutable _impl::EventHandler<std::string> onLongPressEvent {};
Expand Down
15 changes: 13 additions & 2 deletions src/gamepad/button.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
#include "gamepad/button.hpp"
#include "gamepad/todo.hpp"
#include "pros/rtos.hpp"
#include <cstdint>
#include <sys/types.h>

namespace gamepad {
void Button::set_long_press_threshold(uint32_t threshold) const {
this->long_press_threshold = threshold;
}

void Button::set_repeat_cooldown(uint32_t cooldown) const {
this->repeat_cooldown = cooldown;
}

bool Button::onPress(std::string listenerName, std::function<void(void)> func) const {
return this->onPressEvent.add_listener(std::move(listenerName) + "_user", std::move(func));
}
Expand Down Expand Up @@ -65,10 +75,10 @@ void Button::update(const bool is_held) {
this->last_long_press_time <= pros::millis() - this->time_held) {
this->onLongPressEvent.fire();
this->last_long_press_time = pros::millis();
this->last_repeat_time = pros::millis();
this->last_repeat_time = pros::millis() - this->repeat_cooldown;
this->repeat_iterations = 0;
} else if (this->is_pressed && this->time_held >= this->long_press_threshold &&
pros::millis() - this->last_repeat_time > this->repeat_cooldown) {
pros::millis() - this->last_repeat_time >= this->repeat_cooldown) {
this->repeat_iterations++;
this->onRepeatPressEvent.fire();
this->last_repeat_time = pros::millis();
Expand All @@ -77,6 +87,7 @@ void Button::update(const bool is_held) {
if (this->time_held < this->long_press_threshold) this->onShortReleaseEvent.fire();
else this->onLongReleaseEvent.fire();
}

if (this->rising_edge) this->time_held = 0;
if (this->falling_edge) this->time_released = 0;
this->last_update_time = pros::millis();
Expand Down
26 changes: 25 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "main.h"
#include "gamepad/api.hpp"
#include "gamepad/controller.hpp"
#include "pros/rtos.hpp"
#include <cstdint>
#include <cstdio>

/**
* Runs initialization code. This occurs as soon as the program is started.
Expand All @@ -8,6 +12,8 @@
* to keep execution time for this mode under a few seconds.
*/

uint32_t last_repeat_press_time = pros::millis();

void downPress1() { printf("Down Press!\n"); }

void upRelease1() { printf("Up Release!\n"); }
Expand All @@ -16,16 +22,34 @@ void leftLongPress1() { printf("Left Long Press!\n"); }

void leftShortRelease1() { printf("Left Short Release!\n"); }

void leftLongRelease1() { printf("Left Long Release!\n"); }

void aPress1() {
last_repeat_press_time = pros::millis();
printf("A Pressed!\n");
}

void aRepeatPress1() {
printf("A Repeat Pressed %ims after last\n", pros::millis() - last_repeat_press_time);
last_repeat_press_time = pros::millis();
}

void initialize() {
// We can register functions to run when buttons are pressed
gamepad::master.Down.onPress("downPress1", downPress1);
// ...or when they're released
gamepad::master.Up.onRelease("downRelease1", upRelease1);
// There's also the longPress event
gamepad::master.Left.onLongPress("leftLongPress1", leftLongPress1);
// We can have two functions on one button,
// We can have two or even more functions on one button,
// just remember to give them different names
gamepad::master.Left.onShortRelease("leftShortRelease", leftShortRelease1);
gamepad::master.Left.onLongRelease("leftLongRelease", leftLongRelease1);
// We also have the repeat press event, where we can adjust the timing
gamepad::master.A.set_long_press_threshold(1000); // in ms
gamepad::master.A.set_repeat_cooldown(100); // in ms
gamepad::master.A.onPress("aStartPress", aPress1);
gamepad::master.A.onRepeatPress("aRepeatPress", aRepeatPress1);
// And we can use lambda's too
gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); });
}
Expand Down

0 comments on commit 510b151

Please sign in to comment.