Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions examples/GamepadPins/GamepadPins.ino
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
* and all of the main buttons.
*
* * Joysticks should be your typical 10k dual potentiometers.
* To prevent random values caused by floating inputs,
joysticks are disabled by default.
* * Triggers can be either analog (pots) or digital (buttons).
* Set the 'TriggerButtons' variable to change between the two.
* * Buttons use the internal pull-ups and should be connected
Expand Down Expand Up @@ -187,24 +189,22 @@ void loop() {

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

XInput.setJoystick(JOY_LEFT, leftJoyX, leftJoyY);
XInput.setJoystickX(JOY_LEFT, leftJoyX);
XInput.setJoystickY(JOY_LEFT, leftJoyY, invert);
}

// Set right joystick
if (UseRightJoystick == true) {
int rightJoyX = analogRead(Pin_RightJoyX);
int rightJoyY = analogRead(Pin_RightJoyY);

if (InvertRightYAxis == false) {
rightJoyY = ADC_Max - rightJoyY;
}
boolean invert = !InvertRightYAxis;

XInput.setJoystick(JOY_RIGHT, rightJoyX, rightJoyY);
XInput.setJoystickX(JOY_RIGHT, rightJoyX);
XInput.setJoystickY(JOY_RIGHT, rightJoyY, invert);
}

// Send control data to the computer
Expand Down
43 changes: 29 additions & 14 deletions src/XInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,12 @@ void XInputController::setJoystick(XInputControl joy, int32_t x, int32_t y) {
setJoystickDirect(joy, x, y);
}

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

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

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

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

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

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

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

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

if (getJoystickX(joy) == x && getJoystickY(joy) == y) return; // Joy hasn't changed

tx[joyData->x_low] = lowByte(x);
tx[joyData->x_high] = highByte(x);
if (getJoystickX(joy) != x) {
tx[joyData->x_low] = lowByte(x);
tx[joyData->x_high] = highByte(x);
newData = true;
}

tx[joyData->y_low] = lowByte(y);
tx[joyData->y_high] = highByte(y);
if (getJoystickY(joy) != y) {
tx[joyData->y_low] = lowByte(y);
tx[joyData->y_high] = highByte(y);
newData = true;
}

newData = true;
autosend();
}

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

boolean XInputController::getButton(uint8_t button) const {
const XInputMap_Button * buttonData = getButtonFromEnum((XInputControl) button);
if (buttonData == nullptr) return 0; // Not a button
return tx[buttonData->index] & buttonData->mask;
const XInputMap_Button* buttonData = getButtonFromEnum((XInputControl) button);
if (buttonData != nullptr) {
return tx[buttonData->index] & buttonData->mask;
}
const XInputMap_Trigger* triggerData = getTriggerFromEnum((XInputControl) button);
if (triggerData != nullptr) {
return getTrigger((XInputControl) button) != 0 ? 1 : 0;
}
return 0; // Not a button or a trigger
}

boolean XInputController::getDpad(XInputControl dpad) const {
Expand Down Expand Up @@ -427,8 +438,8 @@ boolean XInputController::connected() {
//Send an update packet to the PC
int XInputController::send() {
if (!newData) return 0; // TX data hasn't changed
#ifdef USB_XINPUT
newData = false;
#ifdef USB_XINPUT
return XInputUSB::send(tx, sizeof(tx));
#else
printDebug();
Expand Down Expand Up @@ -511,13 +522,17 @@ XInputController::Range * XInputController::getRangeFromEnum(XInputControl ctrl)
}
}

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

int16_t XInputController::invertInput(int16_t val, const Range& range) {
return range.max - val + range.min;
}

void XInputController::setTriggerRange(int32_t rangeMin, int32_t rangeMax) {
setRange(TRIGGER_LEFT, rangeMin, rangeMax);
setRange(TRIGGER_RIGHT, rangeMin, rangeMax);
Expand Down
13 changes: 7 additions & 6 deletions src/XInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ class XInputController {
void setButton(uint8_t button, boolean state);

void setDpad(XInputControl pad, boolean state);
void setDpad(boolean up, boolean down, boolean left, boolean right, boolean useSOCD = true);
void setDpad(boolean up, boolean down, boolean left, boolean right, boolean useSOCD=true);

void setTrigger(XInputControl trigger, int32_t val);

void setJoystick(XInputControl joy, int32_t x, int32_t y);
void setJoystick(XInputControl joy, boolean up, boolean down, boolean left, boolean right, boolean useSOCD = true);
void setJoystickX(XInputControl joy, int32_t x);
void setJoystickY(XInputControl joy, int32_t y);
void setJoystick(XInputControl joy, boolean up, boolean down, boolean left, boolean right, boolean useSOCD=true);
void setJoystickX(XInputControl joy, int32_t x, boolean invert=false);
void setJoystickY(XInputControl joy, int32_t y, boolean invert=false);

void releaseAll();

Expand Down Expand Up @@ -136,7 +136,7 @@ class XInputController {
void reset();

// Debug
void printDebug(Print& output = Serial) const;
void printDebug(Print& output=Serial) const;

private:
// Sent Data
Expand All @@ -161,7 +161,8 @@ class XInputController {
// Control Input Ranges
Range rangeTrigLeft, rangeTrigRight, rangeJoyLeft, rangeJoyRight;
Range * getRangeFromEnum(XInputControl ctrl);
int32_t rescaleInput(int32_t val, Range in, Range out);
static int32_t rescaleInput(int32_t val, const Range& in, const Range &out);
static int16_t invertInput(int16_t val, const Range& range);
};

extern XInputController XInput;
Expand Down