From 5f510e3401171a895a5bc7bb28703e6b6ecad417 Mon Sep 17 00:00:00 2001 From: miles352 Date: Thu, 28 Nov 2024 13:59:55 -0500 Subject: [PATCH 1/2] Implemented get_digital_new_release --- include/pros/misc.h | 39 ++++++++++++++++++++++++++++++++++++++ include/pros/misc.hpp | 39 ++++++++++++++++++++++++++++++++++++++ src/devices/controller.c | 21 ++++++++++++++++++++ src/devices/controller.cpp | 4 ++++ 4 files changed, 103 insertions(+) diff --git a/include/pros/misc.h b/include/pros/misc.h index eacff86d..af9c9d11 100644 --- a/include/pros/misc.h +++ b/include/pros/misc.h @@ -481,6 +481,45 @@ int32_t controller_get_digital(controller_id_e_t id, controller_digital_e_t butt */ int32_t controller_get_digital_new_press(controller_id_e_t id, controller_digital_e_t button); +/** + * Returns a falling-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. + * Task B may call this function for button 3, but should not for buttons + * 1 or 2. A typical use-case for this function is to call inside opcontrol + * to detect new button releases, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is not pressed and had been + * pressed the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital_new_release(pros::E_CONTROLLER_DIGITAL_A)) { + * // Toggle pneumatics or other similar actions + * } + * + * delay(2); + * } + * } + * \endcode + */ +int32_t controller_get_digital_new_release(controller_id_e_t id, controller_digital_e_t button); + /** * Sets text to the controller LCD screen. * diff --git a/include/pros/misc.hpp b/include/pros/misc.hpp index 8df6a827..b0a115e4 100644 --- a/include/pros/misc.hpp +++ b/include/pros/misc.hpp @@ -211,6 +211,45 @@ class Controller { */ std::int32_t get_digital_new_press(controller_digital_e_t button); + /** + * Returns a falling-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. + * Task B may call this function for button 3, but should not for buttons + * 1 or 2. A typical use-case for this function is to call inside opcontrol + * to detect new button releases, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is not pressed and had been + * pressed the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital_new_release(pros::E_CONTROLLER_DIGITAL_A)) { + * // Toggle pneumatics or other similar actions + * } + * + * delay(2); + * } + * } + * \endcode + */ + std::int32_t get_digital_new_release(controller_digital_e_t button); + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" template diff --git a/src/devices/controller.c b/src/devices/controller.c index ad335c24..ec625799 100644 --- a/src/devices/controller.c +++ b/src/devices/controller.c @@ -98,6 +98,27 @@ int32_t controller_get_digital_new_press(controller_id_e_t id, controller_digita } } +int32_t controller_get_digital_new_release(controller_id_e_t id, controller_digital_e_t button) { + int32_t pressed = controller_get_digital(id, button); + uint8_t port; + CONTROLLER_PORT_MUTEX_TAKE(id, port) + uint8_t button_num = button - E_CONTROLLER_DIGITAL_L1; + + if (pressed) { + set_button_pressed(port, button_num, true); + } + if (!pressed && get_button_pressed(port, button_num)) { + // button is currently not pressed and was detected as being pressed during + // last check + set_button_pressed(port, button_num, false); + internal_port_mutex_give(port); + return true; + } else { + internal_port_mutex_give(port); + return false; // button is pressed or was already detected + } +} + int32_t controller_set_text(controller_id_e_t id, uint8_t line, uint8_t col, const char* str) { uint8_t port; CONTROLLER_PORT_MUTEX_TAKE(id, port) diff --git a/src/devices/controller.cpp b/src/devices/controller.cpp index 04bce52e..20736a70 100644 --- a/src/devices/controller.cpp +++ b/src/devices/controller.cpp @@ -44,6 +44,10 @@ std::int32_t Controller::get_digital_new_press(pros::controller_digital_e_t butt return controller_get_digital_new_press(_id, button); } +std::int32_t Controller::get_digital_new_release(pros::controller_digital_e_t button) { + return controller_get_digital_new_release(_id, button); +} + std::int32_t Controller::set_text(std::uint8_t line, std::uint8_t col, const char* str) { return controller_set_text(_id, line, col, str); } From d62dda0baf3f591288a430fab5a77346e457ba43 Mon Sep 17 00:00:00 2001 From: miles352 Date: Wed, 4 Dec 2024 13:18:35 -0500 Subject: [PATCH 2/2] Added separate store for get_digital_new_press and get_digital_new_release to fix bug. --- src/devices/controller.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/devices/controller.c b/src/devices/controller.c index ec625799..52278578 100644 --- a/src/devices/controller.c +++ b/src/devices/controller.c @@ -23,8 +23,10 @@ // From enum in misc.h #define NUM_BUTTONS 12 +// button_pressed is used for get_digital_new_press and button_released is used for get_digital_new_release typedef struct controller_data { bool button_pressed[NUM_BUTTONS]; + bool button_released[NUM_BUTTONS]; } controller_data_s_t; bool get_button_pressed(int port, int button) { @@ -36,6 +38,15 @@ void set_button_pressed(int port, int button, bool state) { data->button_pressed[button] = state; } +bool get_button_released(int port, int button) { + return ((controller_data_s_t*)registry_get_device_internal(port)->pad)->button_released[button]; +} + +void set_button_released(int port, int button, bool state) { + controller_data_s_t* data = (controller_data_s_t*)registry_get_device_internal(port)->pad; + data->button_released[button] = state; +} + int32_t controller_is_connected(controller_id_e_t id) { uint8_t port; CONTROLLER_PORT_MUTEX_TAKE(id, port) @@ -105,12 +116,12 @@ int32_t controller_get_digital_new_release(controller_id_e_t id, controller_digi uint8_t button_num = button - E_CONTROLLER_DIGITAL_L1; if (pressed) { - set_button_pressed(port, button_num, true); + set_button_released(port, button_num, false); } - if (!pressed && get_button_pressed(port, button_num)) { + if (!pressed && !get_button_released(port, button_num)) { // button is currently not pressed and was detected as being pressed during // last check - set_button_pressed(port, button_num, false); + set_button_released(port, button_num, true); internal_port_mutex_give(port); return true; } else {