Skip to content

Commit 306847e

Browse files
committed
Only send data when changed
Avoids spamming USB packets with the same data. Matches behavior of the 360 controller.
1 parent 45104e2 commit 306847e

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

src/XInput.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,11 @@ void XInputGamepad::release(XInputControl button) {
198198
void XInputGamepad::setButton(XInputControl button, boolean state) {
199199
const XInputMap_Button * buttonData = getButtonFromEnum(button);
200200
if (buttonData != nullptr) {
201+
if (getButton(button) == state) return; // Button hasn't changed
202+
201203
if (state) { tx[buttonData->index] |= buttonData->mask; } // Press
202204
else { tx[buttonData->index] &= ~(buttonData->mask); } // Release
205+
newData = true;
203206
}
204207
else {
205208
Range * triggerRange = getRangeFromEnum(button);
@@ -226,8 +229,12 @@ void XInputGamepad::setDpad(boolean up, boolean down, boolean left, boolean righ
226229
void XInputGamepad::setTrigger(XInputControl trigger, int32_t val) {
227230
const XInputMap_Trigger * triggerData = getTriggerFromEnum(trigger);
228231
if (triggerData == nullptr) return; // Not a trigger
232+
229233
val = rescaleInput(val, *getRangeFromEnum(trigger), triggerData->range);
234+
if (getTrigger(trigger) == val) return; // Trigger hasn't changed
235+
230236
tx[triggerData->index] = val;
237+
newData = true;
231238
}
232239

233240
void XInputGamepad::setJoystick(XInputControl joy, int32_t x, int32_t y) {
@@ -237,16 +244,21 @@ void XInputGamepad::setJoystick(XInputControl joy, int32_t x, int32_t y) {
237244
x = rescaleInput(x, *getRangeFromEnum(joy), joyData->range);
238245
y = rescaleInput(y, *getRangeFromEnum(joy), joyData->range);
239246

247+
if (getJoystickX(joy) == x && getJoystickY(joy) == y) return; // Joy hasn't changed
248+
240249
tx[joyData->x_low] = lowByte(x);
241250
tx[joyData->x_high] = highByte(x);
242251

243252
tx[joyData->y_low] = lowByte(y);
244253
tx[joyData->y_high] = highByte(y);
254+
255+
newData = true;
245256
}
246257

247258
void XInputGamepad::releaseAll() {
248259
const uint8_t offset = 2; // Skip message type and packet size
249260
memset(tx + offset, 0x00, sizeof(tx) - offset); // Clear TX array
261+
newData = true; // Data changed and is unsent
250262
}
251263

252264
boolean XInputGamepad::getButton(XInputControl button) {
@@ -303,7 +315,9 @@ uint8_t XInputGamepad::getLEDPatternID() const {
303315

304316
//Send an update packet to the PC
305317
void XInputGamepad::send() {
318+
if (!newData) return; // TX data hasn't changed
306319
XInputUSB.send(tx, USB_Timeout);
320+
newData = false;
307321
}
308322

309323
void XInputGamepad::receive() {

src/XInput.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class XInputGamepad {
119119
private:
120120
static const uint32_t USB_Timeout = 12840; // Packet timeout, in milliseconds
121121
uint8_t tx[20]; // USB transmit data
122+
boolean newData; // Flag for tx data changed
122123

123124
uint8_t player; // Gamepad player #, buffered
124125
uint8_t rumble[2]; // Rumble motor data in, buffered

0 commit comments

Comments
 (0)