forked from lemmingDev/ESP32-BLE-Gamepad
-
Notifications
You must be signed in to change notification settings - Fork 2
/
XboxXInputController.ino
154 lines (132 loc) · 5.15 KB
/
XboxXInputController.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <BleConnectionStatus.h>
#include <BleCompositeHID.h>
#include <XboxGamepadDevice.h>
int ledPin = 5; // LED connected to digital pin 13
XboxGamepadDevice *gamepad;
BleCompositeHID compositeHID("ESP32 SeriesX Controller", "Mystfit", 100);
void OnVibrateEvent(XboxGamepadOutputReportData data)
{
if(data.weakMotorMagnitude > 0 || data.strongMotorMagnitude > 0){
digitalWrite(ledPin, LOW);
} else {
digitalWrite(ledPin, HIGH);
}
Serial.println("Vibration event. Weak motor: " + String(data.weakMotorMagnitude) + " Strong motor: " + String(data.strongMotorMagnitude));
}
void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT); // sets the digital pin as output
// Uncomment one of the following two config types depending on which controller version you want to use
// The XBox series X controller only works on linux kernels >= 6.5
//XboxOneSControllerDeviceConfiguration* config = new XboxOneSControllerDeviceConfiguration();
XboxSeriesXControllerDeviceConfiguration* config = new XboxSeriesXControllerDeviceConfiguration();
// The composite HID device pretends to be a valid Xbox controller via vendor and product IDs (VID/PID).
// Platforms like windows/linux need this in order to pick an XInput driver over the generic BLE GATT HID driver.
BLEHostConfiguration hostConfig = config->getIdealHostConfiguration();
Serial.println("Using VID source: " + String(hostConfig.getVidSource(), HEX));
Serial.println("Using VID: " + String(hostConfig.getVid(), HEX));
Serial.println("Using PID: " + String(hostConfig.getPid(), HEX));
Serial.println("Using GUID version: " + String(hostConfig.getGuidVersion(), HEX));
Serial.println("Using serial number: " + String(hostConfig.getSerialNumber()));
// Set up gamepad
gamepad = new XboxGamepadDevice(config);
// Set up vibration event handler
FunctionSlot<XboxGamepadOutputReportData> vibrationSlot(OnVibrateEvent);
gamepad->onVibrate.attach(vibrationSlot);
// Add all child devices to the top-level composite HID device to manage them
compositeHID.addDevice(gamepad);
// Start the composite HID device to broadcast HID reports
Serial.println("Starting composite HID device...");
compositeHID.begin(hostConfig);
}
void loop()
{
if(compositeHID.isConnected()){
testButtons();
testPads();
testTriggers();
testThumbsticks();
}
}
void testButtons(){
// Test each button
uint16_t buttons[] = {
XBOX_BUTTON_A,
XBOX_BUTTON_B,
XBOX_BUTTON_X,
XBOX_BUTTON_Y,
XBOX_BUTTON_LB,
XBOX_BUTTON_RB,
XBOX_BUTTON_START,
XBOX_BUTTON_SELECT,
//XBOX_BUTTON_HOME, // Uncomment this to test the hom/guide button. Steam will flip out and enter big picture mode when running this sketch though so be warned!
XBOX_BUTTON_LS,
XBOX_BUTTON_RS
};
for (uint16_t button : buttons)
{
Serial.println("Pressing button " + String(button));
gamepad->press(button);
gamepad->sendGamepadReport();
delay(500);
gamepad->release(button);
gamepad->sendGamepadReport();
delay(100);
}
// The share button is a seperate call since it doesn't live in the same
// bitflag as the rest of the buttons
gamepad->pressShare();
gamepad->sendGamepadReport();
delay(500);
gamepad->releaseShare();
gamepad->sendGamepadReport();
delay(100);
}
void testPads(){
XboxDpadFlags directions[] = {
XboxDpadFlags::NORTH,
XboxDpadFlags((uint8_t)XboxDpadFlags::NORTH | (uint8_t)XboxDpadFlags::EAST),
XboxDpadFlags::EAST,
XboxDpadFlags((uint8_t)XboxDpadFlags::EAST | (uint8_t)XboxDpadFlags::SOUTH),
XboxDpadFlags::SOUTH,
XboxDpadFlags((uint8_t)XboxDpadFlags::SOUTH | (uint8_t)XboxDpadFlags::WEST),
XboxDpadFlags::WEST,
XboxDpadFlags((uint8_t)XboxDpadFlags::WEST | (uint8_t)XboxDpadFlags::NORTH)
};
for (XboxDpadFlags direction : directions)
{
Serial.println("Pressing DPad: " + String(direction));
gamepad->pressDPadDirectionFlag(direction);
gamepad->sendGamepadReport();
delay(500);
gamepad->releaseDPad();
gamepad->sendGamepadReport();
delay(100);
}
}
void testTriggers(){
for(int16_t val = XBOX_TRIGGER_MIN; val <= XBOX_TRIGGER_MAX; val++){
if(val % 8 == 0)
Serial.println("Setting trigger value to " + String(val));
gamepad->setLeftTrigger(val);
gamepad->setRightTrigger(val);
gamepad->sendGamepadReport();
delay(8);
}
}
void testThumbsticks(){
int startTime = millis();
int reportCount = 0;
while(millis() - startTime < 8000){
reportCount++;
int16_t x = cos((float)millis() / 1000.0f) * XBOX_STICK_MAX;
int16_t y = sin((float)millis() / 1000.0f) * XBOX_STICK_MAX;
gamepad->setLeftThumb(x, y);
gamepad->setRightThumb(x, y);
gamepad->sendGamepadReport();
if(reportCount % 8 == 0)
Serial.println("Setting left thumb to " + String(x) + ", " + String(y));
delay(8);
}
}