From 8ca3ab8fd1244a0455fffff0f2d110ea03a2092a Mon Sep 17 00:00:00 2001 From: Kristian Sloth Lauszus Date: Sun, 17 Feb 2013 01:03:32 +0100 Subject: [PATCH] Updated XBOXUSB library so it doesn't conflict with the other libraries --- XBOXRECV.cpp | 31 ------ XBOXRECV.h | 20 ++-- XBOXUSB.cpp | 111 ++++++++++---------- XBOXUSB.h | 167 ++++++++++++++++++------------ examples/Xbox/XBOXUSB/XBOXUSB.ino | 115 ++++++++++---------- xboxEnums.h | 64 ++++++++++++ 6 files changed, 280 insertions(+), 228 deletions(-) create mode 100644 xboxEnums.h diff --git a/XBOXRECV.cpp b/XBOXRECV.cpp index 59d301c7..becfa5b9 100644 --- a/XBOXRECV.cpp +++ b/XBOXRECV.cpp @@ -22,37 +22,6 @@ //#define EXTRADEBUG // Uncomment to get even more debugging data //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller -const uint8_t LEDS[] PROGMEM = { - 0x02, // LED1 - 0x03, // LED2 - 0x04, // LED3 - 0x05, // LED4 - 0x01 // ALL - Used to blink all LEDs - }; -const uint16_t BUTTONS[] PROGMEM = { - 0x0100, // UP - 0x0800, // RIGHT - 0x0200, // DOWN - 0x0400, // LEFT - - 0x2000, // BACK - 0x1000, // START - 0x4000, // L3 - 0x8000, // R3 - - 0,0, // Skip L2 and R2 as these are analog buttons - 0x0001, // L1 - 0x0002, // R1 - - 0x0020, // B - 0x0010, // A - 0x0040, // X - 0x0080, // Y - - 0x0004, // XBOX - 0x0008 // SYNC -}; - XBOXRECV::XBOXRECV(USB *p): pUsb(p), // pointer to USB class instance - mandatory bAddress(0), // device address - mandatory diff --git a/XBOXRECV.h b/XBOXRECV.h index b005f75a..ce88c12c 100644 --- a/XBOXRECV.h +++ b/XBOXRECV.h @@ -27,7 +27,7 @@ #endif #include "Usb.h" -#include "controllerEnums.h" +#include "xboxEnums.h" /* Data Xbox 360 taken from descriptors */ #define EP_MAXPKTSIZE 32 // max size for data via USB @@ -51,18 +51,10 @@ #define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver #define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver -#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers +#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz receivers #define XBOX_MAX_ENDPOINTS 9 -/** Enum used to set special LED modes supported by the Xbox controller. */ -enum LEDMode { - ROTATING = 0x0A, - FASTBLINK = 0x0B, - SLOWBLINK = 0x0C, - ALTERNATING = 0x0D, -}; - /** * This class implements support for a Xbox Wirless receiver. * @@ -78,7 +70,7 @@ public: /** @name USBDeviceConfig implementation */ /** - * Initialize the Xbox Controller. + * Initialize the Xbox wireless receiver. * @param parent Hub number. * @param port Port number on the hub. * @param lowspeed Speed of the device. @@ -109,8 +101,10 @@ public: /** @name Xbox Controller functions */ /** - * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down - * While getButtonClick(uint8_t controller, Button b) will only return it once + * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down. + * + * While getButtonClick(uint8_t controller, Button b) will only return it once. + * * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b). * @param controller The controller to read from. diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp index 333897ca..cf3e0485 100644 --- a/XBOXUSB.cpp +++ b/XBOXUSB.cpp @@ -175,13 +175,11 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { goto FailSetConf; #ifdef DEBUG - Notify(PSTR("\r\nXbox 360 Controller Connected")); + Notify(PSTR("\r\nXbox 360 Controller Connected\r\n")); #endif - setLedMode(ROTATING); - Xbox360Connected = true; - + setLedOn(LED1); + Xbox360Connected = true; bPollEnable = true; - Notify(PSTR("\r\n")); return 0; // successful configuration /* diagnostic messages */ @@ -245,27 +243,24 @@ void XBOXUSB::readReport() { return; } - ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16) | ((uint32_t)readBuf[5] << 24)); + ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); - //Notify(PSTR("\r\nButtonState"); + hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); + hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); + hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); + hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); + + //Notify(PSTR("\r\nButtonState")); //PrintHex(ButtonState); if(ButtonState != OldButtonState) { - buttonChanged = true; - if(ButtonState != 0x00) { - buttonPressed = true; - buttonReleased = false; - } else { - buttonPressed = false; - buttonReleased = true; - } - } else { - buttonChanged = false; - buttonPressed = false; - buttonReleased = false; + ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 + if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons + R2Clicked = true; + if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) + L2Clicked = true; + OldButtonState = ButtonState; } - - OldButtonState = ButtonState; } void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller @@ -276,64 +271,62 @@ void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the rep PrintHex(readBuf[i]); Serial.print(" "); } - Serial.println(""); + Serial.println(); #endif } -uint8_t XBOXUSB::getButton(Button b) { - if (readBuf == NULL) +uint8_t XBOXUSB::getButtonPress(Button b) { + if(b == L2) // These are analog buttons + return (uint8_t)(ButtonState >> 8); + else if(b == R2) + return (uint8_t)ButtonState; + return (ButtonState & ((uint32_t)pgm_read_word(&BUTTONS[(uint8_t)b]) << 16)); +} +bool XBOXUSB::getButtonClick(Button b) { + if(b == L2) { + if(L2Clicked) { + L2Clicked = false; + return true; + } return false; - if(b == L2 || b == R2) { // These are analog buttons - return (uint8_t)(readBuf[(uint8_t)b]); } - else { - if ((readBuf[(uint16_t)b >> 8] & ((uint8_t)b & 0xff)) > 0) - return 1; - else - return 0; + else if(b == R2) { + if(R2Clicked) { + R2Clicked = false; + return true; + } + return false; } + uint16_t button = pgm_read_word(&BUTTONS[(uint8_t)b]); + bool click = (ButtonClickState & button); + ButtonClickState &= ~button; // clear "click" event + return click; } int16_t XBOXUSB::getAnalogHat(AnalogHat a) { - if (readBuf == NULL) - return 0; - return (int16_t)(readBuf[(uint8_t)a+1] << 8 | readBuf[(uint8_t)a]); + return hatValue[a]; } -/* Playstation Sixaxis Dualshock and Navigation Controller commands */ +/* Xbox Controller commands */ void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) pUsb->ctrlReq(bAddress,epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); } -void XBOXUSB::setLedOn(LED l) { - if(l == ALL) // All LEDs can't be on a the same time - return; +void XBOXUSB::setLedRaw(uint8_t value) { writeBuf[0] = 0x01; writeBuf[1] = 0x03; - writeBuf[2] = (uint8_t)l; - writeBuf[2] += 4; - - XboxCommand(writeBuf, 3); -} -void XBOXUSB::setLedOff() { - writeBuf[0] = 0x01; - writeBuf[1] = 0x03; - writeBuf[2] = 0x00; + writeBuf[2] = value; XboxCommand(writeBuf, 3); } -void XBOXUSB::setLedBlink(LED l) { - writeBuf[0] = 0x01; - writeBuf[1] = 0x03; - writeBuf[2] = (uint8_t)l; - - XboxCommand(writeBuf, 3); +void XBOXUSB::setLedOn(LED led) { + if(led != ALL) // All LEDs can't be on a the same time + setLedRaw((pgm_read_byte(&LEDS[(uint8_t)led]))+4); } -void XBOXUSB::setLedMode(LEDMode lm) { // This function is used to do some speciel LED stuff the controller supports - writeBuf[0] = 0x01; - writeBuf[1] = 0x03; - writeBuf[2] = (uint8_t)lm; - - XboxCommand(writeBuf, 3); +void XBOXUSB::setLedBlink(LED led) { + setLedRaw(pgm_read_byte(&LEDS[(uint8_t)led])); +} +void XBOXUSB::setLedMode(LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports + setLedRaw((uint8_t)ledMode); } void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { writeBuf[0] = 0x00; diff --git a/XBOXUSB.h b/XBOXUSB.h index 3d20b867..9ab4b186 100644 --- a/XBOXUSB.h +++ b/XBOXUSB.h @@ -25,6 +25,7 @@ #endif #include "Usb.h" +#include "xboxEnums.h" /* Data Xbox 360 taken from descriptors */ #define EP_MAXPKTSIZE 32 // max size for data via USB @@ -54,99 +55,137 @@ #define XBOX_MAX_ENDPOINTS 3 -enum LED { - ALL = 0x01, // Used to blink all LEDs - LED1 = 0x02, - LED2 = 0x03, - LED3 = 0x04, - LED4 = 0x05, -}; -enum LEDMode { - ROTATING = 0x0A, - FASTBLINK = 0x0B, - SLOWBLINK = 0x0C, - ALTERNATING = 0x0D, -}; - -enum Button { - // byte location | bit location - UP = (2 << 8) | 0x01, - DOWN = (2 << 8) | 0x02, - LEFT = (2 << 8) | 0x04, - RIGHT = (2 << 8) | 0x08, - - START = (2 << 8) | 0x10, - BACK = (2 << 8) | 0x20, - L3 = (2 << 8) | 0x40, - R3 = (2 << 8) | 0x80, - - L1 = (3 << 8) | 0x01, - R1 = (3 << 8) | 0x02, - XBOX = (3 << 8) | 0x04, - - A = (3 << 8) | 0x10, - B = (3 << 8) | 0x20, - X = (3 << 8) | 0x40, - Y = (3 << 8) | 0x80, - - // These buttons are analog - L2 = 4, - R2 = 5, -}; -enum AnalogHat { - LeftHatX = 6, - LeftHatY = 8, - RightHatX = 10, - RightHatY = 12, -}; - +/** This class implements support for a Xbox wired controller via USB. */ class XBOXUSB : public USBDeviceConfig { public: + /** + * Constructor for the XBOXUSB class. + * @param pUsb Pointer to USB class instance. + */ XBOXUSB(USB *pUsb); - // USBDeviceConfig implementation + /** @name USBDeviceConfig implementation */ + /** + * Initialize the Xbox Controller. + * @param parent Hub number. + * @param port Port number on the hub. + * @param lowspeed Speed of the device. + * @return 0 on success. + */ virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + /** + * Release the USB device. + * @return 0 on success. + */ virtual uint8_t Release(); + /** + * Poll the USB Input endpoins and run the state machines. + * @return 0 on success. + */ virtual uint8_t Poll(); + /** + * Get the device address. + * @return The device address. + */ virtual uint8_t GetAddress() { return bAddress; }; + /** + * Used to check if the controller has been initialized. + * @return True if it's ready. + */ virtual bool isReady() { return bPollEnable; }; + /**@}*/ - /* XBOX Controller Readings */ - uint8_t getButton(Button b); + /** @name Xbox Controller functions */ + /** + * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down. + * + * While getButtonClick(uint8_t controller, Button b) will only return it once. + * + * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), + * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b). + * @param b ::Button to read. + * @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b) + * will return a byte if reading ::L2 or ::R2. + */ + uint8_t getButtonPress(Button b); + bool getButtonClick(Button b); + /**@}*/ + + /** @name Xbox Controller functions */ + /** + * Return the analog value from the joysticks on the controller. + * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. + * @return Returns a signed 16-bit integer. + */ int16_t getAnalogHat(AnalogHat a); - /* Commands for Dualshock 3 and Navigation controller */ - void setAllOff() { setRumbleOn(0,0); setLedOff(); }; + /** Turn rumble off and all the LEDs on the controller. */ + void setAllOff() { setRumbleOn(0,0); setLedRaw(0); }; + /** Turn rumble off the controller. */ void setRumbleOff() { setRumbleOn(0,0); }; + /** + * Turn rumble on. + * @param lValue Left motor (big weight) inside the controller. + * @param rValue Right motor (small weight) inside the controller. + */ void setRumbleOn(uint8_t lValue, uint8_t rValue); - void setLedOff(); - void setLedOn(LED l); + /** + * Set LED value. Without using the ::LED or ::LEDMode enum. + * @param value See: + * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), + * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). + */ + void setLedRaw(uint8_t value); + /** Turn all LEDs off the controller. */ + void setLedOff() { setLedRaw(0); }; + /** + * Turn on a LED by using the ::LED enum. + * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ + void setLedOn(LED l); + /** + * Turn on a LED by using the ::LED enum. + * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller. + */ void setLedBlink(LED l); + /** + * Used to set special LED modes supported by the Xbox controller. + * @param controller The controller to write to. + * @param lm See ::LEDMode. + */ void setLedMode(LEDMode lm); - - bool Xbox360Connected;// Variable used to indicate if the XBOX 360 controller is successfully connected - bool buttonChanged;//Indicate if a button has been changed - bool buttonPressed;//Indicate if a button has been pressed - bool buttonReleased;//Indicate if a button has been released + /**@}*/ + + /** True if a Xbox 360 controller is connected. */ + bool Xbox360Connected; protected: - /* mandatory members */ + /** Pointer to USB class instance. */ USB *pUsb; - uint8_t bAddress; // device address - EpInfo epInfo[XBOX_MAX_ENDPOINTS]; //endpoint info structure + /** Device address. */ + uint8_t bAddress; + /** Endpoint info structure. */ + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; private: - bool bPollEnable; + bool bPollEnable; + /* Variables to store the buttons */ uint32_t ButtonState; - uint32_t OldButtonState; + uint32_t OldButtonState; + uint16_t ButtonClickState; + int16_t hatValue[4]; + uint16_t controllerStatus; + + bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not + bool R2Clicked; uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data void readReport(); // read incoming data void printReport(); // print incoming date - Uncomment for debugging - + /* Private commands */ void XboxCommand(uint8_t* data, uint16_t nbytes); }; diff --git a/examples/Xbox/XBOXUSB/XBOXUSB.ino b/examples/Xbox/XBOXUSB/XBOXUSB.ino index 338c279e..2f209ce3 100644 --- a/examples/Xbox/XBOXUSB/XBOXUSB.ino +++ b/examples/Xbox/XBOXUSB/XBOXUSB.ino @@ -10,7 +10,6 @@ XBOXUSB Xbox(&Usb); void setup() { Serial.begin(115200); - if (Usb.Init() == -1) { Serial.print(F("\r\nOSC did not start")); while(1); //halt @@ -20,7 +19,14 @@ void setup() { void loop() { Usb.Task(); if(Xbox.Xbox360Connected) { - Xbox.setRumbleOn(Xbox.getButton(L2),Xbox.getButton(R2)); + if(Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) { + Serial.print("L2: "); + Serial.print(Xbox.getButtonPress(L2)); + Serial.print("\tR2: "); + Serial.println(Xbox.getButtonPress(R2)); + Xbox.setRumbleOn(Xbox.getButtonPress(L2),Xbox.getButtonPress(R2)); + } else + Xbox.setRumbleOn(0,0); if(Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { if(Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) { Serial.print(F("LeftHatX: ")); @@ -41,69 +47,56 @@ void loop() { Serial.print(F("RightHatY: ")); Serial.print(Xbox.getAnalogHat(RightHatY)); } - Serial.println(""); + Serial.println(); + } + + if(Xbox.getButtonClick(UP)) { + Xbox.setLedOn(LED1); + Serial.println(F("Up")); + } + if(Xbox.getButtonClick(DOWN)) { + Xbox.setLedOn(LED4); + Serial.println(F("Down")); + } + if(Xbox.getButtonClick(LEFT)) { + Xbox.setLedOn(LED3); + Serial.println(F("Left")); + } + if(Xbox.getButtonClick(RIGHT)) { + Xbox.setLedOn(LED2); + Serial.println(F("Right")); } - if(Xbox.buttonPressed) { - Serial.print(F("Xbox 360 Controller")); - if(Xbox.getButton(UP)) { - Xbox.setLedOn(LED1); - Serial.print(F(" - UP")); - } - if(Xbox.getButton(DOWN)) { - Xbox.setLedOn(LED4); - Serial.print(F(" - DOWN")); - } - if(Xbox.getButton(LEFT)) { - Xbox.setLedOn(LED3); - Serial.print(F(" - LEFT")); - } - if(Xbox.getButton(RIGHT)) { - Xbox.setLedOn(LED2); - Serial.print(F(" - RIGHT")); - } + if(Xbox.getButtonClick(START)) { + Xbox.setLedMode(ALTERNATING); + Serial.println(F("Start")); + } + if(Xbox.getButtonClick(BACK)) { + Xbox.setLedBlink(ALL); + Serial.println(F("Back")); + } + if(Xbox.getButtonClick(L3)) + Serial.println(F("L3")); + if(Xbox.getButtonClick(R3)) + Serial.println(F("R3")); - if(Xbox.getButton(START)) { - Xbox.setLedMode(ALTERNATING); - Serial.print(F(" - START")); - } - if(Xbox.getButton(BACK)) { - Xbox.setLedBlink(ALL); - Serial.print(F(" - BACK")); - } - if(Xbox.getButton(L3)) - Serial.print(F(" - L3")); - if(Xbox.getButton(R3)) - Serial.print(F(" - R3")); + if(Xbox.getButtonClick(L1)) + Serial.println(F("L1")); + if(Xbox.getButtonClick(R1)) + Serial.println(F("R1")); + if(Xbox.getButtonClick(XBOX)) { + Xbox.setLedMode(ROTATING); + Serial.println(F("Xbox")); + } - if(Xbox.getButton(L1)) - Serial.print(F(" - L1")); - if(Xbox.getButton(R1)) - Serial.print(F(" - R1")); - if(Xbox.getButton(XBOX)) { - Xbox.setLedMode(ROTATING); - Serial.print(F(" - XBOX")); - } - - if(Xbox.getButton(A)) - Serial.print(F(" - A")); - if(Xbox.getButton(B)) - Serial.print(F(" - B")); - if(Xbox.getButton(X)) - Serial.print(F(" - X")); - if(Xbox.getButton(Y)) - Serial.print(F(" - Y")); - - if(Xbox.getButton(L2)) { - Serial.print(F(" - L2:")); - Serial.print(Xbox.getButton(L2)); - } - if(Xbox.getButton(R2)) { - Serial.print(F(" - R2:")); - Serial.print(Xbox.getButton(R2)); - } - Serial.println(); - } + if(Xbox.getButtonClick(A)) + Serial.println(F("A")); + if(Xbox.getButtonClick(B)) + Serial.println(F("B")); + if(Xbox.getButtonClick(X)) + Serial.println(F("X")); + if(Xbox.getButtonClick(Y)) + Serial.println(F("Y")); } delay(1); } diff --git a/xboxEnums.h b/xboxEnums.h new file mode 100644 index 00000000..b1eb5b1f --- /dev/null +++ b/xboxEnums.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. + + This software may be distributed and modified under the terms of the GNU + General Public License version 2 (GPL2) as published by the Free Software + Foundation and appearing in the file GPL2.TXT included in the packaging of + this file. Please note that GPL2 Section 2[b] requires that all works based + on this software must also be made publicly available under the terms of + the GPL2 ("Copyleft"). + + Contact information + ------------------- + + Kristian Lauszus, TKJ Electronics + Web : http://www.tkjelectronics.com + e-mail : kristianl@tkjelectronics.com + */ + +#ifndef _xboxenums_h +#define _xboxenums_h + +#include "controllerEnums.h" + +/** Enum used to set special LED modes supported by the Xbox controller. */ +enum LEDMode { + ROTATING = 0x0A, + FASTBLINK = 0x0B, + SLOWBLINK = 0x0C, + ALTERNATING = 0x0D, +}; + +/** Used to set the LEDs on the controllers */ +const uint8_t LEDS[] PROGMEM = { + 0x02, // LED1 + 0x03, // LED2 + 0x04, // LED3 + 0x05, // LED4 + 0x01 // ALL - Used to blink all LEDs + }; +/** Buttons on the controllers */ +const uint16_t BUTTONS[] PROGMEM = { + 0x0100, // UP + 0x0800, // RIGHT + 0x0200, // DOWN + 0x0400, // LEFT + + 0x2000, // BACK + 0x1000, // START + 0x4000, // L3 + 0x8000, // R3 + + 0,0, // Skip L2 and R2 as these are analog buttons + 0x0001, // L1 + 0x0002, // R1 + + 0x0020, // B + 0x0010, // A + 0x0040, // X + 0x0080, // Y + + 0x0004, // XBOX + 0x0008 // SYNC +}; + +#endif \ No newline at end of file