Skip to content

Commit

Permalink
Merge branch 'text' of https://github.com/PA055/Gamepad into text
Browse files Browse the repository at this point in the history
  • Loading branch information
PA055 committed Sep 4, 2024
2 parents 23c4bbf + 3929050 commit bf82fef
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 131 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/clang-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ jobs:

steps:
- uses: actions/checkout@v2
- uses: DoozyX/clang-format-lint-action@v0.17
- uses: DoozyX/clang-format-lint-action@v0.18
with:
source: './src/gamepad ./include/gamepad'
extensions: 'hpp,cpp'
clangFormatVersion: 17
clangFormatVersion: 18
2 changes: 1 addition & 1 deletion .github/workflows/pros-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ jobs:

steps:
- uses: actions/checkout@v4
- uses: LemLib/pros-build@e0f3251974c2f5b044b8e5d8665db7cfcb5dfad7
- uses: LemLib/pros-build@v2.0.2
with:
library-path: gamepad
65 changes: 37 additions & 28 deletions include/gamepad/controller.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "pros/misc.h"
#include <cstdint>
#include <functional>
#include <memory>
Expand All @@ -23,34 +24,32 @@ 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<void(void)> func);
uint32_t onLongPress(std::function<void(void)> func);
uint32_t onRelease(std::function<void(void)> func);
uint32_t addListener(EventType event, std::function<void(void)> func);
bool removeListener(uint32_t id);
uint32_t onPress(std::function<void(void)> func);
uint32_t onLongPress(std::function<void(void)> func);
uint32_t onRelease(std::function<void(void)> func);
uint32_t addListener(EventType event, std::function<void(void)> 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) {}
/**
* Updates the state of the gamepad (all joysticks and buttons), and also runs
* any registered handlers.
Expand Down Expand Up @@ -80,14 +79,18 @@ class Controller {
* @param joystick Which joystick axis's value to return
*/
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{};
TODO("hide memebrs and expose getters/const refs")
Button L1 {}, L2 {}, R1 {}, R2 {}, Up {}, Down {}, Left {}, Right {}, X {}, B {}, Y {}, A {};
float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0;
/// The master controller, same as @ref Gamepad::master
static Controller master;
/// The partner controller, same as @ref Gamepad::partner
static Controller partner;
private:
static Button Controller::* button_to_ptr(pros::controller_digital_e_t button);
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();
Expand All @@ -101,6 +104,12 @@ class Controller {
uint last_print_time = 0;
uint last_update_time = 0;
pros::Mutex mut;
};

}; // namespace Gamepad
}
inline Controller Controller::master {pros::E_CONTROLLER_MASTER};
inline Controller Controller::partner {pros::E_CONTROLLER_PARTNER};
/// The master controller
inline Controller& master = Controller::master;
/// The partner controller
inline Controller& partner = Controller::partner;
} // namespace Gamepad
70 changes: 36 additions & 34 deletions include/gamepad/event_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,46 @@
namespace Gamepad {

class MonotonicCounter {
template<typename... Args> friend class EventHandler;
static uint32_t next_value() {
static std::atomic<uint32_t> counter = 0;
return ++counter;
}
template <typename... Args> friend class EventHandler;

static uint32_t next_value() {
static std::atomic<uint32_t> counter = 0;
return ++counter;
}
};

template <typename... Args>
class EventHandler {
template <typename... Args> class EventHandler {
public:
using Listener = std::function<void(Args...)>;
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<void(Args...)>;

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<uint32_t, Listener> listeners;
pros::Mutex mutex;
std::map<uint32_t, Listener> listeners;
pros::Mutex mutex;
};
}
} // namespace Gamepad
6 changes: 3 additions & 3 deletions include/gamepad/todo.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once

#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))
#define FIXME(x) DO_PRAGMA(warning ("FIXME - " #x))
#define DO_PRAGMA(x) _Pragma(#x)
#define TODO(x) DO_PRAGMA(message("TODO - " #x))
#define FIXME(x) DO_PRAGMA(warning("FIXME - " #x))
65 changes: 28 additions & 37 deletions src/gamepad/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
#include <vector>

namespace Gamepad {

uint32_t Button::onPress(std::function<void(void)> func) {
return this->onPressEvent.add_listener(std::move(func));
}
uint32_t Button::onPress(std::function<void(void)> func) { return this->onPressEvent.add_listener(std::move(func)); }

uint32_t Button::onLongPress(std::function<void(void)> func) {
return this->onLongPressEvent.add_listener(std::move(func));
Expand All @@ -39,12 +36,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();
Expand All @@ -56,7 +49,7 @@ 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);
}
Expand Down Expand Up @@ -109,15 +102,15 @@ void Controller::updateScreens() {
}

void Controller::update() {
for(int i = DIGITAL_L1; i != DIGITAL_A; ++i) {
for (int i = pros::E_CONTROLLER_DIGITAL_L1; i != pros::E_CONTROLLER_DIGITAL_A; ++i) {
this->updateButton(static_cast<pros::controller_digital_e_t>(i));
}

this->LeftX = this->controller.get_analog(ANALOG_LEFT_X);
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->LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X);
this->LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
this->RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X);
this->RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y);
this->updateScreens();
}

Expand All @@ -138,31 +131,29 @@ const Button& Controller::operator[](pros::controller_digital_e_t button) {

float Controller::operator[](pros::controller_analog_e_t axis) {
switch (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 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; TODO("change handling for default")
default: std::exit(1);
}
}

Button Controller::* Controller::button_to_ptr(pros::controller_digital_e_t button) {
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;
case DIGITAL_R1: return &Controller::R1;
case DIGITAL_R2: return &Controller::R2;
case DIGITAL_UP: return &Controller::Up;
case DIGITAL_DOWN: return &Controller::Down;
case DIGITAL_LEFT: return &Controller::Left;
case DIGITAL_RIGHT: return &Controller::Right;
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 pros::E_CONTROLLER_DIGITAL_L1: return &Controller::L1;
case pros::E_CONTROLLER_DIGITAL_L2: return &Controller::L2;
case pros::E_CONTROLLER_DIGITAL_R1: return &Controller::R1;
case pros::E_CONTROLLER_DIGITAL_R2: return &Controller::R2;
case pros::E_CONTROLLER_DIGITAL_UP: return &Controller::Up;
case pros::E_CONTROLLER_DIGITAL_DOWN: return &Controller::Down;
case pros::E_CONTROLLER_DIGITAL_LEFT: return &Controller::Left;
case pros::E_CONTROLLER_DIGITAL_RIGHT: return &Controller::Right;
case pros::E_CONTROLLER_DIGITAL_X: return &Controller::X;
case pros::E_CONTROLLER_DIGITAL_B: return &Controller::B;
case pros::E_CONTROLLER_DIGITAL_Y: return &Controller::Y;
case pros::E_CONTROLLER_DIGITAL_A: return &Controller::A; TODO("change handling for default")
default: std::exit(1);
}
}
}
} // namespace Gamepad
48 changes: 22 additions & 26 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "main.h"
#include "gamepad/api.hpp"

/**
* A callback function for LLEMU's center button.
Expand All @@ -7,13 +8,13 @@
* "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);
}
static bool pressed = false;
pressed = !pressed;
if (pressed) {
pros::lcd::set_text(2, "I was pressed!");
} else {
pros::lcd::clear_line(2);
}
}

/**
Expand All @@ -23,10 +24,10 @@ void on_center_button() {
* to keep execution time for this mode under a few seconds.
*/
void initialize() {
pros::lcd::initialize();
pros::lcd::set_text(1, "Hello PROS User!");
pros::lcd::initialize();
pros::lcd::set_text(1, "Hello PROS User!");

pros::lcd::register_btn1_cb(on_center_button);
pros::lcd::register_btn1_cb(on_center_button);
}

/**
Expand Down Expand Up @@ -74,21 +75,16 @@ void autonomous() {}
* task, not resume it from where it left off.
*/
void opcontrol() {
pros::Controller master(pros::E_CONTROLLER_MASTER);
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) {
pros::lcd::print(0, "%d %d %d", (pros::lcd::read_buttons() & LCD_BTN_LEFT) >> 2,
(pros::lcd::read_buttons() & LCD_BTN_CENTER) >> 1,

(pros::lcd::read_buttons() & LCD_BTN_RIGHT) >> 0); // Prints status of the emulated screen LCDs

// Arcade control scheme
int dir = master.get_analog(ANALOG_LEFT_Y); // Gets amount forward/backward from left joystick
int turn = master.get_analog(ANALOG_RIGHT_X); // 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(20); // Run for 20 ms then update
}
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
}
}

0 comments on commit bf82fef

Please sign in to comment.