27#include <SoftwareSerial.h>
47using namespace gamepad::input;
54constexpr uint8_t kDebugSerialRxPin = 6;
55constexpr uint8_t kDebugSerialTxPin = 5;
59const String kBluetoothDeviceAddress =
"16:00:00:00:03:05";
64constexpr uint32_t kBluetoothModuleSerialBaudRate = 115200;
66constexpr Button kAllButtons[] = {Button::kUp, Button::kDown, Button::kLeft, Button::kRight, Button::kSquareX,
67 Button::kTriangleY, Button::kCrossA, Button::kCircleB, Button::kL1, Button::kL2,
68 Button::kL3, Button::kR1, Button::kR2, Button::kR3, Button::kSelect,
69 Button::kStart, Button::kHome};
77SoftwareSerial g_debug_serial(kDebugSerialRxPin, kDebugSerialTxPin);
79const String ButtonToString(Button button) {
90 case Button::kRight: {
93 case Button::kSquareX: {
96 case Button::kTriangleY: {
99 case Button::kCrossA: {
102 case Button::kCircleB: {
123 case Button::kSelect: {
126 case Button::kStart: {
129 case Button::kHome: {
159void Connect(Stream &bluetooth_stream,
const String &bluetooth_device_address) {
160 if (bluetooth_device_address.length() != 17 || bluetooth_device_address[2] !=
':' || bluetooth_device_address[5] !=
':' ||
161 bluetooth_device_address[8] !=
':' || bluetooth_device_address[11] !=
':' || bluetooth_device_address[14] !=
':') {
162 g_debug_serial.println(
"Error: Invalid MAC address format. Expected: XX:XX:XX:XX:XX:XX");
166 g_debug_serial.print(
"Start to connect ");
167 g_debug_serial.println(kBluetoothDeviceAddress);
172 bluetooth_stream.println(
"AT+DISCON");
177 bluetooth_stream.println(
"AT+RESET");
182 bluetooth_stream.println(
"AT+ECHO=0");
187 bluetooth_stream.println(
"AT+ROLE=0");
192 bluetooth_stream.println(
"AT+AUTOCON=0");
197 bluetooth_stream.print(
"AT+CON=");
198 bluetooth_stream.println(bluetooth_device_address);
201 g_debug_serial.println(
"Connected");
206 g_debug_serial.begin(115200);
208 Serial.begin(kBluetoothModuleSerialBaudRate);
210 Connect(Serial, kBluetoothDeviceAddress);
235 const Tracker &it = g_decoder.Update();
267 for (
auto button : kAllButtons) {
268 if (it.pressed(button)) {
269 g_debug_serial.print(
"Button ");
270 g_debug_serial.print(ButtonToString(button));
271 g_debug_serial.println(
": pressed");
272 }
else if (it.released(button)) {
273 g_debug_serial.print(
"Button ");
274 g_debug_serial.print(ButtonToString(button));
275 g_debug_serial.println(
": released");
276 }
else if (it.holding(button)) {
277 g_debug_serial.print(
"Button ");
278 g_debug_serial.print(ButtonToString(button));
279 g_debug_serial.println(
": holding");
294 constexpr uint8_t kAxisValueChangeThreshold = 2;
296 if (it.AxisChanged(Axis::kLeftStickX, kAxisValueChangeThreshold) ||
297 it.AxisChanged(Axis::kLeftStickY, kAxisValueChangeThreshold) ||
298 it.AxisChanged(Axis::kRightStickX, kAxisValueChangeThreshold) ||
299 it.AxisChanged(Axis::kRightStickY, kAxisValueChangeThreshold)) {
300 g_debug_serial.print(
"L(X: ");
301 g_debug_serial.print(it[Axis::kLeftStickX]);
302 g_debug_serial.print(
", Y: ");
303 g_debug_serial.print(it[Axis::kLeftStickY]);
304 g_debug_serial.print(
"), R(X: ");
305 g_debug_serial.print(it[Axis::kRightStickX]);
306 g_debug_serial.print(
", Y: ");
307 g_debug_serial.print(it[Axis::kRightStickY]);
308 g_debug_serial.println(
")");
Decoder class responsible for parsing gamepad input frames from a byte stream and updating the state ...