Skip to content

Commit 87b5507

Browse files
authored
Merge pull request #5 from dmadison/development
Optional XInputUSB Support
2 parents 7d7fd84 + 90bc8f4 commit 87b5507

4 files changed

Lines changed: 97 additions & 17 deletions

File tree

examples/WiiClassicController/WiiClassicController.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ ClassicController classic;
3636
void setup() {
3737
classic.begin();
3838

39-
XInput.setTriggerRange(2, 28);
39+
XInput.setTriggerRange(4, 26);
4040

4141
XInput.setRange(JOY_LEFT, 8, 56);
4242
XInput.setRange(JOY_RIGHT, 4, 28);

keywords.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ getRumbleRight KEYWORD2
4747
getLEDPatternID KEYWORD2
4848

4949
# USB I/O
50+
connected KEYWORD2
5051
send KEYWORD2
5152
receive KEYWORD2
5253

@@ -57,6 +58,7 @@ setRange KEYWORD2
5758

5859
# Other
5960
reset KEYWORD2
61+
printDebug KEYWORD2
6062

6163
#######################################
6264
# Instances (KEYWORD2)

src/XInput.cpp

Lines changed: 88 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626

2727
#include "XInput.h"
2828

29+
#ifndef USB_XINPUT
30+
#warning "USB type is not set to XInput in boards menu! Board will not behave as an XInput device"
31+
#endif
32+
2933
// Teensy 3.1-3.2: __MK20DX256__
3034
// Teensy LC: __MKL26Z64__
3135
// Teensy 3.5: __MK64FX512__
@@ -34,13 +38,8 @@
3438
#if defined(TEENSYDUINO) && \
3539
(defined(__MK20DX256__) || defined(__MKL26Z64__) || \
3640
defined(__MK64FX512__) || defined(__MK66FX1M0__))
37-
38-
#ifndef USB_XINPUT
39-
#error "USB type is not set to XInput in boards menu!"
40-
#endif
41-
4241
#else
43-
#error "Not a supported board! Must use Teensy 3.1/3.2, LC, 3.5, or 3.6"
42+
#warning "Not a supported board! Must use Teensy 3.1/3.2, LC, 3.5, or 3.6"
4443
#endif
4544

4645
// --------------------------------------------------------
@@ -305,21 +304,36 @@ uint8_t XInputGamepad::getLEDPatternID() const {
305304
return (uint8_t)ledPattern;
306305
}
307306

307+
boolean XInputGamepad::connected() {
308+
#ifdef USB_XINPUT
309+
return XInputUSB::connected();
310+
#else
311+
return false;
312+
#endif
313+
}
314+
308315
//Send an update packet to the PC
309-
void XInputGamepad::send() {
310-
if (!newData) return; // TX data hasn't changed
311-
XInputUSB.send(tx, USB_Timeout);
316+
size_t XInputGamepad::send() {
317+
if (!newData) return 0; // TX data hasn't changed
318+
#ifdef USB_XINPUT
319+
XInputUSB::send(tx, USB_Timeout);
312320
newData = false;
321+
#else
322+
#warning "Using debug output for XInput send()"
323+
printDebug();
324+
#endif
325+
return sizeof(tx);
313326
}
314327

315-
void XInputGamepad::receive() {
316-
if (XInputUSB.available() == 0) {
317-
return; // No packet available
328+
size_t XInputGamepad::receive() {
329+
#ifdef USB_XINPUT
330+
if (XInputUSB::available() == 0) {
331+
return 0; // No packet available
318332
}
319333

320334
// Grab packet and store it in rx array
321335
uint8_t rx[8];
322-
XInputUSB.recv(rx, USB_Timeout);
336+
size_t bytesRecv = XInputUSB::recv(rx, USB_Timeout);
323337

324338
// Rumble Packet
325339
if ((rx[0] == 0x00) & (rx[1] == 0x08)) {
@@ -330,6 +344,10 @@ void XInputGamepad::receive() {
330344
else if (rx[0] == 0x01) {
331345
parseLED(rx[2]);
332346
}
347+
return bytesRecv;
348+
#else
349+
return 0;
350+
#endif
333351
}
334352

335353
void XInputGamepad::parseLED(uint8_t leds) {
@@ -372,9 +390,9 @@ XInputGamepad::Range * XInputGamepad::getRangeFromEnum(XInputControl ctrl) {
372390
}
373391

374392
int32_t XInputGamepad::rescaleInput(int32_t val, Range in, Range out) {
375-
if (in.min == out.min && in.max == out.max) return val; // Ranges identical
376393
if (val <= in.min) return out.min; // Out of range -
377394
if (val >= in.max) return out.max; // Out of range +
395+
if (in.min == out.min && in.max == out.max) return val; // Ranges identical
378396
return map(val, in.min, in.max, out.min, out.max);
379397
}
380398

@@ -415,4 +433,60 @@ void XInputGamepad::reset() {
415433
setJoystickRange(XInputMap_Joystick::range.min, XInputMap_Joystick::range.max);
416434
}
417435

436+
void XInputGamepad::printDebug(Print &output) const {
437+
const char fillCharacter = '_';
438+
439+
char buffer[80];
440+
441+
// Buttons
442+
const char dpadLPrint = getButton(DPAD_LEFT) ? '<' : fillCharacter;
443+
const char dpadUPrint = getButton(DPAD_UP) ? '^' : fillCharacter;
444+
const char dpadDPrint = getButton(DPAD_DOWN) ? 'v' : fillCharacter;
445+
const char dpadRPrint = getButton(DPAD_RIGHT) ? '>' : fillCharacter;
446+
447+
const char aButtonPrint = getButton(BUTTON_A) ? 'A' : fillCharacter;
448+
const char bButtonPrint = getButton(BUTTON_B) ? 'B' : fillCharacter;
449+
const char xButtonPrint = getButton(BUTTON_X) ? 'X' : fillCharacter;
450+
const char yButtonPrint = getButton(BUTTON_Y) ? 'Y' : fillCharacter;
451+
452+
const char startPrint = getButton(BUTTON_START) ? '>' : fillCharacter;
453+
const char backPrint = getButton(BUTTON_BACK) ? '<' : fillCharacter;
454+
455+
const char logoPrint = getButton(BUTTON_LOGO) ? 'X' : fillCharacter;
456+
457+
// Bumpers
458+
char leftBumper[3] = "LB";
459+
char rightBumper[3] = "RB";
460+
461+
if (!getButton(BUTTON_LB)) {
462+
leftBumper[0] = fillCharacter;
463+
leftBumper[1] = fillCharacter;
464+
}
465+
if (!getButton(BUTTON_RB)) {
466+
rightBumper[0] = fillCharacter;
467+
rightBumper[1] = fillCharacter;
468+
}
469+
470+
output.print("XInput Debug: ");
471+
sprintf(buffer,
472+
"LT: %3u %s L:(%6d, %6d) %c%c%c%c | %c%c%c | %c%c%c%c R:(%6d, %6d) %s RT: %3u",
473+
474+
// Left side controls
475+
getTrigger(TRIGGER_LEFT),
476+
leftBumper,
477+
getJoystickX(JOY_LEFT), getJoystickY(JOY_LEFT),
478+
479+
// Buttons
480+
dpadLPrint, dpadUPrint, dpadDPrint, dpadRPrint,
481+
backPrint, logoPrint, startPrint,
482+
aButtonPrint, bButtonPrint, xButtonPrint, yButtonPrint,
483+
484+
// Right side controls
485+
getJoystickX(JOY_RIGHT), getJoystickY(JOY_RIGHT),
486+
rightBumper,
487+
getTrigger(TRIGGER_RIGHT)
488+
);
489+
output.println(buffer);
490+
}
491+
418492
XInputGamepad XInput;

src/XInput.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ class XInputGamepad {
104104
XInputLEDPattern getLEDPattern() const; // Returns LED pattern type
105105

106106
// USB IO
107-
void send();
108-
void receive();
107+
boolean connected();
108+
size_t send();
109+
size_t receive();
109110

110111
// Control Input Ranges
111112
struct Range { int32_t min; int32_t max; };
@@ -117,6 +118,9 @@ class XInputGamepad {
117118
// Setup
118119
void reset();
119120

121+
// Debug
122+
void printDebug(Print& output = Serial) const;
123+
120124
private:
121125
static const uint32_t USB_Timeout = 12840; // Packet timeout, in milliseconds
122126
uint8_t tx[20]; // USB transmit data

0 commit comments

Comments
 (0)