From dee3d536cbde6cba96c4b77d292edb5d397d9b60 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 21 May 2024 20:19:26 -0400 Subject: [PATCH 001/108] add buffer and handling --- include/gamepad/controller.hpp | 12 ++++++++++++ src/gamepad/controller.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index d552aac..dd80ad3 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,7 +1,10 @@ #pragma once #include +#include #include +#include +#include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif @@ -47,6 +50,8 @@ class Controller { * @note Create a separate instance for each task. */ void update(); + + void println(std::uint8_t line, std::string str, std::uint32_t duration); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -57,6 +62,7 @@ class Controller { * @param joystick Which joystick axis's value to return */ float operator[](pros::controller_analog_e_t joystick); + Button L1{}, L2{}, R1{}, R2{}, Up{}, Down{}, Left{}, Right{}, X{}, B{}, Y{}, A{}; @@ -64,6 +70,12 @@ class Controller { private: static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); + void updateScreen(); + + std::deque> screen_buffer[3]; + std::pair screen_contents[3]; + uint32_t line_set_time[3]; + uint32_t last_print_time = 0; pros::Controller controller; }; // namespace Gamepad } \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 595bdef..a8e66c5 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -1,4 +1,9 @@ #include "gamepad/controller.hpp" +#include "pros/rtos.hpp" +#include +#include +#include +#include namespace Gamepad { void Controller::updateButton(pros::controller_digital_e_t button_id) { @@ -15,6 +20,25 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) { } } +void Controller::updateScreen() { + if (pros::millis() - this->last_print_time < 50) { + return; + } + + for (int line = 0; line < 3; line++) { + if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].second) { + continue; + } + + this->controller.clear_line(line); + this->controller.set_text(line, 0, this->screen_buffer[line][0].first.c_str()); + this->screen_contents[line] = this->screen_buffer[line][0]; + this->screen_buffer[line].pop_front(); + this->last_print_time = pros::millis(); + break; + } +} + void Controller::update() { for(int i = DIGITAL_L1; i != DIGITAL_A; ++i) { this->updateButton(static_cast(i)); @@ -24,6 +48,14 @@ void Controller::update() { this->LeftY = this->controller.get_analog(ANALOG_LEFT_Y); this->RightX = this->controller.get_analog(ANALOG_RIGHT_X); this->RightY = this->controller.get_analog(ANALOG_RIGHT_Y); + + this->updateScreen(); +} + +void Controller::println(uint8_t line, std::string str, std::uint32_t duration) { + if (line > 2) std::exit(1); // TODO: change handling + + screen_buffer[line].push_back(std::make_pair(str, duration)); } const Button& Controller::operator[](pros::controller_digital_e_t button) { From 246c7817e8a3a44235130b3c715bbb6d25e6bc0e Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 21 May 2024 20:42:01 -0400 Subject: [PATCH 002/108] added line cycleing --- include/gamepad/controller.hpp | 1 + src/gamepad/controller.cpp | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index dd80ad3..5435a06 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -75,6 +75,7 @@ class Controller { std::deque> screen_buffer[3]; std::pair screen_contents[3]; uint32_t line_set_time[3]; + uint8_t last_printed_line = 0; uint32_t last_print_time = 0; pros::Controller controller; }; // namespace Gamepad diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index a8e66c5..d7e2790 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -21,19 +21,21 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) { } void Controller::updateScreen() { - if (pros::millis() - this->last_print_time < 50) { + if (pros::millis() - this->last_print_time < 50) return; - } - for (int line = 0; line < 3; line++) { - if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].second) { + for (int i = 1; i < 3; i++) { + int line = (this->last_printed_line + i) % 3; + + if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].second) continue; - } - + this->controller.clear_line(line); this->controller.set_text(line, 0, this->screen_buffer[line][0].first.c_str()); this->screen_contents[line] = this->screen_buffer[line][0]; this->screen_buffer[line].pop_front(); + + this->last_printed_line = line; this->last_print_time = pros::millis(); break; } From e129183e6ff308dbe7f3e893e51911910b69d899 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 13:13:54 -0400 Subject: [PATCH 003/108] fix critical bug :) --- src/gamepad/controller.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index d7e2790..897dee5 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -30,12 +30,14 @@ void Controller::updateScreen() { if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].second) continue; + this->controller.clear_line(line); this->controller.set_text(line, 0, this->screen_buffer[line][0].first.c_str()); this->screen_contents[line] = this->screen_buffer[line][0]; this->screen_buffer[line].pop_front(); this->last_printed_line = line; + this->line_set_time[line] = pros::millis(); this->last_print_time = pros::millis(); break; } From 2b8d9c93c3f060d4e2c81925dfb7d3684b011d9e Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 18:37:18 -0400 Subject: [PATCH 004/108] add rumble and make clarity changes --- include/gamepad/controller.hpp | 15 +++++++++++---- src/gamepad/controller.cpp | 21 ++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 5435a06..c8d0b86 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,9 +1,11 @@ #pragma once +#include #include #include #include #include +#include #include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES @@ -51,7 +53,7 @@ class Controller { */ void update(); - void println(std::uint8_t line, std::string str, std::uint32_t duration); + void print_line(std::uint8_t line, std::string str, std::uint32_t duration); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -68,13 +70,18 @@ class Controller { X{}, B{}, Y{}, A{}; float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0; private: + struct Line { + std::string text; + uint duration; + }; + static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreen(); - std::deque> screen_buffer[3]; - std::pair screen_contents[3]; - uint32_t line_set_time[3]; + std::array, 4> screen_buffer{}; + std::array screen_contents{}; + std::array line_set_time{}; uint8_t last_printed_line = 0; uint32_t last_print_time = 0; pros::Controller controller; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 897dee5..f2e27db 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -24,23 +24,26 @@ void Controller::updateScreen() { if (pros::millis() - this->last_print_time < 50) return; - for (int i = 1; i < 3; i++) { + for (int i = 1; i <= 3; i++) { int line = (this->last_printed_line + i) % 3; - if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].second) + if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) continue; - - - this->controller.clear_line(line); - this->controller.set_text(line, 0, this->screen_buffer[line][0].first.c_str()); + + this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); this->screen_contents[line] = this->screen_buffer[line][0]; this->screen_buffer[line].pop_front(); this->last_printed_line = line; this->line_set_time[line] = pros::millis(); this->last_print_time = pros::millis(); - break; + return; } + + // nothing to print to screen this update so rumble controller + this->controller.rumble(this->screen_buffer[4][0].text.c_str()); + this->screen_buffer[4].pop_front(); + this->last_print_time = pros::millis(); } void Controller::update() { @@ -56,10 +59,10 @@ void Controller::update() { this->updateScreen(); } -void Controller::println(uint8_t line, std::string str, std::uint32_t duration) { +void Controller::print_line(uint8_t line, std::string str, std::uint32_t duration) { if (line > 2) std::exit(1); // TODO: change handling - screen_buffer[line].push_back(std::make_pair(str, duration)); + screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } const Button& Controller::operator[](pros::controller_digital_e_t button) { From 3fc76b49f9e449ec0681a04961188a526c5f8b7c Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 18:38:51 -0400 Subject: [PATCH 005/108] merge changes --- include/gamepad/controller.hpp | 1 - src/gamepad/controller.cpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index c716b8b..f60f3cc 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 01bcafc..99dad9c 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -93,7 +93,8 @@ void Controller::update() { } void Controller::print_line(uint8_t line, std::string str, std::uint32_t duration) { - if (line > 2) std::exit(1); // TODO: change handling + TODO("change handling for off screen lines") + if (line > 2) std::exit(1); screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } From 0d64b620c2f394021f3748b15efa3aed5aed524c Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 18:41:18 -0400 Subject: [PATCH 006/108] oops, forgot the rumble function --- include/gamepad/controller.hpp | 2 ++ src/gamepad/controller.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index f60f3cc..5aebd3f 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -60,6 +60,8 @@ class Controller { void update(); void print_line(std::uint8_t line, std::string str, std::uint32_t duration); + + void rumble(std::string rumble_pattern); /** * Get the state of a button on the controller. * @param button Which button's state you want. diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 99dad9c..083a86b 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -75,7 +75,7 @@ void Controller::updateScreen() { // nothing to print to screen this update so rumble controller this->controller.rumble(this->screen_buffer[4][0].text.c_str()); - this->screen_buffer[4].pop_front(); + this->screen_buffer[3].pop_front(); this->last_print_time = pros::millis(); } @@ -99,6 +99,10 @@ void Controller::print_line(uint8_t line, std::string str, std::uint32_t duratio screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } +void Controller::rumble(std::string rumble_pattern) { + this->screen_buffer[3].push_back({.text = std::move(rumble_pattern), .duration = 0}); +} + const Button& Controller::operator[](pros::controller_digital_e_t button) { return this->*Controller::button_to_ptr(button); } From f04764bc9a10017b104ec1fbef21891ca14ddfc9 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 20:36:04 -0400 Subject: [PATCH 007/108] check for rumble pattern length --- src/gamepad/controller.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 083a86b..727cffd 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -100,6 +100,9 @@ void Controller::print_line(uint8_t line, std::string str, std::uint32_t duratio } void Controller::rumble(std::string rumble_pattern) { + TODO("change handling for too long rumble patterns") + if (rumble_pattern.size() > 8) std::exit(1); + this->screen_buffer[3].push_back({.text = std::move(rumble_pattern), .duration = 0}); } From c5a89821cd82f8b87e8f9c1eb5378238e9d8e405 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 22 May 2024 20:42:11 -0400 Subject: [PATCH 008/108] changed std::uint... to uint... --- include/gamepad/controller.hpp | 2 +- src/gamepad/controller.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 5aebd3f..2bf7ac2 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -59,7 +59,7 @@ class Controller { */ void update(); - void print_line(std::uint8_t line, std::string str, std::uint32_t duration); + void print_line(uint8_t line, std::string str, uint32_t duration); void rumble(std::string rumble_pattern); /** diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 727cffd..70d3fc1 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -92,7 +92,7 @@ void Controller::update() { this->updateScreen(); } -void Controller::print_line(uint8_t line, std::string str, std::uint32_t duration) { +void Controller::print_line(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); From acda18e1cac593c74c1e4c8c872adcfa8eaca974 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 23 May 2024 09:48:49 -0700 Subject: [PATCH 009/108] Minor change to formatting to trigger pros-build action --- include/gamepad/controller.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 2bf7ac2..a368bf2 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -74,7 +74,6 @@ class Controller { float operator[](pros::controller_analog_e_t joystick); TODO("hide members and expose getters/const refs") - Button L1{}, L2{}, R1{}, R2{}, Up{}, Down{}, Left{}, Right{}, X{}, B{}, Y{}, A{}; @@ -96,4 +95,4 @@ class Controller { uint32_t last_print_time = 0; pros::Controller controller; }; // namespace Gamepad -} \ No newline at end of file +} From 26053a52e9529964e0f009d771d6fcb0018593a0 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Fri, 24 May 2024 14:49:18 -0700 Subject: [PATCH 010/108] Fixed off by one error in Gamepad::updateScreen --- src/gamepad/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 70d3fc1..a3d37c9 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -74,7 +74,7 @@ void Controller::updateScreen() { } // nothing to print to screen this update so rumble controller - this->controller.rumble(this->screen_buffer[4][0].text.c_str()); + this->controller.rumble(this->screen_buffer[3][0].text.c_str()); this->screen_buffer[3].pop_front(); this->last_print_time = pros::millis(); } From 735acae1b7d65fbae2d4eaccb9f1efb45952dec1 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 26 May 2024 08:58:21 -0400 Subject: [PATCH 011/108] add rumble to cycle --- src/gamepad/controller.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 70d3fc1..3009a50 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -57,9 +57,19 @@ void Controller::updateScreen() { if (pros::millis() - this->last_print_time < 50) return; - for (int i = 1; i <= 3; i++) { - int line = (this->last_printed_line + i) % 3; - + for (int i = 1; i <= 4; i++) { + int line = (this->last_printed_line + i) % 4; + + // not part of the screen so rumble + if (line == 3) { + this->controller.rumble(this->screen_buffer[line][0].text.c_str()); + this->screen_buffer[line].pop_front(); + this->last_printed_line = line; + this->last_print_time = pros::millis(); + return; + } + + // else print to screen if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) continue; @@ -72,11 +82,6 @@ void Controller::updateScreen() { this->last_print_time = pros::millis(); return; } - - // nothing to print to screen this update so rumble controller - this->controller.rumble(this->screen_buffer[4][0].text.c_str()); - this->screen_buffer[3].pop_front(); - this->last_print_time = pros::millis(); } void Controller::update() { From d1394b3abaaab2c3076e3b1d95bccc98f125b43e Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:40:25 -0400 Subject: [PATCH 012/108] seperate alerts and prints --- include/gamepad/controller.hpp | 5 ++++- src/gamepad/controller.cpp | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index a368bf2..a4be7a1 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -59,7 +59,9 @@ class Controller { */ void update(); - void print_line(uint8_t line, std::string str, uint32_t duration); + void add_alert(uint8_t line, std::string str, uint32_t duration); + + void print_line(uint8_t line, std::string str); void rumble(std::string rumble_pattern); /** @@ -90,6 +92,7 @@ class Controller { std::array, 4> screen_buffer{}; std::array screen_contents{}; + std::array next_print{}; std::array line_set_time{}; uint8_t last_printed_line = 0; uint32_t last_print_time = 0; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index be4c3c5..a3127a6 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -3,6 +3,7 @@ #include "pros/rtos.hpp" #include #include +#include #include #include @@ -60,6 +61,16 @@ void Controller::updateScreen() { for (int i = 1; i <= 4; i++) { int line = (this->last_printed_line + i) % 4; + if (this->screen_buffer[line].size() == 0 && next_print[line] != "") { + this->controller.set_text(line, 0, this->next_print[line]); + this->next_print[line] = ""; + this->last_printed_line = line; + this->last_print_time = pros::millis(); + return; + } + + if (screen_buffer[line].size() == 0) return; + // not part of the screen so rumble if (line == 3) { this->controller.rumble(this->screen_buffer[line][0].text.c_str()); @@ -98,13 +109,20 @@ void Controller::update() { this->updateScreen(); } -void Controller::print_line(uint8_t line, std::string str, uint32_t duration) { +void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } +void Controller::print_line(uint8_t line, std::string str) { + TODO("change handling for off screen lines") + if (line > 2) std::exit(1); + + next_print[line] = str; +} + void Controller::rumble(std::string rumble_pattern) { TODO("change handling for too long rumble patterns") if (rumble_pattern.size() > 8) std::exit(1); From 5cdd7a10f559afef3b59c2874ae1aa085e0e6693 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 8 Jun 2024 08:07:31 -0400 Subject: [PATCH 013/108] change rumble from alert like to print like --- include/gamepad/controller.hpp | 4 ++-- src/gamepad/controller.cpp | 24 +++++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index a4be7a1..daa6f2d 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -90,10 +90,10 @@ class Controller { void updateButton(pros::controller_digital_e_t button_id); void updateScreen(); - std::array, 4> screen_buffer{}; + std::array, 3> screen_buffer{}; std::array screen_contents{}; - std::array next_print{}; std::array line_set_time{}; + std::array next_print{}; uint8_t last_printed_line = 0; uint32_t last_print_time = 0; pros::Controller controller; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index a3127a6..d9df8f4 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -1,6 +1,7 @@ #include "gamepad/controller.hpp" #include "gamepad/todo.hpp" #include "pros/rtos.hpp" +#include #include #include #include @@ -61,25 +62,26 @@ void Controller::updateScreen() { for (int i = 1; i <= 4; i++) { int line = (this->last_printed_line + i) % 4; - if (this->screen_buffer[line].size() == 0 && next_print[line] != "") { - this->controller.set_text(line, 0, this->next_print[line]); + // not part of the screen so rumble + if (line == 3) { + this->controller.rumble(this->next_print[line].c_str()); this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); return; } - if (screen_buffer[line].size() == 0) return; - - // not part of the screen so rumble - if (line == 3) { - this->controller.rumble(this->screen_buffer[line][0].text.c_str()); - this->screen_buffer[line].pop_front(); + // no alerts so print from string + if (this->screen_buffer[line].size() == 0 && next_print[line] != "") { + this->controller.set_text(line, 0, this->next_print[line]); + this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); return; } + if (screen_buffer[line].size() == 0) return; + // else print to screen if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) continue; @@ -113,21 +115,21 @@ void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); + this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } void Controller::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - next_print[line] = str; + this->next_print[line] = std::move(str); } void Controller::rumble(std::string rumble_pattern) { TODO("change handling for too long rumble patterns") if (rumble_pattern.size() > 8) std::exit(1); - this->screen_buffer[3].push_back({.text = std::move(rumble_pattern), .duration = 0}); + this->next_print[3] = std::move(rumble_pattern); } const Button& Controller::operator[](pros::controller_digital_e_t button) { From 749edf40d76bc68cef463732f850a3227c572623 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 16 Jun 2024 18:59:49 -0700 Subject: [PATCH 014/108] feat: :sparkles: add drive curve implementation Add an abstarct DriveCurve class and a concrete ExproDriveCurve class, both based on LemLib's implementation. --- include/gamepad/drive_curve.hpp | 77 +++++++++++++++++++++++++++++++++ src/gamepad/drive_curve.cpp | 23 ++++++++++ 2 files changed, 100 insertions(+) create mode 100644 include/gamepad/drive_curve.hpp create mode 100644 src/gamepad/drive_curve.cpp diff --git a/include/gamepad/drive_curve.hpp b/include/gamepad/drive_curve.hpp new file mode 100644 index 0000000..96182d6 --- /dev/null +++ b/include/gamepad/drive_curve.hpp @@ -0,0 +1,77 @@ +#pragma once + +namespace Gamepad { + +/** + * @brief abstract DriveCurve class + * + * This is an abstract class to enable users to provide their own, custom drive + * curves for LemLib to use. + */ +class DriveCurve { + public: + /** + * @brief Processes an input and returns an output + * + * This is a pure virtual function that needs to be overriden by child classes + * + * @param input the input to process + * @return float output + */ + virtual float curve(float input) = 0; +}; + +/** + * @brief ExpoDriveCurve class. Inherits from the DriveCurve class. This is a exponential drive curve. + * + * see https://www.desmos.com/calculator/umicbymbnl for an interactive graph + * see https://www.vexforum.com/t/expo-drive-lemlibs-implementation for a detailed explanation + */ +class ExpoDriveCurve : public DriveCurve { + public: + /** + * @brief Construct a new Expo Drive Curve object + * + * see https://www.desmos.com/calculator/umicbymbnl for an interactive graph + * see https://www.vexforum.com/t/expo-drive-lemlibs-implementation for a detailed explanation + * + * @param deadband range where input is considered to be input + * @param minOutput the minimum output that can be returned + * @param curve how "curved" the graph is + * + * @b Example + * @code {.cpp} + * // create a new exponential drive curve + * // controller deadband is set to 5 + * // minimum output is set to 12 + * // curve gain is set to 1.132 + * lemlib::ExpoDriveCurve driveCurve(5, 12, 1.132); + * @endcode + */ + ExpoDriveCurve(float deadband, float minOutput, float curve); + /** + * @brief curve an input + * + * @param input the input to curve + * @return float the curved output + * + * @b Example + * @code {.cpp} + * void opcontrol() { + * // create a new exponential drive curve + * lemlib::ExpoDriveCurve driveCurve(5, 12, 1.132); + * // input 4 + * std::cout << driveCurve.curve(4) << std::endl; // outputs 0 because input is within deadzone + * // input 6 + * std::cout << driveCurve.curve(6) << std::endl; // outputs 12, the minimum output + * std::cout << driveCurve.curve(127) << std::endl; // outputs 127, the maximum output + * } + * @endcode + */ + float curve(float input); + private: + const float deadband = 0; + const float minOutput = 0; + const float curveGain = 1; +}; +} // namespace Gamepad \ No newline at end of file diff --git a/src/gamepad/drive_curve.cpp b/src/gamepad/drive_curve.cpp new file mode 100644 index 0000000..61ece3f --- /dev/null +++ b/src/gamepad/drive_curve.cpp @@ -0,0 +1,23 @@ +#include "gamepad/drive_curve.hpp" +#include + +namespace Gamepad { +ExpoDriveCurve::ExpoDriveCurve(float deadband, float minOutput, float curve) + : deadband(deadband), + minOutput(minOutput), + curveGain(curve) {} + +float ExpoDriveCurve::curve(float input) { + // return 0 if input is within deadzone + if (std::abs(input) <= deadband) return 0; + // g is the output of g(x) as defined in the Desmos graph + const float g = std::abs(input) - deadband; + // g127 is the output of g(127) as defined in the Desmos graph + const float g127 = 127 - deadband; + // i is the output of i(x) as defined in the Desmos graph + const float i = std::copysign(std::pow(curveGain, g - 127) * g, input); + // i127 is the output of i(127) as defined in the Desmos graph + const float i127 = std::pow(curveGain, g127 - 127) * g127; + return (127.0 - minOutput) / (127) * i * 127 / i127 + std::copysign(minOutput, input); +} +} // namespace Gamepad \ No newline at end of file From 1ca81b01eb5896eb519a442e71cad99b83c825fb Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 16 Jun 2024 19:24:44 -0700 Subject: [PATCH 015/108] feat: :sparkles: Add joystick curves to controller Allow users to assign a DriveCurve per axis to be used by the controller when updating joystick values. --- include/gamepad/controller.hpp | 57 +++++++++++++++++++--------------- src/gamepad/controller.cpp | 46 +++++++++++++++------------ 2 files changed, 59 insertions(+), 44 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 2c520e0..9484156 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -2,11 +2,13 @@ #include #include +#include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif #include "event_handler.hpp" +#include "drive_curve.hpp" #include "pros/misc.hpp" #include "pros/rtos.hpp" @@ -19,34 +21,35 @@ enum EventType { }; class Button { - friend class Controller; + friend class Controller; public: - bool rising_edge = false; - bool falling_edge = false; - bool is_pressed = false; - uint32_t last_press_time = pros::millis(); - uint32_t last_release_time = last_press_time; - uint32_t time_held = 0; - uint32_t time_released = 0; - uint32_t long_press_threshold = 500; + bool rising_edge = false; + bool falling_edge = false; + bool is_pressed = false; + uint32_t last_press_time = pros::millis(); + uint32_t last_release_time = last_press_time; + uint32_t time_held = 0; + uint32_t time_released = 0; + uint32_t long_press_threshold = 500; - uint32_t onPress(std::function func); - uint32_t onLongPress(std::function func); - uint32_t onRelease(std::function func); - uint32_t addListener(EventType event, std::function func); - bool removeListener(uint32_t id); + uint32_t onPress(std::function func); + uint32_t onLongPress(std::function func); + uint32_t onRelease(std::function func); + uint32_t addListener(EventType event, std::function func); + bool removeListener(uint32_t id); private: + void update(bool is_held); - void update(bool is_held); - - EventHandler<> onPressEvent; - EventHandler<> onLongPressEvent; - EventHandler<> onReleaseEvent; + EventHandler<> onPressEvent; + EventHandler<> onLongPressEvent; + EventHandler<> onReleaseEvent; }; class Controller { public: - explicit Controller(pros::controller_id_e_t id): controller(id) {} + explicit Controller(pros::controller_id_e_t id) + : controller(id) {} + /** * Updates the state of the gamepad (all joysticks and buttons), and also runs * any registered handlers. @@ -64,14 +67,18 @@ class Controller { * @param joystick Which joystick axis's value to return */ float operator[](pros::controller_analog_e_t joystick); + void setCurve(pros::controller_analog_e_t joystick, std::shared_ptr curve); + void setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve); TODO("hide memebrs and expose getters/const refs") - Button L1{}, L2{}, R1{}, R2{}, - Up{}, Down{}, Left{}, Right{}, - X{}, B{}, Y{}, A{}; + Button L1 {}, L2 {}, R1 {}, R2 {}, Up {}, Down {}, Left {}, Right {}, X {}, B {}, Y {}, A {}; float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0; private: - static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); + std::shared_ptr CurveLeftX {nullptr}; + std::shared_ptr CurveLeftY {nullptr}; + std::shared_ptr CurveRightX {nullptr}; + std::shared_ptr CurveRightY {nullptr}; + static Button Controller::*button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); pros::Controller controller; }; // namespace Gamepad -} \ No newline at end of file +} // namespace Gamepad \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 4472527..80d2657 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -3,9 +3,7 @@ namespace Gamepad { -uint32_t Button::onPress(std::function func) { - return this->onPressEvent.add_listener(std::move(func)); -} +uint32_t Button::onPress(std::function func) { return this->onPressEvent.add_listener(std::move(func)); } uint32_t Button::onLongPress(std::function func) { return this->onLongPressEvent.add_listener(std::move(func)); @@ -26,12 +24,8 @@ void Button::update(const bool is_held) { } else { this->time_released += pros::millis() - last_update_time; } - if (this->rising_edge) { - this->time_held = 0; - } - if (this->falling_edge) { - this->time_released = 0; - } + if (this->rising_edge) { this->time_held = 0; } + if (this->falling_edge) { this->time_released = 0; } if (this->rising_edge) { onPressEvent.fire(); @@ -43,20 +37,22 @@ void Button::update(const bool is_held) { } void Controller::updateButton(pros::controller_digital_e_t button_id) { - Button Controller::* button = Controller::button_to_ptr(button_id); + Button Controller::*button = Controller::button_to_ptr(button_id); bool is_held = this->controller.get_digital(button_id); (this->*button).update(is_held); } void Controller::update() { - for(int i = DIGITAL_L1; i != DIGITAL_A; ++i) { - this->updateButton(static_cast(i)); - } + for (int i = DIGITAL_L1; i != DIGITAL_A; ++i) { this->updateButton(static_cast(i)); } this->LeftX = this->controller.get_analog(ANALOG_LEFT_X); + if (this->CurveLeftX) this->LeftX = this->CurveLeftX->curve(this->LeftX); this->LeftY = this->controller.get_analog(ANALOG_LEFT_Y); + if (this->CurveLeftY) this->LeftY = this->CurveLeftY->curve(this->LeftY); this->RightX = this->controller.get_analog(ANALOG_RIGHT_X); + if (this->CurveRightX) this->RightX = this->CurveRightX->curve(this->RightX); this->RightY = this->controller.get_analog(ANALOG_RIGHT_Y); + if (this->CurveRightY) this->RightY = this->CurveRightY->curve(this->RightY); } const Button& Controller::operator[](pros::controller_digital_e_t button) { @@ -68,13 +64,26 @@ float Controller::operator[](pros::controller_analog_e_t axis) { case ANALOG_LEFT_X: return this->LeftX; case ANALOG_LEFT_Y: return this->LeftY; case ANALOG_RIGHT_X: return this->RightX; - case ANALOG_RIGHT_Y: return this->RightY; - TODO("change handling for default") + case ANALOG_RIGHT_Y: return this->RightY; TODO("change handling for default") default: std::exit(1); } } -Button Controller::* Controller::button_to_ptr(pros::controller_digital_e_t button) { +void Controller::setCurve(pros::controller_analog_e_t joystick, std::shared_ptr curve) { + switch (axis) { + case ANALOG_LEFT_X: this->CurveLeftX = curve; + case ANALOG_LEFT_Y: this->CurveLeftY = curve; + case ANALOG_RIGHT_X: this->CurveRightX = curve; + case ANALOG_RIGHT_Y: this->CurveRightY = curve; TODO("add error logging") + default: errno = EINVAL; + } +} + +void Controller::setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve) { + this->setCurve(joystick, std::shared_ptr(&curve, [](void*) {})); +} + +Button Controller::*Controller::button_to_ptr(pros::controller_digital_e_t button) { switch (button) { case DIGITAL_L1: return &Controller::L1; case DIGITAL_L2: return &Controller::L2; @@ -87,9 +96,8 @@ Button Controller::* Controller::button_to_ptr(pros::controller_digital_e_t butt case DIGITAL_X: return &Controller::X; case DIGITAL_B: return &Controller::B; case DIGITAL_Y: return &Controller::Y; - case DIGITAL_A: return &Controller::A; - TODO("change handling for default") + case DIGITAL_A: return &Controller::A; TODO("change handling for default") default: std::exit(1); } } -} \ No newline at end of file +} // namespace Gamepad \ No newline at end of file From 0772340a65c33d36074cb890a5a83e3de95ab5fe Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 16 Jun 2024 19:25:12 -0700 Subject: [PATCH 016/108] style: :art: Format event_handler.hpp --- include/gamepad/event_handler.hpp | 70 ++++++++++++++++--------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index 6bdc188..d4660a0 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -12,44 +12,46 @@ namespace Gamepad { class MonotonicCounter { - template friend class EventHandler; - static uint32_t next_value() { - static std::atomic counter = 0; - return ++counter; - } + template friend class EventHandler; + + static uint32_t next_value() { + static std::atomic counter = 0; + return ++counter; + } }; -template -class EventHandler { +template class EventHandler { public: - using Listener = std::function; - uint32_t add_listener(Listener func) { - std::lock_guard lock(mutex); - uint32_t id = MonotonicCounter::next_value(); - listeners.emplace(id, std::move(func)); - return id; - } - bool remove_listener(uint32_t id) { - std::lock_guard lock(mutex); - if(listeners.find(id) == listeners.end()) { - TODO("change handling maybe?") - return false; + using Listener = std::function; + + uint32_t add_listener(Listener func) { + std::lock_guard lock(mutex); + uint32_t id = MonotonicCounter::next_value(); + listeners.emplace(id, std::move(func)); + return id; + } + + bool remove_listener(uint32_t id) { + std::lock_guard lock(mutex); + if (listeners.find(id) == listeners.end()) { + TODO("change handling maybe?") + return false; + } + listeners.erase(id); + return true; + } + + bool is_empty() { + std::lock_guard lock(mutex); + return listeners.empty(); } - listeners.erase(id); - return true; - } - bool is_empty() { - std::lock_guard lock(mutex); - return listeners.empty(); - } - void fire(Args... args) { - std::lock_guard lock(mutex); - for(auto listener : listeners) { - listener.second(args...); + + void fire(Args... args) { + std::lock_guard lock(mutex); + for (auto listener : listeners) { listener.second(args...); } } - } private: - std::map listeners; - pros::Mutex mutex; + std::map listeners; + pros::Mutex mutex; }; -} \ No newline at end of file +} // namespace Gamepad \ No newline at end of file From 846ba1a62518b99d8c0be0d7366c42bf4e110696 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:49:37 -0700 Subject: [PATCH 017/108] fix: :bug: Fix variable name typo --- src/gamepad/controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 80d2657..8a7fb3c 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -69,7 +69,7 @@ float Controller::operator[](pros::controller_analog_e_t axis) { } } -void Controller::setCurve(pros::controller_analog_e_t joystick, std::shared_ptr curve) { +void Controller::setCurve(pros::controller_analog_e_t axis, std::shared_ptr curve) { switch (axis) { case ANALOG_LEFT_X: this->CurveLeftX = curve; case ANALOG_LEFT_Y: this->CurveLeftY = curve; From 734183b3c144afa159a8d0b529f7301403ee2d12 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:18:52 -0700 Subject: [PATCH 018/108] refactor: :construction: Remove deadband from curve --- include/gamepad/drive_curve.hpp | 4 +--- src/gamepad/drive_curve.cpp | 13 +++---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/include/gamepad/drive_curve.hpp b/include/gamepad/drive_curve.hpp index 96182d6..8d9c80a 100644 --- a/include/gamepad/drive_curve.hpp +++ b/include/gamepad/drive_curve.hpp @@ -35,7 +35,6 @@ class ExpoDriveCurve : public DriveCurve { * see https://www.desmos.com/calculator/umicbymbnl for an interactive graph * see https://www.vexforum.com/t/expo-drive-lemlibs-implementation for a detailed explanation * - * @param deadband range where input is considered to be input * @param minOutput the minimum output that can be returned * @param curve how "curved" the graph is * @@ -48,7 +47,7 @@ class ExpoDriveCurve : public DriveCurve { * lemlib::ExpoDriveCurve driveCurve(5, 12, 1.132); * @endcode */ - ExpoDriveCurve(float deadband, float minOutput, float curve); + ExpoDriveCurve(float minOutput, float curve); /** * @brief curve an input * @@ -70,7 +69,6 @@ class ExpoDriveCurve : public DriveCurve { */ float curve(float input); private: - const float deadband = 0; const float minOutput = 0; const float curveGain = 1; }; diff --git a/src/gamepad/drive_curve.cpp b/src/gamepad/drive_curve.cpp index 61ece3f..2d4f17a 100644 --- a/src/gamepad/drive_curve.cpp +++ b/src/gamepad/drive_curve.cpp @@ -2,22 +2,15 @@ #include namespace Gamepad { -ExpoDriveCurve::ExpoDriveCurve(float deadband, float minOutput, float curve) - : deadband(deadband), +ExpoDriveCurve::ExpoDriveCurve(float minOutput, float curve) : minOutput(minOutput), curveGain(curve) {} float ExpoDriveCurve::curve(float input) { - // return 0 if input is within deadzone - if (std::abs(input) <= deadband) return 0; // g is the output of g(x) as defined in the Desmos graph - const float g = std::abs(input) - deadband; - // g127 is the output of g(127) as defined in the Desmos graph - const float g127 = 127 - deadband; + const float g = std::abs(input); // i is the output of i(x) as defined in the Desmos graph const float i = std::copysign(std::pow(curveGain, g - 127) * g, input); - // i127 is the output of i(127) as defined in the Desmos graph - const float i127 = std::pow(curveGain, g127 - 127) * g127; - return (127.0 - minOutput) / (127) * i * 127 / i127 + std::copysign(minOutput, input); + return (127.0 - minOutput) / (127) * i + std::copysign(minOutput, input); } } // namespace Gamepad \ No newline at end of file From 2bc3862e361dfc59c7d19ce4113a05e44d8d5c02 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 26 Jun 2024 08:08:37 -0700 Subject: [PATCH 019/108] add multi line alerts --- include/gamepad/controller.hpp | 4 +++- src/gamepad/controller.cpp | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index daa6f2d..ef25509 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -59,7 +59,8 @@ class Controller { */ void update(); - void add_alert(uint8_t line, std::string str, uint32_t duration); + void add_alerts(uint8_t line, std::string str, uint32_t duration); + void add_alerts(std::vector lines, std::vector strs, uint32_t duration); void print_line(uint8_t line, std::string str); @@ -89,6 +90,7 @@ class Controller { static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreen(); + uint getTotalDuration(uint8_t line); std::array, 3> screen_buffer{}; std::array screen_contents{}; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index d9df8f4..6aa692f 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -2,6 +2,7 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include +#include #include #include #include @@ -73,7 +74,7 @@ void Controller::updateScreen() { // no alerts so print from string if (this->screen_buffer[line].size() == 0 && next_print[line] != "") { - this->controller.set_text(line, 0, this->next_print[line]); + this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); @@ -111,11 +112,38 @@ void Controller::update() { this->updateScreen(); } -void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { +uint Controller::getTotalDuration(uint8_t line) { + uint total = 0; + for (Line msg : this->screen_buffer[line]) + total += msg.duration; + return total; +} + +void Controller::add_alerts(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); + this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); +} + +void Controller::add_alerts(std::vector lines, std::vector strs, uint32_t duration) { + assert(lines.size() == strs.size()); + + // get nex available time slot for all lines + uint minSpot = -1; // max uint value + for (uint8_t line : lines) { + TODO("change handling for off screen lines") + if (line > 2) std::exit(1); + + if (getTotalDuration(line) < minSpot) + minSpot = getTotalDuration(line); + } + + for (int i = 0; i < lines.size(); i++) { + if (getTotalDuration(lines[i]) < minSpot) + this->screen_buffer[lines[i]].push_back({ .text = "", .duration = (minSpot - getTotalDuration(lines[i])) }); + this->screen_buffer[lines[i]].push_back({ .text = std::move(strs[i]), .duration = duration }); + } } void Controller::print_line(uint8_t line, std::string str) { From 1e8182ecf33b7df116cdc7b2964a2662de45771b Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:08:48 -0700 Subject: [PATCH 020/108] add ability to have newlines in alerts --- src/gamepad/controller.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 6aa692f..3cf9b05 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -6,8 +6,10 @@ #include #include #include +#include #include #include +#include namespace Gamepad { @@ -123,6 +125,22 @@ void Controller::add_alerts(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); + if (str.find('\n') != std::string::npos) { + std::vector strs; + std::vector lines; + std::stringstream ss(str); + uint8_t l = line; + std::string to; + + while (std::getline(ss, to, '\n')) { + strs.push_back(to); + lines.push_back(l++); + } + + add_alerts(lines, strs, duration); + return; + } + this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } From ec5c814201e166e7391a6a5f74b5f7e7447f5c38 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Thu, 27 Jun 2024 16:31:12 -0700 Subject: [PATCH 021/108] make add_alerts private --- include/gamepad/controller.hpp | 5 +++-- src/gamepad/controller.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index ef25509..3b4a707 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -59,8 +59,7 @@ class Controller { */ void update(); - void add_alerts(uint8_t line, std::string str, uint32_t duration); - void add_alerts(std::vector lines, std::vector strs, uint32_t duration); + void add_alert(uint8_t line, std::string str, uint32_t duration); void print_line(uint8_t line, std::string str); @@ -92,6 +91,8 @@ class Controller { void updateScreen(); uint getTotalDuration(uint8_t line); + void add_alerts(std::vector lines, std::vector strs, uint32_t duration); + std::array, 3> screen_buffer{}; std::array screen_contents{}; std::array line_set_time{}; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 3cf9b05..957f486 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -121,7 +121,7 @@ uint Controller::getTotalDuration(uint8_t line) { return total; } -void Controller::add_alerts(uint8_t line, std::string str, uint32_t duration) { +void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); From 599d3c1a745853e6e039ce36d3128380b8be8451 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Thu, 27 Jun 2024 18:43:21 -0700 Subject: [PATCH 022/108] remove unnessasary lines parameter --- include/gamepad/controller.hpp | 4 ++-- src/gamepad/controller.cpp | 33 +++++++++++++++++---------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 3b4a707..05a8238 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -91,8 +91,8 @@ class Controller { void updateScreen(); uint getTotalDuration(uint8_t line); - void add_alerts(std::vector lines, std::vector strs, uint32_t duration); - + void add_alerts(std::vector strs, uint32_t duration); + std::array, 3> screen_buffer{}; std::array screen_contents{}; std::array line_set_time{}; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 957f486..e225753 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -126,41 +126,42 @@ void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { if (line > 2) std::exit(1); if (str.find('\n') != std::string::npos) { - std::vector strs; - std::vector lines; + TODO("warn instead of throw error if there are too many lines") + if (std::ranges::count(str, '\n') > 2) std::exit(1); + + std::vector strs = {"", "", ""}; std::stringstream ss(str); - uint8_t l = line; std::string to; - while (std::getline(ss, to, '\n')) { - strs.push_back(to); - lines.push_back(l++); + for (int i = line; i < 3; i++) { + if (!std::getline(ss, to, '\n')) break; + strs[i] = std::move(to); } - add_alerts(lines, strs, duration); + add_alerts(strs, duration); return; } this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } -void Controller::add_alerts(std::vector lines, std::vector strs, uint32_t duration) { - assert(lines.size() == strs.size()); +void Controller::add_alerts(std::vector strs, uint32_t duration) { + TODO("change handling for too many lines") + if (strs.size() > 3) std::exit(1); + // get nex available time slot for all lines uint minSpot = -1; // max uint value - for (uint8_t line : lines) { - TODO("change handling for off screen lines") - if (line > 2) std::exit(1); + for (uint8_t line = 0; line < 3; line++) { if (getTotalDuration(line) < minSpot) minSpot = getTotalDuration(line); } - for (int i = 0; i < lines.size(); i++) { - if (getTotalDuration(lines[i]) < minSpot) - this->screen_buffer[lines[i]].push_back({ .text = "", .duration = (minSpot - getTotalDuration(lines[i])) }); - this->screen_buffer[lines[i]].push_back({ .text = std::move(strs[i]), .duration = duration }); + for (int i = 0; i < 3; i++) { + if (getTotalDuration(i) < minSpot) + this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); + this->screen_buffer[i].push_back({ .text = std::move(strs[i]), .duration = duration }); } } From 20138bb1d851fdfca664e908904d4d48a240401f Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Fri, 5 Jul 2024 20:36:17 -0700 Subject: [PATCH 023/108] add multiline prints --- src/gamepad/controller.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index e225753..e5ff7e4 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -129,13 +129,11 @@ void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { TODO("warn instead of throw error if there are too many lines") if (std::ranges::count(str, '\n') > 2) std::exit(1); - std::vector strs = {"", "", ""}; + std::vector strs(3); std::stringstream ss(str); - std::string to; for (int i = line; i < 3; i++) { - if (!std::getline(ss, to, '\n')) break; - strs[i] = std::move(to); + if (!std::getline(ss, strs[i], '\n')) break; } add_alerts(strs, duration); @@ -149,15 +147,12 @@ void Controller::add_alerts(std::vector strs, uint32_t duration) { TODO("change handling for too many lines") if (strs.size() > 3) std::exit(1); - // get nex available time slot for all lines uint minSpot = -1; // max uint value - for (uint8_t line = 0; line < 3; line++) { - - if (getTotalDuration(line) < minSpot) - minSpot = getTotalDuration(line); - } + for (uint8_t line = 0; line < 3; line++) + minSpot = std::min(minSpot, getTotalDuration(line)); + // Schedule alerts for (int i = 0; i < 3; i++) { if (getTotalDuration(i) < minSpot) this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); @@ -169,6 +164,22 @@ void Controller::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); + if (str.find('\n') != std::string::npos) { + TODO("warn instead of throw error if there are too many lines") + if (std::ranges::count(str, '\n') > 2) std::exit(1); + + std::vector strs(3); + std::stringstream ss(str); + + for (int i = line; i < 3; i++) { + if (!std::getline(ss, strs[i], '\n')) break; + } + + for (uint8_t l = 0; l < 3; l++) + this->next_print[l] = std::move(strs[l]); + return; + } + this->next_print[line] = std::move(str); } From e73d095b3b4d1b459e7628466e89b6a6d07769b3 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:54:12 -0700 Subject: [PATCH 024/108] add rumbles to alerts --- include/gamepad/controller.hpp | 16 ++++++++++------ src/gamepad/controller.cpp | 27 ++++++++++++++++++++------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 05a8238..7f2f02f 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -59,7 +59,7 @@ class Controller { */ void update(); - void add_alert(uint8_t line, std::string str, uint32_t duration); + void add_alert(uint8_t line, std::string str, uint32_t duration, std::string rumble = ""); void print_line(uint8_t line, std::string str); @@ -88,17 +88,21 @@ class Controller { static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); + void updateScreen(); + void add_alerts(std::vector strs, uint32_t duration, std::string rumble = ""); uint getTotalDuration(uint8_t line); - void add_alerts(std::vector strs, uint32_t duration); + pros::Controller controller; + + // alert queue + std::array, 4> screen_buffer{}; + std::array screen_contents{}; + std::array line_set_time{}; - std::array, 3> screen_buffer{}; - std::array screen_contents{}; - std::array line_set_time{}; std::array next_print{}; uint8_t last_printed_line = 0; uint32_t last_print_time = 0; - pros::Controller controller; + }; // namespace Gamepad } diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index e5ff7e4..af61b8a 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -67,6 +67,18 @@ void Controller::updateScreen() { // not part of the screen so rumble if (line == 3) { + if (this->screen_buffer[line].size() != 0) { + if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) + continue; + + this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); + this->screen_contents[line] = this->screen_buffer[line][0]; + this->screen_buffer[line].pop_front(); + + this->last_printed_line = line; + this->line_set_time[line] = pros::millis(); + this->last_print_time = pros::millis(); + } this->controller.rumble(this->next_print[line].c_str()); this->next_print[line] = ""; this->last_printed_line = line; @@ -121,7 +133,7 @@ uint Controller::getTotalDuration(uint8_t line) { return total; } -void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { +void Controller::add_alert(uint8_t line, std::string str, uint32_t duration, std::string rumble) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); @@ -136,27 +148,28 @@ void Controller::add_alert(uint8_t line, std::string str, uint32_t duration) { if (!std::getline(ss, strs[i], '\n')) break; } - add_alerts(strs, duration); + add_alerts(strs, duration, rumble); return; } this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } -void Controller::add_alerts(std::vector strs, uint32_t duration) { +void Controller::add_alerts(std::vector strs, uint32_t duration, std::string rumble) { TODO("change handling for too many lines") if (strs.size() > 3) std::exit(1); // get nex available time slot for all lines uint minSpot = -1; // max uint value - for (uint8_t line = 0; line < 3; line++) - minSpot = std::min(minSpot, getTotalDuration(line)); + for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); // Schedule alerts - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 4; i++) { if (getTotalDuration(i) < minSpot) this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); - this->screen_buffer[i].push_back({ .text = std::move(strs[i]), .duration = duration }); + + if (i == 3) this->screen_buffer[i].push_back({.text = std::move(rumble), .duration = duration}); + else this->screen_buffer[i].push_back({.text = std::move(strs[i]), .duration = 0}); } } From 57371a6e1860f7cb1f2645d81f970cff11eee55e Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:41:16 -0700 Subject: [PATCH 025/108] refactored screen update loop --- src/gamepad/controller.cpp | 62 ++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index af61b8a..1e4d758 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -65,52 +65,50 @@ void Controller::updateScreen() { for (int i = 1; i <= 4; i++) { int line = (this->last_printed_line + i) % 4; - // not part of the screen so rumble - if (line == 3) { - if (this->screen_buffer[line].size() != 0) { - if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) + // duration expired + if (pros::millis() - this->line_set_time[line] >= this->screen_contents[line].duration) { + if (this->screen_buffer[line].size() == 0) { + // no need to update text + if (this->screen_contents[line].text == this->next_print[line] && line != 3) { + this->next_print[line] = ""; continue; + } + + if (line == 3) this->controller.rumble(this->next_print[line].c_str()); + else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); + this->screen_contents[line].text = std::move(this->next_print[line]); + this->next_print[line] = ""; + } else { + // no need to update text + if (this->screen_contents[line].text == this->screen_buffer[line][0].text && line != 3) { + this->screen_contents[line] = this->screen_buffer[line][0]; + this->screen_buffer[line].pop_front(); + this->line_set_time[line] = pros::millis(); + continue; + } - this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); + if (line == 3) this->controller.rumble(this->screen_buffer[line][0].text.c_str()); + else this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); this->screen_contents[line] = this->screen_buffer[line][0]; this->screen_buffer[line].pop_front(); - - this->last_printed_line = line; this->line_set_time[line] = pros::millis(); - this->last_print_time = pros::millis(); } - this->controller.rumble(this->next_print[line].c_str()); - this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); - return; - } + } else if (this->screen_contents[line].text == "") { + // no need to update text + if (this->screen_contents[line].text == this->next_print[line] && line != 3) { + this->next_print[line] = ""; + continue; + } - // no alerts so print from string - if (this->screen_buffer[line].size() == 0 && next_print[line] != "") { - this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); + if (line == 3) this->controller.rumble(this->next_print[line].c_str()); + else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); - return; } - - if (screen_buffer[line].size() == 0) return; - - // else print to screen - if (pros::millis() - this->line_set_time[line] < this->screen_contents[line].duration) - continue; - - this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); - this->screen_contents[line] = this->screen_buffer[line][0]; - this->screen_buffer[line].pop_front(); - - this->last_printed_line = line; - this->line_set_time[line] = pros::millis(); - this->last_print_time = pros::millis(); - return; } - } void Controller::update() { From 022b4df2e75591be519c72181a4616bf47a3853e Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:41:28 -0700 Subject: [PATCH 026/108] add thread safety... hopefully? --- include/gamepad/controller.hpp | 9 +++++++-- src/gamepad/controller.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 7f2f02f..9f92f14 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -97,12 +97,17 @@ class Controller { // alert queue std::array, 4> screen_buffer{}; - std::array screen_contents{}; - std::array line_set_time{}; + pros::Mutex alert_mut; + std::array next_print{}; + pros::Mutex print_mut; + + std::array screen_contents{}; + std::array line_set_time{}; uint8_t last_printed_line = 0; uint32_t last_print_time = 0; + pros::Mutex scheduling_mut; }; // namespace Gamepad } diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 1e4d758..419b0e3 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,10 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) { } void Controller::updateScreen() { + std::lock_guard guard_scheduling(this->scheduling_mut); + std::lock_guard guard_print(this->print_mut); + std::lock_guard guard_alert(this->alert_mut); + if (pros::millis() - this->last_print_time < 50) return; @@ -150,6 +155,7 @@ void Controller::add_alert(uint8_t line, std::string str, uint32_t duration, std return; } + std::lock_guard guard(this->alert_mut); this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); } @@ -157,6 +163,8 @@ void Controller::add_alerts(std::vector strs, uint32_t duration, st TODO("change handling for too many lines") if (strs.size() > 3) std::exit(1); + std::lock_guard guard(this->alert_mut); + // get nex available time slot for all lines uint minSpot = -1; // max uint value for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); @@ -175,6 +183,8 @@ void Controller::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); + std::lock_guard guard(this->print_mut); + if (str.find('\n') != std::string::npos) { TODO("warn instead of throw error if there are too many lines") if (std::ranges::count(str, '\n') > 2) std::exit(1); @@ -198,6 +208,7 @@ void Controller::rumble(std::string rumble_pattern) { TODO("change handling for too long rumble patterns") if (rumble_pattern.size() > 8) std::exit(1); + std::lock_guard guard(this->print_mut); this->next_print[3] = std::move(rumble_pattern); } From b8eb2426d52d6a289f415ff01865cc902687a420 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 27 Jul 2024 08:32:36 -0400 Subject: [PATCH 027/108] some comments --- src/gamepad/controller.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 419b0e3..8fa94c5 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -60,31 +60,35 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) { } void Controller::updateScreen() { + // Lock Mutexes for Thread Safety std::lock_guard guard_scheduling(this->scheduling_mut); std::lock_guard guard_print(this->print_mut); std::lock_guard guard_alert(this->alert_mut); + // Check if enough time has passed for the controller to poll for updates if (pros::millis() - this->last_print_time < 50) return; for (int i = 1; i <= 4; i++) { + // start from the line thats after the line thats been set so we dont get stuck setting the first line int line = (this->last_printed_line + i) % 4; - // duration expired + // if the last alert's duration expired if (pros::millis() - this->line_set_time[line] >= this->screen_contents[line].duration) { + // No alerts to print if (this->screen_buffer[line].size() == 0) { - // no need to update text + // text on screen is the same as last frame's text so no use updating if (this->screen_contents[line].text == this->next_print[line] && line != 3) { this->next_print[line] = ""; continue; } - + // UPDATE TEXT/RUMBLE if (line == 3) this->controller.rumble(this->next_print[line].c_str()); else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); this->screen_contents[line].text = std::move(this->next_print[line]); this->next_print[line] = ""; } else { - // no need to update text + // text on screen is the same as the alert's text so just set vars, dont update controller if (this->screen_contents[line].text == this->screen_buffer[line][0].text && line != 3) { this->screen_contents[line] = this->screen_buffer[line][0]; this->screen_buffer[line].pop_front(); @@ -92,6 +96,7 @@ void Controller::updateScreen() { continue; } + // SET ALERT/RUMBLE ALERT if (line == 3) this->controller.rumble(this->screen_buffer[line][0].text.c_str()); else this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); this->screen_contents[line] = this->screen_buffer[line][0]; @@ -101,14 +106,16 @@ void Controller::updateScreen() { this->last_printed_line = line; this->last_print_time = pros::millis(); } else if (this->screen_contents[line].text == "") { - // no need to update text + // text is the same as last frame's text so no use updating if (this->screen_contents[line].text == this->next_print[line] && line != 3) { this->next_print[line] = ""; continue; } + // UPDATE TEXT/RUMBLE if (line == 3) this->controller.rumble(this->next_print[line].c_str()); else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); + this->screen_contents[line].text = std::move(this->next_print[line]); this->next_print[line] = ""; this->last_printed_line = line; this->last_print_time = pros::millis(); @@ -165,12 +172,13 @@ void Controller::add_alerts(std::vector strs, uint32_t duration, st std::lock_guard guard(this->alert_mut); - // get nex available time slot for all lines + // get next available time slot for all lines uint minSpot = -1; // max uint value for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); // Schedule alerts for (int i = 0; i < 4; i++) { + // add delay until theres a spot for all lines together if (getTotalDuration(i) < minSpot) this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); From 12f4d6f2c90a2b0c38c0088210834ec0e4ea6dd3 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:15:55 -0400 Subject: [PATCH 028/108] finished abstract screen interface --- include/gamepad/abstractScreen.hpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 include/gamepad/abstractScreen.hpp diff --git a/include/gamepad/abstractScreen.hpp b/include/gamepad/abstractScreen.hpp new file mode 100644 index 0000000..74c1adf --- /dev/null +++ b/include/gamepad/abstractScreen.hpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +#include "pros/misc.h" + + +namespace Gamepad { + +typedef std::array, 3> ScreenBuffer; + +class AbstractScreen { + public: + AbstractScreen(uint priority): priority(priority) {} + virtual ScreenBuffer get_screen(std::set visible_lines) = 0; + virtual void handle_events(std::set button_events) = 0; + uint get_priority(); + private: + uint priority; +}; + +} // namespace Gamepad \ No newline at end of file From 7781c59904e2b16b7bfa6ef7ec582d842fb5d165 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Mon, 12 Aug 2024 22:17:25 -0400 Subject: [PATCH 029/108] moved the stuff that needs to be moved... kinda --- include/gamepad/abstractScreen.hpp | 23 ------ include/gamepad/controller.hpp | 38 +++------ include/gamepad/screens/abstractScreen.hpp | 30 +++++++ include/gamepad/screens/alertScreen.hpp | 35 ++++++++ include/gamepad/screens/defaultScreen.hpp | 24 ++++++ src/gamepad/controller.cpp | 93 ++-------------------- src/gamepad/screens/alertScreen.cpp | 56 +++++++++++++ src/gamepad/screens/defaultScreen.cpp | 43 ++++++++++ 8 files changed, 205 insertions(+), 137 deletions(-) delete mode 100644 include/gamepad/abstractScreen.hpp create mode 100644 include/gamepad/screens/abstractScreen.hpp create mode 100644 include/gamepad/screens/alertScreen.hpp create mode 100644 include/gamepad/screens/defaultScreen.hpp create mode 100644 src/gamepad/screens/alertScreen.cpp create mode 100644 src/gamepad/screens/defaultScreen.cpp diff --git a/include/gamepad/abstractScreen.hpp b/include/gamepad/abstractScreen.hpp deleted file mode 100644 index 74c1adf..0000000 --- a/include/gamepad/abstractScreen.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include -#include -#include - -#include "pros/misc.h" - - -namespace Gamepad { - -typedef std::array, 3> ScreenBuffer; - -class AbstractScreen { - public: - AbstractScreen(uint priority): priority(priority) {} - virtual ScreenBuffer get_screen(std::set visible_lines) = 0; - virtual void handle_events(std::set button_events) = 0; - uint get_priority(); - private: - uint priority; -}; - -} // namespace Gamepad \ No newline at end of file diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 9f92f14..1a8a360 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,15 +1,14 @@ #pragma once -#include #include -#include #include -#include +#include #include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif +#include "gamepad/screens/abstractScreen.hpp" #include "event_handler.hpp" #include "pros/misc.hpp" #include "pros/rtos.hpp" @@ -58,12 +57,6 @@ class Controller { * @note Create a separate instance for each task. */ void update(); - - void add_alert(uint8_t line, std::string str, uint32_t duration, std::string rumble = ""); - - void print_line(uint8_t line, std::string str); - - void rumble(std::string rumble_pattern); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -81,33 +74,24 @@ class Controller { X{}, B{}, Y{}, A{}; float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0; private: - struct Line { - std::string text; - uint duration; - }; + + struct { + bool operator()(AbstractScreen &l, AbstractScreen &r) { return l.get_priority() < r.get_priority(); } + } AbstractScreenSort; static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); - void updateScreen(); - void add_alerts(std::vector strs, uint32_t duration, std::string rumble = ""); - uint getTotalDuration(uint8_t line); + void updateScreens(); + std::vector screens; pros::Controller controller; - // alert queue - std::array, 4> screen_buffer{}; - pros::Mutex alert_mut; - - - std::array next_print{}; - pros::Mutex print_mut; - std::array screen_contents{}; - std::array line_set_time{}; uint8_t last_printed_line = 0; - uint32_t last_print_time = 0; - pros::Mutex scheduling_mut; + uint last_print_time = 0; + uint last_update_time = 0; + pros::Mutex mut; }; // namespace Gamepad } diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp new file mode 100644 index 0000000..8e50463 --- /dev/null +++ b/include/gamepad/screens/abstractScreen.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include +#include "pros/misc.h" + +namespace Gamepad { + +/** + * @brief type for conveying a full screen with the first 3 being the lines + * of text on the controller screen and the last being a rumble pattern + */ +typedef std::array, 4> ScreenBuffer; + +class AbstractScreen { + public: + AbstractScreen(uint priority): priority(priority) {} + void update(double delta_time) {} + virtual ScreenBuffer get_screen(std::set visible_lines) = 0; + virtual void handle_events(std::set button_events) = 0; + const uint get_priority(); + + bool operator()(AbstractScreen *l, AbstractScreen *r) { return l->get_priority() < r->get_priority(); } + private: + const uint priority; +}; + +} // namespace Gamepad \ No newline at end of file diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp new file mode 100644 index 0000000..ffd901b --- /dev/null +++ b/include/gamepad/screens/alertScreen.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include "pros/rtos.hpp" +#include "gamepad/screens/abstractScreen.hpp" + +namespace Gamepad { + +class AlertScreen : AbstractScreen { + public: + AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} + void update(double delta_time); + ScreenBuffer get_screen(std::set visible_lines); + void handle_events(std::set button_events); + + void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); + + private: + struct Line { + std::string text; + uint duration; + }; + + uint getTotalDuration(uint8_t line); + + std::array, 4> screen_buffer{}; + std::array screen_contents{}; + std::array line_set_time{}; + pros::Mutex mut; +}; + +} \ No newline at end of file diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp new file mode 100644 index 0000000..719082e --- /dev/null +++ b/include/gamepad/screens/defaultScreen.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "gamepad/screens/abstractScreen.hpp" +#include "pros/rtos.hpp" + +namespace Gamepad { + +class DefaultScreen : AbstractScreen { + public: + DefaultScreen() : AbstractScreen(1) {} + void update(double delta_time); + ScreenBuffer get_screen(std::set visible_lines); + void handle_events(std::set button_events); + + void print_line(uint8_t line, std::string str); + void rumble(std::string rumble_pattern); + + private: + ScreenBuffer currentBuffer; + pros::Mutex mut; + +}; + +} \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 8fa94c5..27f7146 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -59,11 +59,13 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) { (this->*button).update(is_held); } -void Controller::updateScreen() { +void Controller::updateScreens() { // Lock Mutexes for Thread Safety - std::lock_guard guard_scheduling(this->scheduling_mut); - std::lock_guard guard_print(this->print_mut); - std::lock_guard guard_alert(this->alert_mut); + std::lock_guard guard_scheduling(this->mut); + + for (int i = 0; i < this->screens.size(); i++) { + this->screens[i].update(pros::millis() - this->last_update_time); + } // Check if enough time has passed for the controller to poll for updates if (pros::millis() - this->last_print_time < 50) @@ -136,89 +138,6 @@ void Controller::update() { this->updateScreen(); } -uint Controller::getTotalDuration(uint8_t line) { - uint total = 0; - for (Line msg : this->screen_buffer[line]) - total += msg.duration; - return total; -} - -void Controller::add_alert(uint8_t line, std::string str, uint32_t duration, std::string rumble) { - TODO("change handling for off screen lines") - if (line > 2) std::exit(1); - - if (str.find('\n') != std::string::npos) { - TODO("warn instead of throw error if there are too many lines") - if (std::ranges::count(str, '\n') > 2) std::exit(1); - - std::vector strs(3); - std::stringstream ss(str); - - for (int i = line; i < 3; i++) { - if (!std::getline(ss, strs[i], '\n')) break; - } - - add_alerts(strs, duration, rumble); - return; - } - - std::lock_guard guard(this->alert_mut); - this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); -} - -void Controller::add_alerts(std::vector strs, uint32_t duration, std::string rumble) { - TODO("change handling for too many lines") - if (strs.size() > 3) std::exit(1); - - std::lock_guard guard(this->alert_mut); - - // get next available time slot for all lines - uint minSpot = -1; // max uint value - for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); - - // Schedule alerts - for (int i = 0; i < 4; i++) { - // add delay until theres a spot for all lines together - if (getTotalDuration(i) < minSpot) - this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); - - if (i == 3) this->screen_buffer[i].push_back({.text = std::move(rumble), .duration = duration}); - else this->screen_buffer[i].push_back({.text = std::move(strs[i]), .duration = 0}); - } -} - -void Controller::print_line(uint8_t line, std::string str) { - TODO("change handling for off screen lines") - if (line > 2) std::exit(1); - - std::lock_guard guard(this->print_mut); - - if (str.find('\n') != std::string::npos) { - TODO("warn instead of throw error if there are too many lines") - if (std::ranges::count(str, '\n') > 2) std::exit(1); - - std::vector strs(3); - std::stringstream ss(str); - - for (int i = line; i < 3; i++) { - if (!std::getline(ss, strs[i], '\n')) break; - } - - for (uint8_t l = 0; l < 3; l++) - this->next_print[l] = std::move(strs[l]); - return; - } - - this->next_print[line] = std::move(str); -} - -void Controller::rumble(std::string rumble_pattern) { - TODO("change handling for too long rumble patterns") - if (rumble_pattern.size() > 8) std::exit(1); - - std::lock_guard guard(this->print_mut); - this->next_print[3] = std::move(rumble_pattern); -} const Button& Controller::operator[](pros::controller_digital_e_t button) { return this->*Controller::button_to_ptr(button); diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp new file mode 100644 index 0000000..2cfe588 --- /dev/null +++ b/src/gamepad/screens/alertScreen.cpp @@ -0,0 +1,56 @@ +#include "gamepad/screens/alertScreen.hpp" +#include +#include +#include +#include +#include "gamepad/todo.hpp" + +namespace Gamepad { + + +uint AlertScreen::getTotalDuration(uint8_t line) { + uint total = 0; + for (Line msg : this->screen_buffer[line]) + total += msg.duration; + return total; +} + +void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { + TODO("change handling for off screen lines") + if (line > 2) std::exit(1); + + if (str.find('\n') != std::string::npos) { + TODO("warn instead of throw error if there are too many lines") + if (std::ranges::count(str, '\n') > 2) std::exit(1); + + std::vector strs(3); + std::stringstream ss(str); + + // split string by newlines but only take the first 3 lines + for (int i = line; i < 3; i++) { + if (!std::getline(ss, strs[i], '\n')) break; + } + + std::lock_guard guard(this->mut); + + // get next available time slot for all lines + uint minSpot = UINT32_MAX; + for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); + + // Schedule alerts + for (int i = 0; i < 4; i++) { + // add delay until theres a spot for all lines together + if (getTotalDuration(i) < minSpot) + this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); + + if (i == 3) this->screen_buffer[i].push_back({.text = std::move(rumble), .duration = duration}); + else this->screen_buffer[i].push_back({.text = std::move(strs[i]), .duration = 0}); + } + return; + } + + std::lock_guard guard(this->mut); + this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); +} + +} \ No newline at end of file diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp new file mode 100644 index 0000000..510f1ed --- /dev/null +++ b/src/gamepad/screens/defaultScreen.cpp @@ -0,0 +1,43 @@ +#include "gamepad/screens/defaultScreen.hpp" +#include +#include +#include +#include "gamepad/todo.hpp" + + +namespace Gamepad { + +void DefaultScreen::print_line(uint8_t line, std::string str) { + TODO("change handling for off screen lines") + if (line > 2) std::exit(1); + + std::lock_guard guard(this->mut); + + if (str.find('\n') != std::string::npos) { + TODO("warn instead of throw error if there are too many lines") + if (std::ranges::count(str, '\n') > 2) std::exit(1); + + std::vector strs(3); + std::stringstream ss(str); + + for (int i = line; i < 3; i++) { + if (!std::getline(ss, strs[i], '\n')) break; + } + + for (uint8_t l = 0; l < 3; l++) + this->currentBuffer[l] = std::move(strs[l]); + return; + } + + this->currentBuffer[line] = std::move(str); +} + +void DefaultScreen::rumble(std::string rumble_pattern) { + TODO("change handling for too long rumble patterns") + if (rumble_pattern.size() > 8) std::exit(1); + + std::lock_guard guard(this->mut); + this->currentBuffer[3] = std::move(rumble_pattern); +} + +} \ No newline at end of file From 18a4ed61f5e65226c4076d0b70d57f82eaab6845 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:49:38 -0400 Subject: [PATCH 030/108] =?UTF-8?q?why=20am=20i=20getting=20these=20errors?= =?UTF-8?q?=F0=9F=92=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/gamepad/controller.hpp | 14 ++--- src/gamepad/controller.cpp | 94 ++++++++++++++++------------------ 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 1a8a360..0d765b8 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,17 +1,16 @@ #pragma once +#include "screens/abstractScreen.hpp" #include #include #include #include -#ifndef PROS_USE_SIMPLE_NAMES -#define PROS_USE_SIMPLE_NAMES -#endif - -#include "gamepad/screens/abstractScreen.hpp" #include "event_handler.hpp" #include "pros/misc.hpp" #include "pros/rtos.hpp" +#ifndef PROS_USE_SIMPLE_NAMES +#define PROS_USE_SIMPLE_NAMES +#endif namespace Gamepad { @@ -57,6 +56,8 @@ class Controller { * @note Create a separate instance for each task. */ void update(); + + void add_screen(AbstractScreen& screen); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -85,9 +86,10 @@ class Controller { void updateScreens(); std::vector screens; + ScreenBuffer currentScreen; + ScreenBuffer nextBuffer; pros::Controller controller; - uint8_t last_printed_line = 0; uint last_print_time = 0; uint last_update_time = 0; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 27f7146..6aa764b 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -1,14 +1,15 @@ #include "gamepad/controller.hpp" #include "gamepad/todo.hpp" #include "pros/rtos.hpp" -#include +#include "pros/misc.h" #include #include #include #include #include -#include +#include #include +#include #include #include @@ -63,65 +64,46 @@ void Controller::updateScreens() { // Lock Mutexes for Thread Safety std::lock_guard guard_scheduling(this->mut); - for (int i = 0; i < this->screens.size(); i++) { + // Update all screens and note deltatime + for (int i = 0; i < this->screens.size(); i++) this->screens[i].update(pros::millis() - this->last_update_time); - } + last_update_time = pros::millis(); // Check if enough time has passed for the controller to poll for updates if (pros::millis() - this->last_print_time < 50) return; + for (int i = 0; i < this->screens.size(); i++) { + // get all lines that arent being used by a higher priority screen + std::set visible_lines; + for (uint8_t j = 0; j < 4; j++) + if (!this->nextBuffer[j].has_value()) + visible_lines.emplace(j); + + // get the buffer of the next lower priority screen and set it to be printed + ScreenBuffer buffer = this->screens[i].get_screen(visible_lines); + for (uint8_t j = 0; j < 4; j++) + if (buffer[j].has_value() && !nextBuffer[j].has_value()) + nextBuffer[j] = std::move(buffer[j]); + } + for (int i = 1; i <= 4; i++) { // start from the line thats after the line thats been set so we dont get stuck setting the first line int line = (this->last_printed_line + i) % 4; - // if the last alert's duration expired - if (pros::millis() - this->line_set_time[line] >= this->screen_contents[line].duration) { - // No alerts to print - if (this->screen_buffer[line].size() == 0) { - // text on screen is the same as last frame's text so no use updating - if (this->screen_contents[line].text == this->next_print[line] && line != 3) { - this->next_print[line] = ""; - continue; - } - // UPDATE TEXT/RUMBLE - if (line == 3) this->controller.rumble(this->next_print[line].c_str()); - else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); - this->screen_contents[line].text = std::move(this->next_print[line]); - this->next_print[line] = ""; - } else { - // text on screen is the same as the alert's text so just set vars, dont update controller - if (this->screen_contents[line].text == this->screen_buffer[line][0].text && line != 3) { - this->screen_contents[line] = this->screen_buffer[line][0]; - this->screen_buffer[line].pop_front(); - this->line_set_time[line] = pros::millis(); - continue; - } - - // SET ALERT/RUMBLE ALERT - if (line == 3) this->controller.rumble(this->screen_buffer[line][0].text.c_str()); - else this->controller.set_text(line, 0, this->screen_buffer[line][0].text + std::string(40, ' ')); - this->screen_contents[line] = this->screen_buffer[line][0]; - this->screen_buffer[line].pop_front(); - this->line_set_time[line] = pros::millis(); - } - this->last_printed_line = line; - this->last_print_time = pros::millis(); - } else if (this->screen_contents[line].text == "") { - // text is the same as last frame's text so no use updating - if (this->screen_contents[line].text == this->next_print[line] && line != 3) { - this->next_print[line] = ""; - continue; - } - - // UPDATE TEXT/RUMBLE - if (line == 3) this->controller.rumble(this->next_print[line].c_str()); - else this->controller.set_text(line, 0, this->next_print[line] + std::string(40, ' ')); - this->screen_contents[line].text = std::move(this->next_print[line]); - this->next_print[line] = ""; - this->last_printed_line = line; - this->last_print_time = pros::millis(); + // text on screen is the same as last frame's text so no use updating + if (this->currentScreen[line] == this->nextBuffer[line] && line != 3) { + this->nextBuffer[line] = std::nullopt; + continue; } + + // print to screen or rumble + if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); + else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); + this->currentScreen[line] = std::move(this->nextBuffer[line]); + this->nextBuffer[line] = std::nullopt; + this->last_printed_line = line; + this->last_print_time = pros::millis(); } } @@ -135,7 +117,17 @@ void Controller::update() { this->RightX = this->controller.get_analog(ANALOG_RIGHT_X); this->RightY = this->controller.get_analog(ANALOG_RIGHT_Y); - this->updateScreen(); + this->updateScreens(); +} + +void Controller::add_screen(AbstractScreen &screen) { + uint last = UINT32_MAX; uint pos = 0; + for (pos = 0; pos < this->screens.size(); pos++) { + if (this->screens[pos].get_priority() < screen.get_priority() && last >= screen.get_priority()) + break; + last = this->screens[pos].get_priority(); + } + this->screens.emplace(this->screens.begin() + pos, screen); } From 66945cf2354feab9a07ddcca0209bf1c4e8c4e61 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:52:19 -0400 Subject: [PATCH 031/108] idk what happened but no errors now, also screen update works hopefully --- include/gamepad/controller.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 0d765b8..893a799 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,16 +1,16 @@ #pragma once -#include "screens/abstractScreen.hpp" #include #include #include #include -#include "event_handler.hpp" -#include "pros/misc.hpp" -#include "pros/rtos.hpp" #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif +#include "screens/abstractScreen.hpp" +#include "event_handler.hpp" +#include "pros/misc.hpp" +#include "pros/rtos.hpp" namespace Gamepad { From 4b17c36cf386fafa854fa0c55eb703b698f3c1c6 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:19:22 -0400 Subject: [PATCH 032/108] shared pointers :sparkles: --- include/gamepad/controller.hpp | 10 +++------- include/gamepad/screens/abstractScreen.hpp | 2 -- include/gamepad/screens/defaultScreen.hpp | 3 +-- src/gamepad/controller.cpp | 11 ++++++----- src/gamepad/screens/alertScreen.cpp | 5 +++++ src/gamepad/screens/defaultScreen.cpp | 10 ++++++++++ 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 893a799..1de2b6b 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #ifndef PROS_USE_SIMPLE_NAMES @@ -57,7 +58,7 @@ class Controller { */ void update(); - void add_screen(AbstractScreen& screen); + void add_screen(std::shared_ptr screen); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -75,17 +76,12 @@ class Controller { X{}, B{}, Y{}, A{}; float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0; private: - - struct { - bool operator()(AbstractScreen &l, AbstractScreen &r) { return l.get_priority() < r.get_priority(); } - } AbstractScreenSort; - static Button Controller::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreens(); - std::vector screens; + std::vector> screens; ScreenBuffer currentScreen; ScreenBuffer nextBuffer; pros::Controller controller; diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 8e50463..e1b0fc1 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -21,8 +21,6 @@ class AbstractScreen { virtual ScreenBuffer get_screen(std::set visible_lines) = 0; virtual void handle_events(std::set button_events) = 0; const uint get_priority(); - - bool operator()(AbstractScreen *l, AbstractScreen *r) { return l->get_priority() < r->get_priority(); } private: const uint priority; }; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 719082e..00e69ff 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -8,9 +8,8 @@ namespace Gamepad { class DefaultScreen : AbstractScreen { public: DefaultScreen() : AbstractScreen(1) {} - void update(double delta_time); ScreenBuffer get_screen(std::set visible_lines); - void handle_events(std::set button_events); + void handle_events(std::set button_events) {} void print_line(uint8_t line, std::string str); void rumble(std::string rumble_pattern); diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 6aa764b..f179ba4 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ void Controller::updateScreens() { // Update all screens and note deltatime for (int i = 0; i < this->screens.size(); i++) - this->screens[i].update(pros::millis() - this->last_update_time); + this->screens[i]->update(pros::millis() - this->last_update_time); last_update_time = pros::millis(); // Check if enough time has passed for the controller to poll for updates @@ -81,7 +82,7 @@ void Controller::updateScreens() { visible_lines.emplace(j); // get the buffer of the next lower priority screen and set it to be printed - ScreenBuffer buffer = this->screens[i].get_screen(visible_lines); + ScreenBuffer buffer = this->screens[i]->get_screen(visible_lines); for (uint8_t j = 0; j < 4; j++) if (buffer[j].has_value() && !nextBuffer[j].has_value()) nextBuffer[j] = std::move(buffer[j]); @@ -120,12 +121,12 @@ void Controller::update() { this->updateScreens(); } -void Controller::add_screen(AbstractScreen &screen) { +void Controller::add_screen(std::shared_ptr screen) { uint last = UINT32_MAX; uint pos = 0; for (pos = 0; pos < this->screens.size(); pos++) { - if (this->screens[pos].get_priority() < screen.get_priority() && last >= screen.get_priority()) + if (this->screens[pos]->get_priority() < screen->get_priority() && last >= screen->get_priority()) break; - last = this->screens[pos].get_priority(); + last = this->screens[pos]->get_priority(); } this->screens.emplace(this->screens.begin() + pos, screen); } diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 2cfe588..28bba30 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -7,6 +7,11 @@ namespace Gamepad { +ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { + ScreenBuffer output; + +} + uint AlertScreen::getTotalDuration(uint8_t line) { uint total = 0; diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 510f1ed..1010451 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -1,12 +1,22 @@ #include "gamepad/screens/defaultScreen.hpp" #include #include +#include #include #include "gamepad/todo.hpp" namespace Gamepad { +ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { + ScreenBuffer output; + for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { + output[*i] = std::move(this->currentBuffer[*i].value_or("")); + this->currentBuffer[*i] = std::nullopt; + } + return output; +} + void DefaultScreen::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); From 6c90b923e58acb2efa83ff2a40392b16d2774605 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:02:55 -0400 Subject: [PATCH 033/108] it builds now --- include/gamepad/screens/abstractScreen.hpp | 2 +- include/gamepad/screens/alertScreen.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index e1b0fc1..7dde3d7 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -20,7 +20,7 @@ class AbstractScreen { void update(double delta_time) {} virtual ScreenBuffer get_screen(std::set visible_lines) = 0; virtual void handle_events(std::set button_events) = 0; - const uint get_priority(); + const uint get_priority() { return this->priority; } private: const uint priority; }; diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index ffd901b..61ead10 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -14,7 +14,7 @@ class AlertScreen : AbstractScreen { AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} void update(double delta_time); ScreenBuffer get_screen(std::set visible_lines); - void handle_events(std::set button_events); + void handle_events(std::set button_events) {} void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); From 8dbb7329338cd9d51e597cc5d7e5eed15d8ee369 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 17 Aug 2024 20:07:57 -0400 Subject: [PATCH 034/108] alerts should work --- include/gamepad/screens/abstractScreen.hpp | 2 +- include/gamepad/screens/alertScreen.hpp | 16 +++--- src/gamepad/screens/alertScreen.cpp | 66 +++++++++++----------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 7dde3d7..665d804 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -17,7 +17,7 @@ typedef std::array, 4> ScreenBuffer; class AbstractScreen { public: AbstractScreen(uint priority): priority(priority) {} - void update(double delta_time) {} + void update(uint delta_time) {} virtual ScreenBuffer get_screen(std::set visible_lines) = 0; virtual void handle_events(std::set button_events) = 0; const uint get_priority() { return this->priority; } diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 61ead10..b725904 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include "abstractScreen.hpp" #include "pros/rtos.hpp" #include "gamepad/screens/abstractScreen.hpp" @@ -12,23 +14,21 @@ namespace Gamepad { class AlertScreen : AbstractScreen { public: AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} - void update(double delta_time); + void update(uint delta_time); ScreenBuffer get_screen(std::set visible_lines); void handle_events(std::set button_events) {} void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: - struct Line { - std::string text; + struct AlertBuffer { + ScreenBuffer screen; uint duration; }; - uint getTotalDuration(uint8_t line); - - std::array, 4> screen_buffer{}; - std::array screen_contents{}; - std::array line_set_time{}; + std::deque screen_buffer{}; + std::optional screen_contents; + uint line_set_time; pros::Mutex mut; }; diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 28bba30..4e01882 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -2,60 +2,60 @@ #include #include #include +#include #include #include "gamepad/todo.hpp" +#include "pros/rtos.hpp" namespace Gamepad { ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { - ScreenBuffer output; + std::lock_guard guard(this->mut); + if (this->screen_contents.has_value()) return this->screen_contents->screen; + if (this->screen_buffer.size() < 1) return ScreenBuffer(); -} + for (uint8_t i = 0; i < 4; i++) { + if (!this->screen_buffer[0].screen[i].has_value()) continue; + if (this->screen_buffer[0].screen[i].has_value() && !visible_lines.contains(i)) return ScreenBuffer(); + } + this->screen_contents = std::move(this->screen_buffer[0]); + this->screen_buffer.pop_front(); + this->line_set_time = pros::millis(); + return this->screen_contents->screen; +} -uint AlertScreen::getTotalDuration(uint8_t line) { - uint total = 0; - for (Line msg : this->screen_buffer[line]) - total += msg.duration; - return total; +void AlertScreen::update(uint delta_time) { + std::lock_guard guard(this->mut); + if (pros::millis() - this->line_set_time >= this->screen_contents->duration) + this->screen_contents = std::nullopt; } void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - if (str.find('\n') != std::string::npos) { - TODO("warn instead of throw error if there are too many lines") - if (std::ranges::count(str, '\n') > 2) std::exit(1); + TODO("warn instead of throw error if there are too many lines") + if (std::ranges::count(str, '\n') > 2) std::exit(1); - std::vector strs(3); - std::stringstream ss(str); + std::vector strs(3, ""); + std::stringstream ss(str); - // split string by newlines but only take the first 3 lines - for (int i = line; i < 3; i++) { - if (!std::getline(ss, strs[i], '\n')) break; - } - - std::lock_guard guard(this->mut); + // split string by newlines but only take the first 3 lines + for (int i = line; i < 3; i++) { + if (!std::getline(ss, strs[i], '\n')) break; + } - // get next available time slot for all lines - uint minSpot = UINT32_MAX; - for (uint8_t line = 0; line < 4; line++) minSpot = std::min(minSpot, getTotalDuration(line)); - // Schedule alerts - for (int i = 0; i < 4; i++) { - // add delay until theres a spot for all lines together - if (getTotalDuration(i) < minSpot) - this->screen_buffer[i].push_back({ .text = "", .duration = (minSpot - getTotalDuration(i)) }); + ScreenBuffer buffer; - if (i == 3) this->screen_buffer[i].push_back({.text = std::move(rumble), .duration = duration}); - else this->screen_buffer[i].push_back({.text = std::move(strs[i]), .duration = 0}); - } - return; - } + if (strs[0] != "") buffer[0] = std::move(strs[0]); + if (strs[1] != "") buffer[1] = std::move(strs[1]); + if (strs[2] != "") buffer[2] = std::move(strs[2]); + if (rumble != "") buffer[3] = std::move(rumble); std::lock_guard guard(this->mut); - this->screen_buffer[line].push_back({ .text = std::move(str), .duration = duration }); + this->screen_buffer.push_back({buffer, duration}); } -} \ No newline at end of file +} From 23c4bbfca211304bfea8dfae6ae5d8f93bdfe9d4 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:24:33 -0400 Subject: [PATCH 035/108] what should i do for this? --- include/gamepad/controller.hpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 1de2b6b..86209c6 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #ifndef PROS_USE_SIMPLE_NAMES @@ -57,8 +58,18 @@ class Controller { * @note Create a separate instance for each task. */ void update(); - + /** + * Add a screen to the sceen update loop that can update the controller's screen + * + * @param screen the `AbstractScreen` to + */ void add_screen(std::shared_ptr screen); + void remove_screen(); // TODO: Find a good way to access the screen to remove + + // TODO: Change this to be a better access point + std::vector> get_screens(); + std::vector> get_screens(uint priority); + std::vector> get_screens(uint min_priority, uint max_priority); /** * Get the state of a button on the controller. * @param button Which button's state you want. From 790929ca03414c2796cc09f403869f8d9670a712 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:20:50 -0400 Subject: [PATCH 036/108] bug fixing :sob: --- Makefile | 2 +- debug.log | 2 ++ include/gamepad/api.hpp | 3 +- include/gamepad/controller.hpp | 27 ++++++++++++------ include/gamepad/screens/abstractScreen.hpp | 4 +-- include/gamepad/screens/alertScreen.hpp | 5 ++-- include/gamepad/screens/defaultScreen.hpp | 6 ++-- src/gamepad/controller.cpp | 16 +++++++++++ src/gamepad/screens/defaultScreen.cpp | 15 ++++++++-- src/main.cpp | 32 ++++------------------ 10 files changed, 64 insertions(+), 48 deletions(-) create mode 100644 debug.log diff --git a/Makefile b/Makefile index 10d24a2..37780c2 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ USE_PACKAGE:=1 EXCLUDE_COLD_LIBRARIES:= # Set this to 1 to add additional rules to compile your project as a PROS library template -IS_LIBRARY:=1 +IS_LIBRARY:=0 # TODO: CHANGE THIS! LIBNAME:=gamepad VERSION:=0.0.1 diff --git a/debug.log b/debug.log new file mode 100644 index 0000000..10fb722 --- /dev/null +++ b/debug.log @@ -0,0 +1,2 @@ +[0909/102831.528:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) +[0909/102852.263:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) diff --git a/include/gamepad/api.hpp b/include/gamepad/api.hpp index 835385a..42d042b 100644 --- a/include/gamepad/api.hpp +++ b/include/gamepad/api.hpp @@ -1,4 +1,5 @@ #pragma once #include "gamepad/event_handler.hpp" // IWYU pragma: export -#include "gamepad/controller.hpp" // IWYU pragma: export \ No newline at end of file +#include "gamepad/controller.hpp" // IWYU pragma: export +#include "gamepad/screens/alertScreen.hpp" // IWYU pragma: export diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 21cca46..f627fd1 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,6 +1,7 @@ #pragma once #include "pros/misc.h" +#include "screens/defaultScreen.hpp" #include #include #include @@ -60,15 +61,23 @@ class Controller { /** * Add a screen to the sceen update loop that can update the controller's screen * - * @param screen the `AbstractScreen` to + * @param screen the `AbstractScreen` to add to the screen queue */ void add_screen(std::shared_ptr screen); - void remove_screen(); // TODO: Find a good way to access the screen to remove + /** + * print a line to the console like pros (low priority) + * + * @param line the line number to print the string on (0-2) + * @param str the string to print onto the controller (\n to go to the next line) + */ + void print_line(uint8_t line, std::string str); + /** + * makes the controller rumble like pros (low priority) + * + * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + */ + void rumble(std::string rumble_pattern); - // TODO: Change this to be a better access point - std::vector> get_screens(); - std::vector> get_screens(uint priority); - std::vector> get_screens(uint min_priority, uint max_priority); /** * Get the state of a button on the controller. * @param button Which button's state you want. @@ -87,15 +96,15 @@ class Controller { /// The partner controller, same as @ref Gamepad::partner static Controller partner; private: - explicit Controller(pros::controller_id_e_t id) - : controller(id) {} + explicit Controller(pros::controller_id_e_t id) : controller(id) {} static Button Controller::*button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreens(); - std::vector> screens; + std::shared_ptr defaultScreen; + std::vector> screens{defaultScreen}; ScreenBuffer currentScreen; ScreenBuffer nextBuffer; pros::Controller controller; diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 665d804..f3e832f 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -18,8 +18,8 @@ class AbstractScreen { public: AbstractScreen(uint priority): priority(priority) {} void update(uint delta_time) {} - virtual ScreenBuffer get_screen(std::set visible_lines) = 0; - virtual void handle_events(std::set button_events) = 0; + ScreenBuffer get_screen(std::set visible_lines) {return {};} + void handle_events(std::set button_events) {} const uint get_priority() { return this->priority; } private: const uint priority; diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index b725904..55e1af8 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -4,14 +4,13 @@ #include #include #include -#include #include "abstractScreen.hpp" #include "pros/rtos.hpp" #include "gamepad/screens/abstractScreen.hpp" namespace Gamepad { -class AlertScreen : AbstractScreen { +class AlertScreen : public AbstractScreen { public: AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} void update(uint delta_time); @@ -32,4 +31,4 @@ class AlertScreen : AbstractScreen { pros::Mutex mut; }; -} \ No newline at end of file +} diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 00e69ff..8333e4e 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -5,9 +5,9 @@ namespace Gamepad { -class DefaultScreen : AbstractScreen { +class DefaultScreen : public AbstractScreen { public: - DefaultScreen() : AbstractScreen(1) {} + DefaultScreen(); ScreenBuffer get_screen(std::set visible_lines); void handle_events(std::set button_events) {} @@ -20,4 +20,4 @@ class DefaultScreen : AbstractScreen { }; -} \ No newline at end of file +} diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index aac68ed..abfae71 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -2,8 +2,11 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include "pros/misc.h" +#include "screens/defaultScreen.hpp" +#include #include #include +#include #include #include #include @@ -124,6 +127,19 @@ void Controller::add_screen(std::shared_ptr screen) { this->screens.emplace(this->screens.begin() + pos, screen); } +void Controller::print_line(uint8_t line, std::string str) { + if (std::count(this->screens.begin(), this->screens.end(), this->defaultScreen) == 0) { + this->add_screen(this->defaultScreen); + } + printf("%i elements in screens\n", this->screens.size()); + + this->defaultScreen->print_line(line, str); +} + +void Controller::rumble(std::string rumble_pattern) { + this->defaultScreen->rumble(rumble_pattern); +} + const Button& Controller::operator[](pros::controller_digital_e_t button) { return this->*Controller::button_to_ptr(button); diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 1010451..c71ad19 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -3,13 +3,23 @@ #include #include #include +#include "abstractScreen.hpp" #include "gamepad/todo.hpp" namespace Gamepad { +DefaultScreen::DefaultScreen() : AbstractScreen(1) { + printf("ran constructor\n"); +} + ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { ScreenBuffer output; + printf("{%s, %s, %s, %s}\n", + currentBuffer.at(0).value_or("N/A").c_str(), + currentBuffer.at(1).value_or("N/A").c_str(), + currentBuffer.at(2).value_or("N/A").c_str(), + currentBuffer.at(3).value_or("N/A").c_str()); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { output[*i] = std::move(this->currentBuffer[*i].value_or("")); this->currentBuffer[*i] = std::nullopt; @@ -18,6 +28,7 @@ ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { } void DefaultScreen::print_line(uint8_t line, std::string str) { + printf("print_line(line: %i, string: %s)\n", line, str.c_str()); TODO("change handling for off screen lines") if (line > 2) std::exit(1); @@ -30,12 +41,12 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { std::vector strs(3); std::stringstream ss(str); - for (int i = line; i < 3; i++) { + for (int i = line; i < 3; i++) if (!std::getline(ss, strs[i], '\n')) break; - } for (uint8_t l = 0; l < 3; l++) this->currentBuffer[l] = std::move(strs[l]); + return; } diff --git a/src/main.cpp b/src/main.cpp index 30d56e9..978f84d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,21 +1,8 @@ #include "main.h" #include "gamepad/api.hpp" +#include "gamepad/controller.hpp" +#include "pros/rtos.hpp" -/** - * A callback function for LLEMU's center button. - * - * When this callback is fired, it will toggle line 2 of the LCD text between - * "I was pressed!" and nothing. - */ -void on_center_button() { - static bool pressed = false; - pressed = !pressed; - if (pressed) { - pros::lcd::set_text(2, "I was pressed!"); - } else { - pros::lcd::clear_line(2); - } -} /** * Runs initialization code. This occurs as soon as the program is started. @@ -25,9 +12,6 @@ void on_center_button() { */ void initialize() { pros::lcd::initialize(); - pros::lcd::set_text(1, "Hello PROS User!"); - - pros::lcd::register_btn1_cb(on_center_button); } /** @@ -75,16 +59,10 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { - pros::MotorGroup left_mg({1, -2, 3}); // Creates a motor group with forwards ports 1 & 3 and reversed port 2 - pros::MotorGroup right_mg({-4, 5, -6}); // Creates a motor group with forwards port 4 and reversed ports 4 & 6 - while (true) { Gamepad::master.update(); - // Arcade control scheme - int dir = Gamepad::master.LeftY; // Gets amount forward/backward from left joystick - int turn = Gamepad::master.RightX; // Gets the turn left/right from right joystick - left_mg.move(dir - turn); // Sets left motor voltage - right_mg.move(dir + turn); // Sets right motor voltage - pros::delay(25); // Run for 25 ms then update + + Gamepad::master.print_line(0, "hello"); + pros::delay(25); } } \ No newline at end of file From d82ef228c4411d6b3a236f6c49abb8fdbbbf3869 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:29:45 -0400 Subject: [PATCH 037/108] help :skull: --- debug.log | 1 + src/gamepad/controller.cpp | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/debug.log b/debug.log index 10fb722..a6ae3a0 100644 --- a/debug.log +++ b/debug.log @@ -1,2 +1,3 @@ [0909/102831.528:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) [0909/102852.263:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) +[0910/182219.664:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index abfae71..4252b3c 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -128,10 +128,7 @@ void Controller::add_screen(std::shared_ptr screen) { } void Controller::print_line(uint8_t line, std::string str) { - if (std::count(this->screens.begin(), this->screens.end(), this->defaultScreen) == 0) { - this->add_screen(this->defaultScreen); - } - printf("%i elements in screens\n", this->screens.size()); + printf("wrapping print_line(line:%i, string:%s)\n", line, str.c_str()); this->defaultScreen->print_line(line, str); } From 385fc82a4af4872e6af546217616774a6492481d Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:33:26 -0400 Subject: [PATCH 038/108] why do i need to commit debug.log :interrobang: --- debug.log | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debug.log b/debug.log index a6ae3a0..86c1de7 100644 --- a/debug.log +++ b/debug.log @@ -1,3 +1,6 @@ [0909/102831.528:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) [0909/102852.263:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) [0910/182219.664:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) +[0910/183206.884:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) +[0910/183223.865:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) +[0910/183232.392:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) From d5b226a0c5d2c9059f47075b3baf903daa18a09a Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:03:50 -0400 Subject: [PATCH 039/108] idk but this breaks it --- src/main.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index abb25a0..f5ba7bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,17 +19,17 @@ void leftLongPress1() { printf("Left Long Press!\n"); } void leftShortRelease1() { printf("Left Short Release!\n"); } 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, - // just remember to give them different names - Gamepad::master.Left.onShortRelease("leftShortRelease", leftShortRelease1); - // And we can use lambda's too - Gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); + // // 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, + // // just remember to give them different names + // Gamepad::master.Left.onShortRelease("leftShortRelease", leftShortRelease1); + // // And we can use lambda's too + // Gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); } /** @@ -77,8 +77,8 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { - pros::MotorGroup left_mg({1, -2, 3}); // Creates a motor group with forwards ports 1 & 3 and reversed port 2 - pros::MotorGroup right_mg({-4, 5, -6}); // Creates a motor group with forwards port 4 and reversed ports 4 & 6 + // pros::MotorGroup left_mg({1, -2, 3}); // Creates a motor group with forwards ports 1 & 3 and reversed port 2 + // pros::MotorGroup right_mg({-4, 5, -6}); // Creates a motor group with forwards port 4 and reversed ports 4 & 6 while (true) { // Remember to ALWAYS call update at the start of your while loop! @@ -87,10 +87,10 @@ void opcontrol() { Gamepad::master.print_line(0, "hello\n\nhi"); // We'll use the arcade control scheme - int dir = Gamepad::master.LeftY; // Gets amount forward/backward from left joystick - int turn = Gamepad::master.RightX; // Gets the turn left/right from right joystick - left_mg.move(dir - turn); // Sets left motor voltage - right_mg.move(dir + turn); // Sets right motor voltage + // int dir = Gamepad::master.LeftY; // Gets amount forward/backward from left joystick + // int turn = Gamepad::master.RightX; // Gets the turn left/right from right joystick + // left_mg.move(dir - turn); // Sets left motor voltage + // right_mg.move(dir + turn); // Sets right motor voltage pros::delay(25); // Wait for 25 ms, then update the motor values again } From 466b8e1c15831b5c008315b38bacd69ffe3c542a Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 21 Sep 2024 10:19:31 -0400 Subject: [PATCH 040/108] bug: :bug: explicit controller constructor isnt getting called --- include/gamepad/controller.hpp | 8 ++++-- include/gamepad/screens/defaultScreen.hpp | 3 ++- src/gamepad/screens/defaultScreen.cpp | 22 +++++++++++++---- src/main.cpp | 30 +---------------------- 4 files changed, 26 insertions(+), 37 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index d725338..6613338 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -267,7 +267,11 @@ class Controller { /// The partner controller, same as @ref Gamepad::partner static Controller partner; private: - explicit Controller(pros::controller_id_e_t id) : controller(id) {} + explicit Controller(pros::controller_id_e_t id) : controller(id) { + printf("screens length: %i\n", screens.size()); + defaultScreen = std::make_shared(); + screens.push_back(defaultScreen); + } Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {}, m_A {}; @@ -288,7 +292,7 @@ class Controller { void updateScreens(); std::shared_ptr defaultScreen; - std::vector> screens{defaultScreen}; + std::vector> screens; ScreenBuffer currentScreen; ScreenBuffer nextBuffer; pros::Controller controller; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 8333e4e..5304d22 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -2,6 +2,7 @@ #include "gamepad/screens/abstractScreen.hpp" #include "pros/rtos.hpp" +#include namespace Gamepad { @@ -15,7 +16,7 @@ class DefaultScreen : public AbstractScreen { void rumble(std::string rumble_pattern); private: - ScreenBuffer currentBuffer; + ScreenBuffer currentBuffer{std::nullopt, std::nullopt, std::nullopt, std::nullopt}; pros::Mutex mut; }; diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index c71ad19..30e3212 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -1,5 +1,6 @@ #include "gamepad/screens/defaultScreen.hpp" #include +#include #include #include #include @@ -20,6 +21,7 @@ ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { currentBuffer.at(1).value_or("N/A").c_str(), currentBuffer.at(2).value_or("N/A").c_str(), currentBuffer.at(3).value_or("N/A").c_str()); + // const std::lock_guard guard(this->mut); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { output[*i] = std::move(this->currentBuffer[*i].value_or("")); this->currentBuffer[*i] = std::nullopt; @@ -32,24 +34,34 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - std::lock_guard guard(this->mut); + printf("is this the problem\n"); + // const std::lock_guard guard(this->mut); + printf("or is this the problem\n"); if (str.find('\n') != std::string::npos) { TODO("warn instead of throw error if there are too many lines") + printf("1\n"); if (std::ranges::count(str, '\n') > 2) std::exit(1); + printf("2\n"); std::vector strs(3); std::stringstream ss(str); - for (int i = line; i < 3; i++) + printf("3\n"); + for (int i = line; i < 3; i++) { + printf("iteration %i\n", i); if (!std::getline(ss, strs[i], '\n')) break; + } - for (uint8_t l = 0; l < 3; l++) - this->currentBuffer[l] = std::move(strs[l]); - + printf("4\n"); + for (uint8_t l = 0; l < 3; l++) { + printf("iteration %i, str: %s, buffer: %s\n", l, strs[l].c_str(), "test"); // currentBuffer[l].value_or("nullopt").c_str()); + if (!strs[l].empty()) this->currentBuffer[l] = (strs[l]); + } return; } + printf("5\n"); this->currentBuffer[line] = std::move(str); } diff --git a/src/main.cpp b/src/main.cpp index f5ba7bc..18f53d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,26 +9,7 @@ * All other competition modes are blocked by initialize; it is recommended * to keep execution time for this mode under a few seconds. */ - -void downPress1() { printf("Down Press!\n"); } - -void upRelease1() { printf("Up Release!\n"); } - -void leftLongPress1() { printf("Left Long Press!\n"); } - -void leftShortRelease1() { printf("Left Short Release!\n"); } - 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, - // // just remember to give them different names - // Gamepad::master.Left.onShortRelease("leftShortRelease", leftShortRelease1); - // // And we can use lambda's too // Gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); } @@ -77,20 +58,11 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { - // pros::MotorGroup left_mg({1, -2, 3}); // Creates a motor group with forwards ports 1 & 3 and reversed port 2 - // pros::MotorGroup right_mg({-4, 5, -6}); // Creates a motor group with forwards port 4 and reversed ports 4 & 6 - while (true) { // Remember to ALWAYS call update at the start of your while loop! Gamepad::master.update(); - Gamepad::master.print_line(0, "hello\n\nhi"); - - // We'll use the arcade control scheme - // int dir = Gamepad::master.LeftY; // Gets amount forward/backward from left joystick - // int turn = Gamepad::master.RightX; // Gets the turn left/right from right joystick - // left_mg.move(dir - turn); // Sets left motor voltage - // right_mg.move(dir + turn); // Sets right motor voltage + // Gamepad::master.print_line(0, "hello\n\nhi"); pros::delay(25); // Wait for 25 ms, then update the motor values again } From 9bfcbb33123ba49cfc9e17f77f1c247995c0b021 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:15:13 -0400 Subject: [PATCH 041/108] fix: :construction: it might work testing in the vexide sim did not result in any errors, idk why --- include/gamepad/screens/defaultScreen.hpp | 2 +- src/gamepad/screens/defaultScreen.cpp | 10 +++++----- src/main.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 5304d22..9101281 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -16,7 +16,7 @@ class DefaultScreen : public AbstractScreen { void rumble(std::string rumble_pattern); private: - ScreenBuffer currentBuffer{std::nullopt, std::nullopt, std::nullopt, std::nullopt}; + ScreenBuffer currentBuffer; pros::Mutex mut; }; diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 30e3212..74a4c49 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -10,17 +10,17 @@ namespace Gamepad { -DefaultScreen::DefaultScreen() : AbstractScreen(1) { +DefaultScreen::DefaultScreen() : AbstractScreen(1), currentBuffer({}) { printf("ran constructor\n"); } ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { ScreenBuffer output; printf("{%s, %s, %s, %s}\n", - currentBuffer.at(0).value_or("N/A").c_str(), - currentBuffer.at(1).value_or("N/A").c_str(), - currentBuffer.at(2).value_or("N/A").c_str(), - currentBuffer.at(3).value_or("N/A").c_str()); + currentBuffer.at(0).value_or("nullopt").c_str(), + currentBuffer.at(1).value_or("nullopt").c_str(), + currentBuffer.at(2).value_or("nullopt").c_str(), + currentBuffer.at(3).value_or("nullopt").c_str()); // const std::lock_guard guard(this->mut); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { output[*i] = std::move(this->currentBuffer[*i].value_or("")); diff --git a/src/main.cpp b/src/main.cpp index 18f53d0..5f61401 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,7 +62,7 @@ void opcontrol() { // Remember to ALWAYS call update at the start of your while loop! Gamepad::master.update(); - // Gamepad::master.print_line(0, "hello\n\nhi"); + Gamepad::master.print_line(0, "hello\n\nhi"); pros::delay(25); // Wait for 25 ms, then update the motor values again } From 4958fa113ce27d101ec20cb422bc4f24deee25df Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 25 Sep 2024 18:22:08 -0400 Subject: [PATCH 042/108] feat: :construction_worker: add vexide sim devcontainer --- .devcontainer/Dockerfile | 62 +++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 13 ++++++- .devcontainer/packagelist | 6 ++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/packagelist diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..1c1b408 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,62 @@ +FROM rust:1.67 as builder + +RUN git clone https://github.com/vexide/vex-v5-qemu.git /vex-v5-qemu + +WORKDIR /vex-v5-qemu +RUN cd packages/kernel; cargo build --target-dir /target/kernel + +RUN cd packages/client-cli; cargo install --path . --root /target/client-cli + +FROM mcr.microsoft.com/devcontainers/cpp:1.0-jammy +# ------------ +# Install Required Packages +# ------------ +RUN sudo apt-get update +COPY ./.devcontainer/packagelist /packagelist +RUN sudo apt-get -y install $(cat /packagelist) +RUN rm /packagelist # Cleanup image +RUN sudo apt-get clean # Cleanup image + +# ------------ +# Install Clangd +# ------------ +RUN curl -sLo clangd.zip $( \ + curl -s https://api.github.com/repos/clangd/clangd/releases/latest \ + | jq -r '[.assets[] | select(.name | test ("^clangd-linux"))][0].browser_download_url' \ + ) \ + && unzip clangd.zip -d /usr/local/share \ + && mv /usr/local/share/clangd_*/ /usr/local/share/clangd \ + && rm clangd.zip + +ENV PATH="$PATH:/usr/local/share/clangd/bin" + +# ------------ +# Install PROS CLI +# ------------ +RUN python3 -m pip install pros-cli + +# ------------ +# Install ARM Toolchain +# ------------ +COPY --from=ghcr.io/lemlib/pros-build:v2.0.2 /gcc-arm-none-eabi-10.3-2021.10 /usr/local/share/arm-none-eabi +ENV PATH="$PATH:/usr/local/share/arm-none-eabi/bin" + +# Copy the simulator binary +COPY --from=builder /target/client-cli/bin/client-cli /usr/local/bin/simulator + +# Clone pros kernel source so we can reference it when debugging +COPY ./project.pros /project.pros +ENV PROS_SOURCE_PATH="$HOME/.pros" +RUN git clone https://github.com/purduesigbots/pros.git $PROS_SOURCE_PATH \ + --depth 1 \ + --branch $( Date: Thu, 26 Sep 2024 00:18:56 +0000 Subject: [PATCH 043/108] =?UTF-8?q?feat:=20=F0=9F=91=B7=20add=20launch=20c?= =?UTF-8?q?onfigs=20and=20tasks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- src/gamepad/screens/defaultScreen.cpp | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 37780c2..fbd001f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ EXTRA_CFLAGS= EXTRA_CXXFLAGS= # Set to 1 to enable hot/cold linking -USE_PACKAGE:=1 +USE_PACKAGE:=0 # Add libraries you do not wish to include in the cold image here # EXCLUDE_COLD_LIBRARIES:= $(FWDIR)/your_library.a diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 74a4c49..121a94e 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -35,27 +35,22 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { if (line > 2) std::exit(1); printf("is this the problem\n"); - // const std::lock_guard guard(this->mut); + const std::lock_guard guard(this->mut); printf("or is this the problem\n"); if (str.find('\n') != std::string::npos) { TODO("warn instead of throw error if there are too many lines") - printf("1\n"); if (std::ranges::count(str, '\n') > 2) std::exit(1); - printf("2\n"); std::vector strs(3); std::stringstream ss(str); - printf("3\n"); for (int i = line; i < 3; i++) { - printf("iteration %i\n", i); if (!std::getline(ss, strs[i], '\n')) break; } - printf("4\n"); for (uint8_t l = 0; l < 3; l++) { - printf("iteration %i, str: %s, buffer: %s\n", l, strs[l].c_str(), "test"); // currentBuffer[l].value_or("nullopt").c_str()); + printf("iteration %i, str: %s, buffer: %s\n", l, strs[l].c_str(), currentBuffer[l].value_or("nullopt").c_str()); if (!strs[l].empty()) this->currentBuffer[l] = (strs[l]); } return; From 76f1af3431f354aeda571c2e888a9164667aea86 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 25 Sep 2024 20:39:46 -0400 Subject: [PATCH 044/108] feat: :construction: Hot/Cold linking breaks it --- Makefile | 2 +- src/gamepad/screens/defaultScreen.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fbd001f..5fccea8 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ EXTRA_CFLAGS= EXTRA_CXXFLAGS= # Set to 1 to enable hot/cold linking -USE_PACKAGE:=0 +USE_PACKAGE:=0 # this doesnt work with hot/cold linking for some reason # Add libraries you do not wish to include in the cold image here # EXCLUDE_COLD_LIBRARIES:= $(FWDIR)/your_library.a diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 121a94e..c7ddf83 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -34,9 +34,7 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - printf("is this the problem\n"); const std::lock_guard guard(this->mut); - printf("or is this the problem\n"); if (str.find('\n') != std::string::npos) { TODO("warn instead of throw error if there are too many lines") @@ -50,7 +48,6 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { } for (uint8_t l = 0; l < 3; l++) { - printf("iteration %i, str: %s, buffer: %s\n", l, strs[l].c_str(), currentBuffer[l].value_or("nullopt").c_str()); if (!strs[l].empty()) this->currentBuffer[l] = (strs[l]); } return; From 4a70a4a071c841f9693acee6e3fac64d07383e57 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Fri, 27 Sep 2024 16:58:00 +0000 Subject: [PATCH 045/108] fix: :construction: reenable hot-cold --- .devcontainer/Dockerfile | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 1c1b408..1214dab 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ FROM rust:1.67 as builder -RUN git clone https://github.com/vexide/vex-v5-qemu.git /vex-v5-qemu +RUN git clone https://github.com/ion098/vex-v5-qemu.git -b feat/hot-cold --single-branch /vex-v5-qemu WORKDIR /vex-v5-qemu RUN cd packages/kernel; cargo build --target-dir /target/kernel diff --git a/Makefile b/Makefile index 5fccea8..09beb71 100644 --- a/Makefile +++ b/Makefile @@ -17,14 +17,14 @@ EXTRA_CFLAGS= EXTRA_CXXFLAGS= # Set to 1 to enable hot/cold linking -USE_PACKAGE:=0 # this doesnt work with hot/cold linking for some reason +USE_PACKAGE:=1 # this doesnt work with hot/cold linking for some reason # Add libraries you do not wish to include in the cold image here # EXCLUDE_COLD_LIBRARIES:= $(FWDIR)/your_library.a EXCLUDE_COLD_LIBRARIES:= # Set this to 1 to add additional rules to compile your project as a PROS library template -IS_LIBRARY:=0 +IS_LIBRARY:=1 # TODO: CHANGE THIS! LIBNAME:=gamepad VERSION:=0.0.1 From b2e027b5ec909536ff75e657dd123c486a4be52d Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Fri, 27 Sep 2024 21:37:48 +0000 Subject: [PATCH 046/108] fix: :construction: more testing --- Makefile | 2 +- src/main.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 09beb71..10d24a2 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ EXTRA_CFLAGS= EXTRA_CXXFLAGS= # Set to 1 to enable hot/cold linking -USE_PACKAGE:=1 # this doesnt work with hot/cold linking for some reason +USE_PACKAGE:=1 # Add libraries you do not wish to include in the cold image here # EXCLUDE_COLD_LIBRARIES:= $(FWDIR)/your_library.a diff --git a/src/main.cpp b/src/main.cpp index 3f362c4..5ee53d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,5 +63,6 @@ void opcontrol() { gamepad::master.print_line(0, "hello\n\nhi"); pros::delay(25); // Wait for 25 ms, then update the motor values again + exit(1); } } \ No newline at end of file From 075c379444a2ac2486384995c653398fd5a4e49d Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:10:37 +0000 Subject: [PATCH 047/108] fix: :bug: Fix usage of unintialized fields This should fix the data aborts that would occur when running the code. Previously the code would access fields in Gamepad that were uninitialized, leading to the code crashing. --- include/gamepad/gamepad.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 2440f18..21e7a80 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -119,16 +119,16 @@ class Gamepad { void updateScreens(); - std::shared_ptr defaultScreen; - std::vector> screens; - ScreenBuffer currentScreen; - ScreenBuffer nextBuffer; + std::shared_ptr defaultScreen = std::make_shared(); + std::vector> screens{}; + ScreenBuffer currentScreen{}; + ScreenBuffer nextBuffer{}; pros::Controller controller; uint8_t last_printed_line = 0; uint last_print_time = 0; uint last_update_time = 0; - pros::Mutex mut; + pros::Mutex mut{}; }; inline Gamepad Gamepad::master {pros::E_CONTROLLER_MASTER}; From fe7fa7a8b540d4eade9189b576954c33d562977f Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:19:50 -0400 Subject: [PATCH 048/108] fix: :bug: initalize attributes in all classes --- include/gamepad/gamepad.hpp | 27 +++++++++++++---------- include/gamepad/screens/alertScreen.hpp | 20 +++++++++-------- include/gamepad/screens/defaultScreen.hpp | 9 ++++---- src/gamepad/gamepad.cpp | 2 +- src/gamepad/screens/alertScreen.cpp | 4 ++-- src/gamepad/screens/defaultScreen.cpp | 4 ++-- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 2440f18..f8461bd 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -33,21 +33,22 @@ class Gamepad { void update(); /** * Add a screen to the sceen update loop that can update the controller's screen - * + * * @param screen the `AbstractScreen` to add to the screen queue */ void add_screen(std::shared_ptr screen); /** * print a line to the console like pros (low priority) - * + * * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) */ void print_line(uint8_t line, std::string str); /** * makes the controller rumble like pros (low priority) - * - * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + * + * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, + * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. */ void rumble(std::string rumble_pattern); /** @@ -99,7 +100,9 @@ class Gamepad { static Gamepad partner; private: Gamepad(pros::controller_id_e_t id) - : controller(id) {} + : controller(id) { + screens.push_back(defaultScreen); + } Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {}, m_A {}; @@ -114,21 +117,21 @@ class Gamepad { * @return std::string A unique listener name */ static std::string unique_name(); - static Button Gamepad::*button_to_ptr(pros::controller_digital_e_t button); + static Button Gamepad::* button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); - + void updateScreens(); - std::shared_ptr defaultScreen; - std::vector> screens; - ScreenBuffer currentScreen; - ScreenBuffer nextBuffer; + std::shared_ptr defaultScreen {}; + std::vector> screens {}; + ScreenBuffer currentScreen {}; + ScreenBuffer nextBuffer {}; pros::Controller controller; uint8_t last_printed_line = 0; uint last_print_time = 0; uint last_update_time = 0; - pros::Mutex mut; + pros::Mutex mut {}; }; inline Gamepad Gamepad::master {pros::E_CONTROLLER_MASTER}; diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 7446c04..2d6926b 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -12,23 +12,25 @@ namespace gamepad { class AlertScreen : public AbstractScreen { public: - AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} + AlertScreen() + : AbstractScreen(UINT32_MAX - 100) {} + void update(uint delta_time); ScreenBuffer get_screen(std::set visible_lines); + void handle_events(std::set button_events) {} void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); - private: struct AlertBuffer { - ScreenBuffer screen; - uint duration; + ScreenBuffer screen; + uint duration; }; - std::deque screen_buffer{}; - std::optional screen_contents; - uint line_set_time; - pros::Mutex mut; + std::deque screen_buffer {}; + std::optional screen_contents {}; + uint line_set_time = 0; + pros::Mutex mut {}; }; -} +} // namespace gamepad diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index d4e4b98..61ebbe4 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -9,15 +9,14 @@ class DefaultScreen : public AbstractScreen { public: DefaultScreen(); ScreenBuffer get_screen(std::set visible_lines); + void handle_events(std::set button_events) {} void print_line(uint8_t line, std::string str); void rumble(std::string rumble_pattern); - private: - ScreenBuffer currentBuffer; - pros::Mutex mut; - + ScreenBuffer currentBuffer {}; + pros::Mutex mut {}; }; -} +} // namespace gamepad diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index f904194..8199d69 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -2,6 +2,7 @@ #include "gamepad/todo.hpp" #include "pros/misc.h" #include "pros/rtos.hpp" +#include #include #include #include @@ -9,7 +10,6 @@ #include #include #include -#include namespace gamepad { diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 10a17c8..7cba265 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -1,11 +1,11 @@ #include "gamepad/screens/alertScreen.hpp" +#include "gamepad/todo.hpp" +#include "pros/rtos.hpp" #include #include #include #include #include -#include "gamepad/todo.hpp" -#include "pros/rtos.hpp" namespace gamepad { diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 777fb25..a7dbb09 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -1,11 +1,11 @@ #include "gamepad/screens/defaultScreen.hpp" +#include "gamepad/screens/abstractScreen.hpp" +#include "gamepad/todo.hpp" #include #include #include #include #include -#include "abstractScreen.hpp" -#include "gamepad/todo.hpp" namespace gamepad { From 72ecda356a79c97206f446b7f57af91254c410e3 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:29:36 -0400 Subject: [PATCH 049/108] fix: :bug: Fix bug where AbsrtactScreen was not abstract marked most functions in abstractScreen as abstract --- include/gamepad/screens/abstractScreen.hpp | 15 +++++--- src/gamepad/gamepad.cpp | 45 +++++++++------------- src/gamepad/screens/defaultScreen.cpp | 23 +++++------ src/main.cpp | 7 +++- 4 files changed, 43 insertions(+), 47 deletions(-) diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index eb6cbb7..502e546 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -10,16 +10,21 @@ namespace gamepad { /** * @brief type for conveying a full screen with the first 3 being the lines - * of text on the controller screen and the last being a rumble pattern + * of text on the controller screen and the last being a rumble pattern */ typedef std::array, 4> ScreenBuffer; class AbstractScreen { public: - AbstractScreen(uint priority): priority(priority) {} - void update(uint delta_time) {} - ScreenBuffer get_screen(std::set visible_lines) {return {};} - void handle_events(std::set button_events) {} + AbstractScreen(uint priority) + : priority(priority) {} + + virtual void update(uint delta_time) {} + + virtual ScreenBuffer get_screen(std::set visible_lines) = 0; + + virtual void handle_events(std::set button_events) {} + const uint get_priority() { return this->priority; } private: const uint priority; diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 8199d69..46c7eb0 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -11,40 +11,39 @@ #include #include - namespace gamepad { void Gamepad::updateButton(pros::controller_digital_e_t button_id) { - Button Gamepad::*button = Gamepad::button_to_ptr(button_id); + Button Gamepad::* button = Gamepad::button_to_ptr(button_id); bool is_held = this->controller.get_digital(button_id); (this->*button).update(is_held); } - void Gamepad::updateScreens() { // Lock Mutexes for Thread Safety std::lock_guard guard_scheduling(this->mut); // Update all screens and note deltatime - for (int i = 0; i < this->screens.size(); i++) - this->screens[i]->update(pros::millis() - this->last_update_time); + for (int i = 0; i < this->screens.size(); i++) this->screens[i]->update(pros::millis() - this->last_update_time); last_update_time = pros::millis(); // Check if enough time has passed for the Gamepad to poll for updates - if (pros::millis() - this->last_print_time < 50) - return; + if (pros::millis() - this->last_print_time < 50) return; for (int i = 0; i < this->screens.size(); i++) { // get all lines that arent being used by a higher priority screen std::set visible_lines; for (uint8_t j = 0; j < 4; j++) - if (!this->nextBuffer[j].has_value()) - visible_lines.emplace(j); - + if (!this->nextBuffer[j].has_value()) visible_lines.emplace(j); + // get the buffer of the next lower priority screen and set it to be printed ScreenBuffer buffer = this->screens[i]->get_screen(visible_lines); for (uint8_t j = 0; j < 4; j++) - if (buffer[j].has_value() && !nextBuffer[j].has_value()) - nextBuffer[j] = std::move(buffer[j]); + if (buffer[j].has_value() && !nextBuffer[j].has_value()) nextBuffer[j] = std::move(buffer[j]); + + printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), + nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), + nextBuffer.at(3).value_or("nullopt").c_str()); + } for (int i = 1; i <= 4; i++) { @@ -81,28 +80,20 @@ void Gamepad::update() { } void Gamepad::add_screen(std::shared_ptr screen) { - uint last = UINT32_MAX; uint pos = 0; + uint last = UINT32_MAX; + uint pos = 0; for (pos = 0; pos < this->screens.size(); pos++) { - if (this->screens[pos]->get_priority() < screen->get_priority() && last >= screen->get_priority()) - break; + if (this->screens[pos]->get_priority() < screen->get_priority() && last >= screen->get_priority()) break; last = this->screens[pos]->get_priority(); } this->screens.emplace(this->screens.begin() + pos, screen); } -void Gamepad::print_line(uint8_t line, std::string str) { - printf("wrapping print_line(line:%i, string:%s)\n", line, str.c_str()); +void Gamepad::print_line(uint8_t line, std::string str) { this->defaultScreen->print_line(line, str); } - this->defaultScreen->print_line(line, str); -} - -void Gamepad::rumble(std::string rumble_pattern) { - this->defaultScreen->rumble(rumble_pattern); -} +void Gamepad::rumble(std::string rumble_pattern) { this->defaultScreen->rumble(rumble_pattern); } -const Button& Gamepad::operator[](pros::controller_digital_e_t button) { - return this->*Gamepad::button_to_ptr(button); -} +const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } float Gamepad::operator[](pros::controller_analog_e_t axis) { switch (axis) { @@ -122,7 +113,7 @@ std::string Gamepad::unique_name() { return std::to_string(i++) + "_internal"; } -Button Gamepad::*Gamepad::button_to_ptr(pros::controller_digital_e_t button) { +Button Gamepad::* Gamepad::button_to_ptr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; case pros::E_CONTROLLER_DIGITAL_L2: return &Gamepad::m_L2; diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index a7dbb09..2c9a22e 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -7,21 +7,20 @@ #include #include - namespace gamepad { -DefaultScreen::DefaultScreen() : AbstractScreen(1), currentBuffer({}) { - printf("ran constructor\n"); -} +DefaultScreen::DefaultScreen() + : AbstractScreen(1), + currentBuffer({}) {} ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { ScreenBuffer output; - printf("{%s, %s, %s, %s}\n", - currentBuffer.at(0).value_or("nullopt").c_str(), - currentBuffer.at(1).value_or("nullopt").c_str(), - currentBuffer.at(2).value_or("nullopt").c_str(), - currentBuffer.at(3).value_or("nullopt").c_str()); - // const std::lock_guard guard(this->mut); + + printf("currentBuffer = {%s, %s, %s, %s}\n", currentBuffer.at(0).value_or("nullopt").c_str(), + currentBuffer.at(1).value_or("nullopt").c_str(), currentBuffer.at(2).value_or("nullopt").c_str(), + currentBuffer.at(3).value_or("nullopt").c_str()); + + const std::lock_guard guard(this->mut); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { output[*i] = std::move(this->currentBuffer[*i].value_or("")); this->currentBuffer[*i] = std::nullopt; @@ -30,7 +29,6 @@ ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { } void DefaultScreen::print_line(uint8_t line, std::string str) { - printf("print_line(line: %i, string: %s)\n", line, str.c_str()); TODO("change handling for off screen lines") if (line > 2) std::exit(1); @@ -53,7 +51,6 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { return; } - printf("5\n"); this->currentBuffer[line] = std::move(str); } @@ -65,4 +62,4 @@ void DefaultScreen::rumble(std::string rumble_pattern) { this->currentBuffer[3] = std::move(rumble_pattern); } -} \ No newline at end of file +} // namespace gamepad \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5ee53d8..3a7a09d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,8 @@ #include "main.h" #include "gamepad/api.hpp" +#include "gamepad/gamepad.hpp" +#include "pros/misc.h" +#include "pros/misc.hpp" /** * Runs initialization code. This occurs as soon as the program is started. @@ -8,7 +11,7 @@ * to keep execution time for this mode under a few seconds. */ void initialize() { - // Gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); + gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); } /** @@ -56,6 +59,7 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { + pros::Controller controller(pros::E_CONTROLLER_MASTER); while (true) { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); @@ -63,6 +67,5 @@ void opcontrol() { gamepad::master.print_line(0, "hello\n\nhi"); pros::delay(25); // Wait for 25 ms, then update the motor values again - exit(1); } } \ No newline at end of file From d06277a87a6be6e6cd00582bc1ce2a8d2d7cf98d Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:58:26 -0400 Subject: [PATCH 050/108] fix: :bug: fix nullpointers getting turned into empty strings --- include/gamepad/gamepad.hpp | 11 +++++++++++ src/gamepad/gamepad.cpp | 26 +++++++++++++++++++------- src/gamepad/screens/defaultScreen.cpp | 8 ++------ src/main.cpp | 1 - 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index ba0ac91..508d494 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -44,6 +44,17 @@ class Gamepad { * @param str the string to print onto the controller (\n to go to the next line) */ void print_line(uint8_t line, std::string str); + /** + * @brief clears all lines on the controller, similar to the pros function (low priority) + * + */ + void clear(); + /** + * @brief clears the specific line on the controller, similar to the pros function clear_line (low priority) + * + * @param line the line to clear (0-2) + */ + void clear(uint8_t line); /** * makes the controller rumble like pros (low priority) * diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 46c7eb0..35a1117 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -38,17 +38,22 @@ void Gamepad::updateScreens() { // get the buffer of the next lower priority screen and set it to be printed ScreenBuffer buffer = this->screens[i]->get_screen(visible_lines); for (uint8_t j = 0; j < 4; j++) - if (buffer[j].has_value() && !nextBuffer[j].has_value()) nextBuffer[j] = std::move(buffer[j]); - - printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - nextBuffer.at(3).value_or("nullopt").c_str()); - + if (buffer[j].has_value() && !buffer[j]->empty() && !nextBuffer[j].has_value()) + nextBuffer[j] = std::move(buffer[j]); } - for (int i = 1; i <= 4; i++) { + for (int i = 0; i < 4; i++) { // start from the line thats after the line thats been set so we dont get stuck setting the first line int line = (this->last_printed_line + i) % 4; + printf("Line = %i\n", line); + + printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), + nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), + nextBuffer.at(3).value_or("nullopt").c_str()); + + printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), + currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), + currentScreen.at(3).value_or("nullopt").c_str()); // text on screen is the same as last frame's text so no use updating if (this->currentScreen[line] == this->nextBuffer[line] && line != 3) { @@ -64,6 +69,9 @@ void Gamepad::updateScreens() { this->last_printed_line = line; this->last_print_time = pros::millis(); } + + // just to make the cycle more regular + this->last_printed_line = 0; } void Gamepad::update() { @@ -91,6 +99,10 @@ void Gamepad::add_screen(std::shared_ptr screen) { void Gamepad::print_line(uint8_t line, std::string str) { this->defaultScreen->print_line(line, str); } +void Gamepad::clear() { this->defaultScreen->print_line(0, " \n \n "); } + +void Gamepad::clear(uint8_t line) { this->defaultScreen->print_line(line, " "); } + void Gamepad::rumble(std::string rumble_pattern) { this->defaultScreen->rumble(rumble_pattern); } const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 2c9a22e..57110be 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -15,14 +15,10 @@ DefaultScreen::DefaultScreen() ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { ScreenBuffer output; - - printf("currentBuffer = {%s, %s, %s, %s}\n", currentBuffer.at(0).value_or("nullopt").c_str(), - currentBuffer.at(1).value_or("nullopt").c_str(), currentBuffer.at(2).value_or("nullopt").c_str(), - currentBuffer.at(3).value_or("nullopt").c_str()); - const std::lock_guard guard(this->mut); + for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { - output[*i] = std::move(this->currentBuffer[*i].value_or("")); + output[*i] = std::move(this->currentBuffer[*i]); this->currentBuffer[*i] = std::nullopt; } return output; diff --git a/src/main.cpp b/src/main.cpp index 3a7a09d..d172ff8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,7 +59,6 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { - pros::Controller controller(pros::E_CONTROLLER_MASTER); while (true) { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); From c3570385c02d87d96400ba47a18355ad0fef6264 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:12:21 -0400 Subject: [PATCH 051/108] fix: :bug: multiples line changes not registering needed to return after writing to a line, and also removed debug statements --- include/gamepad/gamepad.hpp | 1 + src/gamepad/gamepad.cpp | 20 +++++++++----------- src/main.cpp | 16 ++++++++++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 508d494..a42216f 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -142,6 +142,7 @@ class Gamepad { uint8_t last_printed_line = 0; uint last_print_time = 0; uint last_update_time = 0; + bool screenCleared = true; pros::Mutex mut {}; }; diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 35a1117..3ab9020 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -27,7 +27,7 @@ void Gamepad::updateScreens() { last_update_time = pros::millis(); // Check if enough time has passed for the Gamepad to poll for updates - if (pros::millis() - this->last_print_time < 50) return; + if (pros::millis() - this->last_print_time <= 50) return; for (int i = 0; i < this->screens.size(); i++) { // get all lines that arent being used by a higher priority screen @@ -45,15 +45,15 @@ void Gamepad::updateScreens() { for (int i = 0; i < 4; i++) { // start from the line thats after the line thats been set so we dont get stuck setting the first line int line = (this->last_printed_line + i) % 4; - printf("Line = %i\n", line); - printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - nextBuffer.at(3).value_or("nullopt").c_str()); + // theres nothing on this line so we can skip it + if (!this->nextBuffer[line].has_value()) continue; - printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), - currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), - currentScreen.at(3).value_or("nullopt").c_str()); + if (!this->screenCleared) { + this->controller.clear(); + this->last_print_time = pros::millis(); + return; + } // text on screen is the same as last frame's text so no use updating if (this->currentScreen[line] == this->nextBuffer[line] && line != 3) { @@ -68,10 +68,8 @@ void Gamepad::updateScreens() { this->nextBuffer[line] = std::nullopt; this->last_printed_line = line; this->last_print_time = pros::millis(); + return; } - - // just to make the cycle more regular - this->last_printed_line = 0; } void Gamepad::update() { diff --git a/src/main.cpp b/src/main.cpp index d172ff8..4b57db6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,12 @@ #include "main.h" #include "gamepad/api.hpp" #include "gamepad/gamepad.hpp" -#include "pros/misc.h" -#include "pros/misc.hpp" +#include "gamepad/screens/alertScreen.hpp" +#include "pros/rtos.hpp" +#include +#include + +std::shared_ptr alerts{}; /** * Runs initialization code. This occurs as soon as the program is started. @@ -11,7 +15,13 @@ * to keep execution time for this mode under a few seconds. */ void initialize() { + gamepad::master.add_screen(alerts); + gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant\nalert", 3000, "-.-"); }); + gamepad::master.B.onPress( + "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); + gamepad::master.Y.onPress("print1", []() { gamepad::master.print_line(1, "this should be cleared"); }); + gamepad::master.Y.onRelease("clear1", []() { gamepad::master.clear(1); }); } /** @@ -63,8 +73,6 @@ void opcontrol() { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); - gamepad::master.print_line(0, "hello\n\nhi"); - pros::delay(25); // Wait for 25 ms, then update the motor values again } } \ No newline at end of file From a1c3f15e862ee86df9a63865e2c47471f5b69c50 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 12 Oct 2024 10:38:32 -0400 Subject: [PATCH 052/108] fix: :bug: screen not being cleared first print i initialized screen cleared to the wrong value, and i forgot to clear it --- include/gamepad/gamepad.hpp | 4 ++-- include/gamepad/screens/abstractScreen.hpp | 8 ++++---- include/gamepad/screens/alertScreen.hpp | 2 -- include/gamepad/screens/defaultScreen.hpp | 6 +++--- src/gamepad/gamepad.cpp | 3 ++- src/gamepad/screens/defaultScreen.cpp | 4 ---- src/main.cpp | 6 ++++-- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index a42216f..5f55367 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -112,7 +112,7 @@ class Gamepad { private: Gamepad(pros::controller_id_e_t id) : controller(id) { - screens.push_back(defaultScreen); + this->add_screen(defaultScreen); } Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {}, @@ -142,7 +142,7 @@ class Gamepad { uint8_t last_printed_line = 0; uint last_print_time = 0; uint last_update_time = 0; - bool screenCleared = true; + bool screenCleared = false; pros::Mutex mut {}; }; diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 502e546..10638f0 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "pros/misc.h" namespace gamepad { @@ -16,8 +17,7 @@ typedef std::array, 4> ScreenBuffer; class AbstractScreen { public: - AbstractScreen(uint priority) - : priority(priority) {} + AbstractScreen(uint priority) : priority(priority) {} virtual void update(uint delta_time) {} @@ -25,8 +25,8 @@ class AbstractScreen { virtual void handle_events(std::set button_events) {} - const uint get_priority() { return this->priority; } - private: + uint get_priority() { return this->priority; } + protected: const uint priority; }; diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 2d6926b..7656eaf 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -18,8 +18,6 @@ class AlertScreen : public AbstractScreen { void update(uint delta_time); ScreenBuffer get_screen(std::set visible_lines); - void handle_events(std::set button_events) {} - void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 61ebbe4..ad62a1c 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -7,10 +7,10 @@ namespace gamepad { class DefaultScreen : public AbstractScreen { public: - DefaultScreen(); - ScreenBuffer get_screen(std::set visible_lines); + DefaultScreen() + : AbstractScreen(1) {} - void handle_events(std::set button_events) {} + ScreenBuffer get_screen(std::set visible_lines); void print_line(uint8_t line, std::string str); void rumble(std::string rumble_pattern); diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 3ab9020..1333b25 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -49,8 +49,9 @@ void Gamepad::updateScreens() { // theres nothing on this line so we can skip it if (!this->nextBuffer[line].has_value()) continue; - if (!this->screenCleared) { + if (!this->screenCleared && line != 3) { this->controller.clear(); + screenCleared = true; this->last_print_time = pros::millis(); return; } diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 57110be..1afd516 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -9,10 +9,6 @@ namespace gamepad { -DefaultScreen::DefaultScreen() - : AbstractScreen(1), - currentBuffer({}) {} - ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { ScreenBuffer output; const std::lock_guard guard(this->mut); diff --git a/src/main.cpp b/src/main.cpp index 4b57db6..2447f38 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "gamepad/gamepad.hpp" #include "gamepad/screens/alertScreen.hpp" #include "pros/rtos.hpp" +#include #include #include @@ -15,8 +16,9 @@ std::shared_ptr alerts{}; * to keep execution time for this mode under a few seconds. */ void initialize() { - gamepad::master.add_screen(alerts); - gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant\nalert", 3000, "-.-"); }); + printf("alert priority: %i\n", alerts->get_priority()); + // gamepad::master.add_screen(alerts); + // gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant\nalert", 3000, "-.-"); }); gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); From dd06cda254dbf4aec4525af09df2b4bd79c04d0f Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 12 Oct 2024 11:23:07 -0400 Subject: [PATCH 053/108] chore: :poop: get_priority is the problem, idk why --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 2447f38..56488d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ std::shared_ptr alerts{}; void initialize() { printf("alert priority: %i\n", alerts->get_priority()); // gamepad::master.add_screen(alerts); - // gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant\nalert", 3000, "-.-"); }); + // gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant alert\nat " + pros::millis() + "ms", 3000, "-.-"); }); gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); From 82c0937c336594bb6994995a5ac210123911f1ad Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:47:15 -0400 Subject: [PATCH 054/108] test: :sparkles: the alerts are kinda working the logic in the abstract screen seems weird based on the behavior --- include/gamepad/gamepad.hpp | 4 ++-- include/gamepad/screens/abstractScreen.hpp | 3 ++- src/gamepad/screens/alertScreen.cpp | 11 ++++------- src/main.cpp | 9 +++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 5f55367..52701f5 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -46,12 +46,12 @@ class Gamepad { void print_line(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) - * + * */ void clear(); /** * @brief clears the specific line on the controller, similar to the pros function clear_line (low priority) - * + * * @param line the line to clear (0-2) */ void clear(uint8_t line); diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 10638f0..0d4f749 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -17,7 +17,8 @@ typedef std::array, 4> ScreenBuffer; class AbstractScreen { public: - AbstractScreen(uint priority) : priority(priority) {} + AbstractScreen(uint priority) + : priority(priority) {} virtual void update(uint delta_time) {} diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 7cba265..c8dae93 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -13,7 +13,7 @@ ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { std::lock_guard guard(this->mut); if (this->screen_contents.has_value()) return this->screen_contents->screen; if (this->screen_buffer.size() < 1) return ScreenBuffer(); - + for (uint8_t i = 0; i < 4; i++) { if (!this->screen_buffer[0].screen[i].has_value()) continue; if (this->screen_buffer[0].screen[i].has_value() && !visible_lines.contains(i)) return ScreenBuffer(); @@ -22,13 +22,11 @@ ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { this->screen_buffer.pop_front(); this->line_set_time = pros::millis(); return this->screen_contents->screen; - } void AlertScreen::update(uint delta_time) { std::lock_guard guard(this->mut); - if (pros::millis() - this->line_set_time >= this->screen_contents->duration) - this->screen_contents = std::nullopt; + if (pros::millis() - this->line_set_time >= this->screen_contents->duration) this->screen_contents = std::nullopt; } void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { @@ -46,8 +44,7 @@ void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, s if (!std::getline(ss, strs[i], '\n')) break; } - - ScreenBuffer buffer; + ScreenBuffer buffer; if (strs[0] != "") buffer[0] = std::move(strs[0]); if (strs[1] != "") buffer[1] = std::move(strs[1]); @@ -58,4 +55,4 @@ void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, s this->screen_buffer.push_back({buffer, duration}); } -} +} // namespace gamepad diff --git a/src/main.cpp b/src/main.cpp index 56488d8..8499e08 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,7 +7,7 @@ #include #include -std::shared_ptr alerts{}; +std::shared_ptr alerts = std::make_shared(); /** * Runs initialization code. This occurs as soon as the program is started. @@ -16,9 +16,10 @@ std::shared_ptr alerts{}; * to keep execution time for this mode under a few seconds. */ void initialize() { - printf("alert priority: %i\n", alerts->get_priority()); - // gamepad::master.add_screen(alerts); - // gamepad::master.A.onPress("alert", []() { alerts->add_alerts(0, "a very\nimportant alert\nat " + pros::millis() + "ms", 3000, "-.-"); }); + printf("alert priority: %u\n", alerts->get_priority()); + gamepad::master.add_screen(alerts); + gamepad::master.A.onPress( + "alert", []() { alerts->add_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); }); gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); From b1e4093bf618443a57ff63b0f861e8f3b7701675 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 13 Oct 2024 08:41:34 -0400 Subject: [PATCH 055/108] fix: :bug: repeated alert rumbles rumbles in alerts were being repeated constantly for the duration of the alert, i had to clear it after 1 iteration --- src/gamepad/gamepad.cpp | 10 ++++++++++ src/gamepad/screens/alertScreen.cpp | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 1333b25..9a26c50 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -62,6 +62,16 @@ void Gamepad::updateScreens() { continue; } + printf("Line = %i\n", line); + + printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), + nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), + nextBuffer.at(3).value_or("nullopt").c_str()); + + // printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), + // currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), + // currentScreen.at(3).value_or("nullopt").c_str()); + // print to screen or rumble if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index c8dae93..a8ea556 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -11,7 +11,10 @@ namespace gamepad { ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { std::lock_guard guard(this->mut); - if (this->screen_contents.has_value()) return this->screen_contents->screen; + if (this->screen_contents.has_value()) { + this->screen_contents->screen.at(3) = std::nullopt; + return this->screen_contents->screen; + } if (this->screen_buffer.size() < 1) return ScreenBuffer(); for (uint8_t i = 0; i < 4; i++) { From aa4904d486059fc3092e2f0055fb90dc50878c07 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 13 Oct 2024 08:42:11 -0400 Subject: [PATCH 056/108] chore: :fire: remove debug prints --- src/gamepad/gamepad.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 9a26c50..1333b25 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -62,16 +62,6 @@ void Gamepad::updateScreens() { continue; } - printf("Line = %i\n", line); - - printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - nextBuffer.at(3).value_or("nullopt").c_str()); - - // printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), - // currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), - // currentScreen.at(3).value_or("nullopt").c_str()); - // print to screen or rumble if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); From 993960fab6a6ce465ef0e217d6c2c1b47503a237 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 13 Oct 2024 08:42:11 -0400 Subject: [PATCH 057/108] chore: :fire: remove debug prints --- src/gamepad/gamepad.cpp | 10 ---------- src/main.cpp | 1 - 2 files changed, 11 deletions(-) diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 9a26c50..1333b25 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -62,16 +62,6 @@ void Gamepad::updateScreens() { continue; } - printf("Line = %i\n", line); - - printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - nextBuffer.at(3).value_or("nullopt").c_str()); - - // printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), - // currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), - // currentScreen.at(3).value_or("nullopt").c_str()); - // print to screen or rumble if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); diff --git a/src/main.cpp b/src/main.cpp index 8499e08..c15ccc6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,6 @@ std::shared_ptr alerts = std::make_sharedget_priority()); gamepad::master.add_screen(alerts); gamepad::master.A.onPress( "alert", []() { alerts->add_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); }); From a5f29cb33a99ded3d48735fe14512d7318868063 Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 13 Oct 2024 09:02:35 -0400 Subject: [PATCH 058/108] refactor: :art: run clang-format --- src/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c15ccc6..c168570 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,8 +17,9 @@ std::shared_ptr alerts = std::make_sharedadd_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); }); + gamepad::master.A.onPress("alert", []() { + alerts->add_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); + }); gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); From 85be74a00939fda5618dffb039b10e5632d6c87a Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:22:00 -0400 Subject: [PATCH 059/108] feat: :sparkles: disconnect/reconnect logic still bugged, debug prints are included however commented out --- src/gamepad/gamepad.cpp | 46 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 1333b25..eb593c7 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -22,9 +22,35 @@ void Gamepad::updateScreens() { // Lock Mutexes for Thread Safety std::lock_guard guard_scheduling(this->mut); + // Disable screen updates if the controller is disconnected + if (!this->controller.is_connected()) { + if (this->screenCleared) { + // printf("disconnected\n"); + + this->nextBuffer = std::move(this->currentScreen); + this->currentScreen = {}; + this->screenCleared = false; + } + return; + } + + // Clear current screen and reset last update time on reconnect + if (this->controller.is_connected() && !screenCleared) { + // printf("reconnected\n"); + + this->currentScreen = {}; + this->last_update_time = pros::millis(); + + // printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), + // nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), + // nextBuffer.at(3).value_or("nullopt").c_str()); + } + // Update all screens and note deltatime - for (int i = 0; i < this->screens.size(); i++) this->screens[i]->update(pros::millis() - this->last_update_time); - last_update_time = pros::millis(); + for (int i = 0; i < this->screens.size(); i++) { + this->screens[i]->update(pros::millis() - this->last_update_time); + } + this->last_update_time = pros::millis(); // Check if enough time has passed for the Gamepad to poll for updates if (pros::millis() - this->last_print_time <= 50) return; @@ -50,8 +76,10 @@ void Gamepad::updateScreens() { if (!this->nextBuffer[line].has_value()) continue; if (!this->screenCleared && line != 3) { + // printf("clearing screen for init\n"); this->controller.clear(); - screenCleared = true; + this->screenCleared = true; + this->currentScreen = {}; this->last_print_time = pros::millis(); return; } @@ -62,10 +90,20 @@ void Gamepad::updateScreens() { continue; } + // printf("\nLine = %i\n", line); + + // printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), + // nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), + // nextBuffer.at(3).value_or("nullopt").c_str()); + + // printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), + // currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), + // currentScreen.at(3).value_or("nullopt").c_str()); + // print to screen or rumble if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); - this->currentScreen[line] = std::move(this->nextBuffer[line]); + if (line != 3) this->currentScreen[line] = std::move(this->nextBuffer[line]); this->nextBuffer[line] = std::nullopt; this->last_printed_line = line; this->last_print_time = pros::millis(); From e22f373c1b8cf3a3caa77c87d67c4cfd9021c83d Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:20:52 -0700 Subject: [PATCH 060/108] ci: :green_heart: Upload template zip on build --- .github/workflows/pros-build.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pros-build.yml b/.github/workflows/pros-build.yml index 88566b5..d34f97d 100644 --- a/.github/workflows/pros-build.yml +++ b/.github/workflows/pros-build.yml @@ -12,7 +12,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: LemLib/pros-build@v2.0.2 + - name: Checkout Code + uses: actions/checkout@v4 + - name: Build Template + id: build_step + uses: LemLib/pros-build@v2.0.2 with: - library-path: gamepad + lib_folder_name: "gamepad" + copy_readme_and_license_to_include: true + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build_step.outputs.name }} + path: ${{ github.workspace }}/template/* From 640015551fab15d8adf15ad2350d8db12334f13f Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:21:43 -0700 Subject: [PATCH 061/108] ci: :construction_worker: Build and upload template on release --- .github/workflows/pros-build-release.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/pros-build-release.yml diff --git a/.github/workflows/pros-build-release.yml b/.github/workflows/pros-build-release.yml new file mode 100644 index 0000000..301a532 --- /dev/null +++ b/.github/workflows/pros-build-release.yml @@ -0,0 +1,24 @@ +name: Build Release + +on: + release: + types: [published] + +jobs: + build-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + - name: Build Template + id: build_step + uses: LemLib/pros-build@v2.0.2 + with: + lib_folder_name: "gamepad" + copy_readme_and_license_to_include: true + no_commit_hash: true + - name: Upload Template To Release + uses: svenstaro/upload-release-action@v2 + with: + file: ${{ github.workspace }}/${{ steps.build_step.outputs.name }} From ae8555444c81456c1e2c503cc8df5bcb0c00bcaa Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 29 Oct 2024 09:29:15 -0700 Subject: [PATCH 062/108] fix: :pencil2: remove merge conflict markers --- include/gamepad/event_handler.hpp | 45 ------------------------------- 1 file changed, 45 deletions(-) diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index 77706a6..bf51b20 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -9,38 +9,6 @@ namespace gamepad::_impl { -<<<<<<< HEAD -class MonotonicCounter { - template friend class EventHandler; - - static uint32_t next_value() { - static std::atomic counter = 0; - return ++counter; - } -}; - -template class EventHandler { - public: - using Listener = std::function; - - uint32_t add_listener(Listener func) { - std::lock_guard lock(mutex); - uint32_t id = MonotonicCounter::next_value(); - listeners.emplace(id, std::move(func)); - return id; - } - - bool remove_listener(uint32_t id) { - std::lock_guard lock(mutex); - if (listeners.find(id) == listeners.end()) { - TODO("change handling maybe?") - return false; - } - listeners.erase(id); - return true; - } - -======= /** * @brief Event handling class with thread safety that supports adding, removing, and running listeners * @@ -91,23 +59,11 @@ template class EventHandler { * @return true There are listeners registered * @return false There are no listeners registered */ ->>>>>>> b19f6224e83dcbbf6f3b02059fa6d64b57af4ac8 bool is_empty() { std::lock_guard lock(mutex); return listeners.empty(); } -<<<<<<< HEAD - void fire(Args... args) { - std::lock_guard lock(mutex); - for (auto listener : listeners) { listener.second(args...); } - } - private: - std::map listeners; - pros::Mutex mutex; -}; -} // namespace Gamepad -======= /** * @brief Runs each listener registered * @@ -123,4 +79,3 @@ template class EventHandler { gamepad::_impl::RecursiveMutex mutex {}; }; } // namespace gamepad::_impl ->>>>>>> b19f6224e83dcbbf6f3b02059fa6d64b57af4ac8 From 982c53b66ceabb84c4e16b83159559247ed9c50e Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:29:15 +0000 Subject: [PATCH 063/108] fix: :bug: Fix compile errors from merging --- include/gamepad/controller.hpp | 1 + include/gamepad/drive_curve.hpp | 4 ++-- src/gamepad/controller.cpp | 16 ++++++++-------- src/gamepad/drive_curve.cpp | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index be76313..5716083 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -4,6 +4,7 @@ #include #include #include "button.hpp" +#include "drive_curve.hpp" #include "pros/misc.hpp" namespace gamepad { diff --git a/include/gamepad/drive_curve.hpp b/include/gamepad/drive_curve.hpp index 8d9c80a..26e5e7e 100644 --- a/include/gamepad/drive_curve.hpp +++ b/include/gamepad/drive_curve.hpp @@ -1,6 +1,6 @@ #pragma once -namespace Gamepad { +namespace gamepad { /** * @brief abstract DriveCurve class @@ -72,4 +72,4 @@ class ExpoDriveCurve : public DriveCurve { const float minOutput = 0; const float curveGain = 1; }; -} // namespace Gamepad \ No newline at end of file +} // namespace gamepad \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index c33a913..acf770b 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -17,13 +17,13 @@ void Gamepad::update() { } this->m_LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X); - if (this->CurveLeftX) this->LeftX = this->CurveLeftX->curve(this->LeftX); + if (this->CurveLeftX) this->m_LeftX = this->CurveLeftX->curve(this->LeftX); this->m_LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y); - if (this->CurveLeftY) this->LeftY = this->CurveLeftY->curve(this->LeftY); + if (this->CurveLeftY) this->m_LeftY = this->CurveLeftY->curve(this->LeftY); this->m_RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X); - if (this->CurveRightX) this->RightX = this->CurveRightX->curve(this->RightX); + if (this->CurveRightX) this->m_RightX = this->CurveRightX->curve(this->RightX); this->m_RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y); - if (this->CurveRightY) this->RightY = this->CurveRightY->curve(this->RightY); + if (this->CurveRightY) this->m_RightY = this->CurveRightY->curve(this->RightY); } const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } @@ -48,10 +48,10 @@ std::string Gamepad::unique_name() { void Gamepad::setCurve(pros::controller_analog_e_t axis, std::shared_ptr curve) { switch (axis) { - case ANALOG_LEFT_X: this->CurveLeftX = curve; - case ANALOG_LEFT_Y: this->CurveLeftY = curve; - case ANALOG_RIGHT_X: this->CurveRightX = curve; - case ANALOG_RIGHT_Y: this->CurveRightY = curve; + case pros::E_CONTROLLER_ANALOG_LEFT_X: this->CurveLeftX = curve; + case pros::E_CONTROLLER_ANALOG_LEFT_Y: this->CurveLeftY = curve; + case pros::E_CONTROLLER_ANALOG_RIGHT_X: this->CurveRightX = curve; + case pros::E_CONTROLLER_ANALOG_RIGHT_Y: this->CurveRightY = curve; default: TODO("add error logging") errno = EINVAL; diff --git a/src/gamepad/drive_curve.cpp b/src/gamepad/drive_curve.cpp index 2d4f17a..dac1875 100644 --- a/src/gamepad/drive_curve.cpp +++ b/src/gamepad/drive_curve.cpp @@ -1,7 +1,7 @@ #include "gamepad/drive_curve.hpp" #include -namespace Gamepad { +namespace gamepad { ExpoDriveCurve::ExpoDriveCurve(float minOutput, float curve) : minOutput(minOutput), curveGain(curve) {} @@ -13,4 +13,4 @@ float ExpoDriveCurve::curve(float input) { const float i = std::copysign(std::pow(curveGain, g - 127) * g, input); return (127.0 - minOutput) / (127) * i + std::copysign(minOutput, input); } -} // namespace Gamepad \ No newline at end of file +} // namespace gamepad \ No newline at end of file From e7f749580c3620d63e3d4b40959ceed8289111d4 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:53:10 +0000 Subject: [PATCH 064/108] refactor: :construction: Start work on joystick modifier classes --- include/gamepad/controller.hpp | 58 ++++++++++++--------- include/gamepad/drive_curve.hpp | 75 --------------------------- include/gamepad/joystick_modifier.hpp | 69 ++++++++++++++++++++++++ src/gamepad/controller.cpp | 28 ++-------- src/gamepad/drive_curve.cpp | 16 ------ src/gamepad/joystick_modifier.cpp | 35 +++++++++++++ src/main.cpp | 24 ++++----- 7 files changed, 154 insertions(+), 151 deletions(-) delete mode 100644 include/gamepad/drive_curve.hpp create mode 100644 include/gamepad/joystick_modifier.hpp delete mode 100644 src/gamepad/drive_curve.cpp create mode 100644 src/gamepad/joystick_modifier.cpp diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 5716083..e44ae58 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -2,9 +2,8 @@ #include "pros/misc.h" #include -#include #include "button.hpp" -#include "drive_curve.hpp" +#include "joystick_modifier.hpp" #include "pros/misc.hpp" namespace gamepad { @@ -54,24 +53,39 @@ class Gamepad { * */ float operator[](pros::controller_analog_e_t joystick); - void setCurve(pros::controller_analog_e_t joystick, std::shared_ptr curve); - void setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve); - const Button& L1 {m_L1}; - const Button& L2 {m_L2}; - const Button& R1 {m_R1}; - const Button& R2 {m_R2}; - const Button& Up {m_Up}; - const Button& Down {m_Down}; - const Button& Left {m_Left}; - const Button& Right {m_Right}; - const Button& X {m_X}; - const Button& B {m_B}; - const Button& Y {m_Y}; - const Button& A {m_A}; - const float& LeftX = m_LeftX; - const float& LeftY = m_LeftY; - const float& RightX = m_RightX; - const float& RightY = m_RightY; + + const Button& L1() { return m_L1; } + + const Button& L2() { return m_L2; } + + const Button& R1() { return m_R1; } + + const Button& R2() { return m_R2; } + + const Button& Up() { return m_Up; } + + const Button& Down() { return m_Down; } + + const Button& Left() { return m_Left; } + + const Button& Right() { return m_Right; } + + const Button& X() { return m_X; } + + const Button& B() { return m_B; } + + const Button& Y() { return m_Y; } + + const Button& A() { return m_A; } + + float LeftX() { return m_LeftX; } + + float LeftY() { return m_LeftY; } + + float RightX() { return m_RightX; } + + float RightY() { return m_RightY; } + /// The master controller, same as @ref gamepad::master static Gamepad master; /// The partner controller, same as @ref gamepad::partner @@ -83,10 +97,6 @@ class Gamepad { Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {}, m_A {}; float m_LeftX = 0, m_LeftY = 0, m_RightX = 0, m_RightY = 0; - std::shared_ptr CurveLeftX {nullptr}; - std::shared_ptr CurveLeftY {nullptr}; - std::shared_ptr CurveRightX {nullptr}; - std::shared_ptr CurveRightY {nullptr}; Button Fake {}; /** * @brief Gets a unique name for a listener that will not conflict with user listener names. diff --git a/include/gamepad/drive_curve.hpp b/include/gamepad/drive_curve.hpp deleted file mode 100644 index 26e5e7e..0000000 --- a/include/gamepad/drive_curve.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -namespace gamepad { - -/** - * @brief abstract DriveCurve class - * - * This is an abstract class to enable users to provide their own, custom drive - * curves for LemLib to use. - */ -class DriveCurve { - public: - /** - * @brief Processes an input and returns an output - * - * This is a pure virtual function that needs to be overriden by child classes - * - * @param input the input to process - * @return float output - */ - virtual float curve(float input) = 0; -}; - -/** - * @brief ExpoDriveCurve class. Inherits from the DriveCurve class. This is a exponential drive curve. - * - * see https://www.desmos.com/calculator/umicbymbnl for an interactive graph - * see https://www.vexforum.com/t/expo-drive-lemlibs-implementation for a detailed explanation - */ -class ExpoDriveCurve : public DriveCurve { - public: - /** - * @brief Construct a new Expo Drive Curve object - * - * see https://www.desmos.com/calculator/umicbymbnl for an interactive graph - * see https://www.vexforum.com/t/expo-drive-lemlibs-implementation for a detailed explanation - * - * @param minOutput the minimum output that can be returned - * @param curve how "curved" the graph is - * - * @b Example - * @code {.cpp} - * // create a new exponential drive curve - * // controller deadband is set to 5 - * // minimum output is set to 12 - * // curve gain is set to 1.132 - * lemlib::ExpoDriveCurve driveCurve(5, 12, 1.132); - * @endcode - */ - ExpoDriveCurve(float minOutput, float curve); - /** - * @brief curve an input - * - * @param input the input to curve - * @return float the curved output - * - * @b Example - * @code {.cpp} - * void opcontrol() { - * // create a new exponential drive curve - * lemlib::ExpoDriveCurve driveCurve(5, 12, 1.132); - * // input 4 - * std::cout << driveCurve.curve(4) << std::endl; // outputs 0 because input is within deadzone - * // input 6 - * std::cout << driveCurve.curve(6) << std::endl; // outputs 12, the minimum output - * std::cout << driveCurve.curve(127) << std::endl; // outputs 127, the maximum output - * } - * @endcode - */ - float curve(float input); - private: - const float minOutput = 0; - const float curveGain = 1; -}; -} // namespace gamepad \ No newline at end of file diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp new file mode 100644 index 0000000..c3c6259 --- /dev/null +++ b/include/gamepad/joystick_modifier.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +namespace gamepad { +class AbstractTransformation { + public: + virtual std::pair get_value(std::pair) = 0; + virtual ~AbstractTransformation() = default; +}; + +class Deadband : public AbstractTransformation { + public: + Deadband(float x_deadband, float y_deadband, float x_spread, float y_spread) + : m_x_deadband(x_deadband), + m_y_deadband(y_deadband), + m_x_spread(x_spread), + m_y_spread(y_spread) {} + + Deadband(float x_deadband, float y_deadband) + : Deadband(x_deadband, y_deadband, 0.0, 0.0) {} + + std::pair get_value(std::pair) override; + private: + float m_x_deadband; + float m_y_deadband; + float m_x_spread; + float m_y_spread; +}; + +class ExpoCurve : public AbstractTransformation { + public: + ExpoCurve(float x_curve, float y_curve) + : m_x_curve(x_curve), + m_y_curve(y_curve) {} + + std::pair get_value(std::pair) override; + private: + float m_x_curve; + float m_y_curve; +}; + +class Transformation final { + friend class TransformationBuilder; + public: + std::pair get_value(std::pair); + private: + std::vector> m_all_transforms; +}; + +class TransformationBuilder final { + public: + template T> TransformationBuilder(T first) { + m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); + } + + TransformationBuilder() = delete; + + template T> TransformationBuilder& and_then(T next) { + m_transform.m_all_transforms.push_back(std::make_unique(std::move(next))); + return *this; + } + private: + Transformation m_transform {}; +}; +} // namespace gamepad \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index acf770b..354bc74 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -17,23 +17,19 @@ void Gamepad::update() { } this->m_LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X); - if (this->CurveLeftX) this->m_LeftX = this->CurveLeftX->curve(this->LeftX); this->m_LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y); - if (this->CurveLeftY) this->m_LeftY = this->CurveLeftY->curve(this->LeftY); this->m_RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X); - if (this->CurveRightX) this->m_RightX = this->CurveRightX->curve(this->RightX); this->m_RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y); - if (this->CurveRightY) this->m_RightY = this->CurveRightY->curve(this->RightY); } const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } float Gamepad::operator[](pros::controller_analog_e_t axis) { switch (axis) { - case pros::E_CONTROLLER_ANALOG_LEFT_X: return this->LeftX; - case pros::E_CONTROLLER_ANALOG_LEFT_Y: return this->LeftY; - case pros::E_CONTROLLER_ANALOG_RIGHT_X: return this->RightX; - case pros::E_CONTROLLER_ANALOG_RIGHT_Y: return this->RightY; + case pros::E_CONTROLLER_ANALOG_LEFT_X: return m_LeftX; + case pros::E_CONTROLLER_ANALOG_LEFT_Y: return m_LeftY; + case pros::E_CONTROLLER_ANALOG_RIGHT_X: return m_RightX; + case pros::E_CONTROLLER_ANALOG_RIGHT_Y: return m_RightY; default: TODO("add error logging") errno = EINVAL; @@ -46,22 +42,6 @@ std::string Gamepad::unique_name() { return std::to_string(i++) + "_internal"; } -void Gamepad::setCurve(pros::controller_analog_e_t axis, std::shared_ptr curve) { - switch (axis) { - case pros::E_CONTROLLER_ANALOG_LEFT_X: this->CurveLeftX = curve; - case pros::E_CONTROLLER_ANALOG_LEFT_Y: this->CurveLeftY = curve; - case pros::E_CONTROLLER_ANALOG_RIGHT_X: this->CurveRightX = curve; - case pros::E_CONTROLLER_ANALOG_RIGHT_Y: this->CurveRightY = curve; - default: - TODO("add error logging") - errno = EINVAL; - } -} - -void Gamepad::setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve) { - this->setCurve(joystick, std::shared_ptr(&curve, [](void*) {})); -} - Button Gamepad::*Gamepad::button_to_ptr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; diff --git a/src/gamepad/drive_curve.cpp b/src/gamepad/drive_curve.cpp deleted file mode 100644 index dac1875..0000000 --- a/src/gamepad/drive_curve.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "gamepad/drive_curve.hpp" -#include - -namespace gamepad { -ExpoDriveCurve::ExpoDriveCurve(float minOutput, float curve) : - minOutput(minOutput), - curveGain(curve) {} - -float ExpoDriveCurve::curve(float input) { - // g is the output of g(x) as defined in the Desmos graph - const float g = std::abs(input); - // i is the output of i(x) as defined in the Desmos graph - const float i = std::copysign(std::pow(curveGain, g - 127) * g, input); - return (127.0 - minOutput) / (127) * i + std::copysign(minOutput, input); -} -} // namespace gamepad \ No newline at end of file diff --git a/src/gamepad/joystick_modifier.cpp b/src/gamepad/joystick_modifier.cpp new file mode 100644 index 0000000..1741acf --- /dev/null +++ b/src/gamepad/joystick_modifier.cpp @@ -0,0 +1,35 @@ +#include "joystick_modifier.hpp" +#include +#include + +using std::abs; +using std::copysign; +using std::pow; + +namespace gamepad { +std::pair Deadband::get_value(std::pair value) { + float x = value.first; + float y = value.second; + float x_deadband = m_x_deadband + abs(y) * m_x_spread; + float y_deadband = m_y_deadband + abs(x) * m_y_spread; + float x_scale = 1 - x_deadband; + float y_scale = 1 - y_deadband; + x = copysign(abs(x) < x_deadband ? 0 : (abs(x) - x_deadband) * x_scale, x); + y = copysign(abs(y) < y_deadband ? 0 : (abs(y) - y_deadband) * y_scale, y); + return {x, y}; +} + +std::pair ExpoCurve::get_value(std::pair value) { + float x = value.first; + float y = value.second; + x = copysign(pow(abs(x), m_x_curve), x); + x = copysign(pow(abs(y), m_y_curve), y); + return {x, y}; +} + +std::pair Transformation::get_value(std::pair value) { + std::pair ret_value {}; + return std::accumulate(m_all_transforms.begin(), m_all_transforms.end(), ret_value, + [](auto last_val, auto& next_transform) { return next_transform->get_value(last_val); }); +} +} // namespace gamepad \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b0bef76..8d2cc4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,22 +36,22 @@ void aRepeatPress1() { void initialize() { // We can register functions to run when buttons are pressed - gamepad::master.Down.onPress("downPress1", downPress1); + gamepad::master.Down().onPress("downPress1", downPress1); // ...or when they're released - gamepad::master.Up.onRelease("downRelease1", upRelease1); + gamepad::master.Up().onRelease("downRelease1", upRelease1); // There's also the longPress event - gamepad::master.Left.onLongPress("leftLongPress1", leftLongPress1); + gamepad::master.Left().onLongPress("leftLongPress1", leftLongPress1); // 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); + 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); + 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"); }); + gamepad::master.X().onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); } /** @@ -106,8 +106,8 @@ void opcontrol() { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); // We'll use the arcade control scheme - int dir = gamepad::master.LeftY; // Gets amount forward/backward from left joystick - int turn = gamepad::master.RightX; // Gets the turn left/right from right joystick + int dir = gamepad::master.LeftY(); // Gets amount forward/backward from left joystick + int turn = gamepad::master.RightX(); // Gets the turn left/right from right joystick left_mg.move(dir - turn); // Sets left motor voltage right_mg.move(dir + turn); // Sets right motor voltage pros::delay(25); // Wait for 25 ms, then update the motor values again From 6812d03ff37669e7776127d1d95aa61e0a39a937 Mon Sep 17 00:00:00 2001 From: lufimio Date: Thu, 31 Oct 2024 14:00:20 -0400 Subject: [PATCH 065/108] test line clearing --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index c168570..3329be2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,6 +25,8 @@ void initialize() { gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); gamepad::master.Y.onPress("print1", []() { gamepad::master.print_line(1, "this should be cleared"); }); gamepad::master.Y.onRelease("clear1", []() { gamepad::master.clear(1); }); + gamepad::master.Up.onPress("long", []() { gamepad::master.print_line(0, "mmmmmmmmmmmmmmm"); }); + gamepad::master.Up.onLongPress("short", []() { gamepad::master.print_line(0, "i"); }); } /** @@ -78,4 +80,4 @@ void opcontrol() { pros::delay(25); // Wait for 25 ms, then update the motor values again } -} \ No newline at end of file +} From 297295aecad553e98e1f4375a7d038e342387ad7 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sat, 2 Nov 2024 11:41:36 -0700 Subject: [PATCH 066/108] feat: :sparkles: Add fisheye joystick modifier --- include/gamepad/joystick_modifier.hpp | 10 ++++++++++ src/gamepad/joystick_modifier.cpp | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp index c3c6259..6ccc509 100644 --- a/include/gamepad/joystick_modifier.hpp +++ b/include/gamepad/joystick_modifier.hpp @@ -43,6 +43,16 @@ class ExpoCurve : public AbstractTransformation { float m_y_curve; }; +class Fisheye : public AbstractTransformation { + public: + Fisheye(float radius) + : m_radius(radius) {} + + std::pair get_value(std::pair) override; + private: + float m_radius; +}; + class Transformation final { friend class TransformationBuilder; public: diff --git a/src/gamepad/joystick_modifier.cpp b/src/gamepad/joystick_modifier.cpp index 1741acf..be8258f 100644 --- a/src/gamepad/joystick_modifier.cpp +++ b/src/gamepad/joystick_modifier.cpp @@ -27,6 +27,22 @@ std::pair ExpoCurve::get_value(std::pair value) { return {x, y}; } +std::pair Fisheye::get_value(std::pair value) { + float x = value.first; + float y = value.second; + float x_abs = abs(x); + float y_abs = abs(y); + float j = std::sqrt(m_radius * m_radius - 127 * 127); + if (x_abs >= j && y_abs >= j) { + float theta = std::atan2(y_abs, x_abs); + x_abs *= std::acos(abs(std::remainder(theta, 90))); + y_abs *= std::acos(abs(std::remainder(theta, 90))); + } + x = std::copysign(std::min(127.0f, x_abs), x); + y = std::copysign(std::min(127.0f, y_abs), y); + return {x, y}; +} + std::pair Transformation::get_value(std::pair value) { std::pair ret_value {}; return std::accumulate(m_all_transforms.begin(), m_all_transforms.end(), ret_value, From 83c831573553bd2465e71d1b67176c79d32e90d6 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 3 Nov 2024 18:36:57 -0800 Subject: [PATCH 067/108] feat: :construction: Add ability to add transformations to gamepad --- include/gamepad/controller.hpp | 33 +++++++++++++++++++++++---- include/gamepad/joystick_modifier.hpp | 12 ++++++++-- src/main.cpp | 5 ++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index e44ae58..86140e9 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -1,6 +1,7 @@ #pragma once #include "pros/misc.h" +#include #include #include "button.hpp" #include "joystick_modifier.hpp" @@ -78,13 +79,35 @@ class Gamepad { const Button& A() { return m_A; } - float LeftX() { return m_LeftX; } + float LeftX(bool use_curve = true) { + if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).first; + else return m_LeftX; + } - float LeftY() { return m_LeftY; } + float LeftY(bool use_curve = true) { + if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).second; + else return m_LeftY; + } - float RightX() { return m_RightX; } + float RightX(bool use_curve = true) { + if (use_curve && m_right_transformation) + return m_right_transformation->get_value({m_RightX, m_RightY}).first; + else return m_RightX; + } - float RightY() { return m_RightY; } + float RightY(bool use_curve = true) { + if (use_curve && m_right_transformation) + return m_right_transformation->get_value({m_RightX, m_RightY}).second; + else return m_RightY; + } + + void set_left_transform(Transformation left_transformation) { + m_left_transformation = std::move(left_transformation); + } + + void set_right_transform(Transformation right_transformation) { + m_right_transformation = std::move(right_transformation); + } /// The master controller, same as @ref gamepad::master static Gamepad master; @@ -98,6 +121,8 @@ class Gamepad { m_A {}; float m_LeftX = 0, m_LeftY = 0, m_RightX = 0, m_RightY = 0; Button Fake {}; + std::optional m_left_transformation {std::nullopt}; + std::optional m_right_transformation {std::nullopt}; /** * @brief Gets a unique name for a listener that will not conflict with user listener names. * diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp index 6ccc509..5819917 100644 --- a/include/gamepad/joystick_modifier.hpp +++ b/include/gamepad/joystick_modifier.hpp @@ -64,15 +64,23 @@ class Transformation final { class TransformationBuilder final { public: template T> TransformationBuilder(T first) { - m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); + m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); } TransformationBuilder() = delete; template T> TransformationBuilder& and_then(T next) { - m_transform.m_all_transforms.push_back(std::make_unique(std::move(next))); + m_transform.m_all_transforms.push_back(std::make_unique(std::move(next))); return *this; } + + Transformation build() { + return std::move(m_transform); + } + + operator Transformation() { + return std::move(m_transform); + } private: Transformation m_transform {}; }; diff --git a/src/main.cpp b/src/main.cpp index 8d2cc4a..dd04b8d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "main.h" #include "gamepad/api.hpp" #include "gamepad/controller.hpp" +#include "gamepad/joystick_modifier.hpp" #include "pros/rtos.hpp" #include #include @@ -52,6 +53,10 @@ void initialize() { gamepad::master.A().onRepeatPress("aRepeatPress", aRepeatPress1); // And we can use lambda's too gamepad::master.X().onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); + + // set up controller curves: + gamepad::master.set_left_transform( + gamepad::TransformationBuilder(gamepad::Deadband(5, 5)).and_then(gamepad::ExpoCurve(2, 2))); } /** From 67695e45ce269389b7b3f0f2af29905dc96b267b Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 4 Nov 2024 08:46:22 -0800 Subject: [PATCH 068/108] style: :art: Fix formatting in joystick_modifier.hpp --- include/gamepad/joystick_modifier.hpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp index 5819917..9eacd53 100644 --- a/include/gamepad/joystick_modifier.hpp +++ b/include/gamepad/joystick_modifier.hpp @@ -74,14 +74,10 @@ class TransformationBuilder final { return *this; } - Transformation build() { - return std::move(m_transform); - } + Transformation build() { return std::move(m_transform); } - operator Transformation() { - return std::move(m_transform); - } + operator Transformation() { return std::move(m_transform); } private: Transformation m_transform {}; }; -} // namespace gamepad \ No newline at end of file +} // namespace gamepad From e27010edd895c906135ca427a08ab7f4a6d5a7e5 Mon Sep 17 00:00:00 2001 From: lufimio Date: Tue, 12 Nov 2024 19:59:53 -0500 Subject: [PATCH 069/108] docs: :memo: Added all of the documentation --- include/gamepad/gamepad.hpp | 17 +++++------- include/gamepad/screens/abstractScreen.hpp | 31 +++++++++++++++++++++- include/gamepad/screens/alertScreen.hpp | 29 ++++++++++++++++++++ include/gamepad/screens/defaultScreen.hpp | 27 +++++++++++++++++++ src/gamepad/gamepad.cpp | 28 +++++-------------- src/main.cpp | 16 +++++++++-- 6 files changed, 114 insertions(+), 34 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 52701f5..f9ce243 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -32,13 +32,13 @@ class Gamepad { */ void update(); /** - * Add a screen to the sceen update loop that can update the controller's screen + * @brief Add a screen to the sceen update loop that can update the controller's screen * * @param screen the `AbstractScreen` to add to the screen queue */ void add_screen(std::shared_ptr screen); /** - * print a line to the console like pros (low priority) + * @brief print a line to the console like pros (low priority) * * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) @@ -110,10 +110,7 @@ class Gamepad { /// The partner controller, same as @ref gamepad::partner static Gamepad partner; private: - Gamepad(pros::controller_id_e_t id) - : controller(id) { - this->add_screen(defaultScreen); - } + Gamepad(pros::controller_id_e_t id); Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {}, m_A {}; @@ -128,15 +125,15 @@ class Gamepad { * @return std::string A unique listener name */ static std::string unique_name(); - static Button Gamepad::* button_to_ptr(pros::controller_digital_e_t button); + static Button Gamepad::*button_to_ptr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreens(); std::shared_ptr defaultScreen = std::make_shared(); - std::vector> screens {}; - ScreenBuffer currentScreen {}; - ScreenBuffer nextBuffer {}; + std::vector> screens = {}; + ScreenBuffer currentScreen = {}; + ScreenBuffer nextBuffer = {}; pros::Controller controller; uint8_t last_printed_line = 0; diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 0d4f749..d248be5 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -15,20 +15,49 @@ namespace gamepad { */ typedef std::array, 4> ScreenBuffer; +/** + * @brief The abstract class for interacting with the controller screen + * + */ class AbstractScreen { public: AbstractScreen(uint priority) : priority(priority) {} + /** + * @brief runs every time the controller's update function is called + * use this if you need to update somthing regardless of if there is an + * available slot in the screen + * + * @param delta_time the time since the last update in milliseconds + */ virtual void update(uint delta_time) {} + /** + * @brief runs if there is an empty line that is available to print + * + * @param visible_lines a set that contains the line numbers of all lines that + * are empty and available for printing + * + * @returns a the lines to be printed, any lines that are not available will be ignored + */ virtual ScreenBuffer get_screen(std::set visible_lines) = 0; + /** + * @brief a function where button events are pushed, use this to handle button events. + * + * @param button_events a set of the button events that happened this update + */ virtual void handle_events(std::set button_events) {} + /** + * @brief returns the priority of the screen + * + * @important it is not reccomended to override this function + */ uint get_priority() { return this->priority; } protected: const uint priority; }; -} // namespace gamepad \ No newline at end of file +} // namespace gamepad diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 7656eaf..df1be99 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -10,14 +10,43 @@ namespace gamepad { +/** + * @brief a screen that sends alerts to the controller, duration of alerts can be customized + * + * @note priority: UINT32_MAX - 100 + */ class AlertScreen : public AbstractScreen { public: AlertScreen() : AbstractScreen(UINT32_MAX - 100) {} + /** + * @brief updates the alert loop + * + * @param delta_time the time since the last update + */ void update(uint delta_time); + + /** + * @brief return the next alert to print if there is space for it on the screen + * + * @param visible_lines a set that contains the line numbers of all lines that + * are empty and available for printing + * + * @returns a the lines to be printed, any lines that are not available will be ignored + */ ScreenBuffer get_screen(std::set visible_lines); + /** + * @brief add an alert to the alert queue, to be printed as soon as there is an available space + * + * @param line the line number to print the alert at (0-2) + * @param strs the string to print on the controller, "\n" to go to the next line + * lines that go over 2 will be cropped out + * @param duration how long the alert should persist on the screen + * @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, + * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + */ void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index ad62a1c..d2a26c8 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -5,14 +5,41 @@ namespace gamepad { +/** + * @brief A basic screen that allows basic prints, similar to pros controller api + * + * @note The gamepad class has wrappers around this class + * @note priority: 1 + */ class DefaultScreen : public AbstractScreen { public: DefaultScreen() : AbstractScreen(1) {} + /** + * @brief returns any lines that have space to print on the controller + * + * @param visible_lines a set that contains the line numbers of all lines that + * are empty and available for printing + * + * @returns a the lines to be printed, any lines that are not available will be ignored + */ ScreenBuffer get_screen(std::set visible_lines); + /** + * @brief print a line to the console like pros + * + * @param line the line number to print the string on (0-2) + * @param str the string to print onto the controller (\n to go to the next line) + */ void print_line(uint8_t line, std::string str); + + /** + * makes the controller rumble like pros + * + * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, + * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + */ void rumble(std::string rumble_pattern); private: ScreenBuffer currentBuffer {}; diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index eb593c7..5012192 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -12,8 +12,13 @@ #include namespace gamepad { +Gamepad::Gamepad(pros::controller_id_e_t id) + : controller(id) { + this->add_screen(defaultScreen); +} + void Gamepad::updateButton(pros::controller_digital_e_t button_id) { - Button Gamepad::* button = Gamepad::button_to_ptr(button_id); + Button Gamepad::*button = Gamepad::button_to_ptr(button_id); bool is_held = this->controller.get_digital(button_id); (this->*button).update(is_held); } @@ -25,8 +30,6 @@ void Gamepad::updateScreens() { // Disable screen updates if the controller is disconnected if (!this->controller.is_connected()) { if (this->screenCleared) { - // printf("disconnected\n"); - this->nextBuffer = std::move(this->currentScreen); this->currentScreen = {}; this->screenCleared = false; @@ -36,14 +39,8 @@ void Gamepad::updateScreens() { // Clear current screen and reset last update time on reconnect if (this->controller.is_connected() && !screenCleared) { - // printf("reconnected\n"); - this->currentScreen = {}; this->last_update_time = pros::millis(); - - // printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - // nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - // nextBuffer.at(3).value_or("nullopt").c_str()); } // Update all screens and note deltatime @@ -76,7 +73,6 @@ void Gamepad::updateScreens() { if (!this->nextBuffer[line].has_value()) continue; if (!this->screenCleared && line != 3) { - // printf("clearing screen for init\n"); this->controller.clear(); this->screenCleared = true; this->currentScreen = {}; @@ -90,16 +86,6 @@ void Gamepad::updateScreens() { continue; } - // printf("\nLine = %i\n", line); - - // printf("nextBuffer = {%s, %s, %s, %s}\n", nextBuffer.at(0).value_or("nullopt").c_str(), - // nextBuffer.at(1).value_or("nullopt").c_str(), nextBuffer.at(2).value_or("nullopt").c_str(), - // nextBuffer.at(3).value_or("nullopt").c_str()); - - // printf("currentScreen = {%s, %s, %s, %s}\n", currentScreen.at(0).value_or("nullopt").c_str(), - // currentScreen.at(1).value_or("nullopt").c_str(), currentScreen.at(2).value_or("nullopt").c_str(), - // currentScreen.at(3).value_or("nullopt").c_str()); - // print to screen or rumble if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); @@ -162,7 +148,7 @@ std::string Gamepad::unique_name() { return std::to_string(i++) + "_internal"; } -Button Gamepad::* Gamepad::button_to_ptr(pros::controller_digital_e_t button) { +Button Gamepad::*Gamepad::button_to_ptr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; case pros::E_CONTROLLER_DIGITAL_L2: return &Gamepad::m_L2; diff --git a/src/main.cpp b/src/main.cpp index 3329be2..2f2ffe2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include #include +// initialize the alerts screen so we can have alerts on the controller std::shared_ptr alerts = std::make_shared(); /** @@ -16,17 +17,28 @@ std::shared_ptr alerts = std::make_sharedadd_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); }); + + // Normally print a string on the first and third line without overriding + // the second line when the B button is pressed gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); + + // rumbles 3 times for a short duration when the X button is pressed gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); + + // when the Y button is pressed and held the text should show up, and when + // the button is released it should be cleared gamepad::master.Y.onPress("print1", []() { gamepad::master.print_line(1, "this should be cleared"); }); gamepad::master.Y.onRelease("clear1", []() { gamepad::master.clear(1); }); - gamepad::master.Up.onPress("long", []() { gamepad::master.print_line(0, "mmmmmmmmmmmmmmm"); }); - gamepad::master.Up.onLongPress("short", []() { gamepad::master.print_line(0, "i"); }); } /** From 0237fe8dce61e5a0b3e6a4af1f45b9121b94daeb Mon Sep 17 00:00:00 2001 From: lufimio Date: Wed, 13 Nov 2024 08:42:04 -0500 Subject: [PATCH 070/108] feat: :sparkles: actually impliment the handle_events interface --- src/gamepad/gamepad.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 5012192..ceda387 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -43,9 +43,18 @@ void Gamepad::updateScreens() { this->last_update_time = pros::millis(); } - // Update all screens and note deltatime + // Get new button presses + std::set buttonUpdates; + for (int i = pros::E_CONTROLLER_DIGITAL_L1; i <= pros::E_CONTROLLER_DIGITAL_A; ++i) { + if ((this->*this->button_to_ptr(static_cast(i))).rising_edge) { + buttonUpdates.emplace(static_cast(i)); + } + } + + // Update all screens, and send new button presses, also note deltatime for (int i = 0; i < this->screens.size(); i++) { this->screens[i]->update(pros::millis() - this->last_update_time); + this->screens[i]->handle_events(buttonUpdates); } this->last_update_time = pros::millis(); From f70c9d6302da4c1fb77ca62bb8a83f717cab5286 Mon Sep 17 00:00:00 2001 From: lufimio Date: Wed, 13 Nov 2024 09:11:29 -0500 Subject: [PATCH 071/108] docs: :memo: Add examples --- include/gamepad/gamepad.hpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index f9ce243..886cbff 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -35,24 +35,45 @@ class Gamepad { * @brief Add a screen to the sceen update loop that can update the controller's screen * * @param screen the `AbstractScreen` to add to the screen queue + * + * @b Example: + * @code {.cpp} + * // initialize the alerts screen so we can have alerts on the controller + * std::shared_ptr alerts = std::make_shared(); + * + * gamepad::master.add_screen(alerts); */ void add_screen(std::shared_ptr screen); /** * @brief print a line to the console like pros (low priority) - * + * * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) + * + * @b Example: + * @code {.cpp} + * gamepad::master.print_line(1, "This will print on the middle line"); + * gamepad::master.print_line(0, "this will print\n\naround the middle line"); */ void print_line(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) * + * @b Example: + * @code {.cpp} + * // clears the whole screen on the controller + * gamepad::master.clear() */ void clear(); /** * @brief clears the specific line on the controller, similar to the pros function clear_line (low priority) * * @param line the line to clear (0-2) + * + * @b Example: + * @code {.cpp} + * // clears the center line on the controller + * gamepad::master.clear(1); */ void clear(uint8_t line); /** @@ -60,6 +81,11 @@ class Gamepad { * * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + * + * @b Example: + * @code {.cpp} + * // rumbles in the folllowing pattern: short, pause, long, short short + * gamepad::master.rumble(". -.."); */ void rumble(std::string rumble_pattern); /** From 2a7ff7a9117536d53302ee93de3517ade99a33a5 Mon Sep 17 00:00:00 2001 From: lufimio Date: Wed, 13 Nov 2024 09:17:01 -0500 Subject: [PATCH 072/108] fix: :bug: actually make it compile also run clang-format --- include/gamepad/gamepad.hpp | 4 ++-- src/gamepad/gamepad.cpp | 2 +- src/main.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 886cbff..f382528 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -36,7 +36,7 @@ class Gamepad { * * @param screen the `AbstractScreen` to add to the screen queue * - * @b Example: + * @b Example: * @code {.cpp} * // initialize the alerts screen so we can have alerts on the controller * std::shared_ptr alerts = std::make_shared(); @@ -46,7 +46,7 @@ class Gamepad { void add_screen(std::shared_ptr screen); /** * @brief print a line to the console like pros (low priority) - * + * * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) * diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index ceda387..7466035 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -47,7 +47,7 @@ void Gamepad::updateScreens() { std::set buttonUpdates; for (int i = pros::E_CONTROLLER_DIGITAL_L1; i <= pros::E_CONTROLLER_DIGITAL_A; ++i) { if ((this->*this->button_to_ptr(static_cast(i))).rising_edge) { - buttonUpdates.emplace(static_cast(i)); + buttonUpdates.emplace(static_cast(i)); } } diff --git a/src/main.cpp b/src/main.cpp index 2f2ffe2..2a7081d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,11 +17,11 @@ std::shared_ptr alerts = std::make_sharedadd_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); @@ -31,7 +31,7 @@ void initialize() { // the second line when the B button is pressed gamepad::master.B.onPress( "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); - + // rumbles 3 times for a short duration when the X button is pressed gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); From bdcd568cbc463dfdf9246f88c868f8c8c6649ae7 Mon Sep 17 00:00:00 2001 From: lufimio Date: Thu, 14 Nov 2024 19:54:18 -0500 Subject: [PATCH 073/108] chore: :fire: removed debug.log --- .gitignore | 3 +++ debug.log | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 debug.log diff --git a/.gitignore b/.gitignore index 37b2094..5419594 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ temp.errors # MacOS .DS_Store + +# Linux +debug.log diff --git a/debug.log b/debug.log deleted file mode 100644 index 86c1de7..0000000 --- a/debug.log +++ /dev/null @@ -1,6 +0,0 @@ -[0909/102831.528:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) -[0909/102852.263:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) -[0910/182219.664:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) -[0910/183206.884:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) -[0910/183223.865:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) -[0910/183232.392:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2) From e0db1e4369b5297f884e0a33a8f9f9ff0174dd52 Mon Sep 17 00:00:00 2001 From: lufimio Date: Thu, 14 Nov 2024 20:04:04 -0500 Subject: [PATCH 074/108] refactor: :white_check_mark: address code review comments --- include/gamepad/gamepad.hpp | 5 ++--- include/gamepad/screens/abstractScreen.hpp | 10 +++++----- include/gamepad/screens/alertScreen.hpp | 6 +++--- src/gamepad/button.cpp | 3 +-- src/gamepad/gamepad.cpp | 17 +++++++++-------- src/gamepad/screens/alertScreen.cpp | 2 +- 6 files changed, 21 insertions(+), 22 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index f382528..5037870 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "screens/abstractScreen.hpp" #include "button.hpp" #include "pros/misc.hpp" @@ -163,8 +162,8 @@ class Gamepad { pros::Controller controller; uint8_t last_printed_line = 0; - uint last_print_time = 0; - uint last_update_time = 0; + uint32_t last_print_time = 0; + uint32_t last_update_time = 0; bool screenCleared = false; pros::Mutex mut {}; }; diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index d248be5..1c23b21 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -1,10 +1,10 @@ #pragma once #include +#include #include #include #include -#include #include "pros/misc.h" namespace gamepad { @@ -21,7 +21,7 @@ typedef std::array, 4> ScreenBuffer; */ class AbstractScreen { public: - AbstractScreen(uint priority) + AbstractScreen(uint32_t priority) : priority(priority) {} /** @@ -31,7 +31,7 @@ class AbstractScreen { * * @param delta_time the time since the last update in milliseconds */ - virtual void update(uint delta_time) {} + virtual void update(uint32_t delta_time) {} /** * @brief runs if there is an empty line that is available to print @@ -55,9 +55,9 @@ class AbstractScreen { * * @important it is not reccomended to override this function */ - uint get_priority() { return this->priority; } + uint32_t get_priority() { return this->priority; } protected: - const uint priority; + const uint32_t priority; }; } // namespace gamepad diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index df1be99..694771b 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -25,7 +25,7 @@ class AlertScreen : public AbstractScreen { * * @param delta_time the time since the last update */ - void update(uint delta_time); + void update(uint32_t delta_time); /** * @brief return the next alert to print if there is space for it on the screen @@ -51,12 +51,12 @@ class AlertScreen : public AbstractScreen { private: struct AlertBuffer { ScreenBuffer screen; - uint duration; + uint32_t duration; }; std::deque screen_buffer {}; std::optional screen_contents {}; - uint line_set_time = 0; + uint32_t line_set_time = 0; pros::Mutex mut {}; }; diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 703c246..9c0bb98 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -2,7 +2,6 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include -#include namespace gamepad { void Button::set_long_press_threshold(uint32_t threshold) const { this->long_press_threshold = threshold; } @@ -88,4 +87,4 @@ void Button::update(const bool is_held) { if (this->falling_edge) this->time_released = 0; this->last_update_time = pros::millis(); } -} // namespace gamepad \ No newline at end of file +} // namespace gamepad diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 7466035..7053d8b 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -2,12 +2,13 @@ #include "gamepad/todo.hpp" #include "pros/misc.h" #include "pros/rtos.hpp" -#include +#include "screens/abstractScreen.hpp" #include #include #include #include #include +#include #include #include @@ -52,23 +53,23 @@ void Gamepad::updateScreens() { } // Update all screens, and send new button presses, also note deltatime - for (int i = 0; i < this->screens.size(); i++) { - this->screens[i]->update(pros::millis() - this->last_update_time); - this->screens[i]->handle_events(buttonUpdates); + for (std::shared_ptr screen : this->screens) { + screen->update(pros::millis() - this->last_update_time); + screen->handle_events(buttonUpdates); } this->last_update_time = pros::millis(); // Check if enough time has passed for the Gamepad to poll for updates if (pros::millis() - this->last_print_time <= 50) return; - for (int i = 0; i < this->screens.size(); i++) { + for (std::shared_ptr screen : this->screens) { // get all lines that arent being used by a higher priority screen std::set visible_lines; for (uint8_t j = 0; j < 4; j++) if (!this->nextBuffer[j].has_value()) visible_lines.emplace(j); // get the buffer of the next lower priority screen and set it to be printed - ScreenBuffer buffer = this->screens[i]->get_screen(visible_lines); + ScreenBuffer buffer = screen->get_screen(visible_lines); for (uint8_t j = 0; j < 4; j++) if (buffer[j].has_value() && !buffer[j]->empty() && !nextBuffer[j].has_value()) nextBuffer[j] = std::move(buffer[j]); @@ -120,8 +121,8 @@ void Gamepad::update() { } void Gamepad::add_screen(std::shared_ptr screen) { - uint last = UINT32_MAX; - uint pos = 0; + uint32_t last = UINT32_MAX; + uint32_t pos = 0; for (pos = 0; pos < this->screens.size(); pos++) { if (this->screens[pos]->get_priority() < screen->get_priority() && last >= screen->get_priority()) break; last = this->screens[pos]->get_priority(); diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index a8ea556..4a45394 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -27,7 +27,7 @@ ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { return this->screen_contents->screen; } -void AlertScreen::update(uint delta_time) { +void AlertScreen::update(uint32_t delta_time) { std::lock_guard guard(this->mut); if (pros::millis() - this->line_set_time >= this->screen_contents->duration) this->screen_contents = std::nullopt; } From fd99f2a1eea3753c4387e2888f2ef41bb98aea33 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:43:57 -0800 Subject: [PATCH 075/108] docs: :memo: Add docs to Gamepad and Transformations --- include/gamepad/controller.hpp | 84 ++++++-- include/gamepad/joystick_modifier.hpp | 83 -------- include/gamepad/joystick_transformation.hpp | 188 ++++++++++++++++++ src/gamepad/controller.cpp | 8 +- ...difier.cpp => joystick_transformation.cpp} | 8 +- src/main.cpp | 27 ++- 6 files changed, 274 insertions(+), 124 deletions(-) delete mode 100644 include/gamepad/joystick_modifier.hpp create mode 100644 include/gamepad/joystick_transformation.hpp rename src/gamepad/{joystick_modifier.cpp => joystick_transformation.cpp} (89%) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 86140e9..7fb642a 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -4,7 +4,7 @@ #include #include #include "button.hpp" -#include "joystick_modifier.hpp" +#include "joystick_transformation.hpp" #include "pros/misc.hpp" namespace gamepad { @@ -46,65 +46,113 @@ class Gamepad { * * @param joystick Which joystick axis to return * + * @return float the value of the joystick, between -1.0 and 1.0. + * * @b Example: * @code {.cpp} * // control a motor with a joystick - * intake.move(gamepad::master[ANALOG_RIGHT_Y]); + * intake.move(gamepad::master[ANALOG_RIGHT_Y] * 127); * @endcode * */ float operator[](pros::controller_analog_e_t joystick); - const Button& L1() { return m_L1; } + /// The L1 button on the top of the controller. + const Button& buttonL1() { return m_L1; } - const Button& L2() { return m_L2; } + /// The L2 button on the top of the controller. + const Button& buttonL2() { return m_L2; } - const Button& R1() { return m_R1; } + /// The R1 button on the top of the controller. + const Button& buttonR1() { return m_R1; } - const Button& R2() { return m_R2; } + /// The R2 button on the top of the controller. + const Button& buttonR2() { return m_R2; } - const Button& Up() { return m_Up; } + /// The up arrow button on the front of the controller. + const Button& buttonUp() { return m_Up; } - const Button& Down() { return m_Down; } + /// The down arrow button on the front of the controller. + const Button& buttonDown() { return m_Down; } - const Button& Left() { return m_Left; } + /// The left arrow button on the front of the controller. + const Button& buttonLeft() { return m_Left; } - const Button& Right() { return m_Right; } + /// The right arrow button on the front of the controller. + const Button& buttonRight() { return m_Right; } - const Button& X() { return m_X; } + /// The X arrow button on the front of the controller. + const Button& buttonX() { return m_X; } - const Button& B() { return m_B; } + /// The B arrow button on the front of the controller. + const Button& buttonB() { return m_B; } - const Button& Y() { return m_Y; } + /// The Y arrow button on the front of the controller. + const Button& buttonY() { return m_Y; } - const Button& A() { return m_A; } + /// The A arrow button on the front of the controller. + const Button& buttonA() { return m_A; } - float LeftX(bool use_curve = true) { + /** + * @brief Gets the value of the left joystick's x axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the left joystick's x-axis, between -1.0 and 1.0. + */ + float axisLeftX(bool use_curve = true) { if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).first; else return m_LeftX; } - float LeftY(bool use_curve = true) { + /** + * @brief Gets the value of the left joystick's y axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the left joystick's y-axis, between -1.0 and 1.0. + */ + float axisLeftY(bool use_curve = true) { if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).second; else return m_LeftY; } - float RightX(bool use_curve = true) { + /** + * @brief Gets the value of the right joystick's x axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the right joystick's x-axis, between -1.0 and 1.0. + */ + float axisRightX(bool use_curve = true) { if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).first; else return m_RightX; } - float RightY(bool use_curve = true) { + /** + * @brief Gets the value of the right joystick's y axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the right joystick's y-axis, between -1.0 and 1.0. + */ + float axisRightY(bool use_curve = true) { if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).second; else return m_RightY; } + /** + * @brief Set the transformation to be used for the left joystick. + * + * @param left_transformation The transformation to be used + */ void set_left_transform(Transformation left_transformation) { m_left_transformation = std::move(left_transformation); } + /** + * @brief Set the transformation to be used for the right joystick. + * + * @param right_transformation The transformation to be used + */ void set_right_transform(Transformation right_transformation) { m_right_transformation = std::move(right_transformation); } diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp deleted file mode 100644 index 9eacd53..0000000 --- a/include/gamepad/joystick_modifier.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace gamepad { -class AbstractTransformation { - public: - virtual std::pair get_value(std::pair) = 0; - virtual ~AbstractTransformation() = default; -}; - -class Deadband : public AbstractTransformation { - public: - Deadband(float x_deadband, float y_deadband, float x_spread, float y_spread) - : m_x_deadband(x_deadband), - m_y_deadband(y_deadband), - m_x_spread(x_spread), - m_y_spread(y_spread) {} - - Deadband(float x_deadband, float y_deadband) - : Deadband(x_deadband, y_deadband, 0.0, 0.0) {} - - std::pair get_value(std::pair) override; - private: - float m_x_deadband; - float m_y_deadband; - float m_x_spread; - float m_y_spread; -}; - -class ExpoCurve : public AbstractTransformation { - public: - ExpoCurve(float x_curve, float y_curve) - : m_x_curve(x_curve), - m_y_curve(y_curve) {} - - std::pair get_value(std::pair) override; - private: - float m_x_curve; - float m_y_curve; -}; - -class Fisheye : public AbstractTransformation { - public: - Fisheye(float radius) - : m_radius(radius) {} - - std::pair get_value(std::pair) override; - private: - float m_radius; -}; - -class Transformation final { - friend class TransformationBuilder; - public: - std::pair get_value(std::pair); - private: - std::vector> m_all_transforms; -}; - -class TransformationBuilder final { - public: - template T> TransformationBuilder(T first) { - m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); - } - - TransformationBuilder() = delete; - - template T> TransformationBuilder& and_then(T next) { - m_transform.m_all_transforms.push_back(std::make_unique(std::move(next))); - return *this; - } - - Transformation build() { return std::move(m_transform); } - - operator Transformation() { return std::move(m_transform); } - private: - Transformation m_transform {}; -}; -} // namespace gamepad diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp new file mode 100644 index 0000000..5d62dcb --- /dev/null +++ b/include/gamepad/joystick_transformation.hpp @@ -0,0 +1,188 @@ +#pragma once + +#include +#include +#include +#include + +namespace gamepad { + +/** + * @brief An abstract class for joystick transformations. + * + * A transformation takes a coordinate representing the value of the joystick, and returns a transformed coordinate + * value + * + */ +class AbstractTransformation { + public: + /** + * @brief Get the transformed coordinate given the original. + * + * @param original The original value of the joystick + * @return std::pair The transformed value + */ + virtual std::pair get_value(std::pair original) = 0; + virtual ~AbstractTransformation() = default; +}; + +/** + * @brief A joystick transformation that applies a deadband to the joystick values + * + * A deadband makes the joystick value zero when the value is close to zero. This helps prevent drifting, since + * joysticks often do not read exactly zero when released. + */ +class Deadband : public AbstractTransformation { + public: + /** + * @brief Construct a new Deadband object + * + * @param x_deadband The deadband to apply for the x axis. + * @param y_deadband The deadband to apply for the x axis. + * @param x_spread How much the deadband for the x axis should widen. + * @param y_spread How much the deadband for the y axis should widen. + */ + Deadband(float x_deadband, float y_deadband, float x_spread, float y_spread) + : m_x_deadband(x_deadband), + m_y_deadband(y_deadband), + m_x_spread(x_spread), + m_y_spread(y_spread) {} + + /** + * @brief Construct a new Deadband object + * + * @param x_deadband The deadband to apply for the x axis. + * @param y_deadband The deadband to apply for the y axis. + */ + Deadband(float x_deadband, float y_deadband) + : Deadband(x_deadband, y_deadband, 0.0, 0.0) {} + + /** + * @brief Get the joystick coordinate after applying the deadband + * + * @param original The value of the joystick before applying the deadband + * @return std::pair The joystick coordinate, with a deadband applied + */ + std::pair get_value(std::pair original) override; + private: + float m_x_deadband; + float m_y_deadband; + float m_x_spread; + float m_y_spread; +}; + +/** + * @brief A joystick transformation that applies an expo curve to the joystick values + * + * An expo curve allows greater control of the joystick, by reducing the joystick values at low speeds, while still + * allowing you to attain the maximum value of the joysticks. + */ +class ExpoCurve : public AbstractTransformation { + public: + /** + * @brief Construct a new Expo Curve object + * + * @param x_curve How much the x axis should be curved. A higher value curves the joystick value more. + * @param y_curve How much the y axis should be curved. A higher value curves the joystick value more. + */ + ExpoCurve(float x_curve, float y_curve) + : m_x_curve(x_curve), + m_y_curve(y_curve) {} + + /** + * @brief Get the joystick coordinate after applying the curve + * + * @param original The value of the joystick before applying the curve + * @return std::pair The joystick coordinate, with a curve applied + */ + std::pair get_value(std::pair original) override; + private: + float m_x_curve; + float m_y_curve; +}; + +/** + * @brief A joystick transformation that applies a fisheye to the joystick values + * + * The vex controller joysticks don't reach their maximum value in the corners. This can be an issue, especially when + * using single stick arcade. The fisheye "stretches" the joystick values so that they attain their maximum value even + * in the corners of the joysticks. + */ +class Fisheye : public AbstractTransformation { + public: + /** + * @brief Construct a new Fisheye object + * + * @param radius The radius of the rounded circle that forms the corners of the joystick's housing. + */ + Fisheye(float radius) + : m_radius(radius) {} + + /** + * @brief Get the joystick coordinate after applying the fisheye + * + * @param original The value of the joystick before applying the fisheye + * @return std::pair The joystick coordinate, with a fisheye applied + */ + std::pair get_value(std::pair original) override; + private: + float m_radius; +}; + +/** + * @brief A chain of transformations. This class should not be directly used, but should be constructed using the + * TransformationBuilder class. + */ +class Transformation final { + friend class TransformationBuilder; + public: + std::pair get_value(std::pair); + private: + std::vector> m_all_transforms; +}; + +/** + * @brief A class to create a chain of transformations. + * + */ +class TransformationBuilder final { + public: + /** + * @brief Construct a new Transformation Builder object + * + * @param first The transformation that should be used first + */ + template T> TransformationBuilder(T first) { + m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); + } + + TransformationBuilder() = delete; + + /** + * @brief Add a transformation to the list of transformations to be applied. + * + * @param next The next transformation to be applied after the previous specified transformation + * @return TransformationBuilder& The original Transformation Builder. + */ + template T> TransformationBuilder& and_then(T next) { + m_transform.m_all_transforms.push_back(std::make_unique(std::move(next))); + return *this; + } + + /** + * @brief Generate the final chained transformation + * + * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform + */ + Transformation build() { return std::move(m_transform); } + + /** + * @brief Generate the final chained transformation + * + * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform + */ + operator Transformation() { return std::move(m_transform); } + private: + Transformation m_transform {}; +}; +} // namespace gamepad diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 354bc74..76ee695 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -16,10 +16,10 @@ void Gamepad::update() { this->updateButton(static_cast(i)); } - this->m_LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X); - this->m_LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y); - this->m_RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X); - this->m_RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y); + this->m_LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X) / 127.0; + this->m_LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y) / 127.0; + this->m_RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X) / 127.0; + this->m_RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y) / 127.0; } const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } diff --git a/src/gamepad/joystick_modifier.cpp b/src/gamepad/joystick_transformation.cpp similarity index 89% rename from src/gamepad/joystick_modifier.cpp rename to src/gamepad/joystick_transformation.cpp index be8258f..10f08d1 100644 --- a/src/gamepad/joystick_modifier.cpp +++ b/src/gamepad/joystick_transformation.cpp @@ -1,4 +1,4 @@ -#include "joystick_modifier.hpp" +#include "joystick_transformation.hpp" #include #include @@ -32,14 +32,14 @@ std::pair Fisheye::get_value(std::pair value) { float y = value.second; float x_abs = abs(x); float y_abs = abs(y); - float j = std::sqrt(m_radius * m_radius - 127 * 127); + float j = std::sqrt(m_radius * m_radius - 1.0 * 1.0); if (x_abs >= j && y_abs >= j) { float theta = std::atan2(y_abs, x_abs); x_abs *= std::acos(abs(std::remainder(theta, 90))); y_abs *= std::acos(abs(std::remainder(theta, 90))); } - x = std::copysign(std::min(127.0f, x_abs), x); - y = std::copysign(std::min(127.0f, y_abs), y); + x = std::copysign(std::min(1.0f, x_abs), x); + y = std::copysign(std::min(1.0f, y_abs), y); return {x, y}; } diff --git a/src/main.cpp b/src/main.cpp index dd04b8d..51a2b1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,5 @@ #include "main.h" #include "gamepad/api.hpp" -#include "gamepad/controller.hpp" -#include "gamepad/joystick_modifier.hpp" -#include "pros/rtos.hpp" #include #include @@ -37,22 +34,22 @@ void aRepeatPress1() { void initialize() { // We can register functions to run when buttons are pressed - gamepad::master.Down().onPress("downPress1", downPress1); + gamepad::master.buttonDown().onPress("downPress1", downPress1); // ...or when they're released - gamepad::master.Up().onRelease("downRelease1", upRelease1); + gamepad::master.buttonUp().onRelease("downRelease1", upRelease1); // There's also the longPress event - gamepad::master.Left().onLongPress("leftLongPress1", leftLongPress1); + gamepad::master.buttonLeft().onLongPress("leftLongPress1", leftLongPress1); // 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); + gamepad::master.buttonLeft().onShortRelease("leftShortRelease", leftShortRelease1); + gamepad::master.buttonLeft().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); + gamepad::master.buttonA().set_long_press_threshold(1000); // in ms + gamepad::master.buttonA().set_repeat_cooldown(100); // in ms + gamepad::master.buttonA().onPress("aStartPress", aPress1); + gamepad::master.buttonA().onRepeatPress("aRepeatPress", aRepeatPress1); // And we can use lambda's too - gamepad::master.X().onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); + gamepad::master.buttonX().onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); // set up controller curves: gamepad::master.set_left_transform( @@ -111,8 +108,8 @@ void opcontrol() { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); // We'll use the arcade control scheme - int dir = gamepad::master.LeftY(); // Gets amount forward/backward from left joystick - int turn = gamepad::master.RightX(); // Gets the turn left/right from right joystick + int dir = gamepad::master.axisLeftY(); // Gets amount forward/backward from left joystick + int turn = gamepad::master.axisRightX(); // Gets the turn left/right from right joystick left_mg.move(dir - turn); // Sets left motor voltage right_mg.move(dir + turn); // Sets right motor voltage pros::delay(25); // Wait for 25 ms, then update the motor values again From 9016a4109f3cb79e68b09b4e970b1a4af51fc427 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:54:58 -0800 Subject: [PATCH 076/108] style: :art: fix docs formatting --- include/gamepad/controller.hpp | 56 ++++++++++----------- include/gamepad/joystick_transformation.hpp | 24 ++++----- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 7fb642a..d586285 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -94,33 +94,33 @@ class Gamepad { const Button& buttonA() { return m_A; } /** - * @brief Gets the value of the left joystick's x axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. - * @return float The value of the left joystick's x-axis, between -1.0 and 1.0. - */ + * @brief Gets the value of the left joystick's x axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the left joystick's x-axis, between -1.0 and 1.0. + */ float axisLeftX(bool use_curve = true) { if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).first; else return m_LeftX; } /** - * @brief Gets the value of the left joystick's y axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. - * @return float The value of the left joystick's y-axis, between -1.0 and 1.0. - */ + * @brief Gets the value of the left joystick's y axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the left joystick's y-axis, between -1.0 and 1.0. + */ float axisLeftY(bool use_curve = true) { if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).second; else return m_LeftY; } /** - * @brief Gets the value of the right joystick's x axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. - * @return float The value of the right joystick's x-axis, between -1.0 and 1.0. - */ + * @brief Gets the value of the right joystick's x axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the right joystick's x-axis, between -1.0 and 1.0. + */ float axisRightX(bool use_curve = true) { if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).first; @@ -128,11 +128,11 @@ class Gamepad { } /** - * @brief Gets the value of the right joystick's y axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. - * @return float The value of the right joystick's y-axis, between -1.0 and 1.0. - */ + * @brief Gets the value of the right joystick's y axis, optionally applying a curve. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * @return float The value of the right joystick's y-axis, between -1.0 and 1.0. + */ float axisRightY(bool use_curve = true) { if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).second; @@ -140,19 +140,19 @@ class Gamepad { } /** - * @brief Set the transformation to be used for the left joystick. - * - * @param left_transformation The transformation to be used - */ + * @brief Set the transformation to be used for the left joystick. + * + * @param left_transformation The transformation to be used + */ void set_left_transform(Transformation left_transformation) { m_left_transformation = std::move(left_transformation); } /** - * @brief Set the transformation to be used for the right joystick. - * - * @param right_transformation The transformation to be used - */ + * @brief Set the transformation to be used for the right joystick. + * + * @param right_transformation The transformation to be used + */ void set_right_transform(Transformation right_transformation) { m_right_transformation = std::move(right_transformation); } diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp index 5d62dcb..f46f400 100644 --- a/include/gamepad/joystick_transformation.hpp +++ b/include/gamepad/joystick_transformation.hpp @@ -111,10 +111,10 @@ class ExpoCurve : public AbstractTransformation { class Fisheye : public AbstractTransformation { public: /** - * @brief Construct a new Fisheye object - * - * @param radius The radius of the rounded circle that forms the corners of the joystick's housing. - */ + * @brief Construct a new Fisheye object + * + * @param radius The radius of the rounded circle that forms the corners of the joystick's housing. + */ Fisheye(float radius) : m_radius(radius) {} @@ -148,10 +148,10 @@ class Transformation final { class TransformationBuilder final { public: /** - * @brief Construct a new Transformation Builder object - * - * @param first The transformation that should be used first - */ + * @brief Construct a new Transformation Builder object + * + * @param first The transformation that should be used first + */ template T> TransformationBuilder(T first) { m_transform.m_all_transforms.push_back(std::make_unique(std::move(first))); } @@ -170,10 +170,10 @@ class TransformationBuilder final { } /** - * @brief Generate the final chained transformation - * - * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform - */ + * @brief Generate the final chained transformation + * + * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform + */ Transformation build() { return std::move(m_transform); } /** From e54e6c73371ac1b48ef61c08b36a13e2e82b8e28 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:20:22 -0800 Subject: [PATCH 077/108] style: :art: remove trailing whitespace --- include/gamepad/controller.hpp | 20 +++++------ include/gamepad/joystick_transformation.hpp | 40 ++++++++++----------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index d586285..db1cdf4 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -95,8 +95,8 @@ class Gamepad { /** * @brief Gets the value of the left joystick's x axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the left joystick's x-axis, between -1.0 and 1.0. */ float axisLeftX(bool use_curve = true) { @@ -106,8 +106,8 @@ class Gamepad { /** * @brief Gets the value of the left joystick's y axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the left joystick's y-axis, between -1.0 and 1.0. */ float axisLeftY(bool use_curve = true) { @@ -117,8 +117,8 @@ class Gamepad { /** * @brief Gets the value of the right joystick's x axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the right joystick's x-axis, between -1.0 and 1.0. */ float axisRightX(bool use_curve = true) { @@ -129,8 +129,8 @@ class Gamepad { /** * @brief Gets the value of the right joystick's y axis, optionally applying a curve. - * - * @param use_curve (optional) Whether or not to use the curve; defaults to true. + * + * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the right joystick's y-axis, between -1.0 and 1.0. */ float axisRightY(bool use_curve = true) { @@ -141,7 +141,7 @@ class Gamepad { /** * @brief Set the transformation to be used for the left joystick. - * + * * @param left_transformation The transformation to be used */ void set_left_transform(Transformation left_transformation) { @@ -150,7 +150,7 @@ class Gamepad { /** * @brief Set the transformation to be used for the right joystick. - * + * * @param right_transformation The transformation to be used */ void set_right_transform(Transformation right_transformation) { diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp index f46f400..eee416b 100644 --- a/include/gamepad/joystick_transformation.hpp +++ b/include/gamepad/joystick_transformation.hpp @@ -8,17 +8,17 @@ namespace gamepad { /** - * @brief An abstract class for joystick transformations. - * - * A transformation takes a coordinate representing the value of the joystick, and returns a transformed coordinate + * @brief An abstract class for joystick transformations. + * + * A transformation takes a coordinate representing the value of the joystick, and returns a transformed coordinate * value - * + * */ class AbstractTransformation { public: /** * @brief Get the transformed coordinate given the original. - * + * * @param original The original value of the joystick * @return std::pair The transformed value */ @@ -28,7 +28,7 @@ class AbstractTransformation { /** * @brief A joystick transformation that applies a deadband to the joystick values - * + * * A deadband makes the joystick value zero when the value is close to zero. This helps prevent drifting, since * joysticks often do not read exactly zero when released. */ @@ -36,7 +36,7 @@ class Deadband : public AbstractTransformation { public: /** * @brief Construct a new Deadband object - * + * * @param x_deadband The deadband to apply for the x axis. * @param y_deadband The deadband to apply for the x axis. * @param x_spread How much the deadband for the x axis should widen. @@ -50,7 +50,7 @@ class Deadband : public AbstractTransformation { /** * @brief Construct a new Deadband object - * + * * @param x_deadband The deadband to apply for the x axis. * @param y_deadband The deadband to apply for the y axis. */ @@ -59,7 +59,7 @@ class Deadband : public AbstractTransformation { /** * @brief Get the joystick coordinate after applying the deadband - * + * * @param original The value of the joystick before applying the deadband * @return std::pair The joystick coordinate, with a deadband applied */ @@ -73,7 +73,7 @@ class Deadband : public AbstractTransformation { /** * @brief A joystick transformation that applies an expo curve to the joystick values - * + * * An expo curve allows greater control of the joystick, by reducing the joystick values at low speeds, while still * allowing you to attain the maximum value of the joysticks. */ @@ -81,7 +81,7 @@ class ExpoCurve : public AbstractTransformation { public: /** * @brief Construct a new Expo Curve object - * + * * @param x_curve How much the x axis should be curved. A higher value curves the joystick value more. * @param y_curve How much the y axis should be curved. A higher value curves the joystick value more. */ @@ -91,7 +91,7 @@ class ExpoCurve : public AbstractTransformation { /** * @brief Get the joystick coordinate after applying the curve - * + * * @param original The value of the joystick before applying the curve * @return std::pair The joystick coordinate, with a curve applied */ @@ -112,15 +112,15 @@ class Fisheye : public AbstractTransformation { public: /** * @brief Construct a new Fisheye object - * + * * @param radius The radius of the rounded circle that forms the corners of the joystick's housing. */ Fisheye(float radius) : m_radius(radius) {} - + /** * @brief Get the joystick coordinate after applying the fisheye - * + * * @param original The value of the joystick before applying the fisheye * @return std::pair The joystick coordinate, with a fisheye applied */ @@ -143,13 +143,13 @@ class Transformation final { /** * @brief A class to create a chain of transformations. - * + * */ class TransformationBuilder final { public: /** * @brief Construct a new Transformation Builder object - * + * * @param first The transformation that should be used first */ template T> TransformationBuilder(T first) { @@ -160,7 +160,7 @@ class TransformationBuilder final { /** * @brief Add a transformation to the list of transformations to be applied. - * + * * @param next The next transformation to be applied after the previous specified transformation * @return TransformationBuilder& The original Transformation Builder. */ @@ -171,14 +171,14 @@ class TransformationBuilder final { /** * @brief Generate the final chained transformation - * + * * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform */ Transformation build() { return std::move(m_transform); } /** * @brief Generate the final chained transformation - * + * * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform */ operator Transformation() { return std::move(m_transform); } From a1cb6d7b70ee50afb92fcdce00b6cdc1a2e9be89 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:09:57 +0000 Subject: [PATCH 078/108] style: :art: fix formatting of doc comments --- include/gamepad/joystick_transformation.hpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp index eee416b..6f028db 100644 --- a/include/gamepad/joystick_transformation.hpp +++ b/include/gamepad/joystick_transformation.hpp @@ -16,12 +16,12 @@ namespace gamepad { */ class AbstractTransformation { public: - /** - * @brief Get the transformed coordinate given the original. - * - * @param original The original value of the joystick - * @return std::pair The transformed value - */ + /** + * @brief Get the transformed coordinate given the original. + * + * @param original The original value of the joystick + * @return std::pair The transformed value + */ virtual std::pair get_value(std::pair original) = 0; virtual ~AbstractTransformation() = default; }; @@ -172,14 +172,16 @@ class TransformationBuilder final { /** * @brief Generate the final chained transformation * - * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform + * @return Transformation The final chained transformation. This can be passed to + * set_left_transform/set_right_transform */ Transformation build() { return std::move(m_transform); } /** * @brief Generate the final chained transformation * - * @return Transformation The final chained transformation. This can be passed to set_left_transform/set_right_transform + * @return Transformation The final chained transformation. This can be passed to + * set_left_transform/set_right_transform */ operator Transformation() { return std::move(m_transform); } private: From 453a2df202cd11298ad994a4e27492b062ced355 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:15:16 +0000 Subject: [PATCH 079/108] refactor: :recycle: Move methods from header to src file --- include/gamepad/controller.hpp | 54 ++++++++++++---------------------- src/gamepad/controller.cpp | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 36 deletions(-) diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index db1cdf4..1073fa4 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -58,40 +58,40 @@ class Gamepad { float operator[](pros::controller_analog_e_t joystick); /// The L1 button on the top of the controller. - const Button& buttonL1() { return m_L1; } + const Button& buttonL1(); /// The L2 button on the top of the controller. - const Button& buttonL2() { return m_L2; } + const Button& buttonL2(); /// The R1 button on the top of the controller. - const Button& buttonR1() { return m_R1; } + const Button& buttonR1(); /// The R2 button on the top of the controller. - const Button& buttonR2() { return m_R2; } + const Button& buttonR2(); /// The up arrow button on the front of the controller. - const Button& buttonUp() { return m_Up; } + const Button& buttonUp(); /// The down arrow button on the front of the controller. - const Button& buttonDown() { return m_Down; } + const Button& buttonDown(); /// The left arrow button on the front of the controller. - const Button& buttonLeft() { return m_Left; } + const Button& buttonLeft(); /// The right arrow button on the front of the controller. - const Button& buttonRight() { return m_Right; } + const Button& buttonRight(); /// The X arrow button on the front of the controller. - const Button& buttonX() { return m_X; } + const Button& buttonX(); /// The B arrow button on the front of the controller. - const Button& buttonB() { return m_B; } + const Button& buttonB(); /// The Y arrow button on the front of the controller. - const Button& buttonY() { return m_Y; } + const Button& buttonY(); /// The A arrow button on the front of the controller. - const Button& buttonA() { return m_A; } + const Button& buttonA(); /** * @brief Gets the value of the left joystick's x axis, optionally applying a curve. @@ -99,10 +99,7 @@ class Gamepad { * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the left joystick's x-axis, between -1.0 and 1.0. */ - float axisLeftX(bool use_curve = true) { - if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).first; - else return m_LeftX; - } + float axisLeftX(bool use_curve = true); /** * @brief Gets the value of the left joystick's y axis, optionally applying a curve. @@ -110,10 +107,7 @@ class Gamepad { * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the left joystick's y-axis, between -1.0 and 1.0. */ - float axisLeftY(bool use_curve = true) { - if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).second; - else return m_LeftY; - } + float axisLeftY(bool use_curve = true); /** * @brief Gets the value of the right joystick's x axis, optionally applying a curve. @@ -121,11 +115,7 @@ class Gamepad { * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the right joystick's x-axis, between -1.0 and 1.0. */ - float axisRightX(bool use_curve = true) { - if (use_curve && m_right_transformation) - return m_right_transformation->get_value({m_RightX, m_RightY}).first; - else return m_RightX; - } + float axisRightX(bool use_curve = true); /** * @brief Gets the value of the right joystick's y axis, optionally applying a curve. @@ -133,29 +123,21 @@ class Gamepad { * @param use_curve (optional) Whether or not to use the curve; defaults to true. * @return float The value of the right joystick's y-axis, between -1.0 and 1.0. */ - float axisRightY(bool use_curve = true) { - if (use_curve && m_right_transformation) - return m_right_transformation->get_value({m_RightX, m_RightY}).second; - else return m_RightY; - } + float axisRightY(bool use_curve = true); /** * @brief Set the transformation to be used for the left joystick. * * @param left_transformation The transformation to be used */ - void set_left_transform(Transformation left_transformation) { - m_left_transformation = std::move(left_transformation); - } + void set_left_transform(Transformation left_transformation); /** * @brief Set the transformation to be used for the right joystick. * * @param right_transformation The transformation to be used */ - void set_right_transform(Transformation right_transformation) { - m_right_transformation = std::move(right_transformation); - } + void set_right_transform(Transformation right_transformation); /// The master controller, same as @ref gamepad::master static Gamepad master; diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 76ee695..8396988 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -42,6 +42,58 @@ std::string Gamepad::unique_name() { return std::to_string(i++) + "_internal"; } +const Button& Gamepad::buttonL1() { return m_L1; } + +const Button& Gamepad::buttonL2() { return m_L2; } + +const Button& Gamepad::buttonR1() { return m_R1; } + +const Button& Gamepad::buttonR2() { return m_R2; } + +const Button& Gamepad::buttonUp() { return m_Up; } + +const Button& Gamepad::buttonDown() { return m_Down; } + +const Button& Gamepad::buttonLeft() { return m_Left; } + +const Button& Gamepad::buttonRight() { return m_Right; } + +const Button& Gamepad::buttonX() { return m_X; } + +const Button& Gamepad::buttonB() { return m_B; } + +const Button& Gamepad::buttonY() { return m_Y; } + +const Button& Gamepad::buttonA() { return m_A; } + +float Gamepad::axisLeftX(bool use_curve) { + if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).first; + else return m_LeftX; +} + +float Gamepad::axisLeftY(bool use_curve) { + if (use_curve && m_left_transformation) return m_left_transformation->get_value({m_LeftX, m_LeftY}).second; + else return m_LeftY; +} + +float Gamepad::axisRightX(bool use_curve) { + if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).first; + else return m_RightX; +} + +float Gamepad::axisRightY(bool use_curve) { + if (use_curve && m_right_transformation) return m_right_transformation->get_value({m_RightX, m_RightY}).second; + else return m_RightY; +} + +void Gamepad::set_left_transform(Transformation left_transformation) { + m_left_transformation = std::move(left_transformation); +} + +void Gamepad::set_right_transform(Transformation right_transformation) { + m_right_transformation = std::move(right_transformation); +} + Button Gamepad::*Gamepad::button_to_ptr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; From 335a1f4732f210cf7c8f1ac2d1a4a37723437740 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:32:39 +0000 Subject: [PATCH 080/108] fix: :bug: Fix outdated code in main.cpp --- src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 51a2b1a..0b00a45 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -53,7 +53,7 @@ void initialize() { // set up controller curves: gamepad::master.set_left_transform( - gamepad::TransformationBuilder(gamepad::Deadband(5, 5)).and_then(gamepad::ExpoCurve(2, 2))); + gamepad::TransformationBuilder(gamepad::Deadband(0.05, 0.05)).and_then(gamepad::ExpoCurve(2, 2))); } /** @@ -108,8 +108,8 @@ void opcontrol() { // Remember to ALWAYS call update at the start of your while loop! gamepad::master.update(); // We'll use the arcade control scheme - int dir = gamepad::master.axisLeftY(); // Gets amount forward/backward from left joystick - int turn = gamepad::master.axisRightX(); // Gets the turn left/right from right joystick + int dir = gamepad::master.axisLeftY() * 127; // Gets amount forward/backward from left joystick + int turn = gamepad::master.axisRightX() * 127; // Gets the turn left/right from right joystick left_mg.move(dir - turn); // Sets left motor voltage right_mg.move(dir + turn); // Sets right motor voltage pros::delay(25); // Wait for 25 ms, then update the motor values again From 057f8d770ee540a30148bae3c61676618728ddcb Mon Sep 17 00:00:00 2001 From: lufimio Date: Tue, 19 Nov 2024 18:06:32 -0500 Subject: [PATCH 081/108] ci: :fire: remove .devcontainer files because of licence stuff --- .devcontainer/Dockerfile | 62 ---------------------------- .devcontainer/devcontainer.json | 14 ------- .devcontainer/packagelist | 6 --- .devcontainer/postCreateCommand.bash | 8 ---- 4 files changed, 90 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .devcontainer/devcontainer.json delete mode 100644 .devcontainer/packagelist delete mode 100755 .devcontainer/postCreateCommand.bash diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 1214dab..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,62 +0,0 @@ -FROM rust:1.67 as builder - -RUN git clone https://github.com/ion098/vex-v5-qemu.git -b feat/hot-cold --single-branch /vex-v5-qemu - -WORKDIR /vex-v5-qemu -RUN cd packages/kernel; cargo build --target-dir /target/kernel - -RUN cd packages/client-cli; cargo install --path . --root /target/client-cli - -FROM mcr.microsoft.com/devcontainers/cpp:1.0-jammy -# ------------ -# Install Required Packages -# ------------ -RUN sudo apt-get update -COPY ./.devcontainer/packagelist /packagelist -RUN sudo apt-get -y install $(cat /packagelist) -RUN rm /packagelist # Cleanup image -RUN sudo apt-get clean # Cleanup image - -# ------------ -# Install Clangd -# ------------ -RUN curl -sLo clangd.zip $( \ - curl -s https://api.github.com/repos/clangd/clangd/releases/latest \ - | jq -r '[.assets[] | select(.name | test ("^clangd-linux"))][0].browser_download_url' \ - ) \ - && unzip clangd.zip -d /usr/local/share \ - && mv /usr/local/share/clangd_*/ /usr/local/share/clangd \ - && rm clangd.zip - -ENV PATH="$PATH:/usr/local/share/clangd/bin" - -# ------------ -# Install PROS CLI -# ------------ -RUN python3 -m pip install pros-cli - -# ------------ -# Install ARM Toolchain -# ------------ -COPY --from=ghcr.io/lemlib/pros-build:v2.0.2 /gcc-arm-none-eabi-10.3-2021.10 /usr/local/share/arm-none-eabi -ENV PATH="$PATH:/usr/local/share/arm-none-eabi/bin" - -# Copy the simulator binary -COPY --from=builder /target/client-cli/bin/client-cli /usr/local/bin/simulator - -# Clone pros kernel source so we can reference it when debugging -COPY ./project.pros /project.pros -ENV PROS_SOURCE_PATH="$HOME/.pros" -RUN git clone https://github.com/purduesigbots/pros.git $PROS_SOURCE_PATH \ - --depth 1 \ - --branch $(> ~/.bashrc -popd From 7e00807679534119571ce56ffc19e21c1f95514b Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:13:55 -0800 Subject: [PATCH 082/108] chore: :technologist: add devcontainer setup with sim --- .devcontainer/Dockerfile | 62 ++++++++++++++++++++++++++++ .devcontainer/LICENSE | 27 ++++++++++++ .devcontainer/devcontainer.json | 22 +++++++++- .devcontainer/packagelist | 7 ++++ .devcontainer/postCreateCommand.bash | 8 ---- LICENSE | 5 +++ 6 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/LICENSE create mode 100644 .devcontainer/packagelist delete mode 100755 .devcontainer/postCreateCommand.bash diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..d5222a4 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,62 @@ +FROM rust:1.67 as builder + +RUN git clone https://github.com/vexide/vex-v5-qemu.git /vex-v5-qemu + +WORKDIR /vex-v5-qemu +RUN cd packages/kernel; cargo build --target-dir /target/kernel + +RUN cd packages/client-cli; cargo install --path . --root /target/client-cli + +FROM mcr.microsoft.com/devcontainers/cpp:1-noble +# ------------ +# Install Required Packages +# ------------ +RUN sudo apt-get update +COPY ./.devcontainer/packagelist /packagelist +RUN sudo apt-get -y install $(cat /packagelist | sed 's/\r//') +RUN rm /packagelist # Cleanup image +RUN sudo apt-get clean # Cleanup image + +# ------------ +# Install Clangd +# ------------ +RUN curl -sLo clangd.zip $( \ + curl -s https://api.github.com/repos/clangd/clangd/releases/latest \ + | jq -r '[.assets[] | select(.name | test ("^clangd-linux"))][0].browser_download_url' \ + ) \ + && unzip clangd.zip -d /usr/local/share \ + && mv /usr/local/share/clangd_*/ /usr/local/share/clangd \ + && rm clangd.zip + +ENV PATH="$PATH:/usr/local/share/clangd/bin" + +# ------------ +# Install PROS CLI +# ------------ +RUN pip install --break-system-packages pros-cli + +# ------------ +# Install ARM Toolchain +# ------------ +COPY --from=ghcr.io/lemlib/pros-build:v2.0.2 /gcc-arm-none-eabi-10.3-2021.10 /usr/local/share/arm-none-eabi +ENV PATH="$PATH:/usr/local/share/arm-none-eabi/bin" + +# Copy the simulator binary +COPY --from=builder /target/client-cli/bin/client-cli /usr/local/bin/simulator + +# Clone pros kernel source so we can reference it when debugging +COPY ./project.pros /project.pros +ENV PROS_SOURCE_PATH="$HOME/.pros" +RUN git clone https://github.com/purduesigbots/pros.git $PROS_SOURCE_PATH \ + --depth 1 \ + --branch $(> ~/.bashrc -popd diff --git a/LICENSE b/LICENSE index b996582..5f38925 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,8 @@ +All files in this repository are licensed under the MIT license as follows, +unless otherwise noted in another LICENSE file + +===== BEGIN LICENSE ===== + MIT License Copyright (c) 2024 Jamie Maki-Fern, Ayaan (ion098), and other contributors From 1c07cd36ff742283cbf420ba17e5f4f575690a23 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:28:02 -0800 Subject: [PATCH 083/108] fix: :bug: Fix bugs in Deadband, ExpoCurve, and Transformation (Note: Fisheye is still broken) --- src/gamepad/joystick_transformation.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gamepad/joystick_transformation.cpp b/src/gamepad/joystick_transformation.cpp index 10f08d1..18ec32a 100644 --- a/src/gamepad/joystick_transformation.cpp +++ b/src/gamepad/joystick_transformation.cpp @@ -12,8 +12,8 @@ std::pair Deadband::get_value(std::pair value) { float y = value.second; float x_deadband = m_x_deadband + abs(y) * m_x_spread; float y_deadband = m_y_deadband + abs(x) * m_y_spread; - float x_scale = 1 - x_deadband; - float y_scale = 1 - y_deadband; + float x_scale = 1.0 / (1.0 - x_deadband); + float y_scale = 1.0 / (1.0 - y_deadband); x = copysign(abs(x) < x_deadband ? 0 : (abs(x) - x_deadband) * x_scale, x); y = copysign(abs(y) < y_deadband ? 0 : (abs(y) - y_deadband) * y_scale, y); return {x, y}; @@ -23,7 +23,7 @@ std::pair ExpoCurve::get_value(std::pair value) { float x = value.first; float y = value.second; x = copysign(pow(abs(x), m_x_curve), x); - x = copysign(pow(abs(y), m_y_curve), y); + y = copysign(pow(abs(y), m_y_curve), y); return {x, y}; } @@ -44,8 +44,7 @@ std::pair Fisheye::get_value(std::pair value) { } std::pair Transformation::get_value(std::pair value) { - std::pair ret_value {}; - return std::accumulate(m_all_transforms.begin(), m_all_transforms.end(), ret_value, + return std::accumulate(m_all_transforms.begin(), m_all_transforms.end(), value, [](auto last_val, auto& next_transform) { return next_transform->get_value(last_val); }); } } // namespace gamepad \ No newline at end of file From 371182de78831aeab0174733d3687edeb78f5aa6 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:32:46 -0800 Subject: [PATCH 084/108] fix: :bug: Fix bug in Fisheye --- src/gamepad/joystick_transformation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gamepad/joystick_transformation.cpp b/src/gamepad/joystick_transformation.cpp index 18ec32a..225c2d1 100644 --- a/src/gamepad/joystick_transformation.cpp +++ b/src/gamepad/joystick_transformation.cpp @@ -35,8 +35,8 @@ std::pair Fisheye::get_value(std::pair value) { float j = std::sqrt(m_radius * m_radius - 1.0 * 1.0); if (x_abs >= j && y_abs >= j) { float theta = std::atan2(y_abs, x_abs); - x_abs *= std::acos(abs(std::remainder(theta, 90))); - y_abs *= std::acos(abs(std::remainder(theta, 90))); + x_abs *= m_radius / std::cos(abs(std::remainder(theta, 90))); + y_abs *= m_radius / std::cos(abs(std::remainder(theta, 90))); } x = std::copysign(std::min(1.0f, x_abs), x); y = std::copysign(std::min(1.0f, y_abs), y); From d2c4702acd5ec6dd64b3dc1baae3395d52915eae Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:30:19 -0800 Subject: [PATCH 085/108] refactor: :recycle: change method names to use lowerCamelCase --- .vscode/settings.json | 5 +++ include/gamepad/button.hpp | 28 +++++++-------- include/gamepad/event_handler.hpp | 6 ++-- include/gamepad/gamepad.hpp | 8 ++--- include/gamepad/recursive_mutex.hpp | 2 +- include/gamepad/screens/abstractScreen.hpp | 6 ++-- include/gamepad/screens/alertScreen.hpp | 4 +-- include/gamepad/screens/defaultScreen.hpp | 6 ++-- src/gamepad/button.cpp | 40 +++++++++++----------- src/gamepad/gamepad.cpp | 14 ++++---- src/gamepad/screens/alertScreen.cpp | 4 +-- src/gamepad/screens/defaultScreen.cpp | 14 ++++---- src/main.cpp | 6 ++-- 13 files changed, 74 insertions(+), 69 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b242572 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "main" + ] +} \ No newline at end of file diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index b867da7..2748827 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -42,14 +42,14 @@ class Button { * @b Example: * @code {.cpp} * // change the threshold - * gamepad::master.Left.set_long_press_threshold(5000); + * gamepad::master.Left.setLongPressThreshold(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; + void setLongPressThreshold(uint32_t threshold) const; /** * @brief Set the interval for the repeatPress event to repeat * @@ -60,14 +60,14 @@ class Button { * @b Example: * @code {.cpp} * // change the threshold - * gamepad::master.Up.set_repeat_cooldown(100); + * gamepad::master.Up.setRepeatCooldown(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; + void setRepeatCooldown(uint32_t cooldown) const; /** * @brief Register a function to run when the button is pressed. * @@ -89,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 via the set_long_press_threshold() method. + * 500ms or more, this threshold can be adjusted via the setLongPressThreshold() method. * * @warning When using this event along with onPress, both the onPress * and onlongPress listeners may fire together. @@ -130,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 via the set_long_press_threshold() method. + * adjusted via the setLongPressThreshold() method. * * @note This event will most likely be used along with the longPress event. * @@ -152,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 via the set_long_press_threshold() method. + * adjusted via the setLongPressThreshold() 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 @@ -173,7 +173,7 @@ class Button { * @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 adjusted via the - * set_long_press_threshold() and set_repeat_cooldown() methods respectively + * setLongPressThreshold() and setRepeatCooldown() 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 @@ -250,11 +250,11 @@ class Button { uint32_t last_long_press_time = 0; /// The last time the repeat event was called uint32_t last_repeat_time = 0; - mutable _impl::EventHandler onPressEvent {}; - mutable _impl::EventHandler onLongPressEvent {}; - mutable _impl::EventHandler onReleaseEvent {}; - mutable _impl::EventHandler onShortReleaseEvent {}; - mutable _impl::EventHandler onLongReleaseEvent {}; - mutable _impl::EventHandler onRepeatPressEvent {}; + mutable _impl::EventHandler on_press_event {}; + mutable _impl::EventHandler on_long_press_event {}; + mutable _impl::EventHandler on_release_event {}; + mutable _impl::EventHandler on_short_release_event {}; + mutable _impl::EventHandler on_long_release_event {}; + mutable _impl::EventHandler on_repeat_press_event {}; }; } // namespace gamepad \ No newline at end of file diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index bf51b20..9a480c8 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -27,7 +27,7 @@ template class EventHandler { * @return true The listener was successfully added * @return false The listener was NOT successfully added (there is already a listener with the same key) */ - bool add_listener(Key key, Listener func) { + bool addListener(Key key, Listener func) { std::lock_guard lock(mutex); if (std::find(keys.begin(), keys.end(), key) != keys.end()) return false; keys.push_back(key); @@ -42,7 +42,7 @@ template class EventHandler { * @return true The listener was successfully removed * @return false The listener was NOT successfully removed (there is no listener with the same key) */ - bool remove_listener(Key key) { + bool removeListener(Key key) { std::lock_guard lock(mutex); auto i = std::find(keys.begin(), keys.end(), key); if (i != keys.end()) { @@ -59,7 +59,7 @@ template class EventHandler { * @return true There are listeners registered * @return false There are no listeners registered */ - bool is_empty() { + bool isEmpty() { std::lock_guard lock(mutex); return listeners.empty(); } diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 5037870..45b1877 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -51,10 +51,10 @@ class Gamepad { * * @b Example: * @code {.cpp} - * gamepad::master.print_line(1, "This will print on the middle line"); - * gamepad::master.print_line(0, "this will print\n\naround the middle line"); + * gamepad::master.printLine(1, "This will print on the middle line"); + * gamepad::master.printLine(0, "this will print\n\naround the middle line"); */ - void print_line(uint8_t line, std::string str); + void printLine(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) * @@ -145,7 +145,7 @@ class Gamepad { * @brief Gets a unique name for a listener that will not conflict with user listener names. * * @important: when using the function, you must register the listener by - * directly calling add_listener on the EventHandler, do NOT use onPress/addListener,etc. + * directly calling addListener on the EventHandler, do NOT use onPress/addListener,etc. * * @return std::string A unique listener name */ diff --git a/include/gamepad/recursive_mutex.hpp b/include/gamepad/recursive_mutex.hpp index cd84052..caeaf9e 100644 --- a/include/gamepad/recursive_mutex.hpp +++ b/include/gamepad/recursive_mutex.hpp @@ -37,7 +37,7 @@ class RecursiveMutex { * @return true The mutex was successfully acquired * @return false The mutex was not successfully acquired */ - bool try_lock() { return this->take(0); } + bool tryLock() { return this->take(0); } /** * @brief Unlocks the mutex diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 1c23b21..0bc5866 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -41,21 +41,21 @@ class AbstractScreen { * * @returns a the lines to be printed, any lines that are not available will be ignored */ - virtual ScreenBuffer get_screen(std::set visible_lines) = 0; + virtual ScreenBuffer getScreen(std::set visible_lines) = 0; /** * @brief a function where button events are pushed, use this to handle button events. * * @param button_events a set of the button events that happened this update */ - virtual void handle_events(std::set button_events) {} + virtual void handleEvents(std::set button_events) {} /** * @brief returns the priority of the screen * * @important it is not reccomended to override this function */ - uint32_t get_priority() { return this->priority; } + uint32_t getPriority() { return this->priority; } protected: const uint32_t priority; }; diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 694771b..718b5af 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -35,7 +35,7 @@ class AlertScreen : public AbstractScreen { * * @returns a the lines to be printed, any lines that are not available will be ignored */ - ScreenBuffer get_screen(std::set visible_lines); + ScreenBuffer getScreen(std::set visible_lines); /** * @brief add an alert to the alert queue, to be printed as soon as there is an available space @@ -47,7 +47,7 @@ class AlertScreen : public AbstractScreen { * @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. */ - void add_alerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); + void addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { ScreenBuffer screen; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index d2a26c8..285b3b2 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -24,7 +24,7 @@ class DefaultScreen : public AbstractScreen { * * @returns a the lines to be printed, any lines that are not available will be ignored */ - ScreenBuffer get_screen(std::set visible_lines); + ScreenBuffer getScreen(std::set visible_lines); /** * @brief print a line to the console like pros @@ -32,7 +32,7 @@ class DefaultScreen : public AbstractScreen { * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) */ - void print_line(uint8_t line, std::string str); + void printLine(uint8_t line, std::string str); /** * makes the controller rumble like pros @@ -42,7 +42,7 @@ class DefaultScreen : public AbstractScreen { */ void rumble(std::string rumble_pattern); private: - ScreenBuffer currentBuffer {}; + ScreenBuffer current_buffer {}; pros::Mutex mut {}; }; diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 9c0bb98..ff99586 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -4,32 +4,32 @@ #include namespace gamepad { -void Button::set_long_press_threshold(uint32_t threshold) const { this->long_press_threshold = threshold; } +void Button::setLongPressThreshold(uint32_t threshold) const { this->long_press_threshold = threshold; } -void Button::set_repeat_cooldown(uint32_t cooldown) const { this->repeat_cooldown = cooldown; } +void Button::setRepeatCooldown(uint32_t cooldown) const { this->repeat_cooldown = cooldown; } bool Button::onPress(std::string listenerName, std::function func) const { - return this->onPressEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onLongPress(std::string listenerName, std::function func) const { - return this->onLongPressEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onRelease(std::string listenerName, std::function func) const { - return this->onReleaseEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onShortRelease(std::string listenerName, std::function func) const { - return this->onShortReleaseEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onLongRelease(std::string listenerName, std::function func) const { - return this->onLongReleaseEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onRepeatPress(std::string listenerName, std::function func) const { - return this->onRepeatPressEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); + return this->on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::addListener(EventType event, std::string listenerName, std::function func) const { @@ -49,12 +49,12 @@ bool Button::addListener(EventType event, std::string listenerName, std::functio } bool Button::removeListener(std::string listenerName) const { - return this->onPressEvent.remove_listener(listenerName + "_user") || - this->onLongPressEvent.remove_listener(listenerName + "_user") || - this->onReleaseEvent.remove_listener(listenerName + "_user") || - this->onShortReleaseEvent.remove_listener(listenerName + "_user") || - this->onLongReleaseEvent.remove_listener(listenerName + "_user") || - this->onRepeatPressEvent.remove_listener(listenerName + "_user"); + return this->on_press_event.removeListener(listenerName + "_user") || + this->on_long_press_event.removeListener(listenerName + "_user") || + this->on_release_event.removeListener(listenerName + "_user") || + this->on_short_release_event.removeListener(listenerName + "_user") || + this->on_long_release_event.removeListener(listenerName + "_user") || + this->on_repeat_press_event.removeListener(listenerName + "_user"); } void Button::update(const bool is_held) { @@ -65,22 +65,22 @@ void Button::update(const bool is_held) { else this->time_released += pros::millis() - this->last_update_time; if (this->rising_edge) { - this->onPressEvent.fire(); + this->on_press_event.fire(); } else if (this->is_pressed && this->time_held >= this->long_press_threshold && this->last_long_press_time <= pros::millis() - this->time_held) { - this->onLongPressEvent.fire(); + this->on_long_press_event.fire(); this->last_long_press_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) { this->repeat_iterations++; - this->onRepeatPressEvent.fire(); + this->on_repeat_press_event.fire(); this->last_repeat_time = pros::millis(); } else if (this->falling_edge) { - this->onReleaseEvent.fire(); - if (this->time_held < this->long_press_threshold) this->onShortReleaseEvent.fire(); - else this->onLongReleaseEvent.fire(); + this->on_release_event.fire(); + if (this->time_held < this->long_press_threshold) this->on_short_release_event.fire(); + else this->on_long_release_event.fire(); } if (this->rising_edge) this->time_held = 0; diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 7053d8b..c3afb33 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -55,7 +55,7 @@ void Gamepad::updateScreens() { // Update all screens, and send new button presses, also note deltatime for (std::shared_ptr screen : this->screens) { screen->update(pros::millis() - this->last_update_time); - screen->handle_events(buttonUpdates); + screen->handleEvents(buttonUpdates); } this->last_update_time = pros::millis(); @@ -69,7 +69,7 @@ void Gamepad::updateScreens() { if (!this->nextBuffer[j].has_value()) visible_lines.emplace(j); // get the buffer of the next lower priority screen and set it to be printed - ScreenBuffer buffer = screen->get_screen(visible_lines); + ScreenBuffer buffer = screen->getScreen(visible_lines); for (uint8_t j = 0; j < 4; j++) if (buffer[j].has_value() && !buffer[j]->empty() && !nextBuffer[j].has_value()) nextBuffer[j] = std::move(buffer[j]); @@ -124,17 +124,17 @@ void Gamepad::add_screen(std::shared_ptr screen) { uint32_t last = UINT32_MAX; uint32_t pos = 0; for (pos = 0; pos < this->screens.size(); pos++) { - if (this->screens[pos]->get_priority() < screen->get_priority() && last >= screen->get_priority()) break; - last = this->screens[pos]->get_priority(); + if (this->screens[pos]->getPriority() < screen->getPriority() && last >= screen->getPriority()) break; + last = this->screens[pos]->getPriority(); } this->screens.emplace(this->screens.begin() + pos, screen); } -void Gamepad::print_line(uint8_t line, std::string str) { this->defaultScreen->print_line(line, str); } +void Gamepad::printLine(uint8_t line, std::string str) { this->defaultScreen->printLine(line, str); } -void Gamepad::clear() { this->defaultScreen->print_line(0, " \n \n "); } +void Gamepad::clear() { this->defaultScreen->printLine(0, " \n \n "); } -void Gamepad::clear(uint8_t line) { this->defaultScreen->print_line(line, " "); } +void Gamepad::clear(uint8_t line) { this->defaultScreen->printLine(line, " "); } void Gamepad::rumble(std::string rumble_pattern) { this->defaultScreen->rumble(rumble_pattern); } diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 4a45394..5de5e66 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -9,7 +9,7 @@ namespace gamepad { -ScreenBuffer AlertScreen::get_screen(std::set visible_lines) { +ScreenBuffer AlertScreen::getScreen(std::set visible_lines) { std::lock_guard guard(this->mut); if (this->screen_contents.has_value()) { this->screen_contents->screen.at(3) = std::nullopt; @@ -32,7 +32,7 @@ void AlertScreen::update(uint32_t delta_time) { if (pros::millis() - this->line_set_time >= this->screen_contents->duration) this->screen_contents = std::nullopt; } -void AlertScreen::add_alerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { +void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 1afd516..e1ba646 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -9,18 +9,18 @@ namespace gamepad { -ScreenBuffer DefaultScreen::get_screen(std::set visible_lines) { +ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { ScreenBuffer output; const std::lock_guard guard(this->mut); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { - output[*i] = std::move(this->currentBuffer[*i]); - this->currentBuffer[*i] = std::nullopt; + output[*i] = std::move(this->current_buffer[*i]); + this->current_buffer[*i] = std::nullopt; } return output; } -void DefaultScreen::print_line(uint8_t line, std::string str) { +void DefaultScreen::printLine(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); @@ -38,12 +38,12 @@ void DefaultScreen::print_line(uint8_t line, std::string str) { } for (uint8_t l = 0; l < 3; l++) { - if (!strs[l].empty()) this->currentBuffer[l] = (strs[l]); + if (!strs[l].empty()) this->current_buffer[l] = (strs[l]); } return; } - this->currentBuffer[line] = std::move(str); + this->current_buffer[line] = std::move(str); } void DefaultScreen::rumble(std::string rumble_pattern) { @@ -51,7 +51,7 @@ void DefaultScreen::rumble(std::string rumble_pattern) { if (rumble_pattern.size() > 8) std::exit(1); std::lock_guard guard(this->mut); - this->currentBuffer[3] = std::move(rumble_pattern); + this->current_buffer[3] = std::move(rumble_pattern); } } // namespace gamepad \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2a7081d..fdf30a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,20 +24,20 @@ void initialize() { // When the A button is pressed, schedule an alert that spans all three // lines, lasts 3 seconds and rumbles in a long-short-long pattern gamepad::master.A.onPress("alert", []() { - alerts->add_alerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); + alerts->addAlerts(0, "a very\nimportant alert\nat " + std::to_string(pros::millis()) + " ms", 3000, "-.-"); }); // Normally print a string on the first and third line without overriding // the second line when the B button is pressed gamepad::master.B.onPress( - "print02", []() { gamepad::master.print_line(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); + "print02", []() { gamepad::master.printLine(0, "the time is\n\n" + std::to_string(pros::millis()) + " ms"); }); // rumbles 3 times for a short duration when the X button is pressed gamepad::master.X.onPress("rumble", []() { gamepad::master.rumble("..."); }); // when the Y button is pressed and held the text should show up, and when // the button is released it should be cleared - gamepad::master.Y.onPress("print1", []() { gamepad::master.print_line(1, "this should be cleared"); }); + gamepad::master.Y.onPress("print1", []() { gamepad::master.printLine(1, "this should be cleared"); }); gamepad::master.Y.onRelease("clear1", []() { gamepad::master.clear(1); }); } From 41d3ee3d75cad96a41fdb3313cf75f62fca4dd4c Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Tue, 31 Dec 2024 09:49:12 -0800 Subject: [PATCH 086/108] refactor: :recycle: Change all member variables to use m_, remove usage of this-> --- include/gamepad/button.hpp | 24 ++--- include/gamepad/event_handler.hpp | 32 +++--- include/gamepad/gamepad.hpp | 30 +++--- include/gamepad/recursive_mutex.hpp | 4 +- include/gamepad/screens/abstractScreen.hpp | 10 +- include/gamepad/screens/alertScreen.hpp | 8 +- include/gamepad/screens/defaultScreen.hpp | 4 +- src/gamepad/button.cpp | 60 ++++++------ src/gamepad/gamepad.cpp | 108 ++++++++++----------- src/gamepad/screens/alertScreen.cpp | 30 +++--- src/gamepad/screens/defaultScreen.cpp | 16 +-- src/main.cpp | 4 +- 12 files changed, 165 insertions(+), 165 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index 2748827..1e25cff 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -92,7 +92,7 @@ class Button { * 500ms or more, this threshold can be adjusted via the setLongPressThreshold() method. * * @warning When using this event along with onPress, both the onPress - * and onlongPress listeners may fire together. + * and onLongPress listeners may fire together. * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is long pressed, the function MUST NOT block @@ -241,20 +241,20 @@ class Button { */ void update(bool is_held); /// How long the threshold should be for the longPress and shortRelease events - mutable uint32_t long_press_threshold = 500; + mutable uint32_t m_long_press_threshold = 500; /// How often repeatPress is called - mutable uint32_t repeat_cooldown = 50; + mutable uint32_t m_repeat_cooldown = 50; /// The last time the update function was called - uint32_t last_update_time = pros::millis(); + uint32_t m_last_update_time = pros::millis(); /// The last time the long press event was fired - uint32_t last_long_press_time = 0; + uint32_t m_last_long_press_time = 0; /// The last time the repeat event was called - uint32_t last_repeat_time = 0; - mutable _impl::EventHandler on_press_event {}; - mutable _impl::EventHandler on_long_press_event {}; - mutable _impl::EventHandler on_release_event {}; - mutable _impl::EventHandler on_short_release_event {}; - mutable _impl::EventHandler on_long_release_event {}; - mutable _impl::EventHandler on_repeat_press_event {}; + uint32_t m_last_repeat_time = 0; + mutable _impl::EventHandler m_on_press_event {}; + mutable _impl::EventHandler m_on_long_press_event {}; + mutable _impl::EventHandler m_on_release_event {}; + mutable _impl::EventHandler m_on_short_release_event {}; + mutable _impl::EventHandler m_on_long_release_event {}; + mutable _impl::EventHandler m_on_repeat_press_event {}; }; } // namespace gamepad \ No newline at end of file diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index 9a480c8..a5a7a5b 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -28,10 +28,10 @@ template class EventHandler { * @return false The listener was NOT successfully added (there is already a listener with the same key) */ bool addListener(Key key, Listener func) { - std::lock_guard lock(mutex); - if (std::find(keys.begin(), keys.end(), key) != keys.end()) return false; - keys.push_back(key); - listeners.push_back(func); + std::lock_guard lock(m_mutex); + if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return false; + m_keys.push_back(key); + m_listeners.push_back(func); return true; } @@ -43,11 +43,11 @@ template class EventHandler { * @return false The listener was NOT successfully removed (there is no listener with the same key) */ bool removeListener(Key key) { - std::lock_guard lock(mutex); - auto i = std::find(keys.begin(), keys.end(), key); - if (i != keys.end()) { - keys.erase(i); - listeners.erase(listeners.begin() + (i - keys.begin())); + std::lock_guard lock(m_mutex); + auto i = std::find(m_keys.begin(), m_keys.end(), key); + if (i != m_keys.end()) { + m_keys.erase(i); + m_listeners.erase(m_listeners.begin() + (i - m_keys.begin())); return true; } return false; @@ -60,8 +60,8 @@ template class EventHandler { * @return false There are no listeners registered */ bool isEmpty() { - std::lock_guard lock(mutex); - return listeners.empty(); + std::lock_guard lock(m_mutex); + return m_listeners.empty(); } /** @@ -70,12 +70,12 @@ template class EventHandler { * @param args The parameters to pass to each listener */ void fire(Args... args) { - std::lock_guard lock(mutex); - for (auto listener : listeners) { listener(args...); } + std::lock_guard lock(m_mutex); + for (auto listener : m_listeners) { listener(args...); } } private: - std::vector keys {}; - std::vector listeners {}; - gamepad::_impl::RecursiveMutex mutex {}; + std::vector m_keys {}; + std::vector m_listeners {}; + gamepad::_impl::RecursiveMutex m_mutex {}; }; } // namespace gamepad::_impl diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 45b1877..901739f 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -31,7 +31,7 @@ class Gamepad { */ void update(); /** - * @brief Add a screen to the sceen update loop that can update the controller's screen + * @brief Add a screen to the screen update loop that can update the controller's screen * * @param screen the `AbstractScreen` to add to the screen queue * @@ -42,7 +42,7 @@ class Gamepad { * * gamepad::master.add_screen(alerts); */ - void add_screen(std::shared_ptr screen); + void addScreen(std::shared_ptr screen); /** * @brief print a line to the console like pros (low priority) * @@ -83,7 +83,7 @@ class Gamepad { * * @b Example: * @code {.cpp} - * // rumbles in the folllowing pattern: short, pause, long, short short + * // rumbles in the following pattern: short, pause, long, short short * gamepad::master.rumble(". -.."); */ void rumble(std::string rumble_pattern); @@ -149,23 +149,23 @@ class Gamepad { * * @return std::string A unique listener name */ - static std::string unique_name(); - static Button Gamepad::*button_to_ptr(pros::controller_digital_e_t button); + static std::string uniqueName(); + static Button Gamepad::*buttonToPtr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreens(); - std::shared_ptr defaultScreen = std::make_shared(); - std::vector> screens = {}; - ScreenBuffer currentScreen = {}; - ScreenBuffer nextBuffer = {}; - pros::Controller controller; + std::shared_ptr m_default_screen = std::make_shared(); + std::vector> m_screens = {}; + ScreenBuffer m_current_screen = {}; + ScreenBuffer m_next_buffer = {}; + pros::Controller m_controller; - uint8_t last_printed_line = 0; - uint32_t last_print_time = 0; - uint32_t last_update_time = 0; - bool screenCleared = false; - pros::Mutex mut {}; + uint8_t m_last_printed_line = 0; + uint32_t m_last_print_time = 0; + uint32_t m_last_update_time = 0; + bool m_screen_cleared = false; + pros::Mutex m_mutex {}; }; inline Gamepad Gamepad::master {pros::E_CONTROLLER_MASTER}; diff --git a/include/gamepad/recursive_mutex.hpp b/include/gamepad/recursive_mutex.hpp index caeaf9e..0df16c3 100644 --- a/include/gamepad/recursive_mutex.hpp +++ b/include/gamepad/recursive_mutex.hpp @@ -24,7 +24,7 @@ class RecursiveMutex { bool take(std::uint32_t timeout = TIMEOUT_MAX) { return pros::c::mutex_recursive_take(mutex, timeout); } /** - * @brief Locks the mutex, waiting indefinetely until the mutex is acquired + * @brief Locks the mutex, waiting indefinitely until the mutex is acquired * */ void lock() { @@ -37,7 +37,7 @@ class RecursiveMutex { * @return true The mutex was successfully acquired * @return false The mutex was not successfully acquired */ - bool tryLock() { return this->take(0); } + bool try_lock() { return this->take(0); } /** * @brief Unlocks the mutex diff --git a/include/gamepad/screens/abstractScreen.hpp b/include/gamepad/screens/abstractScreen.hpp index 0bc5866..2e0f91d 100644 --- a/include/gamepad/screens/abstractScreen.hpp +++ b/include/gamepad/screens/abstractScreen.hpp @@ -22,11 +22,11 @@ typedef std::array, 4> ScreenBuffer; class AbstractScreen { public: AbstractScreen(uint32_t priority) - : priority(priority) {} + : m_priority(priority) {} /** * @brief runs every time the controller's update function is called - * use this if you need to update somthing regardless of if there is an + * use this if you need to update something regardless of if there is an * available slot in the screen * * @param delta_time the time since the last update in milliseconds @@ -53,11 +53,11 @@ class AbstractScreen { /** * @brief returns the priority of the screen * - * @important it is not reccomended to override this function + * @warning it is not recommended to override this function */ - uint32_t getPriority() { return this->priority; } + uint32_t getPriority() { return m_priority; } protected: - const uint32_t priority; + const uint32_t m_priority; }; } // namespace gamepad diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 718b5af..50a40cc 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -54,10 +54,10 @@ class AlertScreen : public AbstractScreen { uint32_t duration; }; - std::deque screen_buffer {}; - std::optional screen_contents {}; - uint32_t line_set_time = 0; - pros::Mutex mut {}; + std::deque m_screen_buffer {}; + std::optional m_screen_contents {}; + uint32_t m_line_set_time = 0; + pros::Mutex m_mutex {}; }; } // namespace gamepad diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 285b3b2..f85363e 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -42,8 +42,8 @@ class DefaultScreen : public AbstractScreen { */ void rumble(std::string rumble_pattern); private: - ScreenBuffer current_buffer {}; - pros::Mutex mut {}; + ScreenBuffer m_current_buffer {}; + pros::Mutex m_mutex {}; }; } // namespace gamepad diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index ff99586..d3f3965 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -4,32 +4,32 @@ #include namespace gamepad { -void Button::setLongPressThreshold(uint32_t threshold) const { this->long_press_threshold = threshold; } +void Button::setLongPressThreshold(uint32_t threshold) const { m_long_press_threshold = threshold; } -void Button::setRepeatCooldown(uint32_t cooldown) const { this->repeat_cooldown = cooldown; } +void Button::setRepeatCooldown(uint32_t cooldown) const { m_repeat_cooldown = cooldown; } bool Button::onPress(std::string listenerName, std::function func) const { - return this->on_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onLongPress(std::string listenerName, std::function func) const { - return this->on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onRelease(std::string listenerName, std::function func) const { - return this->on_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onShortRelease(std::string listenerName, std::function func) const { - return this->on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onLongRelease(std::string listenerName, std::function func) const { - return this->on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::onRepeatPress(std::string listenerName, std::function func) const { - return this->on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); + return m_on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } bool Button::addListener(EventType event, std::string listenerName, std::function func) const { @@ -49,42 +49,42 @@ bool Button::addListener(EventType event, std::string listenerName, std::functio } bool Button::removeListener(std::string listenerName) const { - return this->on_press_event.removeListener(listenerName + "_user") || - this->on_long_press_event.removeListener(listenerName + "_user") || - this->on_release_event.removeListener(listenerName + "_user") || - this->on_short_release_event.removeListener(listenerName + "_user") || - this->on_long_release_event.removeListener(listenerName + "_user") || - this->on_repeat_press_event.removeListener(listenerName + "_user"); + return m_on_press_event.removeListener(listenerName + "_user") || + m_on_long_press_event.removeListener(listenerName + "_user") || + m_on_release_event.removeListener(listenerName + "_user") || + m_on_short_release_event.removeListener(listenerName + "_user") || + m_on_long_release_event.removeListener(listenerName + "_user") || + m_on_repeat_press_event.removeListener(listenerName + "_user"); } void Button::update(const bool is_held) { this->rising_edge = !this->is_pressed && is_held; this->falling_edge = this->is_pressed && !is_held; this->is_pressed = is_held; - if (is_held) this->time_held += pros::millis() - this->last_update_time; - else this->time_released += pros::millis() - this->last_update_time; + if (is_held) this->time_held += pros::millis() - m_last_update_time; + else this->time_released += pros::millis() - m_last_update_time; if (this->rising_edge) { - this->on_press_event.fire(); - } else if (this->is_pressed && this->time_held >= this->long_press_threshold && - this->last_long_press_time <= pros::millis() - this->time_held) { - this->on_long_press_event.fire(); - this->last_long_press_time = pros::millis(); - this->last_repeat_time = pros::millis() - this->repeat_cooldown; + m_on_press_event.fire(); + } else if (this->is_pressed && this->time_held >= m_long_press_threshold && + m_last_long_press_time <= pros::millis() - this->time_held) { + m_on_long_press_event.fire(); + m_last_long_press_time = pros::millis(); + m_last_repeat_time = pros::millis() - m_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) { + } else if (this->is_pressed && this->time_held >= m_long_press_threshold && + pros::millis() - m_last_repeat_time >= m_repeat_cooldown) { this->repeat_iterations++; - this->on_repeat_press_event.fire(); - this->last_repeat_time = pros::millis(); + m_on_repeat_press_event.fire(); + m_last_repeat_time = pros::millis(); } else if (this->falling_edge) { - this->on_release_event.fire(); - if (this->time_held < this->long_press_threshold) this->on_short_release_event.fire(); - else this->on_long_release_event.fire(); + m_on_release_event.fire(); + if (this->time_held < m_long_press_threshold) m_on_short_release_event.fire(); + else m_on_long_release_event.fire(); } if (this->rising_edge) this->time_held = 0; if (this->falling_edge) this->time_released = 0; - this->last_update_time = pros::millis(); + m_last_update_time = pros::millis(); } } // namespace gamepad diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index c3afb33..486b7d7 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -14,95 +14,95 @@ namespace gamepad { Gamepad::Gamepad(pros::controller_id_e_t id) - : controller(id) { - this->add_screen(defaultScreen); + : m_controller(id) { + this->addScreen(m_default_screen); } void Gamepad::updateButton(pros::controller_digital_e_t button_id) { - Button Gamepad::*button = Gamepad::button_to_ptr(button_id); - bool is_held = this->controller.get_digital(button_id); + Button Gamepad::*button = Gamepad::buttonToPtr(button_id); + bool is_held = m_controller.get_digital(button_id); (this->*button).update(is_held); } void Gamepad::updateScreens() { // Lock Mutexes for Thread Safety - std::lock_guard guard_scheduling(this->mut); + std::lock_guard guard_scheduling(m_mutex); // Disable screen updates if the controller is disconnected - if (!this->controller.is_connected()) { - if (this->screenCleared) { - this->nextBuffer = std::move(this->currentScreen); - this->currentScreen = {}; - this->screenCleared = false; + if (!m_controller.is_connected()) { + if (m_screen_cleared) { + m_next_buffer = std::move(m_current_screen); + m_current_screen = {}; + m_screen_cleared = false; } return; } // Clear current screen and reset last update time on reconnect - if (this->controller.is_connected() && !screenCleared) { - this->currentScreen = {}; - this->last_update_time = pros::millis(); + if (m_controller.is_connected() && !m_screen_cleared) { + m_current_screen = {}; + m_last_update_time = pros::millis(); } // Get new button presses std::set buttonUpdates; for (int i = pros::E_CONTROLLER_DIGITAL_L1; i <= pros::E_CONTROLLER_DIGITAL_A; ++i) { - if ((this->*this->button_to_ptr(static_cast(i))).rising_edge) { + if ((this->*this->buttonToPtr(static_cast(i))).rising_edge) { buttonUpdates.emplace(static_cast(i)); } } // Update all screens, and send new button presses, also note deltatime - for (std::shared_ptr screen : this->screens) { - screen->update(pros::millis() - this->last_update_time); + for (std::shared_ptr screen : m_screens) { + screen->update(pros::millis() - m_last_update_time); screen->handleEvents(buttonUpdates); } - this->last_update_time = pros::millis(); + m_last_update_time = pros::millis(); // Check if enough time has passed for the Gamepad to poll for updates - if (pros::millis() - this->last_print_time <= 50) return; + if (pros::millis() - m_last_print_time <= 50) return; - for (std::shared_ptr screen : this->screens) { - // get all lines that arent being used by a higher priority screen + for (std::shared_ptr screen : m_screens) { + // get all lines that aren't being used by a higher priority screen std::set visible_lines; for (uint8_t j = 0; j < 4; j++) - if (!this->nextBuffer[j].has_value()) visible_lines.emplace(j); + if (!m_next_buffer[j].has_value()) visible_lines.emplace(j); // get the buffer of the next lower priority screen and set it to be printed ScreenBuffer buffer = screen->getScreen(visible_lines); for (uint8_t j = 0; j < 4; j++) - if (buffer[j].has_value() && !buffer[j]->empty() && !nextBuffer[j].has_value()) - nextBuffer[j] = std::move(buffer[j]); + if (buffer[j].has_value() && !buffer[j]->empty() && !m_next_buffer[j].has_value()) + m_next_buffer[j] = std::move(buffer[j]); } for (int i = 0; i < 4; i++) { // start from the line thats after the line thats been set so we dont get stuck setting the first line - int line = (this->last_printed_line + i) % 4; + int line = (m_last_printed_line + i) % 4; // theres nothing on this line so we can skip it - if (!this->nextBuffer[line].has_value()) continue; + if (!m_next_buffer[line].has_value()) continue; - if (!this->screenCleared && line != 3) { - this->controller.clear(); - this->screenCleared = true; - this->currentScreen = {}; - this->last_print_time = pros::millis(); + if (!m_screen_cleared && line != 3) { + m_controller.clear(); + m_screen_cleared = true; + m_current_screen = {}; + m_last_print_time = pros::millis(); return; } // text on screen is the same as last frame's text so no use updating - if (this->currentScreen[line] == this->nextBuffer[line] && line != 3) { - this->nextBuffer[line] = std::nullopt; + if (m_current_screen[line] == m_next_buffer[line] && line != 3) { + m_next_buffer[line] = std::nullopt; continue; } // print to screen or rumble - if (line == 3) this->controller.rumble(this->nextBuffer[line].value_or("").c_str()); - else this->controller.set_text(line, 0, this->nextBuffer[line].value_or("") + std::string(40, ' ')); - if (line != 3) this->currentScreen[line] = std::move(this->nextBuffer[line]); - this->nextBuffer[line] = std::nullopt; - this->last_printed_line = line; - this->last_print_time = pros::millis(); + if (line == 3) m_controller.rumble(m_next_buffer[line].value_or("").c_str()); + else m_controller.set_text(line, 0, m_next_buffer[line].value_or("") + std::string(40, ' ')); + if (line != 3) m_current_screen[line] = std::move(m_next_buffer[line]); + m_next_buffer[line] = std::nullopt; + m_last_printed_line = line; + m_last_print_time = pros::millis(); return; } } @@ -112,33 +112,33 @@ void Gamepad::update() { this->updateButton(static_cast(i)); } - this->m_LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X); - this->m_LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y); - this->m_RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X); - this->m_RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y); + m_LeftX = m_controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X); + m_LeftY = m_controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y); + m_RightX = m_controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X); + m_RightY = m_controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y); this->updateScreens(); } -void Gamepad::add_screen(std::shared_ptr screen) { +void Gamepad::addScreen(std::shared_ptr screen) { uint32_t last = UINT32_MAX; uint32_t pos = 0; - for (pos = 0; pos < this->screens.size(); pos++) { - if (this->screens[pos]->getPriority() < screen->getPriority() && last >= screen->getPriority()) break; - last = this->screens[pos]->getPriority(); + for (pos = 0; pos < m_screens.size(); pos++) { + if (m_screens[pos]->getPriority() < screen->getPriority() && last >= screen->getPriority()) break; + last = m_screens[pos]->getPriority(); } - this->screens.emplace(this->screens.begin() + pos, screen); + m_screens.emplace(m_screens.begin() + pos, screen); } -void Gamepad::printLine(uint8_t line, std::string str) { this->defaultScreen->printLine(line, str); } +void Gamepad::printLine(uint8_t line, std::string str) { m_default_screen->printLine(line, str); } -void Gamepad::clear() { this->defaultScreen->printLine(0, " \n \n "); } +void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); } -void Gamepad::clear(uint8_t line) { this->defaultScreen->printLine(line, " "); } +void Gamepad::clear(uint8_t line) { m_default_screen->printLine(line, " "); } -void Gamepad::rumble(std::string rumble_pattern) { this->defaultScreen->rumble(rumble_pattern); } +void Gamepad::rumble(std::string rumble_pattern) { m_default_screen->rumble(rumble_pattern); } -const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::button_to_ptr(button); } +const Button& Gamepad::operator[](pros::controller_digital_e_t button) { return this->*Gamepad::buttonToPtr(button); } float Gamepad::operator[](pros::controller_analog_e_t axis) { switch (axis) { @@ -153,12 +153,12 @@ float Gamepad::operator[](pros::controller_analog_e_t axis) { } } -std::string Gamepad::unique_name() { +std::string Gamepad::uniqueName() { static std::atomic i = 0; return std::to_string(i++) + "_internal"; } -Button Gamepad::*Gamepad::button_to_ptr(pros::controller_digital_e_t button) { +Button Gamepad::*Gamepad::buttonToPtr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; case pros::E_CONTROLLER_DIGITAL_L2: return &Gamepad::m_L2; diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 5de5e66..4d23d45 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -10,26 +10,26 @@ namespace gamepad { ScreenBuffer AlertScreen::getScreen(std::set visible_lines) { - std::lock_guard guard(this->mut); - if (this->screen_contents.has_value()) { - this->screen_contents->screen.at(3) = std::nullopt; - return this->screen_contents->screen; + std::lock_guard guard(m_mutex); + if (m_screen_contents.has_value()) { + m_screen_contents->screen.at(3) = std::nullopt; + return m_screen_contents->screen; } - if (this->screen_buffer.size() < 1) return ScreenBuffer(); + if (m_screen_buffer.size() < 1) return ScreenBuffer(); for (uint8_t i = 0; i < 4; i++) { - if (!this->screen_buffer[0].screen[i].has_value()) continue; - if (this->screen_buffer[0].screen[i].has_value() && !visible_lines.contains(i)) return ScreenBuffer(); + if (!m_screen_buffer[0].screen[i].has_value()) continue; + if (m_screen_buffer[0].screen[i].has_value() && !visible_lines.contains(i)) return ScreenBuffer(); } - this->screen_contents = std::move(this->screen_buffer[0]); - this->screen_buffer.pop_front(); - this->line_set_time = pros::millis(); - return this->screen_contents->screen; + m_screen_contents = std::move(m_screen_buffer[0]); + m_screen_buffer.pop_front(); + m_line_set_time = pros::millis(); + return m_screen_contents->screen; } void AlertScreen::update(uint32_t delta_time) { - std::lock_guard guard(this->mut); - if (pros::millis() - this->line_set_time >= this->screen_contents->duration) this->screen_contents = std::nullopt; + std::lock_guard guard(m_mutex); + if (pros::millis() - m_line_set_time >= m_screen_contents->duration) m_screen_contents = std::nullopt; } void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { @@ -54,8 +54,8 @@ void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, st if (strs[2] != "") buffer[2] = std::move(strs[2]); if (rumble != "") buffer[3] = std::move(rumble); - std::lock_guard guard(this->mut); - this->screen_buffer.push_back({buffer, duration}); + std::lock_guard guard(m_mutex); + m_screen_buffer.push_back({buffer, duration}); } } // namespace gamepad diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index e1ba646..6fa23d4 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -11,11 +11,11 @@ namespace gamepad { ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { ScreenBuffer output; - const std::lock_guard guard(this->mut); + const std::lock_guard guard(m_mutex); for (auto i = visible_lines.begin(); i != visible_lines.end(); ++i) { - output[*i] = std::move(this->current_buffer[*i]); - this->current_buffer[*i] = std::nullopt; + output[*i] = std::move(m_current_buffer[*i]); + m_current_buffer[*i] = std::nullopt; } return output; } @@ -24,7 +24,7 @@ void DefaultScreen::printLine(uint8_t line, std::string str) { TODO("change handling for off screen lines") if (line > 2) std::exit(1); - const std::lock_guard guard(this->mut); + const std::lock_guard guard(m_mutex); if (str.find('\n') != std::string::npos) { TODO("warn instead of throw error if there are too many lines") @@ -38,20 +38,20 @@ void DefaultScreen::printLine(uint8_t line, std::string str) { } for (uint8_t l = 0; l < 3; l++) { - if (!strs[l].empty()) this->current_buffer[l] = (strs[l]); + if (!strs[l].empty()) m_current_buffer[l] = (strs[l]); } return; } - this->current_buffer[line] = std::move(str); + m_current_buffer[line] = std::move(str); } void DefaultScreen::rumble(std::string rumble_pattern) { TODO("change handling for too long rumble patterns") if (rumble_pattern.size() > 8) std::exit(1); - std::lock_guard guard(this->mut); - this->current_buffer[3] = std::move(rumble_pattern); + std::lock_guard guard(m_mutex); + m_current_buffer[3] = std::move(rumble_pattern); } } // namespace gamepad \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fdf30a2..9e99fa5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,8 +18,8 @@ std::shared_ptr alerts = std::make_shared Date: Thu, 2 Jan 2025 14:40:43 -0800 Subject: [PATCH 087/108] refactor: :goal_net: Change error handling in screen code to use errno --- src/gamepad/screens/alertScreen.cpp | 12 ++++++++---- src/gamepad/screens/defaultScreen.cpp | 16 +++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 4d23d45..f8f590d 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -33,11 +33,15 @@ void AlertScreen::update(uint32_t delta_time) { } void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { - TODO("change handling for off screen lines") - if (line > 2) std::exit(1); + if (line > 2) { + TODO("add error logging") + errno = EINVAL; + return; + } - TODO("warn instead of throw error if there are too many lines") - if (std::ranges::count(str, '\n') > 2) std::exit(1); + if (std::ranges::count(str, '\n') > 2) { + TODO("add warn logging") + } std::vector strs(3, ""); std::stringstream ss(str); diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 6fa23d4..998abfe 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -22,13 +22,17 @@ ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { void DefaultScreen::printLine(uint8_t line, std::string str) { TODO("change handling for off screen lines") - if (line > 2) std::exit(1); + if (line > 2) { + errno = EINVAL; + return; + } const std::lock_guard guard(m_mutex); if (str.find('\n') != std::string::npos) { - TODO("warn instead of throw error if there are too many lines") - if (std::ranges::count(str, '\n') > 2) std::exit(1); + if (std::ranges::count(str, '\n') > 2) { + TODO("add warn logging for too many lines") + } std::vector strs(3); std::stringstream ss(str); @@ -47,8 +51,10 @@ void DefaultScreen::printLine(uint8_t line, std::string str) { } void DefaultScreen::rumble(std::string rumble_pattern) { - TODO("change handling for too long rumble patterns") - if (rumble_pattern.size() > 8) std::exit(1); + if (rumble_pattern.size() > 8) { + TODO("add warn logging") + rumble_pattern.resize(8); + } std::lock_guard guard(m_mutex); m_current_buffer[3] = std::move(rumble_pattern); From 366415f4a3fa9b51dfc81404b9cc8fca6ee061e1 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 2 Jan 2025 14:46:32 -0800 Subject: [PATCH 088/108] style: :art: Fix formatting --- src/gamepad/screens/alertScreen.cpp | 4 +--- src/gamepad/screens/defaultScreen.cpp | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index f8f590d..1621d35 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -39,9 +39,7 @@ void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, st return; } - if (std::ranges::count(str, '\n') > 2) { - TODO("add warn logging") - } + if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") } std::vector strs(3, ""); std::stringstream ss(str); diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 998abfe..abf4f09 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -30,9 +30,7 @@ void DefaultScreen::printLine(uint8_t line, std::string str) { const std::lock_guard guard(m_mutex); if (str.find('\n') != std::string::npos) { - if (std::ranges::count(str, '\n') > 2) { - TODO("add warn logging for too many lines") - } + if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging for too many lines") } std::vector strs(3); std::stringstream ss(str); From 14737339b936cfdebb24f970221b4b57d4ce7201 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sat, 4 Jan 2025 14:36:49 -0800 Subject: [PATCH 089/108] refactor: :goal_net: Add return value to functions that set errno --- include/gamepad/gamepad.hpp | 5 ++++- include/gamepad/screens/alertScreen.hpp | 4 +++- include/gamepad/screens/defaultScreen.hpp | 4 +++- src/gamepad/gamepad.cpp | 12 +++--------- src/gamepad/screens/alertScreen.cpp | 5 +++-- src/gamepad/screens/defaultScreen.cpp | 9 +++++---- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 901739f..1e369c3 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -53,8 +53,11 @@ class Gamepad { * @code {.cpp} * gamepad::master.printLine(1, "This will print on the middle line"); * gamepad::master.printLine(0, "this will print\n\naround the middle line"); + * @endcode + * + * @return true if the alert was added successfully, false if there was an error. */ - void printLine(uint8_t line, std::string str); + bool printLine(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) * diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 50a40cc..0180608 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -46,8 +46,10 @@ class AlertScreen : public AbstractScreen { * @param duration how long the alert should persist on the screen * @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + * + * @return true if the alert was added successfully, false if there was an error. */ - void addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); + bool addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { ScreenBuffer screen; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index f85363e..00c98c4 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -31,8 +31,10 @@ class DefaultScreen : public AbstractScreen { * * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) + * + * @return true if the alert was added successfully, false if there was an error. */ - void printLine(uint8_t line, std::string str); + bool printLine(uint8_t line, std::string str); /** * makes the controller rumble like pros diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 486b7d7..5ab4ce8 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -130,7 +130,7 @@ void Gamepad::addScreen(std::shared_ptr screen) { m_screens.emplace(m_screens.begin() + pos, screen); } -void Gamepad::printLine(uint8_t line, std::string str) { m_default_screen->printLine(line, str); } +bool Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); } void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); } @@ -146,10 +146,7 @@ float Gamepad::operator[](pros::controller_analog_e_t axis) { case pros::E_CONTROLLER_ANALOG_LEFT_Y: return this->LeftY; case pros::E_CONTROLLER_ANALOG_RIGHT_X: return this->RightX; case pros::E_CONTROLLER_ANALOG_RIGHT_Y: return this->RightY; - default: - TODO("add error logging") - errno = EINVAL; - return 0; + default: TODO("add error logging") return 0; } } @@ -172,10 +169,7 @@ Button Gamepad::*Gamepad::buttonToPtr(pros::controller_digital_e_t button) { case pros::E_CONTROLLER_DIGITAL_B: return &Gamepad::m_B; case pros::E_CONTROLLER_DIGITAL_Y: return &Gamepad::m_Y; case pros::E_CONTROLLER_DIGITAL_A: return &Gamepad::m_A; - default: - TODO("add error logging") - errno = EINVAL; - return &Gamepad::Fake; + default: TODO("add error logging") return &Gamepad::Fake; } } } // namespace gamepad diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 1621d35..c1784d2 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -32,11 +32,11 @@ void AlertScreen::update(uint32_t delta_time) { if (pros::millis() - m_line_set_time >= m_screen_contents->duration) m_screen_contents = std::nullopt; } -void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { +bool AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { if (line > 2) { TODO("add error logging") errno = EINVAL; - return; + return false; } if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") } @@ -58,6 +58,7 @@ void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, st std::lock_guard guard(m_mutex); m_screen_buffer.push_back({buffer, duration}); + return true; } } // namespace gamepad diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index abf4f09..771f538 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -20,11 +20,11 @@ ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { return output; } -void DefaultScreen::printLine(uint8_t line, std::string str) { - TODO("change handling for off screen lines") +bool DefaultScreen::printLine(uint8_t line, std::string str) { if (line > 2) { + TODO("add error logging") errno = EINVAL; - return; + return false; } const std::lock_guard guard(m_mutex); @@ -42,10 +42,11 @@ void DefaultScreen::printLine(uint8_t line, std::string str) { for (uint8_t l = 0; l < 3; l++) { if (!strs[l].empty()) m_current_buffer[l] = (strs[l]); } - return; + return true; } m_current_buffer[line] = std::move(str); + return true; } void DefaultScreen::rumble(std::string rumble_pattern) { From 277b08458c0f001233824bb5548f189f355d96b5 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 8 Jan 2025 17:06:54 +0000 Subject: [PATCH 090/108] refactor: :recycle: Change functions to return 0 on success --- include/gamepad/button.hpp | 16 ++++++++-------- include/gamepad/event_handler.hpp | 20 ++++++++++---------- include/gamepad/gamepad.hpp | 4 ++-- include/gamepad/screens/alertScreen.hpp | 4 ++-- include/gamepad/screens/defaultScreen.hpp | 4 ++-- src/gamepad/button.cpp | 18 +++++++++--------- src/gamepad/gamepad.cpp | 2 +- src/gamepad/screens/alertScreen.cpp | 6 +++--- src/gamepad/screens/defaultScreen.cpp | 10 ++++++---- 9 files changed, 43 insertions(+), 41 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index 1e25cff..80781bb 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -84,7 +84,7 @@ class Button { * gamepad::master.Up.onPress("upPress1", []() { std::cout << "I was pressed!" << std::endl; }); * @endcode */ - bool onPress(std::string listenerName, std::function func) const; + uint32_t onPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is long pressed. * @@ -108,7 +108,7 @@ class Button { * std::endl; }); * @endcode */ - bool onLongPress(std::string listenerName, std::function func) const; + uint32_t onLongPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is released. * @@ -125,7 +125,7 @@ class Button { * gamepad::master.Y.onRelease("stopIntake", []() { intake.move(0); }); * @endcode */ - bool onRelease(std::string listenerName, std::function func) const; + uint32_t onRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is short released. * @@ -147,7 +147,7 @@ class Button { * gamepad::master.B.onShortRelease("intakeOnePiece", []() { intake.move_relative(600, 100); }); * @endcode */ - bool onShortRelease(std::string listenerName, std::function func) const; + uint32_t onShortRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is long released. * @@ -168,7 +168,7 @@ class Button { * @endcode * */ - bool onLongRelease(std::string listenerName, std::function func) const; + uint32_t onLongRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run periodically after its been held * @@ -189,7 +189,7 @@ class Button { * @endcode * */ - bool onRepeatPress(std::string listenerName, std::function func) const; + uint32_t onRepeatPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run for a given event. * @@ -207,7 +207,7 @@ class Button { * gamepad::master.L1.addListener(gamepad::ON_RELEASE, "stop_spin", []() { motor1.brake(); }); * @endcode */ - bool addListener(EventType event, std::string listenerName, std::function func) const; + uint32_t addListener(EventType event, std::string listenerName, std::function func) const; /** * @brief Removes a listener from the button * @warning Usage of this function is discouraged. @@ -224,7 +224,7 @@ class Button { * gamepad::master.L1.removeListener("do_something"); * @endcode */ - bool removeListener(std::string listenerName) const; + uint32_t removeListener(std::string listenerName) const; /** * @brief Returns a value indicating whether the button is currently being held. diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index a5a7a5b..345ccce 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -24,33 +24,33 @@ template class EventHandler { * * @param key The listener key (this must be a unique key value) * @param func The function to run when this event is fired - * @return true The listener was successfully added - * @return false The listener was NOT successfully added (there is already a listener with the same key) + * @return 0 The listener was successfully added + * @return UINT32_MAX The listener was NOT successfully added (there is already a listener with the same key) */ - bool addListener(Key key, Listener func) { + uint32_t addListener(Key key, Listener func) { std::lock_guard lock(m_mutex); - if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return false; + if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return UINT32_MAX; m_keys.push_back(key); m_listeners.push_back(func); - return true; + return 0; } /** * @brief Remove a listener from the list of listeners * * @param key The listener key (this must be a unique key value) - * @return true The listener was successfully removed - * @return false The listener was NOT successfully removed (there is no listener with the same key) + * @return 0 The listener was successfully removed + * @return UINT32_MAX The listener was NOT successfully removed (there is no listener with the same key) */ - bool removeListener(Key key) { + uint32_t removeListener(Key key) { std::lock_guard lock(m_mutex); auto i = std::find(m_keys.begin(), m_keys.end(), key); if (i != m_keys.end()) { m_keys.erase(i); m_listeners.erase(m_listeners.begin() + (i - m_keys.begin())); - return true; + return 0; } - return false; + return UINT32_MAX; } /** diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 1e369c3..83c4c74 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -55,9 +55,9 @@ class Gamepad { * gamepad::master.printLine(0, "this will print\n\naround the middle line"); * @endcode * - * @return true if the alert was added successfully, false if there was an error. + * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. */ - bool printLine(uint8_t line, std::string str); + uint32_t printLine(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) * diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 0180608..64157ae 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -47,9 +47,9 @@ class AlertScreen : public AbstractScreen { * @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. * - * @return true if the alert was added successfully, false if there was an error. + * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. */ - bool addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); + uint32_t addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { ScreenBuffer screen; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 00c98c4..ff23eb1 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -32,9 +32,9 @@ class DefaultScreen : public AbstractScreen { * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) * - * @return true if the alert was added successfully, false if there was an error. + * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. */ - bool printLine(uint8_t line, std::string str); + uint32_t printLine(uint8_t line, std::string str); /** * makes the controller rumble like pros diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index d3f3965..94e41b3 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -8,31 +8,31 @@ void Button::setLongPressThreshold(uint32_t threshold) const { m_long_press_thre void Button::setRepeatCooldown(uint32_t cooldown) const { m_repeat_cooldown = cooldown; } -bool Button::onPress(std::string listenerName, std::function func) const { +uint32_t Button::onPress(std::string listenerName, std::function func) const { return m_on_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::onLongPress(std::string listenerName, std::function func) const { +uint32_t Button::onLongPress(std::string listenerName, std::function func) const { return m_on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::onRelease(std::string listenerName, std::function func) const { +uint32_t Button::onRelease(std::string listenerName, std::function func) const { return m_on_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::onShortRelease(std::string listenerName, std::function func) const { +uint32_t Button::onShortRelease(std::string listenerName, std::function func) const { return m_on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::onLongRelease(std::string listenerName, std::function func) const { +uint32_t Button::onLongRelease(std::string listenerName, std::function func) const { return m_on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::onRepeatPress(std::string listenerName, std::function func) const { +uint32_t Button::onRepeatPress(std::string listenerName, std::function func) const { return m_on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -bool Button::addListener(EventType event, std::string listenerName, std::function func) const { +uint32_t Button::addListener(EventType event, std::string listenerName, std::function func) const { switch (event) { case gamepad::EventType::ON_PRESS: return this->onPress(std::move(listenerName), std::move(func)); case gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(listenerName), std::move(func)); @@ -44,11 +44,11 @@ bool Button::addListener(EventType event, std::string listenerName, std::functio default: TODO("add error logging") errno = EINVAL; - return false; + return UINT32_MAX; } } -bool Button::removeListener(std::string listenerName) const { +uint32_t Button::removeListener(std::string listenerName) const { return m_on_press_event.removeListener(listenerName + "_user") || m_on_long_press_event.removeListener(listenerName + "_user") || m_on_release_event.removeListener(listenerName + "_user") || diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 5ab4ce8..effe524 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -130,7 +130,7 @@ void Gamepad::addScreen(std::shared_ptr screen) { m_screens.emplace(m_screens.begin() + pos, screen); } -bool Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); } +uint32_t Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); } void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); } diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index c1784d2..6e56940 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -32,11 +32,11 @@ void AlertScreen::update(uint32_t delta_time) { if (pros::millis() - m_line_set_time >= m_screen_contents->duration) m_screen_contents = std::nullopt; } -bool AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { +uint32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { if (line > 2) { TODO("add error logging") errno = EINVAL; - return false; + return UINT32_MAX; } if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") } @@ -58,7 +58,7 @@ bool AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, st std::lock_guard guard(m_mutex); m_screen_buffer.push_back({buffer, duration}); - return true; + return 0; } } // namespace gamepad diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 771f538..e7a99d0 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -2,6 +2,7 @@ #include "gamepad/screens/abstractScreen.hpp" #include "gamepad/todo.hpp" #include +#include #include #include #include @@ -20,11 +21,11 @@ ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { return output; } -bool DefaultScreen::printLine(uint8_t line, std::string str) { +uint32_t DefaultScreen::printLine(uint8_t line, std::string str) { if (line > 2) { TODO("add error logging") errno = EINVAL; - return false; + return UINT32_MAX; } const std::lock_guard guard(m_mutex); @@ -42,15 +43,16 @@ bool DefaultScreen::printLine(uint8_t line, std::string str) { for (uint8_t l = 0; l < 3; l++) { if (!strs[l].empty()) m_current_buffer[l] = (strs[l]); } - return true; + return 0; } m_current_buffer[line] = std::move(str); - return true; + return 0; } void DefaultScreen::rumble(std::string rumble_pattern) { if (rumble_pattern.size() > 8) { + errno = EINVAL; TODO("add warn logging") rumble_pattern.resize(8); } From 4da1dc584ee630bd393790bca64150fb49035712 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 22 Jan 2025 18:44:24 +0000 Subject: [PATCH 091/108] refactor: :technologist: Hide TODO messages from compiler output --- include/gamepad/todo.hpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/include/gamepad/todo.hpp b/include/gamepad/todo.hpp index c1e0b7b..4b0ffd4 100644 --- a/include/gamepad/todo.hpp +++ b/include/gamepad/todo.hpp @@ -1,5 +1,13 @@ #pragma once #define DO_PRAGMA(x) _Pragma(#x) -#define TODO(x) DO_PRAGMA(message("TODO - " #x)) -#define FIXME(x) DO_PRAGMA(warning("FIXME - " #x)) \ No newline at end of file + +// We only define the TODO/FIXME macros if the file is being compiled by Microsoft Intellisense +// or clangd. This way, the TODO/FIXME messages don't clutter the compilation messages. +#if defined(_debug) || defined(__clang__) +#define TODO(x) DO_PRAGMA(message("TODO - " x)) +#define FIXME(x) DO_PRAGMA(warning("FIXME - " x)) +#else +#define TODO(x) +#define FIXME(x) +#endif \ No newline at end of file From 5a5fced8735727990b9cfd00f4caf22db3704ef0 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 22 Jan 2025 18:45:01 +0000 Subject: [PATCH 092/108] refactor: :recycle: Change functions to return int32_t error codes --- include/gamepad/gamepad.hpp | 13 +++++++++++-- include/gamepad/screens/alertScreen.hpp | 10 ++++++++-- include/gamepad/screens/defaultScreen.hpp | 11 ++++++++--- src/gamepad/gamepad.cpp | 2 +- src/gamepad/screens/alertScreen.cpp | 4 ++-- src/gamepad/screens/defaultScreen.cpp | 18 ++++++++++++++---- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 83c4c74..7adeeca 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -49,15 +49,20 @@ class Gamepad { * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) * + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The line number is not in the interval [0, 2] + * * @b Example: * @code {.cpp} * gamepad::master.printLine(1, "This will print on the middle line"); * gamepad::master.printLine(0, "this will print\n\naround the middle line"); * @endcode * - * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. + * @return 0 if the alert was added successfully + * @return INT32_MAX if there was an error, setting errno */ - uint32_t printLine(uint8_t line, std::string str); + int32_t printLine(uint8_t line, std::string str); /** * @brief clears all lines on the controller, similar to the pros function (low priority) * @@ -84,6 +89,10 @@ class Gamepad { * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. * + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The rumble pattern was truncated to 8 characters + * * @b Example: * @code {.cpp} * // rumbles in the following pattern: short, pause, long, short short diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 64157ae..09d1fca 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -47,9 +47,15 @@ class AlertScreen : public AbstractScreen { * @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. * - * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The line number is not in the interval [0, 2] + * + * @return 0 if the alert was added successfully + * @return INT32_MAX if there was an error, setting errno + * */ - uint32_t addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); + int32_t addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: struct AlertBuffer { ScreenBuffer screen; diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index ff23eb1..1f31381 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -32,9 +32,14 @@ class DefaultScreen : public AbstractScreen { * @param line the line number to print the string on (0-2) * @param str the string to print onto the controller (\n to go to the next line) * - * @return 0 if the alert was added successfully, UINT32_MAX if there was an error. + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The line number is not in the interval [0, 2] + * + * @return 0 if the alert was added successfully + * @return INT32_MAX if there was an error, setting errno */ - uint32_t printLine(uint8_t line, std::string str); + int32_t printLine(uint8_t line, std::string str); /** * makes the controller rumble like pros @@ -42,7 +47,7 @@ class DefaultScreen : public AbstractScreen { * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. */ - void rumble(std::string rumble_pattern); + int32_t rumble(std::string rumble_pattern); private: ScreenBuffer m_current_buffer {}; pros::Mutex m_mutex {}; diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index effe524..cbd3c27 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -130,7 +130,7 @@ void Gamepad::addScreen(std::shared_ptr screen) { m_screens.emplace(m_screens.begin() + pos, screen); } -uint32_t Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); } +int32_t Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); } void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); } diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 6e56940..0c4ee31 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -32,11 +32,11 @@ void AlertScreen::update(uint32_t delta_time) { if (pros::millis() - m_line_set_time >= m_screen_contents->duration) m_screen_contents = std::nullopt; } -uint32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { +int32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { if (line > 2) { TODO("add error logging") errno = EINVAL; - return UINT32_MAX; + return INT32_MAX; } if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") } diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index e7a99d0..4ac099a 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -21,11 +21,11 @@ ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { return output; } -uint32_t DefaultScreen::printLine(uint8_t line, std::string str) { +int32_t DefaultScreen::printLine(uint8_t line, std::string str) { if (line > 2) { TODO("add error logging") errno = EINVAL; - return UINT32_MAX; + return INT32_MAX; } const std::lock_guard guard(m_mutex); @@ -50,15 +50,25 @@ uint32_t DefaultScreen::printLine(uint8_t line, std::string str) { return 0; } -void DefaultScreen::rumble(std::string rumble_pattern) { +int32_t DefaultScreen::rumble(std::string rumble_pattern) { + bool is_err = false; if (rumble_pattern.size() > 8) { - errno = EINVAL; TODO("add warn logging") + errno = EINVAL; + is_err = true; rumble_pattern.resize(8); } + if (rumble_pattern.find_first_not_of(".- ") != std::string::npos) { + TODO("add error logging") + errno = EINVAL; + return INT32_MAX; + } + std::lock_guard guard(m_mutex); m_current_buffer[3] = std::move(rumble_pattern); + if (is_err) return INT32_MAX; + else return 0; } } // namespace gamepad \ No newline at end of file From f127b09f4d8173894f08b6e3f4859aada983e100 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:08:06 +0000 Subject: [PATCH 093/108] style: :art: Format code --- include/gamepad/gamepad.hpp | 2 +- include/gamepad/screens/alertScreen.hpp | 2 +- src/gamepad/gamepad.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index 7adeeca..c14d34b 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -162,7 +162,7 @@ class Gamepad { * @return std::string A unique listener name */ static std::string uniqueName(); - static Button Gamepad::*buttonToPtr(pros::controller_digital_e_t button); + static Button Gamepad::* buttonToPtr(pros::controller_digital_e_t button); void updateButton(pros::controller_digital_e_t button_id); void updateScreens(); diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index 09d1fca..ac4fb9e 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -53,7 +53,7 @@ class AlertScreen : public AbstractScreen { * * @return 0 if the alert was added successfully * @return INT32_MAX if there was an error, setting errno - * + * */ int32_t addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = ""); private: diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index cbd3c27..69155c3 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -19,7 +19,7 @@ Gamepad::Gamepad(pros::controller_id_e_t id) } void Gamepad::updateButton(pros::controller_digital_e_t button_id) { - Button Gamepad::*button = Gamepad::buttonToPtr(button_id); + Button Gamepad::* button = Gamepad::buttonToPtr(button_id); bool is_held = m_controller.get_digital(button_id); (this->*button).update(is_held); } @@ -155,7 +155,7 @@ std::string Gamepad::uniqueName() { return std::to_string(i++) + "_internal"; } -Button Gamepad::*Gamepad::buttonToPtr(pros::controller_digital_e_t button) { +Button Gamepad::* Gamepad::buttonToPtr(pros::controller_digital_e_t button) { switch (button) { case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1; case pros::E_CONTROLLER_DIGITAL_L2: return &Gamepad::m_L2; From 8828d333f49c377fcf650120ae8d2802be045a6e Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:44:07 +0000 Subject: [PATCH 094/108] fix: :bug: Fix Fisheye transformation implementation --- src/gamepad/joystick_transformation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gamepad/joystick_transformation.cpp b/src/gamepad/joystick_transformation.cpp index 225c2d1..07de716 100644 --- a/src/gamepad/joystick_transformation.cpp +++ b/src/gamepad/joystick_transformation.cpp @@ -34,9 +34,9 @@ std::pair Fisheye::get_value(std::pair value) { float y_abs = abs(y); float j = std::sqrt(m_radius * m_radius - 1.0 * 1.0); if (x_abs >= j && y_abs >= j) { - float theta = std::atan2(y_abs, x_abs); - x_abs *= m_radius / std::cos(abs(std::remainder(theta, 90))); - y_abs *= m_radius / std::cos(abs(std::remainder(theta, 90))); + float scale = std::hypot(std::min(x_abs / y_abs, y_abs / x_abs), 1.0) / m_radius; + x_abs *= scale; + y_abs *= scale; } x = std::copysign(std::min(1.0f, x_abs), x); y = std::copysign(std::min(1.0f, y_abs), y); From a347bd51f9b81c91834c4385a05f2f21b4893c5f Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:33:09 +0000 Subject: [PATCH 095/108] refactor: :recycle: Factor out common code in deadband impl --- include/gamepad/joystick_transformation.hpp | 9 +++++++++ src/gamepad/joystick_transformation.cpp | 11 +++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp index 6f028db..54210eb 100644 --- a/include/gamepad/joystick_transformation.hpp +++ b/include/gamepad/joystick_transformation.hpp @@ -65,6 +65,15 @@ class Deadband : public AbstractTransformation { */ std::pair get_value(std::pair original) override; private: + /** + * @brief Applies a deadband to a joystick axis + * + * @param value The value of the joystick axis + * @param deadband The deadband to use + * @return float The joystick axis value with deadband applied + */ + static float apply_deadband(float value, float deadband); + float m_x_deadband; float m_y_deadband; float m_x_spread; diff --git a/src/gamepad/joystick_transformation.cpp b/src/gamepad/joystick_transformation.cpp index 07de716..a0722a8 100644 --- a/src/gamepad/joystick_transformation.cpp +++ b/src/gamepad/joystick_transformation.cpp @@ -7,15 +7,18 @@ using std::copysign; using std::pow; namespace gamepad { +float Deadband::apply_deadband(float value, float deadband) { + float abs_val = abs(value); + return copysign(abs_val < deadband ? 0 : (abs_val - deadband) / (1.0 - deadband), value); +} + std::pair Deadband::get_value(std::pair value) { float x = value.first; float y = value.second; float x_deadband = m_x_deadband + abs(y) * m_x_spread; float y_deadband = m_y_deadband + abs(x) * m_y_spread; - float x_scale = 1.0 / (1.0 - x_deadband); - float y_scale = 1.0 / (1.0 - y_deadband); - x = copysign(abs(x) < x_deadband ? 0 : (abs(x) - x_deadband) * x_scale, x); - y = copysign(abs(y) < y_deadband ? 0 : (abs(y) - y_deadband) * y_scale, y); + x = apply_deadband(x, x_deadband); + y = apply_deadband(y, y_deadband); return {x, y}; } From 08e67239c49cf4015f6cf410008f1472038983b7 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:50:47 +0000 Subject: [PATCH 096/108] refactor: :label: Change functions returning uint32_t to return int32_t --- include/gamepad/button.hpp | 16 ++++++++-------- include/gamepad/event_handler.hpp | 8 ++++---- src/gamepad/button.cpp | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index 80781bb..82423e9 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -84,7 +84,7 @@ class Button { * gamepad::master.Up.onPress("upPress1", []() { std::cout << "I was pressed!" << std::endl; }); * @endcode */ - uint32_t onPress(std::string listenerName, std::function func) const; + int32_t onPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is long pressed. * @@ -108,7 +108,7 @@ class Button { * std::endl; }); * @endcode */ - uint32_t onLongPress(std::string listenerName, std::function func) const; + int32_t onLongPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is released. * @@ -125,7 +125,7 @@ class Button { * gamepad::master.Y.onRelease("stopIntake", []() { intake.move(0); }); * @endcode */ - uint32_t onRelease(std::string listenerName, std::function func) const; + int32_t onRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is short released. * @@ -147,7 +147,7 @@ class Button { * gamepad::master.B.onShortRelease("intakeOnePiece", []() { intake.move_relative(600, 100); }); * @endcode */ - uint32_t onShortRelease(std::string listenerName, std::function func) const; + int32_t onShortRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run when the button is long released. * @@ -168,7 +168,7 @@ class Button { * @endcode * */ - uint32_t onLongRelease(std::string listenerName, std::function func) const; + int32_t onLongRelease(std::string listenerName, std::function func) const; /** * @brief Register a function to run periodically after its been held * @@ -189,7 +189,7 @@ class Button { * @endcode * */ - uint32_t onRepeatPress(std::string listenerName, std::function func) const; + int32_t onRepeatPress(std::string listenerName, std::function func) const; /** * @brief Register a function to run for a given event. * @@ -207,7 +207,7 @@ class Button { * gamepad::master.L1.addListener(gamepad::ON_RELEASE, "stop_spin", []() { motor1.brake(); }); * @endcode */ - uint32_t addListener(EventType event, std::string listenerName, std::function func) const; + int32_t addListener(EventType event, std::string listenerName, std::function func) const; /** * @brief Removes a listener from the button * @warning Usage of this function is discouraged. @@ -224,7 +224,7 @@ class Button { * gamepad::master.L1.removeListener("do_something"); * @endcode */ - uint32_t removeListener(std::string listenerName) const; + int32_t removeListener(std::string listenerName) const; /** * @brief Returns a value indicating whether the button is currently being held. diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index 345ccce..c0b4d8f 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -27,9 +27,9 @@ template class EventHandler { * @return 0 The listener was successfully added * @return UINT32_MAX The listener was NOT successfully added (there is already a listener with the same key) */ - uint32_t addListener(Key key, Listener func) { + int32_t addListener(Key key, Listener func) { std::lock_guard lock(m_mutex); - if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return UINT32_MAX; + if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return INT32_MAX; m_keys.push_back(key); m_listeners.push_back(func); return 0; @@ -42,7 +42,7 @@ template class EventHandler { * @return 0 The listener was successfully removed * @return UINT32_MAX The listener was NOT successfully removed (there is no listener with the same key) */ - uint32_t removeListener(Key key) { + int32_t removeListener(Key key) { std::lock_guard lock(m_mutex); auto i = std::find(m_keys.begin(), m_keys.end(), key); if (i != m_keys.end()) { @@ -50,7 +50,7 @@ template class EventHandler { m_listeners.erase(m_listeners.begin() + (i - m_keys.begin())); return 0; } - return UINT32_MAX; + return INT32_MAX; } /** diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 94e41b3..6b24de1 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -8,31 +8,31 @@ void Button::setLongPressThreshold(uint32_t threshold) const { m_long_press_thre void Button::setRepeatCooldown(uint32_t cooldown) const { m_repeat_cooldown = cooldown; } -uint32_t Button::onPress(std::string listenerName, std::function func) const { +int32_t Button::onPress(std::string listenerName, std::function func) const { return m_on_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::onLongPress(std::string listenerName, std::function func) const { +int32_t Button::onLongPress(std::string listenerName, std::function func) const { return m_on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::onRelease(std::string listenerName, std::function func) const { +int32_t Button::onRelease(std::string listenerName, std::function func) const { return m_on_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::onShortRelease(std::string listenerName, std::function func) const { +int32_t Button::onShortRelease(std::string listenerName, std::function func) const { return m_on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::onLongRelease(std::string listenerName, std::function func) const { +int32_t Button::onLongRelease(std::string listenerName, std::function func) const { return m_on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::onRepeatPress(std::string listenerName, std::function func) const { +int32_t Button::onRepeatPress(std::string listenerName, std::function func) const { return m_on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func)); } -uint32_t Button::addListener(EventType event, std::string listenerName, std::function func) const { +int32_t Button::addListener(EventType event, std::string listenerName, std::function func) const { switch (event) { case gamepad::EventType::ON_PRESS: return this->onPress(std::move(listenerName), std::move(func)); case gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(listenerName), std::move(func)); @@ -48,7 +48,7 @@ uint32_t Button::addListener(EventType event, std::string listenerName, std::fun } } -uint32_t Button::removeListener(std::string listenerName) const { +int32_t Button::removeListener(std::string listenerName) const { return m_on_press_event.removeListener(listenerName + "_user") || m_on_long_press_event.removeListener(listenerName + "_user") || m_on_release_event.removeListener(listenerName + "_user") || From 0ac0ebdb2761ad376e4a249093859ea50e4ef47d Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 23:50:50 +0000 Subject: [PATCH 097/108] fix: :bug: Fix broken impl of Button::removeListener --- include/gamepad/button.hpp | 13 ++++++++++-- src/gamepad/button.cpp | 42 ++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index 82423e9..1ebbd19 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -212,6 +212,7 @@ class Button { * @brief Removes a listener from the button * @warning Usage of this function is discouraged. * + * @param event the event type of the listener * @param listenerName The name of the listener to remove * @return true The specified listener was successfully removed * @return false The specified listener could not be removed @@ -221,10 +222,10 @@ class Button { * // Add an event listener... * gamepad::master.L1.addListener(gamepad::ON_PRESS, "do_something", doSomething); * // ...and now get rid of it - * gamepad::master.L1.removeListener("do_something"); + * gamepad::master.L1.removeListener(gamepad::ON_PRESS, "do_something"); * @endcode */ - int32_t removeListener(std::string listenerName) const; + int32_t removeListener(EventType event, std::string listenerName) const; /** * @brief Returns a value indicating whether the button is currently being held. @@ -240,6 +241,14 @@ class Button { * @param is_held Whether or not the button is currently held down */ void update(bool is_held); + /** + * @brief Get the handler object for the given event type + * + * @param event The desired event type + * @return nullptr The event value is invalid + * @return _impl::EventHandler* A pointer to the given event's handler + */ + _impl::EventHandler* get_handler(EventType event) const; /// How long the threshold should be for the longPress and shortRelease events mutable uint32_t m_long_press_threshold = 500; /// How often repeatPress is called diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 6b24de1..037b4db 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -2,8 +2,21 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include +#include namespace gamepad { +_impl::EventHandler* Button::get_handler(EventType event) const { + switch (event) { + case gamepad::EventType::ON_PRESS: return &m_on_press_event; + case gamepad::EventType::ON_LONG_PRESS: return &m_on_long_press_event; + case gamepad::EventType::ON_RELEASE: return &m_on_release_event; + case gamepad::EventType::ON_SHORT_RELEASE: return &m_on_short_release_event; + case gamepad::EventType::ON_LONG_RELEASE: return &m_on_long_release_event; + case gamepad::EventType::ON_REPEAT_PRESS: return &m_on_repeat_press_event; + default: return nullptr; + } +} + void Button::setLongPressThreshold(uint32_t threshold) const { m_long_press_threshold = threshold; } void Button::setRepeatCooldown(uint32_t cooldown) const { m_repeat_cooldown = cooldown; } @@ -33,28 +46,31 @@ int32_t Button::onRepeatPress(std::string listenerName, std::function func) const { - switch (event) { - case gamepad::EventType::ON_PRESS: return this->onPress(std::move(listenerName), std::move(func)); - case gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(listenerName), std::move(func)); - case gamepad::EventType::ON_RELEASE: return this->onRelease(std::move(listenerName), std::move(func)); - case gamepad::EventType::ON_SHORT_RELEASE: - return this->onShortRelease(std::move(listenerName), std::move(func)); - case gamepad::EventType::ON_LONG_RELEASE: return this->onLongRelease(std::move(listenerName), std::move(func)); - case gamepad::EventType::ON_REPEAT_PRESS: return this->onRepeatPress(std::move(listenerName), std::move(func)); - default: - TODO("add error logging") - errno = EINVAL; - return UINT32_MAX; + auto handler = this->get_handler(event); + if (handler != nullptr) { + return handler->addListener(listenerName + "_user", func); + } else { + TODO("add error logging") + errno = EINVAL; + return INT32_MAX; } } -int32_t Button::removeListener(std::string listenerName) const { +int32_t Button::removeListener(EventType event, std::string listenerName) const { return m_on_press_event.removeListener(listenerName + "_user") || m_on_long_press_event.removeListener(listenerName + "_user") || m_on_release_event.removeListener(listenerName + "_user") || m_on_short_release_event.removeListener(listenerName + "_user") || m_on_long_release_event.removeListener(listenerName + "_user") || m_on_repeat_press_event.removeListener(listenerName + "_user"); + auto handler = this->get_handler(event); + if (handler != nullptr) { + return handler->removeListener(listenerName + "_user"); + } else { + TODO("add error logging") + errno = EINVAL; + return INT32_MAX; + } } void Button::update(const bool is_held) { From 607f3fc82233c357442c508b198950631c67a85b Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:10:07 -0800 Subject: [PATCH 098/108] fix(display): :bug: Add handling for too big messages --- src/gamepad/screens/alertScreen.cpp | 10 ++++++++-- src/gamepad/screens/defaultScreen.cpp | 23 ++++++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index 0c4ee31..d960d16 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -2,6 +2,7 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include +#include #include #include #include @@ -33,13 +34,18 @@ void AlertScreen::update(uint32_t delta_time) { } int32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) { + int32_t ret_val = 0; if (line > 2) { TODO("add error logging") errno = EINVAL; return INT32_MAX; } - if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") } + if (std::ranges::count(str, '\n') > 2) { + TODO("add warn logging") + errno = EMSGSIZE; + ret_val = INT32_MAX; + } std::vector strs(3, ""); std::stringstream ss(str); @@ -58,7 +64,7 @@ int32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::lock_guard guard(m_mutex); m_screen_buffer.push_back({buffer, duration}); - return 0; + return ret_val; } } // namespace gamepad diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index 4ac099a..eade5b1 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -2,6 +2,7 @@ #include "gamepad/screens/abstractScreen.hpp" #include "gamepad/todo.hpp" #include +#include #include #include #include @@ -22,6 +23,7 @@ ScreenBuffer DefaultScreen::getScreen(std::set visible_lines) { } int32_t DefaultScreen::printLine(uint8_t line, std::string str) { + int32_t ret_val = 0; if (line > 2) { TODO("add error logging") errno = EINVAL; @@ -31,7 +33,11 @@ int32_t DefaultScreen::printLine(uint8_t line, std::string str) { const std::lock_guard guard(m_mutex); if (str.find('\n') != std::string::npos) { - if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging for too many lines") } + if (std::ranges::count(str, '\n') > 2) { + TODO("add warn logging for too many lines") + errno = EMSGSIZE; + ret_val = INT32_MAX; + } std::vector strs(3); std::stringstream ss(str); @@ -43,19 +49,19 @@ int32_t DefaultScreen::printLine(uint8_t line, std::string str) { for (uint8_t l = 0; l < 3; l++) { if (!strs[l].empty()) m_current_buffer[l] = (strs[l]); } - return 0; + return ret_val; } m_current_buffer[line] = std::move(str); - return 0; + return ret_val; } int32_t DefaultScreen::rumble(std::string rumble_pattern) { - bool is_err = false; + int32_t ret_val = 0; if (rumble_pattern.size() > 8) { - TODO("add warn logging") - errno = EINVAL; - is_err = true; + TODO("add error logging") + errno = EMSGSIZE; + ret_val = INT32_MAX; rumble_pattern.resize(8); } @@ -67,8 +73,7 @@ int32_t DefaultScreen::rumble(std::string rumble_pattern) { std::lock_guard guard(m_mutex); m_current_buffer[3] = std::move(rumble_pattern); - if (is_err) return INT32_MAX; - else return 0; + return ret_val; } } // namespace gamepad \ No newline at end of file From 38aa8d933121d8d4172175a316c8d7037582d733 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:12:26 -0800 Subject: [PATCH 099/108] refactor(buttons): :heavy_minus_sign: Remove unneeded include --- src/gamepad/button.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 037b4db..f343eeb 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -2,7 +2,6 @@ #include "gamepad/todo.hpp" #include "pros/rtos.hpp" #include -#include namespace gamepad { _impl::EventHandler* Button::get_handler(EventType event) const { From 739c0f5ddb5c389ae1e97dd6443fad9c8d84c5d9 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:13:09 -0800 Subject: [PATCH 100/108] docs(display): :memo: Document all possible errno values --- include/gamepad/screens/alertScreen.hpp | 1 + include/gamepad/screens/defaultScreen.hpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/gamepad/screens/alertScreen.hpp b/include/gamepad/screens/alertScreen.hpp index ac4fb9e..3c8edc6 100644 --- a/include/gamepad/screens/alertScreen.hpp +++ b/include/gamepad/screens/alertScreen.hpp @@ -50,6 +50,7 @@ class AlertScreen : public AbstractScreen { * This function uses the following value(s) of errno when an error state is reached: * * EINVAL: The line number is not in the interval [0, 2] + * EMSGSIZE: The alert is more than 3 lines long * * @return 0 if the alert was added successfully * @return INT32_MAX if there was an error, setting errno diff --git a/include/gamepad/screens/defaultScreen.hpp b/include/gamepad/screens/defaultScreen.hpp index 1f31381..6c46c82 100644 --- a/include/gamepad/screens/defaultScreen.hpp +++ b/include/gamepad/screens/defaultScreen.hpp @@ -35,6 +35,7 @@ class DefaultScreen : public AbstractScreen { * This function uses the following value(s) of errno when an error state is reached: * * EINVAL: The line number is not in the interval [0, 2] + * EMSGSIZE: The string is more than 3 lines long * * @return 0 if the alert was added successfully * @return INT32_MAX if there was an error, setting errno @@ -46,6 +47,14 @@ class DefaultScreen : public AbstractScreen { * * @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles, * dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters. + * + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The rumble pattern contains a character other than '.', '-', or ' ' + * EMSGSIZE: The pattern is more than 8 characters long + * + * @return 0 if the alert was added successfully + * @return INT32_MAX if there was an error, setting errno */ int32_t rumble(std::string rumble_pattern); private: From 0ffae91828beaf4b785dd0b25b695667dbcfe51c Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:16:55 -0800 Subject: [PATCH 101/108] chore: :technologist: Add conventional commits scopes --- .gitignore | 5 ++++- .vscode/settings.json | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5419594..c64778c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ # PROS bin/ -.vscode/ +.vscode/* .cache/ compile_commands.json temp.log @@ -24,3 +24,6 @@ temp.errors # Linux debug.log + +# Always include development settings +!.vscode/settings.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index b242572..0120171 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,10 @@ { "githubPullRequests.ignoredPullRequestBranches": [ "main" + ], + "conventionalCommits.scopes": [ + "buttons", + "display", + "joysticks" ] } \ No newline at end of file From 5ce9764aec45c52eb205299df494fc2a9b2460ce Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:39:40 -0800 Subject: [PATCH 102/108] fix(display): :bug: Return error code from clear method --- include/gamepad/gamepad.hpp | 21 ++++++++++++++++++--- src/gamepad/gamepad.cpp | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/gamepad/gamepad.hpp b/include/gamepad/gamepad.hpp index c14d34b..64bc7ea 100644 --- a/include/gamepad/gamepad.hpp +++ b/include/gamepad/gamepad.hpp @@ -52,6 +52,7 @@ class Gamepad { * This function uses the following value(s) of errno when an error state is reached: * * EINVAL: The line number is not in the interval [0, 2] + * EMSGSIZE: The string is more than 3 lines long * * @b Example: * @code {.cpp} @@ -59,7 +60,7 @@ class Gamepad { * gamepad::master.printLine(0, "this will print\n\naround the middle line"); * @endcode * - * @return 0 if the alert was added successfully + * @return 0 if the line was printed successfully * @return INT32_MAX if there was an error, setting errno */ int32_t printLine(uint8_t line, std::string str); @@ -70,6 +71,7 @@ class Gamepad { * @code {.cpp} * // clears the whole screen on the controller * gamepad::master.clear() + * @endcode */ void clear(); /** @@ -77,12 +79,20 @@ class Gamepad { * * @param line the line to clear (0-2) * + * This function uses the following value(s) of errno when an error state is reached: + * + * EINVAL: The line number is not in the interval [0, 2] + * * @b Example: * @code {.cpp} * // clears the center line on the controller * gamepad::master.clear(1); + * @endcode + * + * @return 0 if the line was cleared successfully + * @return INT32_MAX if there was an error, setting errno */ - void clear(uint8_t line); + int32_t clear(uint8_t line); /** * makes the controller rumble like pros (low priority) * @@ -91,12 +101,17 @@ class Gamepad { * * This function uses the following value(s) of errno when an error state is reached: * - * EINVAL: The rumble pattern was truncated to 8 characters + * EINVAL: The rumble pattern contains a character other than '.', '-', or ' ' + * EMSGSIZE: The pattern is more than 8 characters long * * @b Example: * @code {.cpp} * // rumbles in the following pattern: short, pause, long, short short * gamepad::master.rumble(". -.."); + * @endcode + * + * @return 0 if the rumble was successful + * @return INT32_MAX if there was an error, setting errno */ void rumble(std::string rumble_pattern); /** diff --git a/src/gamepad/gamepad.cpp b/src/gamepad/gamepad.cpp index 69155c3..cbaa797 100644 --- a/src/gamepad/gamepad.cpp +++ b/src/gamepad/gamepad.cpp @@ -134,7 +134,7 @@ int32_t Gamepad::printLine(uint8_t line, std::string str) { return m_default_scr void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); } -void Gamepad::clear(uint8_t line) { m_default_screen->printLine(line, " "); } +int32_t Gamepad::clear(uint8_t line) { return m_default_screen->printLine(line, " "); } void Gamepad::rumble(std::string rumble_pattern) { m_default_screen->rumble(rumble_pattern); } From f584161ff9e51d4cf3a21d6428c13065f677b8a4 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:40:17 -0800 Subject: [PATCH 103/108] docs(display): :memo: Fix incorrect docs for error codes --- include/gamepad/button.hpp | 32 +++++++++++++++---------------- include/gamepad/event_handler.hpp | 6 +++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index 1ebbd19..a0a63ac 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -73,8 +73,8 @@ class Button { * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is pressed, the function MUST NOT block - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -96,8 +96,8 @@ class Button { * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is long pressed, the function MUST NOT block - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -114,8 +114,8 @@ class Button { * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is released, the function MUST NOT block - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -136,8 +136,8 @@ class Button { * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is short released, the function MUST NOT block - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -156,8 +156,8 @@ class Button { * * @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 - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -177,8 +177,8 @@ class Button { * * @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 - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -196,8 +196,8 @@ class Button { * @param event Which event to register the listener on. * @param listenerName The name of the listener, this must be a unique name * @param func The function to run for the given event, the function MUST NOT block - * @return true The listener was successfully registered - * @return false The listener was not successfully registered (there is already a listener with this name) + * @return 0 The listener was successfully registered + * @return INT32_MAX The listener was not successfully registered (there is already a listener with this name) * * @b Example: * @code {.cpp} @@ -214,8 +214,8 @@ class Button { * * @param event the event type of the listener * @param listenerName The name of the listener to remove - * @return true The specified listener was successfully removed - * @return false The specified listener could not be removed + * @return 0 The specified listener was successfully removed + * @return INT32_MAX The specified listener could not be removed * * @b Example: * @code {.cpp} diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index c0b4d8f..c9f3d47 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -25,7 +25,7 @@ template class EventHandler { * @param key The listener key (this must be a unique key value) * @param func The function to run when this event is fired * @return 0 The listener was successfully added - * @return UINT32_MAX The listener was NOT successfully added (there is already a listener with the same key) + * @return INT32_MAX The listener was NOT successfully added (there is already a listener with the same key) */ int32_t addListener(Key key, Listener func) { std::lock_guard lock(m_mutex); @@ -40,7 +40,7 @@ template class EventHandler { * * @param key The listener key (this must be a unique key value) * @return 0 The listener was successfully removed - * @return UINT32_MAX The listener was NOT successfully removed (there is no listener with the same key) + * @return INT32_MAX The listener was NOT successfully removed (there is no listener with the same key) */ int32_t removeListener(Key key) { std::lock_guard lock(m_mutex); @@ -54,7 +54,7 @@ template class EventHandler { } /** - * @brief Whther or not there are any listeners registered + * @brief Whether or not there are any listeners registered * * @return true There are listeners registered * @return false There are no listeners registered From 896e7837ff6689dd6a930bdbe61c30b673e1550e Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Sat, 8 Feb 2025 15:39:41 -0800 Subject: [PATCH 104/108] chore: :bookmark: Bump version to 0.3.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d97a45b..d06743f 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ EXCLUDE_COLD_LIBRARIES:= # Set this to 1 to add additional rules to compile your project as a PROS library template IS_LIBRARY:=1 LIBNAME:=gamepad -VERSION:=0.2.0 +VERSION:=0.3.0 # EXCLUDE_SRC_FROM_LIB= $(SRCDIR)/unpublishedfile.c # this line excludes opcontrol.c and similar files EXCLUDE_SRC_FROM_LIB+=$(foreach file, $(SRCDIR)/main,$(foreach cext,$(CEXTS),$(file).$(cext)) $(foreach cxxext,$(CXXEXTS),$(file).$(cxxext))) From 4502c8d6e97db22b26257bc54ad22f893b02f7f5 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Thu, 13 Feb 2025 18:37:58 +0000 Subject: [PATCH 105/108] chore: :technologist: Fix devcontainer build --- .devcontainer/Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d5222a4..de2ed94 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,11 +1,14 @@ -FROM rust:1.67 as builder +FROM rust:1.84 as builder RUN git clone https://github.com/vexide/vex-v5-qemu.git /vex-v5-qemu WORKDIR /vex-v5-qemu RUN cd packages/kernel; cargo build --target-dir /target/kernel -RUN cd packages/client-cli; cargo install --path . --root /target/client-cli +# FIXME: This should probably be removed in the future since it's very fragile +RUN rustup toolchain install nightly + +RUN cd packages/client-cli; cargo +nightly install --path . --root /target/client-cli FROM mcr.microsoft.com/devcontainers/cpp:1-noble # ------------ From 672229ab2234ff2b893efd2063c087018bbe2093 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:12:13 -0800 Subject: [PATCH 106/108] style: :art: Format code --- include/gamepad/button.hpp | 2 +- src/gamepad/screens/alertScreen.cpp | 2 +- src/gamepad/screens/defaultScreen.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index a0a63ac..1c651ea 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -243,7 +243,7 @@ class Button { void update(bool is_held); /** * @brief Get the handler object for the given event type - * + * * @param event The desired event type * @return nullptr The event value is invalid * @return _impl::EventHandler* A pointer to the given event's handler diff --git a/src/gamepad/screens/alertScreen.cpp b/src/gamepad/screens/alertScreen.cpp index d960d16..b7e9c1b 100644 --- a/src/gamepad/screens/alertScreen.cpp +++ b/src/gamepad/screens/alertScreen.cpp @@ -41,7 +41,7 @@ int32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, return INT32_MAX; } - if (std::ranges::count(str, '\n') > 2) { + if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") errno = EMSGSIZE; ret_val = INT32_MAX; diff --git a/src/gamepad/screens/defaultScreen.cpp b/src/gamepad/screens/defaultScreen.cpp index eade5b1..70941b1 100644 --- a/src/gamepad/screens/defaultScreen.cpp +++ b/src/gamepad/screens/defaultScreen.cpp @@ -33,8 +33,8 @@ int32_t DefaultScreen::printLine(uint8_t line, std::string str) { const std::lock_guard guard(m_mutex); if (str.find('\n') != std::string::npos) { - if (std::ranges::count(str, '\n') > 2) { - TODO("add warn logging for too many lines") + if (std::ranges::count(str, '\n') > 2) { + TODO("add warn logging for too many lines") errno = EMSGSIZE; ret_val = INT32_MAX; } From 4b170726635a3372dfa9d0b7fc2b1e58cb5b0c54 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:12:38 -0800 Subject: [PATCH 107/108] ci: :green_heart: Update clang-format CI to v19 --- .github/workflows/clang-format.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 29121bb..213e552 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -11,11 +11,15 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + path: + - './src/gamepad' + - './include/gamepad' steps: - uses: actions/checkout@v2 - - uses: DoozyX/clang-format-lint-action@v0.18 + - uses: jidicula/clang-format-action@v4.14.0 with: - source: './src/gamepad ./include/gamepad' - extensions: 'hpp,cpp' - clangFormatVersion: 18 + clang-format-version: '19' + check-path: ${{ matrix.path }} From 18e20daf26825e086d6b78e97b6a75b43fa0e761 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Wed, 19 Feb 2025 10:17:36 -0800 Subject: [PATCH 108/108] style: :art: Fix formatting --- include/gamepad/joystick_transformation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gamepad/joystick_transformation.hpp b/include/gamepad/joystick_transformation.hpp index 54210eb..62df78d 100644 --- a/include/gamepad/joystick_transformation.hpp +++ b/include/gamepad/joystick_transformation.hpp @@ -67,7 +67,7 @@ class Deadband : public AbstractTransformation { private: /** * @brief Applies a deadband to a joystick axis - * + * * @param value The value of the joystick axis * @param deadband The deadband to use * @return float The joystick axis value with deadband applied