The demonstration regularly prints the status of all buttons and joystick values using a basic polling method.
The demonstration regularly prints the status of all buttons and joystick values using a basic polling method. This example first sends AT commands to connect to a target device, then enters a simple polling loop. Every 30 milliseconds, it prints the current state of all buttons (pressed/released) and the raw analog values (0‑255) of both joysticks. It showcases the fundamental usage of gamepad::input::Tracker[Button] for discrete button queries and gamepad::input::Tracker[Axis] for continuous joystick readings.
#include <SoftwareSerial.h>
using namespace gamepad::input;
namespace {
constexpr uint8_t kDebugSerialRxPin = 6;
constexpr uint8_t kDebugSerialTxPin = 5;
const String kBluetoothDeviceAddress = "16:00:00:00:03:05";
constexpr uint32_t kBluetoothModuleSerialBaudRate = 115200;
SoftwareSerial g_debug_serial(kDebugSerialRxPin, kDebugSerialTxPin);
void Connect(Stream &bluetooth_stream, const String &bluetooth_device_address) {
if (bluetooth_device_address.length() != 17 || bluetooth_device_address[2] != ':' || bluetooth_device_address[5] != ':' ||
bluetooth_device_address[8] != ':' || bluetooth_device_address[11] != ':' || bluetooth_device_address[14] != ':') {
g_debug_serial.println("Error: Invalid MAC address format. Expected: XX:XX:XX:XX:XX:XX");
while (true);
}
g_debug_serial.print("Start to connect ");
g_debug_serial.println(kBluetoothDeviceAddress);
bluetooth_stream.println("AT+DISCON");
delay(100);
bluetooth_stream.println("AT+RESET");
delay(100);
bluetooth_stream.println("AT+ECHO=0");
delay(100);
bluetooth_stream.println("AT+ROLE=0");
delay(100);
bluetooth_stream.println("AT+AUTOCON=0");
delay(100);
bluetooth_stream.print("AT+CON=");
bluetooth_stream.println(bluetooth_device_address);
delay(100);
g_debug_serial.println("Connected");
}
}
void setup() {
g_debug_serial.begin(115200);
Serial.begin(kBluetoothModuleSerialBaudRate);
Connect(Serial, kBluetoothDeviceAddress);
}
void loop() {
const Tracker &it = g_decoder.Update();
static uint32_t s_print_time = 0;
if (s_print_time != 0 && s_print_time + 30 > millis()) {
return;
}
s_print_time = millis();
g_debug_serial.print("Up:");
g_debug_serial.print(it[Button::kUp]);
g_debug_serial.print(", ");
g_debug_serial.print("Down:");
g_debug_serial.print(it[Button::kDown]);
g_debug_serial.print(", ");
g_debug_serial.print("Left:");
g_debug_serial.print(it[Button::kLeft]);
g_debug_serial.print(", ");
g_debug_serial.print("Right:");
g_debug_serial.print(it[Button::kRight]);
g_debug_serial.print(", ");
g_debug_serial.print("Square(X):");
g_debug_serial.print(it[Button::kSquareX]);
g_debug_serial.print(", ");
g_debug_serial.print("Triangle(Y):");
g_debug_serial.print(it[Button::kTriangleY]);
g_debug_serial.print(", ");
g_debug_serial.print("Cross(A):");
g_debug_serial.print(it[Button::kCrossA]);
g_debug_serial.print(", ");
g_debug_serial.print("Circle(B):");
g_debug_serial.print(it[Button::kCircleB]);
g_debug_serial.print(", ");
g_debug_serial.print("L1:");
g_debug_serial.print(it[Button::kL1]);
g_debug_serial.print(", ");
g_debug_serial.print("L2:");
g_debug_serial.print(it[Button::kL2]);
g_debug_serial.print(", ");
g_debug_serial.print("L3:");
g_debug_serial.print(it[Button::kL3]);
g_debug_serial.print(", ");
g_debug_serial.print("R1:");
g_debug_serial.print(it[Button::kR1]);
g_debug_serial.print(", ");
g_debug_serial.print("R2:");
g_debug_serial.print(it[Button::kR2]);
g_debug_serial.print(", ");
g_debug_serial.print("R3:");
g_debug_serial.print(it[Button::kR3]);
g_debug_serial.print(", ");
g_debug_serial.print("Select:");
g_debug_serial.print(it[Button::kSelect]);
g_debug_serial.print(", ");
g_debug_serial.print("Start:");
g_debug_serial.print(it[Button::kStart]);
g_debug_serial.print(", ");
g_debug_serial.print("Home:");
g_debug_serial.print(it[Button::kHome]);
g_debug_serial.print(", ");
g_debug_serial.print("L(X:");
g_debug_serial.print(it[Axis::kLeftStickX]);
g_debug_serial.print(", Y:");
g_debug_serial.print(it[Axis::kLeftStickY]);
g_debug_serial.print("), R(X:");
g_debug_serial.print(it[Axis::kRightStickX]);
g_debug_serial.print(", Y:");
g_debug_serial.print(it[Axis::kRightStickY]);
g_debug_serial.println(")");
}
Decoder class responsible for parsing gamepad input frames from a byte stream and updating the state ...