Skip to content

Commit ac8ead1

Browse files
authored
Merge pull request #43 from dmadison/development
Joystick Invert Option
2 parents 4613ca7 + 5d205ce commit ac8ead1

3 files changed

Lines changed: 45 additions & 29 deletions

File tree

examples/GamepadPins/GamepadPins.ino

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
* and all of the main buttons.
2929
*
3030
* * Joysticks should be your typical 10k dual potentiometers.
31+
* To prevent random values caused by floating inputs,
32+
joysticks are disabled by default.
3133
* * Triggers can be either analog (pots) or digital (buttons).
3234
* Set the 'TriggerButtons' variable to change between the two.
3335
* * Buttons use the internal pull-ups and should be connected
@@ -187,24 +189,22 @@ void loop() {
187189

188190
// White lie here... most generic joysticks are typically
189191
// inverted by default. If the "Invert" variable is false
190-
// then we need to do this transformation.
191-
if (InvertLeftYAxis == false) {
192-
leftJoyY = ADC_Max - leftJoyY;
193-
}
192+
// then we'll take the opposite value with 'not' (!).
193+
boolean invert = !InvertLeftYAxis;
194194

195-
XInput.setJoystick(JOY_LEFT, leftJoyX, leftJoyY);
195+
XInput.setJoystickX(JOY_LEFT, leftJoyX);
196+
XInput.setJoystickY(JOY_LEFT, leftJoyY, invert);
196197
}
197198

198199
// Set right joystick
199200
if (UseRightJoystick == true) {
200201
int rightJoyX = analogRead(Pin_RightJoyX);
201202
int rightJoyY = analogRead(Pin_RightJoyY);
202203

203-
if (InvertRightYAxis == false) {
204-
rightJoyY = ADC_Max - rightJoyY;
205-
}
204+
boolean invert = !InvertRightYAxis;
206205

207-
XInput.setJoystick(JOY_RIGHT, rightJoyX, rightJoyY);
206+
XInput.setJoystickX(JOY_RIGHT, rightJoyX);
207+
XInput.setJoystickY(JOY_RIGHT, rightJoyY, invert);
208208
}
209209

210210
// Send control data to the computer

src/XInput.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,12 @@ void XInputController::setJoystick(XInputControl joy, int32_t x, int32_t y) {
277277
setJoystickDirect(joy, x, y);
278278
}
279279

280-
void XInputController::setJoystickX(XInputControl joy, int32_t x) {
280+
void XInputController::setJoystickX(XInputControl joy, int32_t x, boolean invert) {
281281
const XInputMap_Joystick * joyData = getJoyFromEnum(joy);
282282
if (joyData == nullptr) return; // Not a joystick
283283

284284
x = rescaleInput(x, *getRangeFromEnum(joy), XInputMap_Joystick::range);
285+
if (invert) x = invertInput(x, XInputMap_Joystick::range);
285286

286287
if (getJoystickX(joy) == x) return; // Axis hasn't changed
287288

@@ -292,11 +293,12 @@ void XInputController::setJoystickX(XInputControl joy, int32_t x) {
292293
autosend();
293294
}
294295

295-
void XInputController::setJoystickY(XInputControl joy, int32_t y) {
296+
void XInputController::setJoystickY(XInputControl joy, int32_t y, boolean invert) {
296297
const XInputMap_Joystick * joyData = getJoyFromEnum(joy);
297298
if (joyData == nullptr) return; // Not a joystick
298299

299300
y = rescaleInput(y, *getRangeFromEnum(joy), XInputMap_Joystick::range);
301+
if (invert) y = invertInput(y, XInputMap_Joystick::range);
300302

301303
if (getJoystickY(joy) == y) return; // Axis hasn't changed
302304

@@ -341,15 +343,18 @@ void XInputController::setJoystickDirect(XInputControl joy, int16_t x, int16_t y
341343
const XInputMap_Joystick * joyData = getJoyFromEnum(joy);
342344
if (joyData == nullptr) return; // Not a joystick
343345

344-
if (getJoystickX(joy) == x && getJoystickY(joy) == y) return; // Joy hasn't changed
345-
346-
tx[joyData->x_low] = lowByte(x);
347-
tx[joyData->x_high] = highByte(x);
346+
if (getJoystickX(joy) != x) {
347+
tx[joyData->x_low] = lowByte(x);
348+
tx[joyData->x_high] = highByte(x);
349+
newData = true;
350+
}
348351

349-
tx[joyData->y_low] = lowByte(y);
350-
tx[joyData->y_high] = highByte(y);
352+
if (getJoystickY(joy) != y) {
353+
tx[joyData->y_low] = lowByte(y);
354+
tx[joyData->y_high] = highByte(y);
355+
newData = true;
356+
}
351357

352-
newData = true;
353358
autosend();
354359
}
355360

@@ -365,9 +370,15 @@ void XInputController::setAutoSend(boolean a) {
365370
}
366371

367372
boolean XInputController::getButton(uint8_t button) const {
368-
const XInputMap_Button * buttonData = getButtonFromEnum((XInputControl) button);
369-
if (buttonData == nullptr) return 0; // Not a button
370-
return tx[buttonData->index] & buttonData->mask;
373+
const XInputMap_Button* buttonData = getButtonFromEnum((XInputControl) button);
374+
if (buttonData != nullptr) {
375+
return tx[buttonData->index] & buttonData->mask;
376+
}
377+
const XInputMap_Trigger* triggerData = getTriggerFromEnum((XInputControl) button);
378+
if (triggerData != nullptr) {
379+
return getTrigger((XInputControl) button) != 0 ? 1 : 0;
380+
}
381+
return 0; // Not a button or a trigger
371382
}
372383

373384
boolean XInputController::getDpad(XInputControl dpad) const {
@@ -427,8 +438,8 @@ boolean XInputController::connected() {
427438
//Send an update packet to the PC
428439
int XInputController::send() {
429440
if (!newData) return 0; // TX data hasn't changed
430-
#ifdef USB_XINPUT
431441
newData = false;
442+
#ifdef USB_XINPUT
432443
return XInputUSB::send(tx, sizeof(tx));
433444
#else
434445
printDebug();
@@ -511,13 +522,17 @@ XInputController::Range * XInputController::getRangeFromEnum(XInputControl ctrl)
511522
}
512523
}
513524

514-
int32_t XInputController::rescaleInput(int32_t val, Range in, Range out) {
525+
int32_t XInputController::rescaleInput(int32_t val, const Range& in, const Range& out) {
515526
if (val <= in.min) return out.min; // Out of range -
516527
if (val >= in.max) return out.max; // Out of range +
517528
if (in.min == out.min && in.max == out.max) return val; // Ranges identical
518529
return map(val, in.min, in.max, out.min, out.max);
519530
}
520531

532+
int16_t XInputController::invertInput(int16_t val, const Range& range) {
533+
return range.max - val + range.min;
534+
}
535+
521536
void XInputController::setTriggerRange(int32_t rangeMin, int32_t rangeMax) {
522537
setRange(TRIGGER_LEFT, rangeMin, rangeMax);
523538
setRange(TRIGGER_RIGHT, rangeMin, rangeMax);

src/XInput.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ class XInputController {
8686
void setButton(uint8_t button, boolean state);
8787

8888
void setDpad(XInputControl pad, boolean state);
89-
void setDpad(boolean up, boolean down, boolean left, boolean right, boolean useSOCD = true);
89+
void setDpad(boolean up, boolean down, boolean left, boolean right, boolean useSOCD=true);
9090

9191
void setTrigger(XInputControl trigger, int32_t val);
9292

9393
void setJoystick(XInputControl joy, int32_t x, int32_t y);
94-
void setJoystick(XInputControl joy, boolean up, boolean down, boolean left, boolean right, boolean useSOCD = true);
95-
void setJoystickX(XInputControl joy, int32_t x);
96-
void setJoystickY(XInputControl joy, int32_t y);
94+
void setJoystick(XInputControl joy, boolean up, boolean down, boolean left, boolean right, boolean useSOCD=true);
95+
void setJoystickX(XInputControl joy, int32_t x, boolean invert=false);
96+
void setJoystickY(XInputControl joy, int32_t y, boolean invert=false);
9797

9898
void releaseAll();
9999

@@ -136,7 +136,7 @@ class XInputController {
136136
void reset();
137137

138138
// Debug
139-
void printDebug(Print& output = Serial) const;
139+
void printDebug(Print& output=Serial) const;
140140

141141
private:
142142
// Sent Data
@@ -161,7 +161,8 @@ class XInputController {
161161
// Control Input Ranges
162162
Range rangeTrigLeft, rangeTrigRight, rangeJoyLeft, rangeJoyRight;
163163
Range * getRangeFromEnum(XInputControl ctrl);
164-
int32_t rescaleInput(int32_t val, Range in, Range out);
164+
static int32_t rescaleInput(int32_t val, const Range& in, const Range &out);
165+
static int16_t invertInput(int16_t val, const Range& range);
165166
};
166167

167168
extern XInputController XInput;

0 commit comments

Comments
 (0)