Skip to content

Commit ca60107

Browse files
committed
easier combo setting
updating code so that it's easier for folks to set custom combos. also improved multi button press detection
1 parent b2ac355 commit ca60107

File tree

2 files changed

+126
-138
lines changed

2 files changed

+126
-138
lines changed

USB_Host_Turbo_Button_Gamepad/Arduino_USB_Host_Turbo_Button_Gamepad/Arduino_USB_Host_Turbo_Button_Gamepad.ino

Lines changed: 119 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -131,159 +131,146 @@ void turbo_button() {
131131
}
132132
}
133133

134+
bool is_combo_detected(const uint8_t* combo, size_t combo_size, const uint8_t* report) {
135+
for (size_t i = 0; i < combo_size; i++) {
136+
uint8_t button = combo[i];
137+
138+
// Determine which byte the button is in and then check if it is pressed
139+
if (button & BUTTON_A || button & BUTTON_B || button & BUTTON_X || button & BUTTON_Y) {
140+
if ((report[BYTE_DPAD_BUTTONS] & button) != button) {
141+
return false; // Button is not pressed
142+
}
143+
} else if (button & BUTTON_LEFT_PADDLE || button & BUTTON_RIGHT_PADDLE ||
144+
button & BUTTON_LEFT_TRIGGER || button & BUTTON_RIGHT_TRIGGER ||
145+
button & BUTTON_BACK || button & BUTTON_START) {
146+
if ((report[BYTE_MISC_BUTTONS] & button) != button) {
147+
return false; // Button is not pressed
148+
}
149+
}
150+
}
151+
return true; // All buttons in the combo are pressed
152+
}
153+
134154
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
135-
// Known report when the combo is pressed
136-
//uint8_t combo_report[] = { 0x80, 0x7F, 0x80, 0x7F, 0x28, 0x03, 0x00, 0xFF };
137-
// Check if the incoming report matches the combo report
138-
bool combo_detected = ((report[4] == combo_report[4]) && (report[5] == combo_report[5]));// len == sizeof(combo_report)) && (memcmp(report, combo_report, sizeof(combo_report)) == 0);
139155

140156
// Manage the combo state and print messages
141-
if (combo_detected && !combo_active) {
157+
if ((is_combo_detected(combo_report, combo_size, report)) && !combo_active) {
142158
combo_active = true;
143159
Serial.println("combo!");
144-
} else if (combo_detected && combo_active) {
160+
} else if ((is_combo_detected(combo_report, combo_size, report)) && combo_active) {
145161
combo_active = false;
146162
Serial.println("combo released!");
147163
}
148-
if (!(combo_active)) {
149-
if (!(report[BYTE_LEFT_STICK_X] == LEFT_STICK_X_NEUTRAL)) {
150-
int16_t leftStickX = report[BYTE_LEFT_STICK_X];
151-
Serial.print("left stick X: ");
152-
Serial.println(leftStickX);
153-
int16_t new_leftStickX = map(leftStickX, 0, 255, -127, 127);
154-
gp.x = new_leftStickX;
164+
// Handle analog stick inputs
165+
gp.x = (report[BYTE_LEFT_STICK_X] != LEFT_STICK_X_NEUTRAL) ? map(report[BYTE_LEFT_STICK_X], 0, 255, -127, 127) : 0;
166+
gp.y = (report[BYTE_LEFT_STICK_Y] != LEFT_STICK_Y_NEUTRAL) ? map(report[BYTE_LEFT_STICK_Y], 0, 255, -127, 127) : 0;
167+
gp.z = (report[BYTE_RIGHT_STICK_X] != RIGHT_STICK_X_NEUTRAL) ? map(report[BYTE_RIGHT_STICK_X], 0, 255, -127, 127) : 0;
168+
gp.rz = (report[BYTE_RIGHT_STICK_Y] != RIGHT_STICK_Y_NEUTRAL) ? map(report[BYTE_RIGHT_STICK_Y], 0, 255, -127, 127) : 0;
169+
170+
// Debug print for report data
171+
/*Serial.print("Report data: ");
172+
for (int i = 0; i < len; i++) {
173+
Serial.print(report[i], HEX);
174+
Serial.print(" ");
175+
}
176+
Serial.println();*/
177+
178+
uint8_t dpad_value = report[BYTE_DPAD_BUTTONS] & DPAD_MASK;
179+
180+
// Handle D-pad direction
181+
if ((report[BYTE_DPAD_BUTTONS] & DPAD_NEUTRAL) == 0) {
182+
switch (dpad_value) {
183+
case DPAD_UP: gp.hat = 1; Serial.println("up"); break;
184+
case DPAD_UP_RIGHT: gp.hat = 2; Serial.println("up/right"); break;
185+
case DPAD_RIGHT: gp.hat = 3; Serial.println("right"); break;
186+
case DPAD_DOWN_RIGHT: gp.hat = 4; Serial.println("down/right"); break;
187+
case DPAD_DOWN: gp.hat = 5; Serial.println("down"); break;
188+
case DPAD_DOWN_LEFT: gp.hat = 6; Serial.println("down/left"); break;
189+
case DPAD_LEFT: gp.hat = 7; Serial.println("left"); break;
190+
case DPAD_UP_LEFT: gp.hat = 8; Serial.println("up/left"); break;
191+
}
155192
} else {
156-
gp.x = 0;
193+
gp.hat = 0;
157194
}
158-
if (!(report[BYTE_LEFT_STICK_Y] == LEFT_STICK_Y_NEUTRAL)) {
159-
int16_t leftStickY = report[BYTE_LEFT_STICK_Y];
160-
Serial.print("left stick Y: ");
161-
Serial.println(leftStickY);
162-
int16_t new_leftStickY = map(leftStickY, 0, 255, -127, 127);
163-
gp.y = new_leftStickY;
195+
uint16_t buttons = gp.buttons;
196+
if ((report[BYTE_DPAD_BUTTONS] & BUTTON_X) == BUTTON_X) {
197+
buttons |= GAMEPAD_BUTTON_X;
198+
Serial.println("x");
164199
} else {
165-
gp.y = 0;
200+
buttons &= ~GAMEPAD_BUTTON_X;
166201
}
167-
if (!(report[BYTE_RIGHT_STICK_X] == RIGHT_STICK_X_NEUTRAL)) {
168-
int8_t rightStickX = report[BYTE_RIGHT_STICK_X];
169-
Serial.print("right stick X: ");
170-
Serial.println(rightStickX);
171-
int16_t new_rightStickX = map(rightStickX, 0, 255, 127, -127);
172-
gp.z = new_rightStickX;
202+
if ((report[BYTE_DPAD_BUTTONS] & BUTTON_A) == BUTTON_A) {
203+
buttons |= GAMEPAD_BUTTON_A;
204+
Serial.println("a");
173205
} else {
174-
gp.z = 0;
206+
buttons &= ~GAMEPAD_BUTTON_A;
175207
}
176-
if (!(report[BYTE_RIGHT_STICK_Y] == RIGHT_STICK_Y_NEUTRAL)) {
177-
int8_t rightStickY = report[BYTE_RIGHT_STICK_Y];
178-
Serial.print("right stick Y: ");
179-
Serial.println(rightStickY);
180-
int16_t new_rightStickY = map(rightStickY, 0, 255, -127, 127);
181-
gp.rz = new_rightStickY;
208+
if ((report[BYTE_DPAD_BUTTONS] & BUTTON_B) == BUTTON_B) {
209+
buttons |= GAMEPAD_BUTTON_B;
210+
Serial.println("b");
182211
} else {
183-
gp.rz = 0;
212+
buttons &= ~GAMEPAD_BUTTON_B;
184213
}
185-
if (!(report[BYTE_DPAD_BUTTONS] == DPAD_NEUTRAL)) {
186-
// D-Pad is active
187-
uint8_t buttonsSelect = report[BYTE_DPAD_BUTTONS];
188-
switch (buttonsSelect) {
189-
case BUTTON_X:
190-
Serial.println("x");
191-
gp.buttons = GAMEPAD_BUTTON_X;
192-
break;
193-
case BUTTON_A:
194-
Serial.println("a");
195-
gp.buttons = GAMEPAD_BUTTON_A;
196-
break;
197-
case BUTTON_B:
198-
Serial.println("b");
199-
gp.buttons = GAMEPAD_BUTTON_B;
200-
break;
201-
case BUTTON_Y:
202-
Serial.println("y");
203-
gp.buttons = GAMEPAD_BUTTON_Y;
204-
break;
205-
}
214+
if ((report[BYTE_DPAD_BUTTONS] & BUTTON_Y) == BUTTON_Y) {
215+
buttons |= GAMEPAD_BUTTON_Y;
216+
Serial.println("y");
206217
} else {
207-
gp.hat = 0;
208-
gp.buttons = 0;
218+
buttons &= ~GAMEPAD_BUTTON_Y;
209219
}
210-
if (!(report[BYTE_DPAD_BUTTONS] == DPAD_NEUTRAL)) {
211-
// D-Pad is active
212-
uint8_t dpadDirection = report[BYTE_DPAD_BUTTONS];
213-
switch (dpadDirection) {
214-
case DPAD_UP:
215-
Serial.println("up");
216-
gp.hat = 1; // GAMEPAD_HAT_UP;
217-
break;
218-
case DPAD_UP_RIGHT:
219-
Serial.println("up/right");
220-
gp.hat = 2;
221-
break;
222-
case DPAD_RIGHT:
223-
Serial.println("right");
224-
gp.hat = 3;
225-
break;
226-
case DPAD_DOWN_RIGHT:
227-
Serial.println("down/right");
228-
gp.hat = 4;
229-
break;
230-
case DPAD_DOWN:
231-
Serial.println("down");
232-
gp.hat = 5;
233-
break;
234-
case DPAD_DOWN_LEFT:
235-
Serial.println("down/left");
236-
gp.hat = 6;
237-
break;
238-
case DPAD_LEFT:
239-
Serial.println("left");
240-
gp.hat = 7;
241-
break;
242-
case DPAD_UP_LEFT:
243-
Serial.println("up/left");
244-
gp.hat = 8;
245-
break;
246-
}
220+
gp.buttons = buttons;
221+
222+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_LEFT_PADDLE) == BUTTON_LEFT_PADDLE) {
223+
buttons |= GAMEPAD_BUTTON_TL;
224+
Serial.println("left paddle");
247225
} else {
248-
gp.hat = 0;
226+
buttons &= ~GAMEPAD_BUTTON_TL;
249227
}
250-
if (!(report[BYTE_MISC_BUTTONS] == MISC_NEUTRAL)) {
251-
// misc are active
252-
uint8_t miscDirection = report[BYTE_MISC_BUTTONS];
253-
switch (miscDirection) {
254-
case BUTTON_LEFT_PADDLE:
255-
Serial.println("left paddle");
256-
gp.buttons = GAMEPAD_BUTTON_TL;
257-
break;
258-
case BUTTON_RIGHT_PADDLE:
259-
Serial.println("right paddle");
260-
gp.buttons = GAMEPAD_BUTTON_TR;
261-
break;
262-
case BUTTON_LEFT_TRIGGER:
263-
Serial.println("left trigger");
264-
gp.buttons = GAMEPAD_BUTTON_TL2;
265-
break;
266-
case BUTTON_RIGHT_TRIGGER:
267-
Serial.println("right trigger");
268-
gp.buttons = GAMEPAD_BUTTON_TR2;
269-
break;
270-
case BUTTON_BACK:
271-
Serial.println("back");
272-
gp.buttons = GAMEPAD_BUTTON_SELECT;
273-
break;
274-
case BUTTON_START:
275-
Serial.println("start");
276-
gp.buttons = GAMEPAD_BUTTON_START;
277-
break;
278-
}
279-
}
280-
} else {
281-
gp.buttons = GAMEPAD_BUTTON_A;
282-
}
283-
while (!usb_hid.ready()) {
284-
yield();
228+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_RIGHT_PADDLE) == BUTTON_RIGHT_PADDLE) {
229+
buttons |= GAMEPAD_BUTTON_TR;
230+
Serial.println("right paddle");
231+
} else {
232+
buttons &= ~GAMEPAD_BUTTON_TR;
285233
}
286-
usb_hid.sendReport(0, &gp, sizeof(gp));
234+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_LEFT_TRIGGER) == BUTTON_LEFT_TRIGGER) {
235+
buttons |= GAMEPAD_BUTTON_TL2;
236+
Serial.println("left trigger");
237+
} else {
238+
buttons &= ~GAMEPAD_BUTTON_TL2;
239+
}
240+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_RIGHT_TRIGGER) == BUTTON_RIGHT_TRIGGER) {
241+
buttons |= GAMEPAD_BUTTON_TR2;
242+
Serial.println("right trigger");
243+
} else {
244+
buttons &= ~GAMEPAD_BUTTON_TR2;
245+
}
246+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_BACK) == BUTTON_BACK) {
247+
buttons |= GAMEPAD_BUTTON_SELECT;
248+
Serial.println("back");
249+
} else {
250+
buttons &= ~GAMEPAD_BUTTON_SELECT;
251+
}
252+
if ((report[BYTE_MISC_BUTTONS] & BUTTON_START) == BUTTON_START) {
253+
buttons |= GAMEPAD_BUTTON_START;
254+
Serial.println("start");
255+
} else {
256+
buttons &= ~GAMEPAD_BUTTON_START;
257+
}
258+
// Set the final buttons state
259+
gp.buttons = buttons;
260+
261+
// Debug print for gp contents
262+
/*Serial.print("gp.x: "); Serial.println(gp.x);
263+
Serial.print("gp.y: "); Serial.println(gp.y);
264+
Serial.print("gp.z: "); Serial.println(gp.z);
265+
Serial.print("gp.rz: "); Serial.println(gp.rz);
266+
Serial.print("gp.hat: "); Serial.println(gp.hat);
267+
Serial.print("gp.buttons: "); Serial.println(gp.buttons, HEX);*/
268+
269+
while (!usb_hid.ready()) {
270+
yield();
271+
}
272+
usb_hid.sendReport(0, &gp, sizeof(gp));
273+
287274
// Continue to receive the next report
288275
if (!tuh_hid_receive_report(dev_addr, instance)) {
289276
Serial.println("Error: cannot request to receive report");

USB_Host_Turbo_Button_Gamepad/Arduino_USB_Host_Turbo_Button_Gamepad/gamepad_reports.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
// HID reports for Logitech Gamepad F310
66
// Update defines and combo_report for your gamepad and/or combo!
77

8-
uint8_t combo_report[] = { 0x80, 0x7F, 0x80, 0x7F, 0x28, 0x03, 0x00, 0xFF };
9-
108
// Byte indices for the gamepad report
119
#define BYTE_LEFT_STICK_X 0 // Left analog stick X-axis
1210
#define BYTE_LEFT_STICK_Y 1 // Left analog stick Y-axis
@@ -32,10 +30,10 @@ uint8_t combo_report[] = { 0x80, 0x7F, 0x80, 0x7F, 0x28, 0x03, 0x00, 0xFF };
3230
#define DPAD_UP_LEFT 0x07 // 0111
3331

3432
// Face buttons (Byte[4] bits 4-7)
35-
#define BUTTON_X 0x18
36-
#define BUTTON_A 0x28
37-
#define BUTTON_B 0x48
38-
#define BUTTON_Y 0x88
33+
#define BUTTON_X 0x10
34+
#define BUTTON_A 0x20
35+
#define BUTTON_B 0x40
36+
#define BUTTON_Y 0x80
3937

4038
// Button masks for Byte[5] (MISC buttons)
4139
#define MISC_NEUTRAL 0x00
@@ -52,3 +50,6 @@ uint8_t combo_report[] = { 0x80, 0x7F, 0x80, 0x7F, 0x28, 0x03, 0x00, 0xFF };
5250
#define LEFT_STICK_Y_NEUTRAL 0x7F
5351
#define RIGHT_STICK_X_NEUTRAL 0x80
5452
#define RIGHT_STICK_Y_NEUTRAL 0x7F
53+
54+
uint8_t combo_report[] = { BUTTON_A, BUTTON_LEFT_PADDLE, BUTTON_RIGHT_PADDLE };
55+
size_t combo_size = sizeof(combo_report) / sizeof(combo_report[0]);

0 commit comments

Comments
 (0)