cc3dsfs/source/ExtraButtons.cpp
2025-04-08 04:20:02 +02:00

130 lines
4.0 KiB
C++
Executable File

#include "ExtraButtons.hpp"
#define NUM_PI_BUTTONS (sizeof(pi_buttons) / sizeof(pi_buttons[0]))
static ExtraButton pi_page_up, pi_page_down, pi_enter, pi_power;
static ExtraButton* pi_buttons[] = {&pi_page_up, &pi_page_down, &pi_enter, &pi_power};
void ExtraButton::initialize(int id, sf::Keyboard::Key corresponding_key, bool is_power, float first_re_press_time, float later_re_press_time, bool use_pud_up, std::string name) {
this->id = id;
this->is_power = is_power;
this->corresponding_key = corresponding_key;
this->started = false;
this->initialized = true;
this->is_time_valid = false;
this->last_press_time = std::chrono::high_resolution_clock::now();
this->first_re_press_time = first_re_press_time;
this->later_re_press_time = later_re_press_time;
this->name = name;
#ifdef RASPI
if(this->id >= 0) {
std::string gpio_str = "GPIO" + std::to_string(this->id);
this->gpioline_ptr = gpiod_line_find(gpio_str.c_str());
}
else
this->gpioline_ptr = NULL;
if(this->gpioline_ptr) {
if(use_pud_up)
gpiod_line_request_input_flags(this->gpioline_ptr, "cc3dsfs", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP);
else
gpiod_line_request_input_flags(this->gpioline_ptr, "cc3dsfs", GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN);
}
#endif
}
void ExtraButton::end() {
if(!initialized)
return;
#ifdef RASPI
if(!this->gpioline_ptr)
return;
gpiod_line_close_chip(this->gpioline_ptr);
gpiod_line_release(this->gpioline_ptr);
this->gpioline_ptr = NULL;
#endif
}
bool ExtraButton::is_pressed() {
#ifdef RASPI
if(this->gpioline_ptr)
return gpiod_line_get_value(this->gpioline_ptr) == 0;
#endif
return false;
}
std::string ExtraButton::get_name() {
if(this->is_valid())
return this->name;
return "";
}
bool ExtraButton::is_button_x(sf::Keyboard::Key corresponding_key) {
return this->is_valid() && this->corresponding_key == corresponding_key;
}
bool ExtraButton::is_valid() {
#ifdef RASPI
return this->initialized && (this->id >= 0) && this->gpioline_ptr;
#else
return false;
#endif
}
void ExtraButton::poll(std::queue<SFEvent> &events_queue) {
if(!this->is_valid())
return;
bool pressed = false;
if(this->is_pressed())
pressed = true;
if(pressed) {
auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - this->last_press_time;
float press_frequency_limit = this->first_re_press_time;
if((!this->started) || this->after_first)
press_frequency_limit = this->later_re_press_time;
// Do this regardless, even if it was previously released.
// This allows being more "lenient" with bad hw connections...
if(this->is_time_valid && (diff.count() < press_frequency_limit))
return;
this->is_time_valid = true;
this->last_press_time = curr_time;
if(!this->started) {
this->started = true;
this->after_first = false;
}
else
this->after_first = true;
}
else
this->started = false;
events_queue.emplace(pressed, this->corresponding_key, this->is_power, true);
}
std::string get_extra_button_name(sf::Keyboard::Key corresponding_key) {
for(size_t i = 0; i < NUM_PI_BUTTONS; i++)
if(pi_buttons[i]->is_button_x(corresponding_key))
return pi_buttons[i]->get_name();
return "";
}
void init_extra_buttons_poll(int page_up_id, int page_down_id, int enter_id, int power_id, bool use_pud_up) {
pi_page_up.initialize(page_up_id, sf::Keyboard::Key::PageUp, false, 0.5f, 0.03f, use_pud_up, "Select");
pi_page_down.initialize(page_down_id, sf::Keyboard::Key::PageDown, false, 0.5f, 0.03f, use_pud_up, "Menu");
pi_enter.initialize(enter_id, sf::Keyboard::Key::Enter, false, 0.5f, 0.075f, use_pud_up, "Enter");
pi_power.initialize(power_id, sf::Keyboard::Key::Escape, true, 30.0f, 30.0f, use_pud_up, "Power");
}
bool are_extra_buttons_usable() {
return (pi_enter.get_name() != "") && (pi_page_down.get_name() != "");
}
void end_extra_buttons_poll() {
for(size_t i = 0; i < NUM_PI_BUTTONS; i++)
pi_buttons[i]->end();
}
void extra_buttons_poll(std::queue<SFEvent> &events_queue) {
for(size_t i = 0; i < NUM_PI_BUTTONS; i++)
pi_buttons[i]->poll(events_queue);
}