|
| 1 | +#include <mutex> |
| 2 | + |
1 | 3 | #include "input.h" |
2 | 4 |
|
3 | 5 | #include "hal_i2c.hpp" |
4 | 6 |
|
5 | | -#include "task.hpp" |
6 | | - |
7 | 7 | #include "mcp23x17.hpp" |
8 | | - |
| 8 | +#include "timer.hpp" |
9 | 9 | #include "touchpad_input.hpp" |
| 10 | +#include "keypad_input.hpp" |
10 | 11 |
|
11 | 12 | using namespace std::chrono_literals; |
12 | 13 | using namespace box_hal; |
13 | 14 |
|
| 15 | +struct TouchpadData { |
| 16 | + uint8_t num_touch_points = 0; |
| 17 | + uint16_t x = 0; |
| 18 | + uint16_t y = 0; |
| 19 | + uint8_t btn_state = 0; |
| 20 | +}; |
| 21 | + |
14 | 22 | static std::shared_ptr<espp::Mcp23x17> mcp23x17; |
15 | 23 | static std::shared_ptr<TouchDriver> touch_driver; |
16 | 24 | static std::shared_ptr<espp::TouchpadInput> touchpad; |
| 25 | +static std::shared_ptr<espp::KeypadInput> keypad; |
| 26 | +static std::shared_ptr<espp::Timer> input_timer; |
| 27 | +static struct InputState gamepad_state; |
| 28 | +static std::mutex gamepad_state_mutex; |
| 29 | +static TouchpadData touchpad_data; |
| 30 | +static std::mutex touchpad_data_mutex; |
17 | 31 |
|
18 | 32 | /** |
19 | 33 | * Touch Controller configuration |
20 | 34 | */ |
21 | 35 | void touchpad_read(uint8_t* num_touch_points, uint16_t* x, uint16_t* y, uint8_t* btn_state) { |
22 | | - *num_touch_points = 0; |
| 36 | + std::lock_guard<std::mutex> lock(touchpad_data_mutex); |
| 37 | + *num_touch_points = touchpad_data.num_touch_points; |
| 38 | + *x = touchpad_data.x; |
| 39 | + *y = touchpad_data.y; |
| 40 | + *btn_state = touchpad_data.btn_state; |
| 41 | +} |
| 42 | + |
| 43 | +void keypad_read(bool *up, bool *down, bool *left, bool *right, bool *enter, bool *escape) { |
| 44 | + InputState state; |
| 45 | + get_input_state(&state); |
| 46 | + *up = state.up; |
| 47 | + *down = state.down; |
| 48 | + *left = state.left; |
| 49 | + *right = state.right; |
| 50 | + |
| 51 | + *enter = state.a || state.start; |
| 52 | + *escape = state.b || state.select; |
| 53 | +} |
| 54 | + |
| 55 | +void update_touchpad_input() { |
23 | 56 | // get the latest data from the device |
24 | 57 | std::error_code ec; |
25 | 58 | bool new_data = touch_driver->update(ec); |
26 | 59 | if (ec) { |
27 | 60 | fmt::print("error updating touch_driver: {}\n", ec.message()); |
| 61 | + std::lock_guard<std::mutex> lock(touchpad_data_mutex); |
| 62 | + touchpad_data = {}; |
28 | 63 | return; |
29 | 64 | } |
30 | 65 | if (!new_data) { |
| 66 | + std::lock_guard<std::mutex> lock(touchpad_data_mutex); |
| 67 | + touchpad_data = {}; |
31 | 68 | return; |
32 | 69 | } |
33 | | - // now hand it off |
34 | | - touch_driver->get_touch_point(num_touch_points, x, y); |
35 | | - *btn_state = touch_driver->get_home_button_state(); |
| 70 | + // get the latest data from the touchpad |
| 71 | + TouchpadData temp_data; |
| 72 | + touch_driver->get_touch_point(&temp_data.num_touch_points, &temp_data.x, &temp_data.y); |
| 73 | + temp_data.btn_state = touch_driver->get_home_button_state(); |
| 74 | + // update the touchpad data |
| 75 | + std::lock_guard<std::mutex> lock(touchpad_data_mutex); |
| 76 | + touchpad_data = temp_data; |
| 77 | +} |
| 78 | + |
| 79 | +void update_gamepad_input() { |
| 80 | + bool is_a_pressed = false; |
| 81 | + bool is_b_pressed = false; |
| 82 | + bool is_x_pressed = false; |
| 83 | + bool is_y_pressed = false; |
| 84 | + bool is_select_pressed = false; |
| 85 | + bool is_start_pressed = false; |
| 86 | + bool is_up_pressed = false; |
| 87 | + bool is_down_pressed = false; |
| 88 | + bool is_left_pressed = false; |
| 89 | + bool is_right_pressed = false; |
| 90 | + if (!mcp23x17) { |
| 91 | + fmt::print("cannot get input state: mcp23x17 not initialized properly!\n"); |
| 92 | + return; |
| 93 | + } |
| 94 | + // pins are active low |
| 95 | + // start, select = A0, A1 |
| 96 | + std::error_code ec; |
| 97 | + auto a_pins = mcp23x17->get_pins(espp::Mcp23x17::Port::A, ec); |
| 98 | + if (ec) { |
| 99 | + fmt::print("error getting pins from mcp23x17: {}\n", ec.message()); |
| 100 | + return; |
| 101 | + } |
| 102 | + // d-pad, abxy = B0-B3, B4-B7 |
| 103 | + auto b_pins = mcp23x17->get_pins(espp::Mcp23x17::Port::B, ec); |
| 104 | + if (ec) { |
| 105 | + fmt::print("error getting pins from mcp23x17: {}\n", ec.message()); |
| 106 | + return; |
| 107 | + } |
| 108 | + is_a_pressed = !(b_pins & 1<<4); |
| 109 | + is_b_pressed = !(b_pins & 1<<5); |
| 110 | + is_x_pressed = !(b_pins & 1<<6); |
| 111 | + is_y_pressed = !(b_pins & 1<<7); |
| 112 | + is_start_pressed = !(a_pins & 1<<0); |
| 113 | + is_select_pressed = !(a_pins & 1<<1); |
| 114 | + is_up_pressed = !(b_pins & 1<<0); |
| 115 | + is_down_pressed = !(b_pins & 1<<1); |
| 116 | + is_left_pressed = !(b_pins & 1<<2); |
| 117 | + is_right_pressed = !(b_pins & 1<<3); |
| 118 | + { |
| 119 | + std::lock_guard<std::mutex> lock(gamepad_state_mutex); |
| 120 | + gamepad_state.a = is_a_pressed; |
| 121 | + gamepad_state.b = is_b_pressed; |
| 122 | + gamepad_state.x = is_x_pressed; |
| 123 | + gamepad_state.y = is_y_pressed; |
| 124 | + gamepad_state.start = is_start_pressed; |
| 125 | + gamepad_state.select = is_select_pressed; |
| 126 | + gamepad_state.up = is_up_pressed; |
| 127 | + gamepad_state.down = is_down_pressed; |
| 128 | + gamepad_state.left = is_left_pressed; |
| 129 | + gamepad_state.right = is_right_pressed; |
| 130 | + } |
36 | 131 | } |
37 | 132 |
|
38 | 133 | static std::atomic<bool> initialized = false; |
@@ -78,56 +173,35 @@ void init_input() { |
78 | 173 | .log_level = espp::Logger::Verbosity::WARN |
79 | 174 | }); |
80 | 175 |
|
| 176 | + fmt::print("Initializing keypad\n"); |
| 177 | + keypad = std::make_shared<espp::KeypadInput>(espp::KeypadInput::Config{ |
| 178 | + .read = keypad_read, |
| 179 | + .log_level = espp::Logger::Verbosity::WARN |
| 180 | + }); |
| 181 | + |
| 182 | + fmt::print("Initializing input task\n"); |
| 183 | + input_timer = std::make_shared<espp::Timer>(espp::Timer::Config{ |
| 184 | + .name = "Input timer", |
| 185 | + .period = 20ms, |
| 186 | + .callback = []() { |
| 187 | + update_touchpad_input(); |
| 188 | + update_gamepad_input(); |
| 189 | + return false; |
| 190 | + }, |
| 191 | + .log_level = espp::Logger::Verbosity::WARN}); |
| 192 | + |
81 | 193 | initialized = true; |
82 | 194 | } |
83 | 195 |
|
84 | | -extern "C" void get_input_state(struct InputState* state) { |
85 | | - bool is_a_pressed = false; |
86 | | - bool is_b_pressed = false; |
87 | | - bool is_x_pressed = false; |
88 | | - bool is_y_pressed = false; |
89 | | - bool is_select_pressed = false; |
90 | | - bool is_start_pressed = false; |
91 | | - bool is_up_pressed = false; |
92 | | - bool is_down_pressed = false; |
93 | | - bool is_left_pressed = false; |
94 | | - bool is_right_pressed = false; |
95 | | - if (!mcp23x17) { |
96 | | - fmt::print("cannot get input state: mcp23x17 not initialized properly!\n"); |
97 | | - return; |
| 196 | +extern "C" lv_indev_t *get_keypad_input_device() { |
| 197 | + if (!keypad) { |
| 198 | + fmt::print("cannot get keypad input device: keypad not initialized properly!\n"); |
| 199 | + return nullptr; |
98 | 200 | } |
99 | | - // pins are active low |
100 | | - // start, select = A0, A1 |
101 | | - std::error_code ec; |
102 | | - auto a_pins = mcp23x17->get_pins(espp::Mcp23x17::Port::A, ec); |
103 | | - if (ec) { |
104 | | - fmt::print("error getting pins from mcp23x17: {}\n", ec.message()); |
105 | | - return; |
106 | | - } |
107 | | - // d-pad, abxy = B0-B3, B4-B7 |
108 | | - auto b_pins = mcp23x17->get_pins(espp::Mcp23x17::Port::B, ec); |
109 | | - if (ec) { |
110 | | - fmt::print("error getting pins from mcp23x17: {}\n", ec.message()); |
111 | | - return; |
112 | | - } |
113 | | - is_a_pressed = !(b_pins & 1<<4); |
114 | | - is_b_pressed = !(b_pins & 1<<5); |
115 | | - is_x_pressed = !(b_pins & 1<<6); |
116 | | - is_y_pressed = !(b_pins & 1<<7); |
117 | | - is_start_pressed = !(a_pins & 1<<0); |
118 | | - is_select_pressed = !(a_pins & 1<<1); |
119 | | - is_up_pressed = !(b_pins & 1<<0); |
120 | | - is_down_pressed = !(b_pins & 1<<1); |
121 | | - is_left_pressed = !(b_pins & 1<<2); |
122 | | - is_right_pressed = !(b_pins & 1<<3); |
123 | | - state->a = is_a_pressed; |
124 | | - state->b = is_b_pressed; |
125 | | - state->x = is_x_pressed; |
126 | | - state->y = is_y_pressed; |
127 | | - state->start = is_start_pressed; |
128 | | - state->select = is_select_pressed; |
129 | | - state->up = is_up_pressed; |
130 | | - state->down = is_down_pressed; |
131 | | - state->left = is_left_pressed; |
132 | | - state->right = is_right_pressed; |
| 201 | + return keypad->get_input_device(); |
| 202 | +} |
| 203 | + |
| 204 | +extern "C" void get_input_state(struct InputState* state) { |
| 205 | + std::lock_guard<std::mutex> lock(gamepad_state_mutex); |
| 206 | + *state = gamepad_state; |
133 | 207 | } |
0 commit comments