2525 */
2626
2727#include " XInput.h"
28+
29+ // Teensy 3.1-3.2: __MK20DX256__
30+ // Teensy LC: __MKL26Z64__
31+ // Teensy 3.5: __MK64FX512__
32+ // Teensy 3.6: __MK66FX1M0__
33+
34+ #if defined(TEENSYDUINO) && \
35+ (defined (__MK20DX256__) || defined (__MKL26Z64__) || \
36+ defined (__MK64FX512__) || defined(__MK66FX1M0__))
37+
38+ #ifndef USB_XINPUT
39+ #error "USB type is not set to XInput in boards menu!"
40+ #endif
41+
42+ #else
43+ #error "Not a supported board! Must use Teensy 3.1/3.2, LC, 3.5, or 3.6"
44+ #endif
45+
2846#include < limits>
2947
3048// --------------------------------------------------------
@@ -55,7 +73,7 @@ static const XInputMap_Button Map_ButtonR3(2, 7);
5573
5674static const XInputMap_Button Map_ButtonLB (3 , 0 );
5775static const XInputMap_Button Map_ButtonRB (3 , 1 );
58- static const XInputMap_Button Map_ButtonLogo (3 , 3 );
76+ static const XInputMap_Button Map_ButtonLogo (3 , 2 );
5977static const XInputMap_Button Map_ButtonA (3 , 4 );
6078static const XInputMap_Button Map_ButtonB (3 , 5 );
6179static const XInputMap_Button Map_ButtonX (3 , 6 );
@@ -180,8 +198,11 @@ void XInputGamepad::release(XInputControl button) {
180198void XInputGamepad::setButton (XInputControl button, boolean state) {
181199 const XInputMap_Button * buttonData = getButtonFromEnum (button);
182200 if (buttonData != nullptr ) {
201+ if (getButton (button) == state) return ; // Button hasn't changed
202+
183203 if (state) { tx[buttonData->index ] |= buttonData->mask ; } // Press
184204 else { tx[buttonData->index ] &= ~(buttonData->mask ); } // Release
205+ newData = true ;
185206 }
186207 else {
187208 Range * triggerRange = getRangeFromEnum (button);
@@ -208,8 +229,12 @@ void XInputGamepad::setDpad(boolean up, boolean down, boolean left, boolean righ
208229void XInputGamepad::setTrigger (XInputControl trigger, int32_t val) {
209230 const XInputMap_Trigger * triggerData = getTriggerFromEnum (trigger);
210231 if (triggerData == nullptr ) return ; // Not a trigger
232+
211233 val = rescaleInput (val, *getRangeFromEnum (trigger), triggerData->range );
234+ if (getTrigger (trigger) == val) return ; // Trigger hasn't changed
235+
212236 tx[triggerData->index ] = val;
237+ newData = true ;
213238}
214239
215240void XInputGamepad::setJoystick (XInputControl joy, int32_t x, int32_t y) {
@@ -219,16 +244,49 @@ void XInputGamepad::setJoystick(XInputControl joy, int32_t x, int32_t y) {
219244 x = rescaleInput (x, *getRangeFromEnum (joy), joyData->range );
220245 y = rescaleInput (y, *getRangeFromEnum (joy), joyData->range );
221246
247+ if (getJoystickX (joy) == x && getJoystickY (joy) == y) return ; // Joy hasn't changed
248+
222249 tx[joyData->x_low ] = lowByte (x);
223250 tx[joyData->x_high ] = highByte (x);
224251
225252 tx[joyData->y_low ] = lowByte (y);
226253 tx[joyData->y_high ] = highByte (y);
254+
255+ newData = true ;
227256}
228257
229258void XInputGamepad::releaseAll () {
230259 const uint8_t offset = 2 ; // Skip message type and packet size
231260 memset (tx + offset, 0x00 , sizeof (tx) - offset); // Clear TX array
261+ newData = true ; // Data changed and is unsent
262+ }
263+
264+ boolean XInputGamepad::getButton (XInputControl button) const {
265+ const XInputMap_Button * buttonData = getButtonFromEnum (button);
266+ if (buttonData == nullptr ) return 0 ; // Not a button
267+ return tx[buttonData->index ] & buttonData->mask ;
268+ }
269+
270+ boolean XInputGamepad::getDpad (XInputControl dpad) const {
271+ return getButton (dpad);
272+ }
273+
274+ uint8_t XInputGamepad::getTrigger (XInputControl trigger) const {
275+ const XInputMap_Trigger * triggerData = getTriggerFromEnum (trigger);
276+ if (triggerData == nullptr ) return 0 ; // Not a trigger
277+ return tx[triggerData->index ];
278+ }
279+
280+ int16_t XInputGamepad::getJoystickX (XInputControl joy) const {
281+ const XInputMap_Joystick * joyData = getJoyFromEnum (joy);
282+ if (joyData == nullptr ) return 0 ; // Not a joystick
283+ return (tx[joyData->x_high ] << 8 ) | tx[joyData->x_low ];
284+ }
285+
286+ int16_t XInputGamepad::getJoystickY (XInputControl joy) const {
287+ const XInputMap_Joystick * joyData = getJoyFromEnum (joy);
288+ if (joyData == nullptr ) return 0 ; // Not a joystick
289+ return (tx[joyData->y_high ] << 8 ) | tx[joyData->y_low ];
232290}
233291
234292uint8_t XInputGamepad::getPlayer () const {
@@ -257,7 +315,9 @@ uint8_t XInputGamepad::getLEDPatternID() const {
257315
258316// Send an update packet to the PC
259317void XInputGamepad::send () {
318+ if (!newData) return ; // TX data hasn't changed
260319 XInputUSB.send (tx, USB_Timeout);
320+ newData = false ;
261321}
262322
263323void XInputGamepad::receive () {
@@ -284,23 +344,28 @@ void XInputGamepad::parseLED(uint8_t leds) {
284344 if (leds > 0x0D ) return ; // Not a known pattern
285345
286346 ledPattern = (XInputLEDPattern) leds; // Save pattern
287- if (ledPattern == XInputLEDPattern::Off || ledPattern == XInputLEDPattern::Blinking) {
347+ switch (ledPattern) {
348+ case (XInputLEDPattern::Off):
349+ case (XInputLEDPattern::Blinking):
288350 player = 0 ; // Not connected
289- }
290- else if (ledPattern == XInputLEDPattern::On1 || ledPattern == XInputLEDPattern::Flash1) {
351+ break ;
352+ case (XInputLEDPattern::On1):
353+ case (XInputLEDPattern::Flash1):
291354 player = 1 ;
292- }
293- else if (ledPattern == XInputLEDPattern::On2 || ledPattern == XInputLEDPattern::Flash2) {
355+ break ;
356+ case (XInputLEDPattern::On2):
357+ case (XInputLEDPattern::Flash2):
294358 player = 2 ;
295- }
296- else if (ledPattern == XInputLEDPattern::On3 || ledPattern == XInputLEDPattern::Flash3) {
359+ break ;
360+ case (XInputLEDPattern::On3):
361+ case (XInputLEDPattern::Flash3):
297362 player = 3 ;
298- }
299- else if (ledPattern == XInputLEDPattern::On4 || ledPattern == XInputLEDPattern::Flash4) {
363+ break ;
364+ case (XInputLEDPattern::On4):
365+ case (XInputLEDPattern::Flash4):
300366 player = 4 ;
301- }
302- else {
303- return ; // Pattern doesn't affect player #
367+ break ;
368+ default : return ; // Pattern doesn't affect player #
304369 }
305370}
306371
0 commit comments