Updated comments to work with Doxygen

This commit is contained in:
Kristian Sloth Lauszus 2013-02-05 19:51:45 +01:00
parent 92d3f2201b
commit 1333e9a63b
11 changed files with 1033 additions and 262 deletions

View file

@ -19,6 +19,7 @@
#define DEBUG // Uncomment to print data for debugging #define DEBUG // Uncomment to print data for debugging
//#define EXTRADEBUG // Uncomment to get even more debugging data //#define EXTRADEBUG // Uncomment to get even more debugging data
const uint8_t BTD::BTD_CONTROL_PIPE = 0;
const uint8_t BTD::BTD_EVENT_PIPE = 1; const uint8_t BTD::BTD_EVENT_PIPE = 1;
const uint8_t BTD::BTD_DATAIN_PIPE = 2; const uint8_t BTD::BTD_DATAIN_PIPE = 2;
const uint8_t BTD::BTD_DATAOUT_PIPE = 3; const uint8_t BTD::BTD_DATAOUT_PIPE = 3;

310
BTD.h
View file

@ -128,38 +128,90 @@
#define WI_PROTOCOL_BT 0x01 // Bluetooth Programming Interface #define WI_PROTOCOL_BT 0x01 // Bluetooth Programming Interface
#define BTD_MAX_ENDPOINTS 4 #define BTD_MAX_ENDPOINTS 4
#define BTD_NUMSERVICES 4 // Max number of Bluetooth services #define BTD_NUMSERVICES 4 // Max number of Bluetooth services
class BluetoothService { // All services should include this class /** All Bluetooth services should include this class. */
class BluetoothService {
public: public:
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services /**
virtual void Run(); // Used to run the different state machines * Used to pass acldata to the Bluetooth service.
virtual void Reset(); // Used to reset the services * @param ACLData Pointer to the incoming acldata.
virtual void disconnect(); // Used to disconnect both the L2CAP Channel and the HCI Connection */
virtual void ACLData(uint8_t* ACLData);
/** Used to run the different state machines in the Bluetooth service. */
virtual void Run();
/** Used to reset the Bluetooth service. */
virtual void Reset();
/** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */
virtual void disconnect();
}; };
/**
* The Bluetooth Dongle class will take care of all the USB communication
* and then pass the data to the BluetoothService classes.
*/
class BTD : public USBDeviceConfig, public UsbConfigXtracter { class BTD : public USBDeviceConfig, public UsbConfigXtracter {
public: public:
BTD(USB *p); // Constructor /**
* Constructor for the BTD class.
* @param p Pointer to USB class instance.
*/
BTD(USB *p);
// USBDeviceConfig implementation /** @name USBDeviceConfig implementation */
/**
* Initialize the Bluetooth dongle.
* @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); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/**
* Release the USB device.
* @return 0 on success.
*/
virtual uint8_t Release(); virtual uint8_t Release();
/**
* Poll the USB Input endpoins and run the state machines.
* @return 0 on success.
*/
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; }; virtual uint8_t GetAddress() { return bAddress; };
/**
* Used to check if the dongle has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; }; virtual bool isReady() { return bPollEnable; };
/**@}*/
// UsbConfigXtracter implementation, used to extract endpoint information /** @name UsbConfigXtracter implementation */
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); /**
* UsbConfigXtracter implementation, used to extract endpoint information.
bool watingForConnection; // Use this to see if it is waiting for a incoming connection * @param conf Configuration value.
void disconnect() { // Used this void to disconnect all services * @param iface Interface number.
* @param alt Alternate setting.
* @param proto Interface Protocol.
* @param ep Endpoint Descriptor.
*/
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
/**@}*/
/** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */
void disconnect() {
for (uint8_t i=0; i<BTD_NUMSERVICES; i++) for (uint8_t i=0; i<BTD_NUMSERVICES; i++)
if (btService[i]) if (btService[i])
btService[i]->disconnect(); // Disconnect both the L2CAP Channel and the HCI Connection btService[i]->disconnect();
}; };
/**
/* Register bluetooth dongle members/services */ * Register bluetooth dongle members/services.
* @param pService Pointer to BluetoothService class instance.
* @return The serice ID on succes or -1 on fail.
*/
int8_t registerServiceClass(BluetoothService *pService) { int8_t registerServiceClass(BluetoothService *pService) {
for (uint8_t i=0; i<BTD_NUMSERVICES; i++) { for (uint8_t i=0; i<BTD_NUMSERVICES; i++) {
if (!btService[i]) { if (!btService[i]) {
@ -168,71 +220,195 @@ public:
} }
} }
return -1; // ErrorregisterServiceClass return -1; // ErrorregisterServiceClass
}; };
bool l2capConnectionClaimed; // This is used by the service to know when to store the device information /** @name HCI Commands */
/**
* Used to send a HCI Command.
* @param data Data to send.
* @param nbytes Number of bytes to send.
*/
void HCI_Command(uint8_t* data, uint16_t nbytes);
/** Reset the Bluetooth dongle. */
void hci_reset();
/** Read the Bluetooth address of the dongle. */
void hci_read_bdaddr();
/** Read the HCI Version of the Bluetooth dongle. */
void hci_read_local_version_information();
/**
* Set the local name of the Bluetooth dongle.
* @param name Desired name.
*/
void hci_set_local_name(const char* name);
/** Enable visibility to other Bluetooth devices. */
void hci_write_scan_enable();
/** Disable visibility to other Bluetooth devices. */
void hci_write_scan_disable();
/** Read the remote devices name. */
void hci_remote_name();
/** Accept the connection with the Bluetooth device. */
void hci_accept_connection();
/**
* Disconnect the HCI connection.
* @param handle The HCI Handle for the connection.
*/
void hci_disconnect(uint16_t handle);
/**
* Respond with the pin for the connection.
* The pin is automatically set for the Wii library,
* but can be customized for the SPP library.
*/
void hci_pin_code_request_reply();
/** Respons when no pin was set. */
void hci_pin_code_negative_request_reply();
/**
* Command is used to reply to a Link Key Request event from the BR/EDR Controller
* if the Host does not have a stored Link Key for the connection.
*/
void hci_link_key_request_negative_reply();
/** Used to try to authenticate with the remote device. */
void hci_authentication_request();
/** Start a HCI inquiry. */
void hci_inquiry();
/** Cancel a HCI inquiry. */
void hci_inquiry_cancel();
/** Connect to a device. */
void hci_connect();
/**@}*/
/** @name L2CAP Commands */
/**
* Used to send L2CAP Commands.
* @param handle HCI Handle.
* @param data Data to send.
* @param nbytes Number of bytes to send.
* @param channelLow,channelHigh Low and high byte of channel to send to.
* If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
*/
void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
/**
* L2CAP Connection Request.
* @param handle HCI handle.
* @param rxid Identifier.
* @param scid Source Channel Identifier.
* @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
*/
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
/**
* L2CAP Connection Response.
* @param handle HCI handle.
* @param rxid Identifier.
* @param dcid Destination Channel Identifier.
* @param scid Source Channel Identifier.
* @param result Result - First send ::PENDING and then ::SUCCESSFUL.
*/
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
/**
* L2CAP Config Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Destination Channel Identifier.
*/
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
/**
* L2CAP Config Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
/**
* L2CAP Disconnection Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Disconnection Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Information Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param infoTypeLow,infoTypeHigh Infotype.
*/
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
/**@}*/
/** Use this to see if it is waiting for a incoming connection. */
bool watingForConnection;
/** This is used by the service to know when to store the device information. */
bool l2capConnectionClaimed;
/** This is used by the SPP library to claim the current SDP incoming request. */
bool sdpConnectionClaimed; bool sdpConnectionClaimed;
/** This is used by the SPP library to claim the current RFCOMM incoming request. */
bool rfcommConnectionClaimed; bool rfcommConnectionClaimed;
const char* btdName; // These are set by the SPP library /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */
const char* btdName;
/** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP library. */
const char* btdPin; const char* btdPin;
uint8_t my_bdaddr[6]; // The bluetooth dongles Bluetooth address /** The bluetooth dongles Bluetooth address. */
uint16_t hci_handle; // HCI handle for the last connection uint8_t my_bdaddr[6];
uint8_t disc_bdaddr[6]; // Last incoming devices Bluetooth address /** HCI handle for the last connection. */
uint8_t remote_name[30]; // First 30 chars of last remote name uint16_t hci_handle;
/** Last incoming devices Bluetooth address. */
uint8_t disc_bdaddr[6];
/** First 30 chars of last remote name. */
uint8_t remote_name[30];
/**
* The supported HCI Version read from the Bluetooth dongle.
* Used by the PS3BT library to check the HCI Version of the Bluetooth dongle,
* it should be at least 3 to work properly with the library.
*/
uint8_t hci_version; uint8_t hci_version;
/** Used to only send the ACL data to the wiimote. */
bool connectToWii; // Used to only send the ACL data to the wiimote bool connectToWii;
/** True if a Wiimote is connecting. */
bool incomingWii; bool incomingWii;
/** True when it should pair with the incoming Wiimote. */
bool pairWithWii; bool pairWithWii;
bool motionPlusInside; // True if it's the new Wiimote with the Motion Plus Inside /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */
bool wiiUProController; // True if it's a Wii U Pro Controller bool motionPlusInside;
/** True if it's a Wii U Pro Controller. */
/* HCI Commands */ bool wiiUProController;
void HCI_Command(uint8_t* data, uint16_t nbytes);
void hci_reset();
void hci_read_bdaddr();
void hci_read_local_version_information();
void hci_set_local_name(const char* name);
void hci_write_scan_enable();
void hci_remote_name();
void hci_accept_connection();
void hci_write_scan_disable();
void hci_disconnect(uint16_t handle);
void hci_pin_code_request_reply();
void hci_pin_code_negative_request_reply();
void hci_link_key_request_negative_reply();
void hci_authentication_request();
void hci_inquiry();
void hci_inquiry_cancel();
void hci_connect();
/* L2CAP Commands */
void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00); // Standard L2CAP header: Channel ID (0x01) for ACL-U
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
protected: protected:
/* Mandatory USB members */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
uint8_t bAddress; // Device address /** Device address. */
EpInfo epInfo[BTD_MAX_ENDPOINTS]; // Endpoint info structure uint8_t bAddress;
/** Endpoint info structure. */
EpInfo epInfo[BTD_MAX_ENDPOINTS];
uint8_t bConfNum; // Configuration number /** Configuration number. */
uint8_t bNumEP; // Total number of endpoints in the configuration uint8_t bConfNum;
uint32_t qNextPollTime; // Next poll time /** Total number of endpoints in the configuration. */
uint8_t bNumEP;
/** Next poll time based on poll interval taken from the USB descriptor. */
uint32_t qNextPollTime;
#define BTD_CONTROL_PIPE 0 // Bluetooth dongles control endpoint /** Bluetooth dongle control endpoint. */
static const uint8_t BTD_EVENT_PIPE; // HCI event endpoint index static const uint8_t BTD_CONTROL_PIPE;
static const uint8_t BTD_DATAIN_PIPE; // ACL In endpoint index /** HCI event endpoint index. */
static const uint8_t BTD_DATAOUT_PIPE; // ACL Out endpoint index static const uint8_t BTD_EVENT_PIPE;
/** ACL In endpoint index. */
static const uint8_t BTD_DATAIN_PIPE;
/** ACL Out endpoint index. */
static const uint8_t BTD_DATAOUT_PIPE;
/**
* Used to print the USB Endpoint Descriptor.
* @param ep_ptr Pointer to USB Endpoint Descriptor.
*/
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
private: private:
@ -241,7 +417,7 @@ private:
bool bPollEnable; bool bPollEnable;
uint8_t pollInterval; uint8_t pollInterval;
/* variables used by high level HCI task */ /* Variables used by high level HCI task */
uint8_t hci_state; //current state of bluetooth hci connection uint8_t hci_state; //current state of bluetooth hci connection
uint16_t hci_counter; // counter used for bluetooth hci reset loops uint16_t hci_counter; // counter used for bluetooth hci reset loops
uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset

145
PS3BT.h
View file

@ -57,52 +57,149 @@
#define l2cap_disconnect_response_control_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE) #define l2cap_disconnect_response_control_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)
#define l2cap_disconnect_response_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) #define l2cap_disconnect_response_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)
/**
* This BluetoothService class implements support for all the official PS3 Controllers:
* Dualshock 3, Navigation or a Motion controller via Bluetooth.
*
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
*/
class PS3BT : public BluetoothService { class PS3BT : public BluetoothService {
public: public:
/**
* Constructor for the PS3BT class.
* @param pBtd Pointer to BTD class instance.
* @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
* Pass your dongles Bluetooth address into the constructor,
* This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller.
*/
PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0);
// BluetoothService implementation /** @name BluetoothService implementation */
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services /**
virtual void Run(); // Used to run part of the state maschine * Used to pass acldata to the services.
virtual void Reset(); // Use this to reset the service * @param ACLData Incoming acldata.
virtual void disconnect(); // Use this void to disconnect any of the controllers */
virtual void ACLData(uint8_t* ACLData);
/** Used to run part of the state maschine. */
virtual void Run();
/** Use this to reset the service. */
virtual void Reset();
/** Used this to disconnect any of the controllers. */
virtual void disconnect();
/**@}*/
/* PS3 Controller Commands */ /** @name PS3 Controller functions */
/* /**
getButtonPress will return true as long as the button is held down * getButtonPress(Button b) will return true as long as the button is held down
While getButtonClick will only return it once * While getButtonClick(Button b) will only return it once
So you instance if you need to increase a variable once you would use getButtonClick, * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
but if you need to drive a robot forward you would use getButtonPress * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ */
bool getButtonPress(Button b); bool getButtonPress(Button b);
bool getButtonClick(Button b); bool getButtonClick(Button b);
/**@}*/
/** @name PS3 Controller functions */
/**
* Used to get the analog value from button presses.
* @param a The ::Button to read.
* The supported buttons are:
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
* @return Analog value in the range of 0-255.
*/
uint8_t getAnalogButton(Button a); uint8_t getAnalogButton(Button a);
/**
* Used to read the analog joystick.
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
* @return Return the analog value in the range of 0-255.
*/
uint8_t getAnalogHat(AnalogHat a); uint8_t getAnalogHat(AnalogHat a);
/**
* Used to read the sensors inside the Dualshock 3 and Move controller.
* @param a
* The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
* The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer
* and a temperature sensor inside.
* @return Return the raw sensor value.
*/
int16_t getSensor(Sensor a); int16_t getSensor(Sensor a);
/**
* Use this to get ::Pitch and ::Roll calculated using the accelerometer.
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(Angle a); double getAngle(Angle a);
/**
* Read the sensors inside the Move controller.
* @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove.
* @return The value in SI units.
*/
double get9DOFValues(Sensor a); double get9DOFValues(Sensor a);
bool getStatus(Status c); /**
String getStatusString(); * Get the ::Status from the controller.
* @param c The ::Status you want to read.
* @return True if correct and false if not.
*/
bool getStatus(Status c);
/**
* Read all the available ::Status from the controller.
* @return One large string with all the information.
*/
String getStatusString();
/**
* Read the temperature from the Move controller.
* @return The temperature in degrees celsius.
*/
String getTemperature(); String getTemperature();
/* HID Commands */ /** Used to set all LEDs and ::Rumble off. */
/* Commands for Dualshock 3 and Navigation controller */
void setAllOff(); void setAllOff();
/** Turn off ::Rumble. */
void setRumbleOff(); void setRumbleOff();
/**
* Turn on ::Rumble.
* @param mode Either ::RumbleHigh or ::RumbleLow.
*/
void setRumbleOn(Rumble mode); void setRumbleOn(Rumble mode);
/**
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a); void setLedOff(LED a);
void setLedOn(LED a); /**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a); void setLedToggle(LED a);
/* Commands for Motion controller only */ /**
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); // Use this to set the Color using RGB values * Use this to set the Color using RGB values.
void moveSetBulb(Colors color); // Use this to set the Color using the predefined colors in "enum Colors" * @param r,g,b RGB value.
*/
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
/**
* Use this to set the color using the predefined colors in ::Colors.
* @param color The desired color.
*/
void moveSetBulb(Colors color);
/**
* Set the rumble value inside the Move controller.
* @param rumble The desired value in the range from 64-255.
*/
void moveSetRumble(uint8_t rumble); void moveSetRumble(uint8_t rumble);
/**@}*/
bool PS3Connected; // Variable used to indicate if the normal playstation controller is successfully connected /** Variable used to indicate if the normal playstation controller is successfully connected. */
bool PS3MoveConnected; // Variable used to indicate if the move controller is successfully connected bool PS3Connected;
bool PS3NavigationConnected; // Variable used to indicate if the navigation controller is successfully connected /** Variable used to indicate if the move controller is successfully connected. */
bool PS3MoveConnected;
/** Variable used to indicate if the navigation controller is successfully connected. */
bool PS3NavigationConnected;
private: private:
/* mandatory members */ /* mandatory members */

View file

@ -20,6 +20,7 @@
#include "controllerEnums.h" #include "controllerEnums.h"
/** Used to set the LEDs on the controllers */
const uint8_t LEDS[] PROGMEM = { const uint8_t LEDS[] PROGMEM = {
0x01, // LED1 0x01, // LED1
0x02, // LED2 0x02, // LED2
@ -33,6 +34,12 @@ const uint8_t LEDS[] PROGMEM = {
0x0E, // LED9 0x0E, // LED9
0x0F // LED10 0x0F // LED10
}; };
/**
* Buttons on the controllers
*
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/
const uint32_t BUTTONS[] PROGMEM = { const uint32_t BUTTONS[] PROGMEM = {
0x10, // UP 0x10, // UP
0x20, // RIGHT 0x20, // RIGHT
@ -59,9 +66,12 @@ const uint32_t BUTTONS[] PROGMEM = {
0x100000 // T - covers 12 bits - we only need to read the top 8 0x100000 // T - covers 12 bits - we only need to read the top 8
}; };
/**
* Analog buttons on the controllers
*
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/
const uint8_t ANALOGBUTTONS[] PROGMEM = { const uint8_t ANALOGBUTTONS[] PROGMEM = {
// Note that the location is shiftet 9 when it's connected via USB
// Sixaxis Dualshcock 3 & Navigation controller
23, // UP_ANALOG 23, // UP_ANALOG
24, // RIGHT_ANALOG 24, // RIGHT_ANALOG
25, // DOWN_ANALOG 25, // DOWN_ANALOG
@ -82,44 +92,69 @@ const uint8_t ANALOGBUTTONS[] PROGMEM = {
15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) 15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading)
}; };
/** Used to set the colors of the move controller. */
enum Colors { enum Colors {
// Used to set the colors of the move controller /** r = 255, g = 0, b = 0 */
Red = 0xFF0000, // r = 255, g = 0, b = 0 Red = 0xFF0000,
Green = 0xFF00, // r = 0, g = 255, b = 0 /** r = 0, g = 255, b = 0 */
Blue = 0xFF, // r = 0, g = 0, b = 255 Green = 0xFF00,
/** r = 0, g = 0, b = 255 */
Blue = 0xFF,
Yellow = 0xFFEB04, // r = 255, g = 235, b = 4 /** r = 255, g = 235, b = 4 */
Lightblue = 0xFFFF, // r = 0, g = 255, b = 255 Yellow = 0xFFEB04,
Purble = 0xFF00FF, // r = 255, g = 0, b = 255 /** r = 0, g = 255, b = 255 */
Lightblue = 0xFFFF,
/** r = 255, g = 0, b = 255 */
Purble = 0xFF00FF,
White = 0xFFFFFF, // r = 255, g = 255, b = 255 /** r = 255, g = 255, b = 255 */
Off = 0x00, // r = 0, g = 0, b = 0 White = 0xFFFFFF,
/** r = 0, g = 0, b = 0 */
Off = 0x00,
}; };
/**
* Sensors inside the Sixaxis Dualshock 3 and Move controller.
*
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/
enum Sensor { enum Sensor {
// Note that the location is shiftet 9 when it's connected via USB /** Accelerometer x-axis */
// Sensors inside the Sixaxis Dualshock 3 controller
aX = 50, aX = 50,
/** Accelerometer y-axis */
aY = 52, aY = 52,
/** Accelerometer z-axis */
aZ = 54, aZ = 54,
/** Gyro z-axis */
gZ = 56, gZ = 56,
// Sensors inside the Move Motion controller /** Accelerometer x-axis */
aXmove = 28, aXmove = 28,
/** Accelerometer z-axis */
aZmove = 30, aZmove = 30,
/** Accelerometer y-axis */
aYmove = 32, aYmove = 32,
/** Gyro x-axis */
gXmove = 40, gXmove = 40,
/** Gyro z-axis */
gZmove = 42, gZmove = 42,
/** Gyro y-axis */
gYmove = 44, gYmove = 44,
/** Temperature sensor */
tempMove = 46, tempMove = 46,
/** Magnetometer x-axis */
mXmove = 47, mXmove = 47,
/** Magnetometer z-axis */
mZmove = 49, mZmove = 49,
/** Magnetometer y-axis */
mYmove = 50, mYmove = 50,
}; };
/** Used to get the angle calculated using the accelerometer. */
enum Angle { enum Angle {
// Used to get the angle calculated using atan2
Pitch = 0x01, Pitch = 0x01,
Roll = 0x02, Roll = 0x02,
}; };

167
PS3USB.h
View file

@ -53,59 +53,174 @@
#define PS3_MAX_ENDPOINTS 3 #define PS3_MAX_ENDPOINTS 3
/**
* This class implements support for all the official PS3 Controllers:
* Dualshock 3, Navigation or a Motion controller via USB.
*
* One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB.
*
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
*/
class PS3USB : public USBDeviceConfig { class PS3USB : public USBDeviceConfig {
public: public:
/**
* Constructor for the PS3USB class.
* @param pUsb Pointer to USB class instance.
* @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
* Pass your dongles Bluetooth address into the constructor,
* so you are able to pair the controller with a Bluetooth dongle.
*/
PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0);
// USBDeviceConfig implementation /** @name USBDeviceConfig implementation */
/**
* Initialize the PS3 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); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/**
* Release the USB device.
* @return 0 on success.
*/
virtual uint8_t Release(); virtual uint8_t Release();
/**
* Poll the USB Input endpoins and run the state machines.
* @return 0 on success.
*/
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; }; virtual uint8_t GetAddress() { return bAddress; };
virtual bool isReady() { return bPollEnable; }; /**
* Used to check if the controller has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; };
/**@}*/
/**
* Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.
* @param BDADDR Your dongles Bluetooth address.
*/
void setBdaddr(uint8_t* BDADDR); void setBdaddr(uint8_t* BDADDR);
/**
* Used to set the Bluetooth address inside the Move controller.
* @param BDADDR Your dongles Bluetooth address.
*/
void setMoveBdaddr(uint8_t* BDADDR); void setMoveBdaddr(uint8_t* BDADDR);
/* PS3 Controller Commands */ /** @name PS3 Controller functions */
/* /**
getButtonPress will return true as long as the button is held down * getButtonPress(Button b) will return true as long as the button is held down
While getButtonClick will only return it once * While getButtonClick(Button b) will only return it once
So you instance if you need to increase a variable once you would use getButtonClick, * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
but if you need to drive a robot forward you would use getButtonPress * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ */
bool getButtonPress(Button b); bool getButtonPress(Button b);
bool getButtonClick(Button b); bool getButtonClick(Button b);
/**@}*/
/** @name PS3 Controller functions */
/**
* Used to get the analog value from button presses.
* @param a The ::Button to read.
* The supported buttons are:
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
* @return Analog value in the range of 0-255.
*/
uint8_t getAnalogButton(Button a); uint8_t getAnalogButton(Button a);
/**
* Used to read the analog joystick.
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
* @return Return the analog value in the range of 0-255.
*/
uint8_t getAnalogHat(AnalogHat a); uint8_t getAnalogHat(AnalogHat a);
/**
* Used to read the sensors inside the Dualshock 3 controller.
* @param a
* The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
* @return Return the raw sensor value.
*/
uint16_t getSensor(Sensor a); uint16_t getSensor(Sensor a);
/**
* Use this to get ::Pitch and ::Roll calculated using the accelerometer.
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(Angle a); double getAngle(Angle a);
bool getStatus(Status c); /**
* Get the ::Status from the controller.
* @param c The ::Status you want to read.
* @return True if correct and false if not.
*/
bool getStatus(Status c);
/**
* Read all the available ::Status from the controller.
* @return One large string with all the information.
*/
String getStatusString(); String getStatusString();
/* Commands for Dualshock 3 and Navigation controller */ /** Used to set all LEDs and ::Rumble off. */
void setAllOff(); void setAllOff();
/** Turn off ::Rumble. */
void setRumbleOff(); void setRumbleOff();
/**
* Turn on ::Rumble.
* @param mode Either ::RumbleHigh or ::RumbleLow.
*/
void setRumbleOn(Rumble mode); void setRumbleOn(Rumble mode);
/**
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a); void setLedOff(LED a);
void setLedOn(LED a); /**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a); void setLedToggle(LED a);
/* Commands for Motion controller only */ /**
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);//Use this to set the Color using RGB values * Use this to set the Color using RGB values.
void moveSetBulb(Colors color);//Use this to set the Color using the predefined colors in "enum Colors" * @param r,g,b RGB value.
*/
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
/**
* Use this to set the color using the predefined colors in ::Colors.
* @param color The desired color.
*/
void moveSetBulb(Colors color);
/**
* Set the rumble value inside the Move controller.
* @param rumble The desired value in the range from 64-255.
*/
void moveSetRumble(uint8_t rumble); void moveSetRumble(uint8_t rumble);
/**@}*/
bool PS3Connected;// Variable used to indicate if the normal playstation controller is successfully connected
bool PS3MoveConnected;// Variable used to indicate if the move controller is successfully connected /** Variable used to indicate if the normal playstation controller is successfully connected. */
bool PS3NavigationConnected;// Variable used to indicate if the navigation controller is successfully connected */ bool PS3Connected;
/** Variable used to indicate if the move controller is successfully connected. */
bool PS3MoveConnected;
/** Variable used to indicate if the navigation controller is successfully connected. */
bool PS3NavigationConnected;
protected: protected:
/* mandatory members */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
uint8_t bAddress; // device address /** Device address. */
EpInfo epInfo[PS3_MAX_ENDPOINTS]; //endpoint info structure uint8_t bAddress;
/** Endpoint info structure. */
EpInfo epInfo[PS3_MAX_ENDPOINTS];
private: private:
bool bPollEnable; bool bPollEnable;

14
SPP.cpp
View file

@ -23,7 +23,7 @@
/* /*
* CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0. * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
*/ */
const uint8_t rfcomm_crc_table[256] PROGMEM = { /* reversed, 8-bit, poly=0x07 */ const uint8_t rfcomm_crc_table[256] PROGMEM = { /* reversed, 8-bit, poly=0x07 */
0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
@ -700,10 +700,10 @@ void SPP::print(const String &str) {
RFCOMM_Command(l2capoutbuf,length+4); RFCOMM_Command(l2capoutbuf,length+4);
} }
void SPP::print(const char* data) { void SPP::print(const char* str) {
if(!connected) if(!connected)
return; return;
uint8_t length = strlen(data); uint8_t length = strlen(str);
if(length > (sizeof(l2capoutbuf)-4)) if(length > (sizeof(l2capoutbuf)-4))
length = sizeof(l2capoutbuf)-4; length = sizeof(l2capoutbuf)-4;
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address
@ -711,7 +711,7 @@ void SPP::print(const char* data) {
l2capoutbuf[2] = length << 1 | 1; // Length l2capoutbuf[2] = length << 1 | 1; // Length
uint8_t i = 0; uint8_t i = 0;
for(; i < length; i++) for(; i < length; i++)
l2capoutbuf[i+3] = data[i]; l2capoutbuf[i+3] = str[i];
l2capoutbuf[i+3] = calcFcs(l2capoutbuf); l2capoutbuf[i+3] = calcFcs(l2capoutbuf);
RFCOMM_Command(l2capoutbuf,length+4); RFCOMM_Command(l2capoutbuf,length+4);
@ -754,9 +754,9 @@ void SPP::println(const String &str) {
String output = str + "\r\n"; String output = str + "\r\n";
print(output); print(output);
} }
void SPP::println(const char* data) { void SPP::println(const char* str) {
char output[strlen(data)+3]; char output[strlen(str)+3];
strcpy(output,data); strcpy(output,str);
strcat(output,"\r\n"); strcat(output,"\r\n");
print(output); print(output);
} }

149
SPP.h
View file

@ -89,42 +89,135 @@
#define BT_RFCOMM_NSC_RSP 0x11 #define BT_RFCOMM_NSC_RSP 0x11
*/ */
/** This BluetoothService class implements the Serial Port Protocol (SPP). */
class SPP : public BluetoothService { class SPP : public BluetoothService {
public: public:
/**
* Constructor for the SPP class.
* @param p Pointer to BTD class instance.
* @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
* @param pin Write the pin to BTD#btdPin. If argument is omitted, then "1234" will be used.
*/
SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234"); SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234");
/** @name BluetoothService implementation */
/**
* Used to pass acldata to the services.
* @param ACLData Incoming acldata.
*/
virtual void ACLData(uint8_t* ACLData);
/** Used to establish the connection automatically. */
virtual void Run();
/** Use this to reset the service. */
virtual void Reset();
/** Used this to disconnect the virtual serial port. */
virtual void disconnect();
/**@}*/
// BluetoothService implementation /** Variable used to indicate if the connection is established. */
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services bool connected;
virtual void Run(); // Used to establish the connection automatically
virtual void Reset(); // Use this to reset the service
virtual void disconnect(); // Used this void to disconnect the virtual serial port
bool connected;// Variable used to indicate if the connection is established /** @name Serial port profile (SPP) Print functions */
/** Used to send Strings. */
/**
* Used to send Arduino String data type.
* @param str String to send.
*/
void print(const String &str);
/**
* Same as print(const String &str), but will include newline and carriage return.
* @param str String to send.
*/
void println(const String &str);
/**
* Used to send standard strings.
* @param str String to send.
*/
void print(const char* str);
/**
* Same as print(const char* data), but will include newline and carriage return.
* @param str String to send.
*/
void println(const char* str);
/**
* Used to send single bytes.
* @param data Data to send.
*/
void print(uint8_t data);
/**
* Same as print(uint8_t data), but will include newline and carriage return.
* @param data Data to send.
*/
void println(uint8_t data);
/**
* Used to send arrays.
* @param array Array to send.
* @param length Number of bytes to send.
*/
void print(uint8_t* array, uint8_t length);
/**
* Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return.
* @param array Array to send.
* @param length Number of bytes to send.
*/
void println(uint8_t* array, uint8_t length);
/**
* Used to print strings stored in flash.
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
*/
void print(const __FlashStringHelper *ifsh);
/**
* Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return.
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
*/
void println(const __FlashStringHelper *ifsh);
/** Use this to print newline and carriage return. */
void println(void);
/* Serial port profile (SPP) commands */ /**
void print(const String &); // Used to send strings * Used to print integers.
void print(const char* data); // Used to send strings * @param n Integers to send.
void print(uint8_t data); // Used to send single bytes */
void print(uint8_t* array, uint8_t length); // Used to send arrays void printNumber(int32_t n);
void print(const __FlashStringHelper *); // Used to print strings stored in flash /**
* Same as printNumber(int32_t n), but will include newline and carriage return.
* @param n Integers to send.
*/
void printNumberln(int32_t n);
/**
* Used to print floating-point numbers.
* @param n Floating-point number to print.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
*/
void printNumber(double n, uint8_t digits = 2);
/**
* Same as printNumber(double n, uint8_t digits), but will include newline and carriage return.
* @param n Floating-point number to print.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
*/
void printNumberln(double n, uint8_t digits = 2);
void println(const String &); // Include newline and carriage return /**
void println(const char* data); // Include newline and carriage return * Helper function to convert from double to string.
void println(uint8_t data); // Include newline and carriage return * @param input Floating-point number to convert.
void println(uint8_t* array, uint8_t length); // Include newline and carriage return * @param output Output buffer.
void println(const __FlashStringHelper *); // Include newline and carriage return * @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used.
void println(void); // Use this to print newline and carriage return */
void doubleToString(double input, char* output, uint8_t digits = 2);
void printNumber(int32_t n); // These must be used to print numbers /**
void printNumberln(int32_t n); // This will include newline and carriage return * Get number of bytes waiting to be read.
void printNumber(double n, uint8_t digits = 2); // These must be used to print floating-point numbers * @return Return the number of bytes ready to be read.
void printNumberln(double n, uint8_t digits = 2); // This will include newline and carriage return */
uint8_t available() { return rfcommAvailable; };
void doubleToString(double input, char* output, uint8_t digits = 2); // Helper function to convert from double to string /**
* Used to read the buffer.
uint8_t available() { return rfcommAvailable; }; // Get the bytes waiting to be read * @return Return the byte. Will return 0 if no byte is available.
uint8_t read(); // Used to read the buffer */
void flush() { rfcommAvailable = 0; }; // Discard all the bytes in the buffer uint8_t read();
/** Discard all the bytes in the buffer. */
void flush() { rfcommAvailable = 0; };
/**@}*/
private: private:
/* Bluetooth dongle library pointer */ /* Bluetooth dongle library pointer */

28
Wii.cpp
View file

@ -292,8 +292,8 @@ void WII::ACLData(uint8_t* l2capinbuf) {
accX = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5))-500; accX = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5))-500;
accY = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4))-500; accY = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4))-500;
accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5))-500; accZ = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5))-500;
wiiMotePitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; wiimotePitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG;
wiiMoteRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; wiimoteRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG;
} }
switch (l2capinbuf[9]) { switch (l2capinbuf[9]) {
case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV
@ -410,13 +410,13 @@ void WII::ACLData(uint8_t* l2capinbuf) {
case 0x30: // Core buttons - (a1) 30 BB BB case 0x30: // Core buttons - (a1) 30 BB BB
break; break;
case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
pitch = wiiMotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected
roll = wiiMoteRoll; roll = wiimoteRoll;
break; break;
case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II
pitch = wiiMotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus data available pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus data available
roll = wiiMoteRoll; roll = wiimoteRoll;
#ifdef WIICAMERA #ifdef WIICAMERA
// Read the IR data // Read the IR data
IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position
@ -479,8 +479,8 @@ void WII::ACLData(uint8_t* l2capinbuf) {
if(!(l2capinbuf[19] & 0x02)) // Check if fast more is used if(!(l2capinbuf[19] & 0x02)) // Check if fast more is used
rollGyroSpeed *= 4.545; rollGyroSpeed *= 4.545;
pitch = (0.93*(pitch+(pitchGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiiMotePitch); // Use a complimentary filter to calculate the angle pitch = (0.93*(pitch+(pitchGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimotePitch); // Use a complimentary filter to calculate the angle
roll = (0.93*(roll+(rollGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiiMoteRoll); roll = (0.93*(roll+(rollGyroSpeed*(double)(micros()-timer)/1000000)))+(0.07*wiimoteRoll);
gyroYaw += (yawGyroSpeed*((double)(micros()-timer)/1000000)); gyroYaw += (yawGyroSpeed*((double)(micros()-timer)/1000000));
gyroRoll += (rollGyroSpeed*((double)(micros()-timer)/1000000)); gyroRoll += (rollGyroSpeed*((double)(micros()-timer)/1000000));
@ -496,10 +496,10 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Serial.print(gyroPitch); Serial.print(gyroPitch);
*/ */
/* /*
Serial.print("\twiiMoteRoll: "); Serial.print("\twiimoteRoll: ");
Serial.print(wiiMoteRoll); Serial.print(wiimoteRoll);
Serial.print("\twiiMotePitch: "); Serial.print("\twiimotePitch: ");
Serial.print(wiiMotePitch); Serial.print(wiimotePitch);
*/ */
} else { } else {
if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
@ -563,8 +563,8 @@ void WII::ACLData(uint8_t* l2capinbuf) {
nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG; nunchuckPitch = (atan2(accY,accZ)+PI)*RAD_TO_DEG;
nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG; nunchuckRoll = (atan2(accX,accZ)+PI)*RAD_TO_DEG;
pitch = wiiMotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected pitch = wiimotePitch; // The pitch is just equal to the angle calculated from the wiimote as there is no Motion Plus connected
roll = wiiMoteRoll; roll = wiimoteRoll;
} else if(wiiUProControllerConnected) { } else if(wiiUProControllerConnected) {
hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8); hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);
hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8); hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);

236
Wii.h
View file

@ -25,7 +25,8 @@
#include "BTD.h" #include "BTD.h"
#include "controllerEnums.h" #include "controllerEnums.h"
//#define WIICAMERA //uncomment to enable IR camera /** You will have to uncomment this to use the IR camera */
//#define WIICAMERA
/* Bluetooth L2CAP states for L2CAP_task() */ /* Bluetooth L2CAP states for L2CAP_task() */
#define L2CAP_WAIT 0 #define L2CAP_WAIT 0
@ -79,107 +80,242 @@
#define PAIR 1 #define PAIR 1
/** Enum used to read the joystick on the Nunchuck. */
enum Hat { enum Hat {
/** Read the x-axis on the Nunchuck joystick. */
HatX = 0, HatX = 0,
/** Read the y-axis on the Nunchuck joystick. */
HatY = 1, HatY = 1,
}; };
/**
* This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension.
*
* It also support the Wii U Pro Controller.
*/
class WII : public BluetoothService { class WII : public BluetoothService {
public: public:
/**
* Constructor for the WII class.
* @param p Pointer to BTD class instance.
* @param pair Set this true to pair with the Wiimote. If the argument is omitted then it won't pair with it.
* One can use ::PAIR to set it to true.
*/
WII(BTD *p, bool pair=false); WII(BTD *p, bool pair=false);
// BluetoothService implementation
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services
virtual void Run(); // Used to run part of the state maschine
virtual void Reset(); // Use this to reset the service
virtual void disconnect(); // Use this void to disconnect any of the controllers
/*
getButtonPress will return true as long as the button is held down
While getButtonClick will only return it once
So you instance if you need to increase a variable once you would use getButtonClick,
but if you need to drive a robot forward you would use getButtonPress
*/
bool getButtonPress(Button b); // This will read true as long as the button is held down
bool getButtonClick(Button b); // This will only be true when the button is clicked the first time
uint8_t getAnalogHat(Hat a); // Used to read the joystick of the Nunchuck
uint16_t getAnalogHat(AnalogHat a); // Used to read the joystick of the Wii U Pro Controller
double getPitch() { return pitch; }; // Fusioned angle using a complimentary filter if the Motion Plus is connected /** @name BluetoothService implementation */
double getRoll() { return roll; }; // Fusioned angle using a complimentary filter if the Motion Plus is connected /**
double getYaw() { return gyroYaw; }; // This is the yaw calculated by the gyro * Used to pass acldata to the services.
* @param ACLData Incoming acldata.
*/
virtual void ACLData(uint8_t* ACLData);
/** Used to run part of the state maschine. */
virtual void Run();
/** Use this to reset the service. */
virtual void Reset();
/** Used this to disconnect any of the controllers. */
virtual void disconnect();
/**@}*/
/** @name Wii Controller functions */
/**
* getButtonPress(Button b) will return true as long as the button is held down
* While getButtonClick(Button b) will only return it once
* So you instance if you need to increase a variable once you would use getButtonClick(Button b),
* but if you need to drive a robot forward you would use getButtonPress(Button b).
*/
bool getButtonPress(Button b);
bool getButtonClick(Button b);
/**@}*/
/** @name Wii Controller functions */
/**
* Used to read the joystick of the Nunchuck.
* @param a Either ::HatX or ::HatY.
* @return Return the analog value in the range from approximately 25-230.
*/
uint8_t getAnalogHat(Hat a);
/**
* Used to read the joystick of the Wii U Pro Controller.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Return the analog value in the range from approximately 800-3200.
*/
uint16_t getAnalogHat(AnalogHat a);
/**
* Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
* @return Pitch in the range from 0-360.
*/
double getPitch() { return pitch; };
/**
* Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
* @return Roll in the range from 0-360.
*/
double getRoll() { return roll; };
/**
* This is the yaw calculated by the gyro.
*
* <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
* @return The angle calculated using the gyro.
*/
double getYaw() { return gyroYaw; };
void setAllOff(); // Turn both rumble and all LEDs off /** Used to set all LEDs and rumble off. */
void setAllOff();
/** Turn off rumble. */
void setRumbleOff(); void setRumbleOff();
/** Turn on rumble. */
void setRumbleOn(); void setRumbleOn();
/** Toggle rumble. */
void setRumbleToggle(); void setRumbleToggle();
/**
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a); void setLedOff(LED a);
/**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a); void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a); void setLedToggle(LED a);
void setLedStatus(); // This will set the LEDs, so the user can see which connections are active /**
* This will set the LEDs, so the user can see which connections are active.
*
* The first ::LED indicate that the Wiimote is connected,
*
* the second ::LED indicate indicate that a Motion Plus is also connected
*
* the third ::LED will indicate that a Nunchuck controller is also connected.
*/
void setLedStatus();
uint8_t getBatteryLevel() { return batteryLevel; }; // Return the battery level /**
uint8_t getWiiState() { return wiiState; }; // Return the wii state, see: http://wiibrew.org/wiki/Wiimote#0x20:_Status * Return the battery level of the Wiimote.
* @return The barrey level in the range form 0-255.
bool wiimoteConnected; // Variable used to indicate if a Wiimote is connected */
bool nunchuckConnected; // Variable used to indicate if a Nunchuck controller is connected uint8_t getBatteryLevel() { return batteryLevel; };
bool motionPlusConnected; // Variable used to indicate if a Nunchuck controller is connected /**
bool wiiUProControllerConnected; // Variable used to indicate if a Wii U Pro controller is connected * Return the Wiimote state.
* @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
*/
uint8_t getWiiState() { return wiiState; };
/**@}*/
/**@{*/
/** Variable used to indicate if a Wiimote is connected. */
bool wiimoteConnected;
/** Variable used to indicate if a Nunchuck controller is connected. */
bool nunchuckConnected;
/** Variable used to indicate if a Nunchuck controller is connected. */
bool motionPlusConnected;
/** Variable used to indicate if a Wii U Pro controller is connected. */
bool wiiUProControllerConnected;
/**@}*/
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
double wiiMotePitch; // Pitch and roll calculated from the accelerometer inside the Wiimote /**@{*/
double wiiMoteRoll; /** Pitch and roll calculated from the accelerometer inside the Wiimote. */
double nunchuckPitch; // Pitch and roll calculated from the accelerometer inside the Nunchuck double wiimotePitch;
double wiimoteRoll;
/**@}*/
/**@{*/
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
double nunchuckPitch;
double nunchuckRoll; double nunchuckRoll;
/**@}*/
int16_t accX; // Accelerometer values used to calculate pitch and roll
/**@{*/
/** Accelerometer values used to calculate pitch and roll. */
int16_t accX;
int16_t accY; int16_t accY;
int16_t accZ; int16_t accZ;
/**@}*/
/* Variables for the gyro inside the Motion Plus */
double gyroPitch; // This is the pitch calculated by the gyro - use this to tune pitchGyroScale
double gyroRoll; // This is the roll calculated by the gyro - use this to tune rollGyroScale
double gyroYaw; // This is the yaw calculated by the gyro - use this to tune yawGyroScale
double pitchGyroSpeed; // The speed in deg/s from the gyro /* Variables for the gyro inside the Motion Plus */
/** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
double gyroPitch;
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
double gyroRoll;
/** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
double gyroYaw;
/**@{*/
/** The speed in deg/s from the gyro. */
double pitchGyroSpeed;
double rollGyroSpeed; double rollGyroSpeed;
double yawGyroSpeed; double yawGyroSpeed;
/**@}*/
uint16_t pitchGyroScale; // You might need to fine-tune these values /**@{*/
/** You might need to fine-tune these values. */
uint16_t pitchGyroScale;
uint16_t rollGyroScale; uint16_t rollGyroScale;
uint16_t yawGyroScale; uint16_t yawGyroScale;
/**@}*/
int16_t gyroYawRaw; // Raw value read directly from the Motion Plus /**@{*/
/** Raw value read directly from the Motion Plus. */
int16_t gyroYawRaw;
int16_t gyroRollRaw; int16_t gyroRollRaw;
int16_t gyroPitchRaw; int16_t gyroPitchRaw;
/**@}*/
int16_t gyroYawZero; // These values are set when the controller is first initialized /**@{*/
/** These values are set when the controller is first initialized. */
int16_t gyroYawZero;
int16_t gyroRollZero; int16_t gyroRollZero;
int16_t gyroPitchZero; int16_t gyroPitchZero;
/**@}*/
#ifdef WIICAMERA #ifdef WIICAMERA
/* These are functions for the IR camera */ /** @name Wiimote IR camera functions
void IRinitialize(); // Initialises the camera as per the steps from http://wiibrew.org/wiki/Wiimote#IR_Camera * You will have to uncomment #WIICAMERA in Wii.h to use the IR camera.
*/
/** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */
void IRinitialize();
uint16_t getIRx1() { return IR_object_x1; }; // IR object 1 x position (0-1023) /** IR object 1 x position (0-1023). */
uint16_t getIRy1() { return IR_object_y1; }; // IR object 1 y position (0-767) uint16_t getIRx1() { return IR_object_x1; };
uint8_t getIRs1() { return IR_object_s1; }; // IR object 1 size (0-15) /** IR object 1 y position (0-767). */
uint16_t getIRy1() { return IR_object_y1; };
/** IR object 1 size (0-15). */
uint8_t getIRs1() { return IR_object_s1; };
/** IR object 2 x position (0-1023). */
uint16_t getIRx2() { return IR_object_x2; }; uint16_t getIRx2() { return IR_object_x2; };
/** IR object 2 y position (0-767). */
uint16_t getIRy2() { return IR_object_y2; }; uint16_t getIRy2() { return IR_object_y2; };
/** IR object 2 size (0-15). */
uint8_t getIRs2() { return IR_object_s2; }; uint8_t getIRs2() { return IR_object_s2; };
/** IR object 3 x position (0-1023). */
uint16_t getIRx3() { return IR_object_x3; }; uint16_t getIRx3() { return IR_object_x3; };
/** IR object 3 y position (0-767). */
uint16_t getIRy3() { return IR_object_y3; }; uint16_t getIRy3() { return IR_object_y3; };
/** IR object 3 size (0-15). */
uint8_t getIRs3() { return IR_object_s3; }; uint8_t getIRs3() { return IR_object_s3; };
/** IR object 4 x position (0-1023). */
uint16_t getIRx4() { return IR_object_x4; }; uint16_t getIRx4() { return IR_object_x4; };
/** IR object 4 y position (0-767). */
uint16_t getIRy4() { return IR_object_y4; }; uint16_t getIRy4() { return IR_object_y4; };
/** IR object 4 size (0-15). */
uint8_t getIRs4() { return IR_object_s4; }; uint8_t getIRs4() { return IR_object_s4; };
/**
* Use this to check if the camera is enabled or not.
* If not call WII#IRinitialize to initialize the IR camera.
* @return True if it's enabled, false if not.
*/
bool isIRCameraEnabled() { return (wiiState & 0x08); }; bool isIRCameraEnabled() { return (wiiState & 0x08); };
/**@}*/
#endif #endif
private: private:

View file

@ -55,6 +55,7 @@
#define XBOX_MAX_ENDPOINTS 9 #define XBOX_MAX_ENDPOINTS 9
/** Enum used to set special LED modes supported by the Xbox controller. */
enum LEDMode { enum LEDMode {
ROTATING = 0x0A, ROTATING = 0x0A,
FASTBLINK = 0x0B, FASTBLINK = 0x0B,
@ -62,48 +63,147 @@ enum LEDMode {
ALTERNATING = 0x0D, ALTERNATING = 0x0D,
}; };
/**
* This class implements support for a Xbox Wirless receiver.
*
* Up to four controllers can connect to one receiver, if more is needed one can use a second receiver via the USBHub class.
*/
class XBOXRECV : public USBDeviceConfig { class XBOXRECV : public USBDeviceConfig {
public: public:
/**
* Constructor for the XBOXRECV class.
* @param pUsb Pointer to USB class instance.
*/
XBOXRECV(USB *pUsb); XBOXRECV(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); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/**
* Release the USB device.
* @return 0 on success.
*/
virtual uint8_t Release(); virtual uint8_t Release();
/**
* Poll the USB Input endpoins and run the state machines.
* @return 0 on success.
*/
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; }; 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; }; virtual bool isReady() { return bPollEnable; };
/**@}*/
/*
Xbox Controller Readings. /** @name Xbox Controller functions */
getButtonPress will return true as long as the button is held down /**
While getButtonClick will only return it once * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down
So for instance if you need to increase a variable once you would use getButtonClick, * While getButtonClick(uint8_t controller, Button b) will only return it once
but if you need to drive a robot forward you would use getButtonPress * 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.
* @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(uint8_t controller, Button b); uint8_t getButtonPress(uint8_t controller, Button b);
bool getButtonClick(uint8_t controller, Button b); bool getButtonClick(uint8_t controller, Button b);
/**@}*/
/** @name Xbox Controller functions */
/**
* Return the analog value from the joysticks on the controller.
* @param controller The controller to read from.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Returns a signed 16-bit integer.
*/
int16_t getAnalogHat(uint8_t controller, AnalogHat a); int16_t getAnalogHat(uint8_t controller, AnalogHat a);
/**
/* Xbox Controller Command */ * Turn rumble off and all the LEDs on the specific controller.
* @param controller The controller to write to.
*/
void setAllOff(uint8_t controller) { setRumbleOn(controller,0,0); setLedOff(controller); }; void setAllOff(uint8_t controller) { setRumbleOn(controller,0,0); setLedOff(controller); };
/**
* Turn rumble off the specific controller.
* @param controller The controller to write to.
*/
void setRumbleOff(uint8_t controller) { setRumbleOn(controller,0,0); }; void setRumbleOff(uint8_t controller) { setRumbleOn(controller,0,0); };
/**
* Turn rumble on.
* @param controller The controller to write to.
* @param lValue Left motor (big weight) inside the controller.
* @param rValue Right motor (small weight) inside the controller.
*/
void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue); void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue);
/**
* Set LED value. Without using the ::LED or ::LEDMode enum.
* @param controller The controller to write to.
* @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 controller, uint8_t value); void setLedRaw(uint8_t controller, uint8_t value);
/**
* Turn all LEDs off the specific controller.
* @param controller The controller to write to.
*/
void setLedOff(uint8_t controller) { setLedRaw(controller,0); }; void setLedOff(uint8_t controller) { setLedRaw(controller,0); };
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedOn(uint8_t controller, LED l); void setLedOn(uint8_t controller, LED l);
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedBlink(uint8_t controller, LED l); void setLedBlink(uint8_t controller, 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(uint8_t controller, LEDMode lm); void setLedMode(uint8_t controller, LEDMode lm);
uint8_t getBatteryLevel(uint8_t controller); // Returns the battery level in percentage in 33% steps /**
* Used to get the battery level from the controller.
* @param controller The controller to read from.
* @return Returns the battery level in percentage in 33% steps.
*/
uint8_t getBatteryLevel(uint8_t controller);
/**
* Used to check if a button has changed.
* @param controller The controller to read from.
* @return True if a button has changed.
*/
bool buttonChanged(uint8_t controller); bool buttonChanged(uint8_t controller);
/**@}*/
bool XboxReceiverConnected; // True if a wireless receiver is connected
uint8_t Xbox360Connected[4]; // Variable used to indicate if the XBOX 360 controller is successfully connected /** True if a wireless receiver is connected. */
bool XboxReceiverConnected;
/** Variable used to indicate if the XBOX 360 controller is successfully connected. */
uint8_t Xbox360Connected[4];
protected: protected:
/* Mandatory members */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
uint8_t bAddress; // device address /** Device address. */
EpInfo epInfo[XBOX_MAX_ENDPOINTS]; //endpoint info structure uint8_t bAddress;
/** Endpoint info structure. */
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
private: private:
bool bPollEnable; bool bPollEnable;

View file

@ -18,13 +18,13 @@
#ifndef _controllerenums_h #ifndef _controllerenums_h
#define _controllerenums_h #define _controllerenums_h
/* /*
This header file is used to store different enums for the controllers, This header file is used to store different enums for the controllers,
This is necessary so all the different libraries can be used at once This is necessary so all the different libraries can be used at once
*/ */
/** Enum used to turn on the LEDs on the different controllers. */
enum LED { enum LED {
/* Enum used to turn on the LEDs on the different controllers */
LED1 = 0, LED1 = 0,
LED2 = 1, LED2 = 1,
LED3 = 2, LED3 = 2,
@ -36,15 +36,21 @@ enum LED {
LED8 = 7, LED8 = 7,
LED9 = 8, LED9 = 8,
LED10 = 9, LED10 = 9,
ALL = 4, // Used to blink all LEDs on the Xbox controller /** Used to blink all LEDs on the Xbox controller */
ALL = 4,
}; };
/** This enum is used to read all the different buttons on the different controllers */
enum Button { enum Button {
/**@{*/
/** These buttons are available on all the the controllers */
UP = 0, UP = 0,
RIGHT = 1, RIGHT = 1,
DOWN = 2, DOWN = 2,
LEFT = 3, LEFT = 3,
/**@}*/
/* Wii buttons */ /**@{*/
/** Wii buttons */
PLUS = 5, PLUS = 5,
TWO = 6, TWO = 6,
ONE = 7, ONE = 7,
@ -54,13 +60,18 @@ enum Button {
C = 11, C = 11,
B = 12, B = 12,
A = 13, A = 13,
/* These are only available on the Wii U Pro Controller */ /**@}*/
/**@{*/
/** These are only available on the Wii U Pro Controller */
L = 16, L = 16,
R = 17, R = 17,
ZL = 18, ZL = 18,
ZR = 19, ZR = 19,
/**@}*/
/* PS3 controllers buttons */ /**@{*/
/** PS3 controllers buttons */
SELECT = 4, SELECT = 4,
START = 5, START = 5,
L3 = 6, L3 = 6,
@ -77,21 +88,28 @@ enum Button {
PS = 16, PS = 16,
MOVE = 17, // covers 12 bits - we only need to read the top 8 MOVE = 17, // Covers 12 bits - we only need to read the top 8
T = 18, // covers 12 bits - we only need to read the top 8 T = 18, // Covers 12 bits - we only need to read the top 8
/**@}*/
/* Xbox buttons */ /**@{*/
/** Xbox buttons */
BACK = 4, BACK = 4,
X = 14, X = 14,
Y = 15, Y = 15,
XBOX = 16, XBOX = 16,
SYNC = 17, SYNC = 17,
/**@}*/
}; };
enum AnalogHat { /** Joysticks on the PS3 and Xbox controllers. */
/* Joysticks on the PS3 and Xbox controllers */ enum AnalogHat {
/** Left joystick x-axis */
LeftHatX = 0, LeftHatX = 0,
/** Left joystick y-axis */
LeftHatY = 1, LeftHatY = 1,
/** Right joystick x-axis */
RightHatX = 2, RightHatX = 2,
/** Right joystick y-axis */
RightHatY = 3, RightHatY = 3,
}; };