Updated XBOXUSB library so it doesn't conflict with the other libraries

This commit is contained in:
Kristian Sloth Lauszus 2013-02-17 01:03:32 +01:00
parent d28cad250d
commit 8ca3ab8fd1
6 changed files with 280 additions and 228 deletions

View file

@ -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

View file

@ -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.

View file

@ -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);
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<uint32_t>(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<uint8_t>(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;
writeBuf[2] = value;
XboxCommand(writeBuf, 3);
}
void XBOXUSB::setLedOff() {
writeBuf[0] = 0x01;
writeBuf[1] = 0x03;
writeBuf[2] = 0x00;
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::setLedBlink(LED l) {
writeBuf[0] = 0x01;
writeBuf[1] = 0x03;
writeBuf[2] = (uint8_t)l;
XboxCommand(writeBuf, 3);
void XBOXUSB::setLedBlink(LED led) {
setLedRaw(pgm_read_byte(&LEDS[(uint8_t)led]));
}
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::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;

157
XBOXUSB.h
View file

@ -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,92 +55,130 @@
#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();
/**
* 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;
/* Variables to store the buttons */
uint32_t ButtonState;
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

View file

@ -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("");
}
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.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.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(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.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.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.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);
}

64
xboxEnums.h Normal file
View file

@ -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