2525 */
2626
2727#include " XInput.h"
28+ #include < limits>
2829
2930// --------------------------------------------------------
3031// XInput Button Maps |
@@ -89,9 +90,15 @@ constexpr const XInputMap_Button * getButtonFromEnum(XInputControl ctrl) {
8990struct XInputMap_Trigger {
9091 constexpr XInputMap_Trigger (uint8_t i)
9192 : index(i) {}
93+ static const XInputGamepad::Range range;
9294 const uint8_t index;
9395};
9496
97+ const XInputGamepad::Range XInputMap_Trigger::range = {
98+ std::numeric_limits<uint8_t >::min (), // 0
99+ std::numeric_limits<uint8_t >::max () // 255
100+ };
101+
95102static const XInputMap_Trigger Map_TriggerLeft (4 );
96103static const XInputMap_Trigger Map_TriggerRight (5 );
97104
@@ -111,12 +118,18 @@ constexpr const XInputMap_Trigger * getTriggerFromEnum(XInputControl ctrl) {
111118struct XInputMap_Joystick {
112119 constexpr XInputMap_Joystick (uint8_t xl, uint8_t xh, uint8_t yl, uint8_t yh)
113120 : x_low(xl), x_high(xh), y_low(yl), y_high(yh) {}
121+ static const XInputGamepad::Range range;
114122 const uint8_t x_low;
115123 const uint8_t x_high;
116124 const uint8_t y_low;
117125 const uint8_t y_high;
118126};
119127
128+ const XInputGamepad::Range XInputMap_Joystick::range = {
129+ std::numeric_limits<int16_t >::min (), // -32768
130+ std::numeric_limits<int16_t >::max () // 32767
131+ };
132+
120133static const XInputMap_Joystick Map_JoystickLeft (6 , 7 , 8 , 9 );
121134static const XInputMap_Joystick Map_JoystickRight (10 , 11 , 12 , 13 );
122135
@@ -169,7 +182,9 @@ void XInputGamepad::setButton(XInputControl button, boolean state) {
169182 else { tx[buttonData->index ] &= ~(buttonData->mask ); } // Release
170183 }
171184 else {
172- setTrigger (button, state ? 255 : 0 ); // Treat trigger like a button
185+ Range * triggerRange = getRangeFromEnum (button);
186+ if (triggerRange == nullptr ) return ; // Not a trigger (or joystick, but the trigger function will ignore that)
187+ setTrigger (button, state ? triggerRange->max : triggerRange->min ); // Treat trigger like a button
173188 }
174189}
175190
@@ -188,16 +203,20 @@ void XInputGamepad::setDpad(boolean up, boolean down, boolean left, boolean righ
188203 setDpad (DPAD_RIGHT, right);
189204}
190205
191- void XInputGamepad::setTrigger (XInputControl trigger, uint8_t val) {
206+ void XInputGamepad::setTrigger (XInputControl trigger, int32_t val) {
192207 const XInputMap_Trigger * triggerData = getTriggerFromEnum (trigger);
193208 if (triggerData == nullptr ) return ; // Not a trigger
209+ val = rescaleInput (val, *getRangeFromEnum (trigger), triggerData->range );
194210 tx[triggerData->index ] = val;
195211}
196212
197- void XInputGamepad::setJoystick (XInputControl joy, int16_t x, int16_t y) {
213+ void XInputGamepad::setJoystick (XInputControl joy, int32_t x, int32_t y) {
198214 const XInputMap_Joystick * joyData = getJoyFromEnum (joy);
199215 if (joyData == nullptr ) return ; // Not a joystick
200216
217+ x = rescaleInput (x, *getRangeFromEnum (joy), joyData->range );
218+ y = rescaleInput (y, *getRangeFromEnum (joy), joyData->range );
219+
201220 tx[joyData->x_low ] = lowByte (x);
202221 tx[joyData->x_high ] = highByte (x);
203222
@@ -283,15 +302,58 @@ void XInputGamepad::parseLED(uint8_t leds) {
283302 }
284303}
285304
305+ XInputGamepad::Range * XInputGamepad::getRangeFromEnum (XInputControl ctrl) {
306+ switch (ctrl) {
307+ case (TRIGGER_LEFT): return &rangeTrigLeft;
308+ case (TRIGGER_RIGHT): return &rangeTrigRight;
309+ case (JOY_LEFT): return &rangeJoyLeft;
310+ case (JOY_RIGHT): return &rangeJoyRight;
311+ default : return nullptr ;
312+ }
313+ }
314+
315+ int32_t XInputGamepad::rescaleInput (int32_t val, Range in, Range out) {
316+ if (in.min == out.min && in.max == out.max ) return val; // Ranges identical
317+ if (val <= in.min ) return out.min ; // Out of range -
318+ if (val >= in.max ) return out.max ; // Out of range +
319+ return map (val, in.min , in.max , out.min , out.max );
320+ }
321+
322+ void XInputGamepad::setTriggerRange (int32_t rangeMin, int32_t rangeMax) {
323+ setRange (TRIGGER_LEFT, rangeMin, rangeMax);
324+ setRange (TRIGGER_RIGHT, rangeMin, rangeMax);
325+ }
326+
327+ void XInputGamepad::setJoystickRange (int32_t rangeMin, int32_t rangeMax) {
328+ setRange (JOY_LEFT, rangeMin, rangeMax);
329+ setRange (JOY_RIGHT, rangeMin, rangeMax);
330+ }
331+
332+ void XInputGamepad::setRange (XInputControl ctrl, int32_t rangeMin, int32_t rangeMax) {
333+ if (rangeMin >= rangeMax) return ; // Error: Max < Min
334+
335+ Range * range = getRangeFromEnum (ctrl);
336+ if (range == nullptr ) return ; // Not an addressable range
337+
338+ range->min = rangeMin;
339+ range->max = rangeMax;
340+ }
341+
286342// Resets class back to initial values
287343void XInputGamepad::reset () {
344+ // Reset control data (tx)
288345 releaseAll (); // Clear TX buffer
289346 tx[0 ] = 0x00 ; // Set tx message type
290347 tx[1 ] = 0x14 ; // Set tx packet size (20)
291348
349+ // Reset received data (rx)
292350 player = 0 ; // Not connected, no player
293351 memset (rumble, 0x00 , sizeof (rumble)); // Clear rumble values
294352 ledPattern = XInputLEDPattern::Off; // No LEDs on
353+
354+ // Reset rescale ranges
355+ setTriggerRange (XInputMap_Trigger::range.min , XInputMap_Trigger::range.max );
356+ setJoystickRange (XInputMap_Joystick::range.min , XInputMap_Joystick::range.max );
295357}
296358
297359XInputGamepad XInput;
0 commit comments