From 28d09e8e9d4d4011d139870a248a9d715a2b1ebd Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 6 Mar 2019 23:15:54 -0500 Subject: [PATCH 1/9] MIT License --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..44a56e2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 David Madison + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From b1e333010fa300bf817a4f2fa76748018490ddba Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 6 Mar 2019 23:18:03 -0500 Subject: [PATCH 2/9] Add license information to README --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8307b9f..a94ce6e 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# Arduino XInput Library \ No newline at end of file +# Arduino XInput Library + +## License + +This library is licensed under the terms of the [MIT license](https://opensource.org/licenses/MIT). See the [LICENSE](LICENSE) file for more information. From 981b4f7cd2ef037aa328a6953390037ee933c1d9 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 7 Mar 2019 19:13:09 -0500 Subject: [PATCH 3/9] Add begin function Unused for now, although it matches the other HID libraries that use a 'begin' function, and it's quite useful to have an initialization function ready if we ever need it. --- examples/Blink/Blink.ino | 2 +- examples/GamepadPins/GamepadPins.ino | 6 +++--- examples/ReceiveCallback/ReceiveCallback.ino | 2 ++ examples/SimulateAll/SimulateAll.ino | 2 ++ examples/WiiClassicController/WiiClassicController.ino | 2 ++ keywords.txt | 5 ++++- src/XInput.cpp | 4 ++++ src/XInput.h | 2 ++ 8 files changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/Blink/Blink.ino b/examples/Blink/Blink.ino index a65a1ab..1dd10b8 100644 --- a/examples/Blink/Blink.ino +++ b/examples/Blink/Blink.ino @@ -31,7 +31,7 @@ #include void setup() { - + XInput.begin(); } void loop() { diff --git a/examples/GamepadPins/GamepadPins.ino b/examples/GamepadPins/GamepadPins.ino index dd30e6c..0c54539 100644 --- a/examples/GamepadPins/GamepadPins.ino +++ b/examples/GamepadPins/GamepadPins.ino @@ -114,10 +114,10 @@ void setup() { pinMode(Pin_DpadLeft, INPUT_PULLUP); pinMode(Pin_DpadRight, INPUT_PULLUP); - // Set joystick range to the ADC max - XInput.setJoystickRange(0, ADC_Max); - + XInput.setJoystickRange(0, ADC_Max); // Set joystick range to the ADC XInput.setAutoSend(false); // Wait for all controls before sending + + XInput.begin(); } void loop() { diff --git a/examples/ReceiveCallback/ReceiveCallback.ino b/examples/ReceiveCallback/ReceiveCallback.ino index 29b2c6d..1cce09f 100644 --- a/examples/ReceiveCallback/ReceiveCallback.ino +++ b/examples/ReceiveCallback/ReceiveCallback.ino @@ -44,6 +44,8 @@ void setup() { // Set callback function. Function must have a 'void' return type // and take a single uint8_t as an argument XInput.setReceiveCallback(rumbleCallback); + + XInput.begin(); } void loop() { diff --git a/examples/SimulateAll/SimulateAll.ino b/examples/SimulateAll/SimulateAll.ino index c8553f2..ddeeccb 100644 --- a/examples/SimulateAll/SimulateAll.ino +++ b/examples/SimulateAll/SimulateAll.ino @@ -75,6 +75,8 @@ double angle = 0.0; void setup() { pinMode(SafetyPin, INPUT_PULLUP); XInput.setAutoSend(false); // Wait for all controls before sending + + XInput.begin(); } void loop() { diff --git a/examples/WiiClassicController/WiiClassicController.ino b/examples/WiiClassicController/WiiClassicController.ino index a9c04ad..88822ef 100644 --- a/examples/WiiClassicController/WiiClassicController.ino +++ b/examples/WiiClassicController/WiiClassicController.ino @@ -43,6 +43,8 @@ void setup() { XInput.setAutoSend(false); // Wait for all controls before sending + XInput.begin(); + while (!classic.connect()) { delay(1000); // Controller not connected } diff --git a/keywords.txt b/keywords.txt index e9757d0..0b99c4a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -21,6 +21,10 @@ XInputLEDPattern KEYWORD1 # Methods and Functions (KEYWORD2) ####################################### +# Setup +begin KEYWORD2 +reset KEYWORD2 + # Set Control Data press KEYWORD2 release KEYWORD2 @@ -61,7 +65,6 @@ setJoystickRange KEYWORD2 setRange KEYWORD2 # Other -reset KEYWORD2 printDebug KEYWORD2 ####################################### diff --git a/src/XInput.cpp b/src/XInput.cpp index 7470ba2..4aebf2e 100644 --- a/src/XInput.cpp +++ b/src/XInput.cpp @@ -203,6 +203,10 @@ XInputGamepad::XInputGamepad() : #endif } +void XInputGamepad::begin() { + // Empty for now +} + void XInputGamepad::press(uint8_t button) { setButton(button, true); } diff --git a/src/XInput.h b/src/XInput.h index f18293b..00c5305 100644 --- a/src/XInput.h +++ b/src/XInput.h @@ -78,6 +78,8 @@ class XInputGamepad { public: XInputGamepad(); + void begin(); + // Set Control Surfaces void press(uint8_t button); void release(uint8_t button); From a07e5a1a5d36b6e4488593b68e63fdc2d0691d88 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 7 Mar 2019 20:07:23 -0500 Subject: [PATCH 4/9] Add initial information to README --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/README.md b/README.md index a94ce6e..b5a0981 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,51 @@ # Arduino XInput Library +This library lets you easily emulate an Xbox 360 controller using a USB-capable Arduino microcontroller. + +## Getting Started + +```cpp +void setup() { + XInput.begin(); +} + +void loop() { + XInput.press(BUTTON_A); + delay(1000); + + XInput.release(BUTTON_A); + delay(1000); +} +``` + +Before the library will work, you must install a compatible boards file that contains the XInput USB descriptors, otherwise the microcontroller won't behave like an XInput device. **This is not optional**. See the [compatible boards](#compatible-boards) section below for more information. + +After installing a compatible boards package, you must then [download and install the library](https://www.arduino.cc/en/guide/libraries). Once the XInput library is installed, open up the Arduino IDE and load an example sketch, located in `File -> Examples -> XInput` (I suggest trying the 'Blink' sketch first). Double-check that you have the correct XInput board selected in the 'Tools' menu, then upload the sketch to your microcontroller. + +On Windows, you can test that the sketch is working properly by opening up the joystick control panel ([joy.cpl](https://support.microsoft.com/en-us/help/831361/how-to-troubleshoot-game-controllers-in-microsoft-games)) or by using [GamepadViewer.com](https://gamepadviewer.com/?p=1). If you uploaded the XInput 'Blink' example, the #1 button ('A') should be slowly turning on and off. + +## Control Surfaces + +The library gives you access to the following controls available on the Xbox 360 controller: +* 10 + 1 Digital Buttons +* 2 Analog Joysticks (16 bit) +* 2 Analog Triggers (8 bit) +* 1 Four-Way Directional Pad (D-Pad) + +The library also processes received data, so you can read the status of the controller's 2 rumble motors (8-bit), the assigned player number (1-4), and the index of the current LED animation. Data is sent and received automatically over USB. + +## Compatible Boards + +To function as an XInput device, you *must* use a compatible boards package with XInput USB descriptors. **This is not optional**. Without these descriptors the library will only function in "debug" mode and the microcontroller will not behave as an XInput device. + +The following boards packages are available: + +* #### [Arduino AVR Boards](https://www.github.com/dmadison/ArduinoXInput_AVR) + Modifies the Arduino AVR core to emulate an XInput device. Includes support for the Arduino Leonardo, Micro, Yun, and more. + +* #### [Teensy 3 Boards](https://www.github.com/dmadison/ArduinoXInput_Teensy) + Includes an 'XInput' USB mode for the Teensy 3.1, 3.2, 3.5, 3.6, and LC microcontrollers. Requires a preexisting Teensyduino installation. + ## License This library is licensed under the terms of the [MIT license](https://opensource.org/licenses/MIT). See the [LICENSE](LICENSE) file for more information. From e67c01e8ba5a44e10f774be76e866f561353c96a Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 9 Mar 2019 22:15:36 -0500 Subject: [PATCH 5/9] Add USB API reference document --- README.md | 2 + extras/XInputUSB_API.md | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 extras/XInputUSB_API.md diff --git a/README.md b/README.md index b5a0981..be11047 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ The following boards packages are available: * #### [Teensy 3 Boards](https://www.github.com/dmadison/ArduinoXInput_Teensy) Includes an 'XInput' USB mode for the Teensy 3.1, 3.2, 3.5, 3.6, and LC microcontrollers. Requires a preexisting Teensyduino installation. + +For information on how to add support for another Arduino-compatible board with native USB support, see [the documentation on the USB API](extras/XInputUSB_API.md). ## License diff --git a/extras/XInputUSB_API.md b/extras/XInputUSB_API.md new file mode 100644 index 0000000..e09e3c6 --- /dev/null +++ b/extras/XInputUSB_API.md @@ -0,0 +1,86 @@ +# Using the XInputUSB API + +The Arduino XInput implementation is broken up into three separate components, of which this library is just one part: + +1. **The Library**, which is user-facing and contains lots of syntactic sugar to make it easy to manipulate the USB data. +2. **The Backend**, which handles the USB communication itself including endpoint memory management. +3. **The USB API**, which provides a standardized interface between these two components. + +The goal of this document is to describe how the USB API works so that you can use it to build XInput support for other board types while maintaining compatibility with this library. + +--- + +## Overview + +Here is the C++ API header in all of its glory: + +```cpp +#define USB_XINPUT + +class XInputUSB { +public: + static bool connected(void); + static uint8_t available(void); + static int send(const void *buffer, uint8_t nbytes); + static int recv(void *buffer, uint8_t nbytes); + static void setRecvCallback(void(*callback)(void)); +}; +``` + +Note the `USB_XINPUT` preprocessor definition. This definition is what tells the library that the API is present and that it can send data over USB. + +## Functions + +The API consists of five core static functions of the `XInputUSB` class that pass the USB data back and forth from the bus to the library. Here is the breakdown: + +### bool connected(void) + +The `connected` function returns the state of the USB interface with respect to XInput. If the device is connected to a host and functional this should return `true`. If the device is disconnected this should return `false`. + +### uint8_t available(void) + +The `available` function returns the number of bytes currently stored in the USB data banks for the received control surface data. If there are no bytes available this function returns 0. + +### int send(const void *buffer, uint8_t nbytes) + +The `send` function is used to send control surface data to the host over USB. It takes two arguments: +1. A pointer to the start of an array of data to be sent +2. The number of bytes to be sent + +The function then blocks until the data is sent, and returns the number of bytes that were transmitted. If an error occurs, the function returns -1. + +### int recv(void *buffer, uint8_t nbytes) + +The `recv` function is used to receive control surface data from the host. It takes two arguments: +1. A pointer to the start of a buffer to store the data +2. The number of bytes available in the buffer + +The function should move any received data from the USB data banks into the user-provided buffer. + +The function returns how many bytes were copied into the provided buffer. If no bytes are copied the function returns 0. If an error occurs the function should return -1. + +### void setRecvCallback(void(*callback)(void)) + +The `setRecvCallback` function is used to set the function callback for received data. It takes one argument, a function pointer with no arguments and a 'void' return type. This function pointer should be invoked whenever a new control surface data packet has been received. + +The API does not specify the storage for this callback pointer. + +## Building a Board Implementation + +These functions make up the API that allows the library to communicate over USB. However, the lower level USB implementation itself is up to the developer's discretion. To be detected by the Windows driver as an XInput device, your board needs to define the following, taken from an existing XInput product: + +* VID / PID +* Device Descriptor +* Configuration Descriptor +* String Descriptors + +This library is built around the official Xbox 360 wired controller's data layout. You can find these descriptors and an explanation of what they mean [here](http://www.partsnotincluded.com/reverse-engineering/understanding-the-xbox-360-wired-controllers-usb-data). If you're emulating another device the layout of the data packet may be different and need to be modified by your implementation. + +Once the board is detected by the host as an XInput device, define the USB API per the information above. Then fire up the library and try it out! + +## Examples + +Here are my two API implementations for reference: + +* [Arduino AVR Boards](https://github.com/dmadison/ArduinoXInput_AVR/blob/master/cores/arduino/xinput/USB_XInput_API.cpp) +* [Teensy 3 Boards](https://github.com/dmadison/ArduinoXInput_Teensy/blob/master/teensy/avr/cores/teensy3/usb_xinput.c) From ac9a5e61a1f2ddd50f9f936f8a9c4e6af9562587 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 9 Mar 2019 23:53:29 -0500 Subject: [PATCH 6/9] Refactor class as XInputController More generic than 'gamepad', since a gamepad is a specific device but a controller can be anything with the same control surfaces. --- keywords.txt | 2 +- src/XInput.cpp | 78 +++++++++++++++++++++++++------------------------- src/XInput.h | 6 ++-- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/keywords.txt b/keywords.txt index 0b99c4a..a9e375a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -10,7 +10,7 @@ XInput KEYWORD1 # Classes -XInputGamepad KEYWORD1 +XInputController KEYWORD1 # Enums XInputControl KEYWORD1 diff --git a/src/XInput.cpp b/src/XInput.cpp index 4aebf2e..ff4dd8d 100644 --- a/src/XInput.cpp +++ b/src/XInput.cpp @@ -119,11 +119,11 @@ const XInputMap_Button * getButtonFromEnum(XInputControl ctrl) { struct XInputMap_Trigger { constexpr XInputMap_Trigger(uint8_t i) : index(i) {} - static const XInputGamepad::Range range; + static const XInputController::Range range; const uint8_t index; }; -const XInputGamepad::Range XInputMap_Trigger::range = { 0, 255 }; // uint8_t +const XInputController::Range XInputMap_Trigger::range = { 0, 255 }; // uint8_t static const XInputMap_Trigger Map_TriggerLeft(4); static const XInputMap_Trigger Map_TriggerRight(5); @@ -144,14 +144,14 @@ const XInputMap_Trigger * getTriggerFromEnum(XInputControl ctrl) { struct XInputMap_Joystick { constexpr XInputMap_Joystick(uint8_t xl, uint8_t xh, uint8_t yl, uint8_t yh) : x_low(xl), x_high(xh), y_low(yl), y_high(yh) {} - static const XInputGamepad::Range range; + static const XInputController::Range range; const uint8_t x_low; const uint8_t x_high; const uint8_t y_low; const uint8_t y_high; }; -const XInputGamepad::Range XInputMap_Joystick::range = { -32768, 32767 }; // int16_t +const XInputController::Range XInputMap_Joystick::range = { -32768, 32767 }; // int16_t static const XInputMap_Joystick Map_JoystickLeft(6, 7, 8, 9); static const XInputMap_Joystick Map_JoystickRight(10, 11, 12, 13); @@ -191,10 +191,10 @@ static void XInputLib_Receive_Callback() { // -------------------------------------------------------- -// XInputGamepad Class (API) | +// XInputController Class (API) | // -------------------------------------------------------- -XInputGamepad::XInputGamepad() : +XInputController::XInputController() : tx(), rumble() // Zero initialize arrays { reset(); @@ -203,19 +203,19 @@ XInputGamepad::XInputGamepad() : #endif } -void XInputGamepad::begin() { +void XInputController::begin() { // Empty for now } -void XInputGamepad::press(uint8_t button) { +void XInputController::press(uint8_t button) { setButton(button, true); } -void XInputGamepad::release(uint8_t button) { +void XInputController::release(uint8_t button) { setButton(button, false); } -void XInputGamepad::setButton(uint8_t button, boolean state) { +void XInputController::setButton(uint8_t button, boolean state) { const XInputMap_Button * buttonData = getButtonFromEnum((XInputControl) button); if (buttonData != nullptr) { if (getButton(button) == state) return; // Button hasn't changed @@ -232,11 +232,11 @@ void XInputGamepad::setButton(uint8_t button, boolean state) { } } -void XInputGamepad::setDpad(XInputControl pad, boolean state) { +void XInputController::setDpad(XInputControl pad, boolean state) { setButton(pad, state); } -void XInputGamepad::setDpad(boolean up, boolean down, boolean left, boolean right) { +void XInputController::setDpad(boolean up, boolean down, boolean left, boolean right) { // Simultaneous Opposite Cardinal Directions (SOCD) Cleaner if (up && down) { down = false; } // Up + Down = Up if (left && right) { left = false; right = false; } // Left + Right = Neutral @@ -253,7 +253,7 @@ void XInputGamepad::setDpad(boolean up, boolean down, boolean left, boolean righ autosend(); } -void XInputGamepad::setTrigger(XInputControl trigger, int32_t val) { +void XInputController::setTrigger(XInputControl trigger, int32_t val) { const XInputMap_Trigger * triggerData = getTriggerFromEnum(trigger); if (triggerData == nullptr) return; // Not a trigger @@ -265,7 +265,7 @@ void XInputGamepad::setTrigger(XInputControl trigger, int32_t val) { autosend(); } -void XInputGamepad::setJoystick(XInputControl joy, int32_t x, int32_t y) { +void XInputController::setJoystick(XInputControl joy, int32_t x, int32_t y) { const XInputMap_Joystick * joyData = getJoyFromEnum(joy); if (joyData == nullptr) return; // Not a joystick @@ -284,70 +284,70 @@ void XInputGamepad::setJoystick(XInputControl joy, int32_t x, int32_t y) { autosend(); } -void XInputGamepad::releaseAll() { +void XInputController::releaseAll() { const uint8_t offset = 2; // Skip message type and packet size memset(tx + offset, 0x00, sizeof(tx) - offset); // Clear TX array newData = true; // Data changed and is unsent autosend(); } -void XInputGamepad::setAutoSend(boolean a) { +void XInputController::setAutoSend(boolean a) { autoSendOption = a; } -boolean XInputGamepad::getButton(uint8_t button) const { +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; } -boolean XInputGamepad::getDpad(XInputControl dpad) const { +boolean XInputController::getDpad(XInputControl dpad) const { return getButton(dpad); } -uint8_t XInputGamepad::getTrigger(XInputControl trigger) const { +uint8_t XInputController::getTrigger(XInputControl trigger) const { const XInputMap_Trigger * triggerData = getTriggerFromEnum(trigger); if (triggerData == nullptr) return 0; // Not a trigger return tx[triggerData->index]; } -int16_t XInputGamepad::getJoystickX(XInputControl joy) const { +int16_t XInputController::getJoystickX(XInputControl joy) const { const XInputMap_Joystick * joyData = getJoyFromEnum(joy); if (joyData == nullptr) return 0; // Not a joystick return (tx[joyData->x_high] << 8) | tx[joyData->x_low]; } -int16_t XInputGamepad::getJoystickY(XInputControl joy) const { +int16_t XInputController::getJoystickY(XInputControl joy) const { const XInputMap_Joystick * joyData = getJoyFromEnum(joy); if (joyData == nullptr) return 0; // Not a joystick return (tx[joyData->y_high] << 8) | tx[joyData->y_low]; } -uint8_t XInputGamepad::getPlayer() const { +uint8_t XInputController::getPlayer() const { return player; } -uint16_t XInputGamepad::getRumble() const { +uint16_t XInputController::getRumble() const { return rumble[RumbleLeft.bufferIndex] << 8 | rumble[RumbleRight.bufferIndex]; } -uint8_t XInputGamepad::getRumbleLeft() const { +uint8_t XInputController::getRumbleLeft() const { return rumble[RumbleLeft.bufferIndex]; } -uint8_t XInputGamepad::getRumbleRight() const { +uint8_t XInputController::getRumbleRight() const { return rumble[RumbleRight.bufferIndex]; } -XInputLEDPattern XInputGamepad::getLEDPattern() const { +XInputLEDPattern XInputController::getLEDPattern() const { return ledPattern; } -void XInputGamepad::setReceiveCallback(RecvCallbackType cback) { +void XInputController::setReceiveCallback(RecvCallbackType cback) { recvCallback = cback; } -boolean XInputGamepad::connected() { +boolean XInputController::connected() { #ifdef USB_XINPUT return XInputUSB::connected(); #else @@ -356,7 +356,7 @@ boolean XInputGamepad::connected() { } //Send an update packet to the PC -int XInputGamepad::send() { +int XInputController::send() { if (!newData) return 0; // TX data hasn't changed #ifdef USB_XINPUT newData = false; @@ -367,7 +367,7 @@ int XInputGamepad::send() { #endif } -int XInputGamepad::receive() { +int XInputController::receive() { #ifdef USB_XINPUT if (XInputUSB::available() == 0) { return 0; // No packet available @@ -403,7 +403,7 @@ int XInputGamepad::receive() { #endif } -void XInputGamepad::parseLED(uint8_t leds) { +void XInputController::parseLED(uint8_t leds) { if (leds > 0x0D) return; // Not a known pattern ledPattern = (XInputLEDPattern) leds; // Save pattern @@ -432,7 +432,7 @@ void XInputGamepad::parseLED(uint8_t leds) { } } -XInputGamepad::Range * XInputGamepad::getRangeFromEnum(XInputControl ctrl) { +XInputController::Range * XInputController::getRangeFromEnum(XInputControl ctrl) { switch (ctrl) { case(TRIGGER_LEFT): return &rangeTrigLeft; case(TRIGGER_RIGHT): return &rangeTrigRight; @@ -442,24 +442,24 @@ XInputGamepad::Range * XInputGamepad::getRangeFromEnum(XInputControl ctrl) { } } -int32_t XInputGamepad::rescaleInput(int32_t val, Range in, Range out) { +int32_t XInputController::rescaleInput(int32_t val, Range in, 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); } -void XInputGamepad::setTriggerRange(int32_t rangeMin, int32_t rangeMax) { +void XInputController::setTriggerRange(int32_t rangeMin, int32_t rangeMax) { setRange(TRIGGER_LEFT, rangeMin, rangeMax); setRange(TRIGGER_RIGHT, rangeMin, rangeMax); } -void XInputGamepad::setJoystickRange(int32_t rangeMin, int32_t rangeMax) { +void XInputController::setJoystickRange(int32_t rangeMin, int32_t rangeMax) { setRange(JOY_LEFT, rangeMin, rangeMax); setRange(JOY_RIGHT, rangeMin, rangeMax); } -void XInputGamepad::setRange(XInputControl ctrl, int32_t rangeMin, int32_t rangeMax) { +void XInputController::setRange(XInputControl ctrl, int32_t rangeMin, int32_t rangeMax) { if (rangeMin >= rangeMax) return; // Error: Max < Min Range * range = getRangeFromEnum(ctrl); @@ -470,7 +470,7 @@ void XInputGamepad::setRange(XInputControl ctrl, int32_t rangeMin, int32_t range } // Resets class back to initial values -void XInputGamepad::reset() { +void XInputController::reset() { // Reset control data (tx) releaseAll(); // Clear TX buffer tx[0] = 0x00; // Set tx message type @@ -490,7 +490,7 @@ void XInputGamepad::reset() { autoSendOption = true; } -void XInputGamepad::printDebug(Print &output) const { +void XInputController::printDebug(Print &output) const { const char fillCharacter = '_'; char buffer[80]; @@ -546,4 +546,4 @@ void XInputGamepad::printDebug(Print &output) const { output.println(buffer); } -XInputGamepad XInput; +XInputController XInput; diff --git a/src/XInput.h b/src/XInput.h index 00c5305..76f5ad1 100644 --- a/src/XInput.h +++ b/src/XInput.h @@ -74,9 +74,9 @@ enum class XInputLEDPattern { }; -class XInputGamepad { +class XInputController { public: - XInputGamepad(); + XInputController(); void begin(); @@ -159,6 +159,6 @@ class XInputGamepad { int32_t rescaleInput(int32_t val, Range in, Range out); }; -extern XInputGamepad XInput; +extern XInputController XInput; #endif \ No newline at end of file From 0ec2a932d0e6905bcedcf8f3a8f7615e082b1cc1 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 11 Mar 2019 01:02:58 -0400 Subject: [PATCH 7/9] Add supported boards file --- README.md | 4 ++-- extras/SupportedBoards.md | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 extras/SupportedBoards.md diff --git a/README.md b/README.md index be11047..95899a8 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ The following boards packages are available: * #### [Teensy 3 Boards](https://www.github.com/dmadison/ArduinoXInput_Teensy) Includes an 'XInput' USB mode for the Teensy 3.1, 3.2, 3.5, 3.6, and LC microcontrollers. Requires a preexisting Teensyduino installation. - -For information on how to add support for another Arduino-compatible board with native USB support, see [the documentation on the USB API](extras/XInputUSB_API.md). + +For a complete list of available packages and compatible boards see [the 'supported boards' file](extras/SupportedBoards.md). For information on how to add support for another Arduino-compatible board with native USB support, see [the documentation on the USB API](extras/XInputUSB_API.md). ## License diff --git a/extras/SupportedBoards.md b/extras/SupportedBoards.md new file mode 100644 index 0000000..fb98f04 --- /dev/null +++ b/extras/SupportedBoards.md @@ -0,0 +1,24 @@ +# Supported Boards + +Here is a complete list of all of the currently supported boards. Each header links to the respective repository where those board files are hosted. You *must* use an XInput specific board package for the library to function properly. + +## [Arduino AVR Core Boards](https://github.com/dmadison/ArduinoXInput_AVR/) + +* [Adafruit Circuit Playground 32u4](https://www.adafruit.com/product/3000) +* [Arduino Esplora](https://store.arduino.cc/usa/arduino-esplora) +* [Arduino Industrial 101](https://store.arduino.cc/usa/arduino-industrial-101) +* [Arduino Leonardo](https://store.arduino.cc/usa/leonardo) +* [Arduino Leonardo ETH](https://store.arduino.cc/usa/arduino-leonardo-eth) +* [Arduino Micro](https://store.arduino.cc/usa/arduino-micro) +* [Arduino Robot Control / Motor](https://store.arduino.cc/usa/arduino-robot) +* [Arduino Yún](https://store.arduino.cc/usa/arduino-yun) +* [Arduino Yún Mini](https://store.arduino.cc/usa/arduino-yun-mini) +* [LilyPad Arduino USB](https://www.sparkfun.com/products/12049) +* [Linino One](https://store.arduino.cc/usa/linino-one) + +## [Teensy 3 Boards](https://github.com/dmadison/ArduinoXInput_Teensy/) + +* [Teensy 3.6](https://www.pjrc.com/store/teensy36.html) +* [Teensy 3.5](https://www.pjrc.com/store/teensy35.html) +* [Teensy 3.1](https://www.pjrc.com/store/teensy31.html) / [3.2](https://www.pjrc.com/store/teensy32.html) +* [Teensy LC](https://www.pjrc.com/teensy/teensyLC.html) From be85bf1ca25f3bcfb3b1cdea1b3618da5e68977c Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 11 Mar 2019 02:10:44 -0400 Subject: [PATCH 8/9] Add SparkFun AVR boards --- README.md | 5 ++++- extras/SupportedBoards.md | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95899a8..fc3f509 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,12 @@ To function as an XInput device, you *must* use a compatible boards package with The following boards packages are available: -* #### [Arduino AVR Boards](https://www.github.com/dmadison/ArduinoXInput_AVR) +* #### [Arduino AVR Core Boards](https://www.github.com/dmadison/ArduinoXInput_AVR) Modifies the Arduino AVR core to emulate an XInput device. Includes support for the Arduino Leonardo, Micro, Yun, and more. +* #### [SparkFun AVR Boards](https://www.github.com/dmadison/ArduinoXInput_SparkFun) + Provides support for the MaKey MaKey, Pro Micro, Fio, Qduino Mini, and LilyPad USB Plus. Requires the XInput AVR Core boards. + * #### [Teensy 3 Boards](https://www.github.com/dmadison/ArduinoXInput_Teensy) Includes an 'XInput' USB mode for the Teensy 3.1, 3.2, 3.5, 3.6, and LC microcontrollers. Requires a preexisting Teensyduino installation. diff --git a/extras/SupportedBoards.md b/extras/SupportedBoards.md index fb98f04..bff64be 100644 --- a/extras/SupportedBoards.md +++ b/extras/SupportedBoards.md @@ -16,6 +16,16 @@ Here is a complete list of all of the currently supported boards. Each header li * [LilyPad Arduino USB](https://www.sparkfun.com/products/12049) * [Linino One](https://store.arduino.cc/usa/linino-one) +## [SparkFun AVR Boards](https://github.com/dmadison/ArduinoXInput_Sparkfun) +(Note: requires the XInput AVR core) + +* [MaKey MaKey](https://www.sparkfun.com/products/11511) +* [Pro Micro 3.3V](https://www.sparkfun.com/products/10999) +* [Pro Micro 5V](https://www.sparkfun.com/products/11098) +* [Fio v3](https://www.sparkfun.com/products/11520) +* [Qduino Mini](https://www.sparkfun.com/products/13614) +* [LilyPad USB Plus](https://www.sparkfun.com/products/14346) + ## [Teensy 3 Boards](https://github.com/dmadison/ArduinoXInput_Teensy/) * [Teensy 3.6](https://www.pjrc.com/store/teensy36.html) From c2ae3819fa4f860ff6c2b6669794ed82ef0f5f24 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 11 Mar 2019 02:11:33 -0400 Subject: [PATCH 9/9] Version 1.0.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index f68263e..f59edf2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=XInput -version=0.0.1 +version=1.0.0 author=David Madison maintainer=David Madison sentence=Library for emulating an Xbox controller over USB.