From 2330fd95becfb594589496eccd5f10b46187d950 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 5 May 2012 20:58:16 +0200 Subject: [PATCH 01/20] Added HCI Version Check --- PS3BT.cpp | 56 +++++++++++++++++++++++++++++++++++++++---------------- PS3BT.h | 17 ++++++++++------- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 92c8a640..f64138ad 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -546,12 +546,6 @@ double PS3BT::getAngle(Angle a) { accZval = ((1+accZval)-(1+1.15))*(-1/0.15); } - double R = sqrt(accXval*accXval + accYval*accYval + accZval*accZval); // Calculate the length of the force vector - // Normalize vectors - accXval = accXval/R; - accYval = accYval/R; - accZval = accZval/R; - // Convert to 360 degrees resolution // atan2 outputs the value of -π to π (radians) // We are then converting it to 0 to 2π and then to degrees @@ -647,11 +641,15 @@ void PS3BT::HCI_event_task() switch (hcibuf[0]) //switch on event type { case EV_COMMAND_COMPLETE: - hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag - if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10))// parameters from read local bluetooth address - { - for (uint8_t i = 0; i < 6; i++) - my_bdaddr[i] = hcibuf[6 + i]; + if (!hcibuf[5]) { // check if command succeeded + hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag + if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) // parameters from read local version information + hci_version = hcibuf[6]; // Check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm + + else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // parameters from read local bluetooth address + for (uint8_t i = 0; i < 6; i++) + my_bdaddr[i] = hcibuf[6 + i]; + } } break; @@ -683,10 +681,7 @@ void PS3BT::HCI_event_task() hci_event_flag |= HCI_FLAG_DISCONN_COMPLETE; //set disconnect commend complete flag hci_event_flag &= ~HCI_FLAG_CONN_COMPLETE; // clear connection complete flag } - break; - - case EV_NUM_COMPLETE_PKT: - break; + break; case EV_REMOTE_NAME_COMPLETE: if (!hcibuf[2]) // check if reading is OK @@ -707,7 +702,11 @@ void PS3BT::HCI_event_task() hci_event_flag |= HCI_FLAG_INCOMING_REQUEST; break; - /* We will just ignore the following events */ + /* We will just ignore the following events */ + + case EV_NUM_COMPLETE_PKT: + break; + case EV_ROLE_CHANGED: break; @@ -782,6 +781,7 @@ void PS3BT::HCI_task() hci_counter = 0; } break; + case HCI_BDADDR_STATE: if (hci_cmd_complete) { @@ -794,8 +794,25 @@ void PS3BT::HCI_task() } PrintHex(my_bdaddr[0]); #endif + hci_read_local_version_information(); + hci_state = HCI_LOCAL_VERSION_STATE; + } + break; + + case HCI_LOCAL_VERSION_STATE: + if (hci_cmd_complete) + { +#ifdef DEBUG + if(hci_version < 3) { + Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: ")); + Serial.print(hci_version); + Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR")); + } +#endif hci_state = HCI_SCANNING_STATE; } + break; + break; case HCI_SCANNING_STATE: #ifdef DEBUG @@ -1319,6 +1336,13 @@ void PS3BT::hci_read_bdaddr() hcibuf[1] = 0x04 << 2; // HCI OGF = 4 hcibuf[2] = 0x00; HCI_Command(hcibuf, 3); +} +void PS3BT::hci_read_local_version_information() +{ + hcibuf[0] = 0x01; // HCI OCF = 1 + hcibuf[1] = 0x04 << 2; // HCI OGF = 4 + hcibuf[2] = 0x00; + HCI_Command(hcibuf, 3); } void PS3BT::hci_accept_connection() { diff --git a/PS3BT.h b/PS3BT.h index 8c1f43df..b228a91c 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -62,13 +62,14 @@ #define HCI_INIT_STATE 0 #define HCI_RESET_STATE 1 #define HCI_BDADDR_STATE 2 -#define HCI_SCANNING_STATE 3 -#define HCI_CONNECT_IN_STATE 4 -#define HCI_REMOTE_NAME_STATE 5 -#define HCI_CONNECTED_STATE 6 -#define HCI_DISABLE_SCAN 7 -#define HCI_DONE_STATE 8 -#define HCI_DISCONNECT_STATE 9 +#define HCI_LOCAL_VERSION_STATE 3 +#define HCI_SCANNING_STATE 4 +#define HCI_CONNECT_IN_STATE 5 +#define HCI_REMOTE_NAME_STATE 6 +#define HCI_CONNECTED_STATE 7 +#define HCI_DISABLE_SCAN 8 +#define HCI_DONE_STATE 9 +#define HCI_DISCONNECT_STATE 10 /* HCI event flags*/ #define HCI_FLAG_CMD_COMPLETE 0x01 @@ -389,6 +390,7 @@ private: int16_t hci_handle; uint8_t disc_bdaddr[6]; // the bluetooth address is always 6 bytes uint8_t remote_name[30]; // first 30 chars of remote name + uint8_t hci_version; /* variables used by high level HCI task */ uint8_t hci_state; //current state of bluetooth hci connection @@ -437,6 +439,7 @@ private: void hci_write_scan_enable(); void hci_write_scan_disable(); void hci_read_bdaddr(); + void hci_read_local_version_information(); void hci_accept_connection(); void hci_remote_name(); void hci_disconnect(); From e60ddbac5a55d21d43dafabf32983414c3a58bcd Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Wed, 9 May 2012 18:38:38 +0200 Subject: [PATCH 02/20] Added setLedToggle() --- PS3BT.cpp | 34 ++++++++++++---------------------- PS3BT.h | 1 + keywords.txt | 1 + 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index f64138ad..3e5f8107 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -406,17 +406,13 @@ uint8_t PS3BT::Poll() return 0; } void PS3BT::setBdaddr(uint8_t* BDADDR) -{ - /* Store the bluetooth address */ - for(uint8_t i = 0; i <6;i++) - my_bdaddr[i] = BDADDR[i]; - +{ /* Set the internal bluetooth address */ uint8_t buf[8]; buf[0] = 0x01; buf[1] = 0x00; for (uint8_t i = 0; i < 6; i++) - buf[i+2] = my_bdaddr[5 - i];//Copy into buffer, has to be written reversed + buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); @@ -433,10 +429,6 @@ void PS3BT::setBdaddr(uint8_t* BDADDR) } void PS3BT::setMoveBdaddr(uint8_t* BDADDR) { - /* Store the bluetooth address */ - for(uint8_t i = 0; i <6;i++) - my_bdaddr[i] = BDADDR[i]; - /* Set the internal bluetooth address */ uint8_t buf[11]; buf[0] = 0x05; @@ -446,7 +438,7 @@ void PS3BT::setMoveBdaddr(uint8_t* BDADDR) buf[10] = 0x12; for (uint8_t i = 0; i < 6; i++) - buf[i + 1] = my_bdaddr[i]; + buf[i + 1] = BDADDR[i]; //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); @@ -798,7 +790,7 @@ void PS3BT::HCI_task() hci_state = HCI_LOCAL_VERSION_STATE; } break; - + case HCI_LOCAL_VERSION_STATE: if (hci_cmd_complete) { @@ -1591,19 +1583,17 @@ void PS3BT::setRumbleOn(Rumble mode) } void PS3BT::setLedOff(LED a) { - //check if LED is already off - if ((uint8_t)((uint8_t)(((uint16_t)a << 1) & HIDBuffer[11])) != 0) - { - //set the LED into the write buffer - HIDBuffer[11] = (uint8_t)((uint8_t)(((uint16_t)a & 0x0f) << 1) ^ HIDBuffer[11]); - - HID_Command(HIDBuffer, HID_BUFFERSIZE); - } + HIDBuffer[11] &= ~((uint8_t)(((uint16_t)a & 0x0f) << 1)); + HID_Command(HIDBuffer, HID_BUFFERSIZE); } void PS3BT::setLedOn(LED a) { - HIDBuffer[11] = (uint8_t)((uint8_t)(((uint16_t)a & 0x0f) << 1) | HIDBuffer[11]); - + HIDBuffer[11] |= (uint8_t)(((uint16_t)a & 0x0f) << 1); + HID_Command(HIDBuffer, HID_BUFFERSIZE); +} +void PS3BT::setLedToggle(LED a) +{ + HIDBuffer[11] ^= (uint8_t)(((uint16_t)a & 0x0f) << 1); HID_Command(HIDBuffer, HID_BUFFERSIZE); } void PS3BT::enable_sixaxis()//Command used to enable the Dualshock 3 and Navigation controller to send data via USB diff --git a/PS3BT.h b/PS3BT.h index b228a91c..b2983b7c 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -352,6 +352,7 @@ public: void setRumbleOn(Rumble mode); void setLedOff(LED a); void setLedOn(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 void moveSetBulb(Colors color);//Use this to set the Color using the predefined colors in "enum Colors" diff --git a/keywords.txt b/keywords.txt index 378fc91a..8b11fbcf 100644 --- a/keywords.txt +++ b/keywords.txt @@ -28,6 +28,7 @@ setRumbleOff KEYWORD2 setRumbleOn KEYWORD2 setLedOff KEYWORD2 setLedOn KEYWORD2 +setLedToggle KEYWORD2 moveSetBulb KEYWORD2 moveSetRumble KEYWORD2 From 95a797e7356809bed713c2dad355e5362cba4118 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Wed, 9 May 2012 19:46:26 +0200 Subject: [PATCH 03/20] Updated getAngle() --- PS3BT.cpp | 54 ++++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 3e5f8107..c80e58ab 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -507,45 +507,39 @@ double PS3BT::getAngle(Angle a) { if(PS3BTConnected) { // Data for the Kionix KXPC4 used in the DualShock 3 - double sensivity = 204.6; // 0.66/3.3*1023 (660mV/g) - double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) - accXval = ((double)getSensor(aX)-zeroG) / sensivity; // Convert to g's - accXval *= 2; - accYval = ((double)getSensor(aY)-zeroG) / sensivity; // Convert to g's - accYval *= 2; - accZval = ((double)getSensor(aZ)-zeroG) / sensivity; // Convert to g's - accZval *= 2; - } else if(PS3MoveBTConnected) { - // It's a Kionix KXSC4 inside the Motion controller - const uint16_t sensivity = 28285; // Find by experimenting - accXval = (double)getSensor(aXmove)/sensivity; - accYval = (double)getSensor(aYmove)/sensivity; - accZval = (double)getSensor(aZmove)/sensivity; + const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) + accXval = -((double)getSensor(aX)-zeroG); + accYval = -((double)getSensor(aY)-zeroG); + accZval = -((double)getSensor(aZ)-zeroG); + } else if(PS3MoveBTConnected) { + // It's a Kionix KXSC4 inside the Motion controller + const uint16_t zeroG = 0x8000; + accXval = getSensor(aXmove); + accYval = getSensor(aYmove); + accZval = getSensor(aZmove); - if(accXval < -1) // Convert to g's - accXval = ((1+accXval)-(1-1.15))*(-1/0.15); - else if(accXval > 1) - accXval = ((1+accXval)-(1+1.15))*(-1/0.15); - - if(accYval < -1) // Convert to g's - accYval = ((1+accYval)-(1-1.15))*(-1/0.15); - else if(accYval > 1) - accYval = ((1+accYval)-(1+1.15))*(-1/0.15); - - if(accZval < -1) // Convert to g's - accZval = ((1+accZval)-(1-1.15))*(-1/0.15); - else if(accZval > 1) - accZval = ((1+accZval)-(1+1.15))*(-1/0.15); + if(accXval < 0) + accXval += zeroG; + else + accXval -= zeroG; + if(accYval < 0) + accYval += zeroG; + else + accYval -= zeroG; + if(accZval < 0) + accZval += zeroG; + else + accZval -= zeroG; } // Convert to 360 degrees resolution // atan2 outputs the value of -π to π (radians) // We are then converting it to 0 to 2π and then to degrees if (a == Pitch) { - double angle = (atan2(-accYval,-accZval)+PI)*RAD_TO_DEG; + double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; return angle; } else { - double angle = (atan2(-accXval,-accZval)+PI)*RAD_TO_DEG; + double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; return angle; } } From 73427c03848c21cfd6651bc2148ebb26db4aaeb2 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Thu, 24 May 2012 14:39:01 +0200 Subject: [PATCH 04/20] Combined constructors --- PS3BT.cpp | 19 ------------------- PS3BT.h | 5 ++--- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index c80e58ab..827e2867 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -62,25 +62,6 @@ bPollEnable(false) // don't start polling before dongle is connected my_bdaddr[0] = btadr0; } -PS3BT::PS3BT(USB *p): -pUsb(p), // pointer to USB class instance - mandatory -bAddress(0), // device address - mandatory -bNumEP(1), // if config descriptor needs to be parsed -qNextPollTime(0), -bPollEnable(false) // don't start polling before dongle is connected -{ - for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry -} - uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; diff --git a/PS3BT.h b/PS3BT.h index b2983b7c..3f326454 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -316,9 +316,8 @@ enum Rumble class PS3BT : public USBDeviceConfig, public UsbConfigXtracter { -public: - PS3BT(USB *pUsb, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0); - PS3BT(USB *pUsb); +public: + PS3BT(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 virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); From 6b93de24ce858507cd0576987b66cb33069fd67b Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Fri, 25 May 2012 18:29:58 +0200 Subject: [PATCH 05/20] Created separate flags for read bdaddr and read local version Sometimes it didn't read the bluetooth address correctly, but still just went on with the state machine. The start number og reset loops also had to be increased. --- PS3BT.cpp | 22 ++++++++++++---------- PS3BT.h | 6 +++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 827e2867..e9b21f57 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -264,7 +264,7 @@ uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed) interrupt_dcid[0] = 0x41;//0x0041 interrupt_dcid[1] = 0x00; - hci_num_reset_loops = 10; // only loop 10 times before trying to send the hci reset command + hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command hci_state = HCI_INIT_STATE; hci_counter = 0; @@ -382,8 +382,8 @@ uint8_t PS3BT::Poll() if (qNextPollTime <= millis()) { // Don't poll if shorter than polling interval HCI_event_task(); // poll the HCI event pipe ACL_event_task(); // start polling the ACL input pipe too, though discard data until connected - } - qNextPollTime = millis() + pollInterval; // Poll time + qNextPollTime = millis() + pollInterval; // Set new poll time + } return 0; } void PS3BT::setBdaddr(uint8_t* BDADDR) @@ -608,15 +608,17 @@ void PS3BT::HCI_event_task() switch (hcibuf[0]) //switch on event type { case EV_COMMAND_COMPLETE: - if (!hcibuf[5]) { // check if command succeeded - hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag - if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) // parameters from read local version information + hci_event_flag |= HCI_FLAG_CMD_COMPLETE; // set command complete flag + if (!hcibuf[5]) { // check if command succeeded + if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // parameters from read local version information hci_version = hcibuf[6]; // Check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm - + hci_event_flag |= HCI_FLAG_READ_VERSION; + } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // parameters from read local bluetooth address for (uint8_t i = 0; i < 6; i++) my_bdaddr[i] = hcibuf[6 + i]; - } + hci_event_flag |= HCI_FLAG_READ_BDADDR; + } } break; @@ -750,7 +752,7 @@ void PS3BT::HCI_task() break; case HCI_BDADDR_STATE: - if (hci_cmd_complete) + if (hci_read_bdaddr_complete) { #ifdef DEBUG Notify(PSTR("\r\nLocal Bluetooth Address: ")); @@ -767,7 +769,7 @@ void PS3BT::HCI_task() break; case HCI_LOCAL_VERSION_STATE: - if (hci_cmd_complete) + if (hci_read_version_complete) { #ifdef DEBUG if(hci_version < 3) { diff --git a/PS3BT.h b/PS3BT.h index 3f326454..27a2decd 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -77,6 +77,8 @@ #define HCI_FLAG_DISCONN_COMPLETE 0x04 #define HCI_FLAG_REMOTE_NAME_COMPLETE 0x08 #define HCI_FLAG_INCOMING_REQUEST 0x10 +#define HCI_FLAG_READ_BDADDR 0x20 +#define HCI_FLAG_READ_VERSION 0x40 /*Macros for HCI event flag tests */ #define hci_cmd_complete (hci_event_flag & HCI_FLAG_CMD_COMPLETE) @@ -84,6 +86,8 @@ #define hci_disconnect_complete (hci_event_flag & HCI_FLAG_DISCONN_COMPLETE) #define hci_remote_name_complete (hci_event_flag & HCI_FLAG_REMOTE_NAME_COMPLETE) #define hci_incoming_connect_request (hci_event_flag & HCI_FLAG_INCOMING_REQUEST) +#define hci_read_bdaddr_complete (hci_event_flag & HCI_FLAG_READ_BDADDR) +#define hci_read_version_complete (hci_event_flag & HCI_FLAG_READ_VERSION) /* HCI Events managed */ #define EV_COMMAND_COMPLETE 0x0E @@ -362,7 +366,7 @@ public: bool PS3NavigationBTConnected;// Variable used to indicate if the navigation 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 pressed + bool buttonReleased;//Indicate if a button has been released protected: /* mandatory members */ From b66a8f214ca2b8b8c46f3a3aa80fc1a06ae02285 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Fri, 25 May 2012 19:59:00 +0200 Subject: [PATCH 06/20] Added small delay in example sketch Also fixed qNextPollTime --- PS3BT.cpp | 4 ++-- examples/PS3BT/PS3BT.ino | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index e9b21f57..9166d7eb 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -380,9 +380,9 @@ uint8_t PS3BT::Poll() if (!bPollEnable) return 0; if (qNextPollTime <= millis()) { // Don't poll if shorter than polling interval - HCI_event_task(); // poll the HCI event pipe - ACL_event_task(); // start polling the ACL input pipe too, though discard data until connected qNextPollTime = millis() + pollInterval; // Set new poll time + HCI_event_task(); // poll the HCI event pipe + ACL_event_task(); // start polling the ACL input pipe too, though discard data until connected } return 0; } diff --git a/examples/PS3BT/PS3BT.ino b/examples/PS3BT/PS3BT.ino index 2b6fbd95..df667a4e 100644 --- a/examples/PS3BT/PS3BT.ino +++ b/examples/PS3BT/PS3BT.ino @@ -198,4 +198,5 @@ void loop() Serial.println(templow); } } + delay(1); } From d638d726e2842f1e7262716f2dab6fa1fa632a7c Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 26 May 2012 01:46:18 +0200 Subject: [PATCH 07/20] Several minor adjustments --- PS3BT.cpp | 73 ++++++------- PS3BT.h | 8 +- examples/PS3/PS3BT/PS3BT.ino | 202 +++++++++++++++++++++++++++++++++++ examples/PS3BT/PS3BT.ino | 202 ----------------------------------- keywords.txt | 25 ++--- 5 files changed, 255 insertions(+), 255 deletions(-) create mode 100644 examples/PS3/PS3BT/PS3BT.ino delete mode 100644 examples/PS3BT/PS3BT.ino diff --git a/PS3BT.cpp b/PS3BT.cpp index 9166d7eb..78712b6b 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -369,6 +369,9 @@ void PS3BT::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr ) /* Performs a cleanup after failed Init() attempt */ uint8_t PS3BT::Release() { + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; pUsb->GetAddressPool().FreeAddress(bAddress); bAddress = 0; bPollEnable = false; @@ -486,13 +489,13 @@ double PS3BT::getAngle(Angle a) { double accYval; double accZval; - if(PS3BTConnected) { + if(PS3Connected) { // Data for the Kionix KXPC4 used in the DualShock 3 const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) accXval = -((double)getSensor(aX)-zeroG); accYval = -((double)getSensor(aY)-zeroG); accZval = -((double)getSensor(aZ)-zeroG); - } else if(PS3MoveBTConnected) { + } else if(PS3MoveConnected) { // It's a Kionix KXSC4 inside the Motion controller const uint16_t zeroG = 0x8000; accXval = getSensor(aXmove); @@ -534,7 +537,7 @@ bool PS3BT::getStatus(Status c) } String PS3BT::getStatusString() { - if (PS3BTConnected || PS3NavigationBTConnected) + if (PS3Connected || PS3NavigationConnected) { char statusOutput[100]; @@ -566,7 +569,7 @@ String PS3BT::getStatusString() return statusOutput; } - else if(PS3MoveBTConnected) + else if(PS3MoveConnected) { char statusOutput[50]; @@ -586,12 +589,12 @@ String PS3BT::getStatusString() } void PS3BT::disconnect()//Use this void to disconnect any of the controllers { - if (PS3BTConnected) - PS3BTConnected = false; - else if (PS3MoveBTConnected) - PS3MoveBTConnected = false; - else if (PS3NavigationBTConnected) - PS3NavigationBTConnected = false; + if (PS3Connected) + PS3Connected = false; + else if (PS3MoveConnected) + PS3MoveConnected = false; + else if (PS3NavigationConnected) + PS3NavigationConnected = false; //First the HID interrupt channel has to be disconencted, then the HID control channel and finally the HCI connection l2cap_disconnection_request(0x0A, interrupt_dcid, interrupt_scid); @@ -1030,7 +1033,7 @@ void PS3BT::ACL_event_task() else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1])//l2cap_interrupt { //Serial.print("\r\nL2CAP Interrupt"); - if(PS3BTConnected || PS3MoveBTConnected || PS3NavigationBTConnected) + if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) { readReport(); #ifdef PRINTREPORT @@ -1155,30 +1158,29 @@ void PS3BT::L2CAP_task() #ifdef DEBUG Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n")); #endif - PS3BTConnected = true; + PS3Connected = true; } else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N') setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller #ifdef DEBUG Notify(PSTR("\r\nNavigation Controller Enabled\r\n")); #endif - PS3NavigationBTConnected = true; + PS3NavigationConnected = true; } else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M') moveSetBulb(Red); timerBulbRumble = millis(); #ifdef DEBUG Notify(PSTR("\r\nMotion Controller Enabled\r\n")); #endif - PS3MoveBTConnected = true; + PS3MoveConnected = true; } l2cap_state = L2CAP_EV_L2CAP_DONE; } break; case L2CAP_EV_L2CAP_DONE: - if (PS3MoveBTConnected)//The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on + if (PS3MoveConnected)//The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on { - dtimeBulbRumble = millis() - timerBulbRumble; - if (dtimeBulbRumble > 4000)//Send at least every 4th second + if (millis() - timerBulbRumble > 4000)//Send at least every 4th second { HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);//The Bulb and rumble values, has to be written again and again, for it to stay turned on timerBulbRumble = millis(); @@ -1217,11 +1219,13 @@ void PS3BT::L2CAP_task() /************************************************************/ void PS3BT::readReport() { + if (l2capinbuf == NULL) + return; if(l2capinbuf[8] == 0xA1)//HID_THDR_DATA_INPUT { - if(PS3BTConnected || PS3NavigationBTConnected) + if(PS3Connected || PS3NavigationConnected) ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16)); - else if(PS3MoveBTConnected) + else if(PS3MoveConnected) ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16)); //Notify(PSTR("\r\nButtonState"); @@ -1251,7 +1255,9 @@ void PS3BT::readReport() } void PS3BT::printReport() //Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers -{ +{ + if (l2capinbuf == NULL) + return; if(l2capinbuf[8] == 0xA1)//HID_THDR_DATA_INPUT { for(uint8_t i = 10; i < 58;i++) @@ -1504,12 +1510,10 @@ void PS3BT::HID_Command(uint8_t* data, uint16_t nbytes) buf[7] = control_scid[1]; for (uint16_t i = 0; i < nbytes; i++)//L2CAP C-frame - buf[8 + i] = data[i]; + buf[8 + i] = data[i]; - dtimeHID = millis() - timerHID; - - if (dtimeHID <= 250)// Check if is has been more than 250ms since last command - delay((uint32_t)(250 - dtimeHID));//There have to be a delay between commands + if (millis() - timerHID <= 250)// Check if is has been more than 250ms since last command + delay((uint32_t)(250 - (millis() - timerHID)));//There have to be a delay between commands pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); @@ -1600,12 +1604,10 @@ void PS3BT::HIDMove_Command(uint8_t* data,uint16_t nbytes) buf[7] = interrupt_scid[1]; for (uint16_t i = 0; i < nbytes; i++)//L2CAP C-frame - buf[8 + i] = data[i]; + buf[8 + i] = data[i]; - dtimeHID = millis() - timerHID; - - if (dtimeHID <= 250)// Check if is has been less than 200ms since last command - delay((uint32_t)(250 - dtimeHID));//There have to be a delay between commands + if (millis() - timerHID <= 250)// Check if is has been less than 200ms since last command + delay((uint32_t)(250 - (millis() - timerHID)));//There have to be a delay between commands pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf); @@ -1622,15 +1624,14 @@ void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b)//Use this to set the Co } void PS3BT::moveSetBulb(Colors color)//Use this to set the Color using the predefined colors in "enums.h" { - //set the Bulb's values into the write buffer - HIDMoveBuffer[3] = (uint8_t)(color >> 16); - HIDMoveBuffer[4] = (uint8_t)(color >> 8); - HIDMoveBuffer[5] = (uint8_t)(color); - - HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); + moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); } void PS3BT::moveSetRumble(uint8_t rumble) { +#ifdef DEBUG + if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%")); +#endif //set the rumble value into the write buffer HIDMoveBuffer[7] = rumble; diff --git a/PS3BT.h b/PS3BT.h index 27a2decd..2e0e4fad 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -361,9 +361,9 @@ public: void moveSetBulb(Colors color);//Use this to set the Color using the predefined colors in "enum Colors" void moveSetRumble(uint8_t rumble); - bool PS3BTConnected;// Variable used to indicate if the normal playstation controller is successfully connected - bool PS3MoveBTConnected;// Variable used to indicate if the move controller is successfully connected - bool PS3NavigationBTConnected;// Variable used to indicate if the navigation controller is successfully connected + 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 + bool PS3NavigationConnected;// Variable used to indicate if the navigation 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 @@ -411,9 +411,7 @@ private: uint32_t ButtonState; uint32_t OldButtonState; uint32_t timerHID;// timer used see if there has to be a delay before a new HID command - uint32_t dtimeHID;// delta time since last HID command uint32_t timerBulbRumble;// used to continuously set PS3 Move controller Bulb and rumble values - uint32_t dtimeBulbRumble;// used to know how longs since last since the Bulb and rumble values was written uint8_t my_bdaddr[6]; //Change to your dongles Bluetooth address in PS3BT.cpp uint8_t hcibuf[BULK_MAXPKTSIZE];//General purpose buffer for hci data diff --git a/examples/PS3/PS3BT/PS3BT.ino b/examples/PS3/PS3BT/PS3BT.ino new file mode 100644 index 00000000..7830aa01 --- /dev/null +++ b/examples/PS3/PS3BT/PS3BT.ino @@ -0,0 +1,202 @@ +/* + Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +USB Usb; +/* You can create the instance of the class in two ways */ +PS3BT PS3(&Usb); // This will just create the instance +//PS3BT PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch + +boolean printTemperature; +boolean printAngle; + +void setup() +{ + Serial.begin(115200); + + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while(1); //halt + } + Serial.print(F("\r\nPS3 Bluetooth Library Started")); +} +void loop() +{ + Usb.Task(); + + if(PS3.PS3Connected || PS3.PS3NavigationConnected) { + if(PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + if(PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117) { + Serial.print(F("LeftHatX: ")); + Serial.print(PS3.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } if(PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117) { + Serial.print(F("LeftHatY: ")); + Serial.print(PS3.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } if(PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117) { + Serial.print(F("RightHatX: ")); + Serial.print(PS3.getAnalogHat(RightHatX)); + Serial.print("\t"); + } if(PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + Serial.print(F("RightHatY: ")); + Serial.print(PS3.getAnalogHat(RightHatY)); + } + Serial.println(""); + } + + //Analog button values can be read from almost all buttons + if(PS3.getAnalogButton(L2_ANALOG) > 0 || PS3.getAnalogButton(R2_ANALOG) > 0) { + if(PS3.getAnalogButton(L2_ANALOG) > 0) { + Serial.print(F("L2: ")); + Serial.print(PS3.getAnalogButton(L2_ANALOG)); + Serial.print("\t"); + } if(PS3.getAnalogButton(R2_ANALOG) > 0) { + Serial.print(F("R2: ")); + Serial.print(PS3.getAnalogButton(R2_ANALOG)); + } + Serial.println(""); + } + + if(PS3.buttonPressed) + { + Serial.print(F("PS3 Controller")); + + if(PS3.getButton(PS)) { + Serial.print(F(" - PS")); + PS3.disconnect(); + } else { + if(PS3.getButton(TRIANGLE)) + Serial.print(F(" - Traingle")); + if(PS3.getButton(CIRCLE)) + Serial.print(F(" - Circle")); + if(PS3.getButton(CROSS)) + Serial.print(F(" - Cross")); + if(PS3.getButton(SQUARE)) + Serial.print(F(" - Square")); + + if(PS3.getButton(UP)) { + Serial.print(F(" - Up")); + PS3.setAllOff(); + PS3.setLedOn(LED4); + } if(PS3.getButton(RIGHT)) { + Serial.print(F(" - Right")); + PS3.setAllOff(); + PS3.setLedOn(LED1); + } if(PS3.getButton(DOWN)) { + Serial.print(F(" - Down")); + PS3.setAllOff(); + PS3.setLedOn(LED2); + } if(PS3.getButton(LEFT)) { + Serial.print(F(" - Left")); + PS3.setAllOff(); + PS3.setLedOn(LED3); + } + + if(PS3.getButton(L1)) + Serial.print(F(" - L1")); + //if(PS3.getButton(L2)) + //Serial.print(F(" - L2")); + if(PS3.getButton(L3)) + Serial.print(F(" - L3")); + if(PS3.getButton(R1)) + Serial.print(F(" - R1")); + //if(PS3.getButton(R2)) + //Serial.print(F(" - R2")); + if(PS3.getButton(R3)) + Serial.print(F(" - R3")); + + if(PS3.getButton(SELECT)) { + Serial.print(F(" - Select - ")); + Serial.print(PS3.getStatusString()); + } if(PS3.getButton(START)) { + Serial.print(F(" - Start")); + printAngle = !printAngle; + while(PS3.getButton(START)) + Usb.Task(); + } + Serial.println(""); + } + } + if(printAngle) { + Serial.print(F("Pitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.println(PS3.getAngle(Roll)); + } + } + else if(PS3.PS3MoveConnected) + { + if(PS3.getAnalogButton(T_MOVE_ANALOG) > 0) { + Serial.print(F("T: ")); + Serial.println(PS3.getAnalogButton(T_MOVE_ANALOG)); + } if(PS3.buttonPressed) { + Serial.print(F("PS3 Move Controller")); + + if(PS3.getButton(PS_MOVE)) { + Serial.print(F(" - PS")); + PS3.disconnect(); + } else { + if(PS3.getButton(SELECT_MOVE)) { + Serial.print(F(" - Select")); + printTemperature = !printTemperature; + while(PS3.getButton(SELECT_MOVE)) + Usb.Task(); + } if(PS3.getButton(START_MOVE)) { + Serial.print(F(" - Start")); + printAngle = !printAngle; + while(PS3.getButton(START_MOVE)) + Usb.Task(); + } if(PS3.getButton(TRIANGLE_MOVE)) { + Serial.print(F(" - Triangle")); + PS3.moveSetBulb(Red); + } if(PS3.getButton(CIRCLE_MOVE)) { + Serial.print(F(" - Circle")); + PS3.moveSetBulb(Green); + } if(PS3.getButton(SQUARE_MOVE)) { + Serial.print(F(" - Square")); + PS3.moveSetBulb(Blue); + } if(PS3.getButton(CROSS_MOVE)) { + Serial.print(F(" - Cross")); + PS3.moveSetBulb(Yellow); + } if(PS3.getButton(MOVE_MOVE)) { + PS3.moveSetBulb(Off); + Serial.print(F(" - Move")); + Serial.print(F(" - ")); + Serial.print(PS3.getStatusString()); + } + //if(PS3.getButton(T)) + //Serial.print(F(" - T")); + + Serial.println(""); + } + } + if(printAngle) { + Serial.print(F("Pitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.println(PS3.getAngle(Roll)); + } + else if(printTemperature) { + String templow; + String temphigh; + String input = String(PS3.getSensor(tempMove)); + + if (input.length() > 3) { + temphigh = input.substring(0, 2); + templow = input.substring(2); + } else { + temphigh = input.substring(0, 1); + templow = input.substring(1); + } + Serial.print(F("Temperature: ")); + Serial.print(temphigh); + Serial.print(F(".")); + Serial.println(templow); + } + } + delay(1); +} diff --git a/examples/PS3BT/PS3BT.ino b/examples/PS3BT/PS3BT.ino deleted file mode 100644 index df667a4e..00000000 --- a/examples/PS3BT/PS3BT.ino +++ /dev/null @@ -1,202 +0,0 @@ -/* - Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus - For more information visit my blog: http://blog.tkjelectronics.dk/ or - send me an e-mail: kristianl@tkjelectronics.com - */ - -#include -USB Usb; -/* You can create the instance of the class in two ways */ -PS3BT BT(&Usb); // This will just create the instance -//PS3BT BT(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch - -boolean printTemperature; -boolean printAngle; - -void setup() -{ - Serial.begin(115200); - - if (Usb.Init() == -1) { - Serial.print(F("\r\nOSC did not start")); - while(1); //halt - } - Serial.print(F("\r\nPS3 Bluetooth Library Started")); -} -void loop() -{ - Usb.Task(); - - if(BT.PS3BTConnected || BT.PS3NavigationBTConnected) { - if(BT.getAnalogHat(LeftHatX) > 137 || BT.getAnalogHat(LeftHatX) < 117 || BT.getAnalogHat(LeftHatY) > 137 || BT.getAnalogHat(LeftHatY) < 117 || BT.getAnalogHat(RightHatX) > 137 || BT.getAnalogHat(RightHatX) < 117 || BT.getAnalogHat(RightHatY) > 137 || BT.getAnalogHat(RightHatY) < 117) { - if(BT.getAnalogHat(LeftHatX) > 137 || BT.getAnalogHat(LeftHatX) < 117) { - Serial.print(F("LeftHatX: ")); - Serial.print(BT.getAnalogHat(LeftHatX)); - Serial.print("\t"); - } if(BT.getAnalogHat(LeftHatY) > 137 || BT.getAnalogHat(LeftHatY) < 117) { - Serial.print(F("LeftHatY: ")); - Serial.print(BT.getAnalogHat(LeftHatY)); - Serial.print("\t"); - } if(BT.getAnalogHat(RightHatX) > 137 || BT.getAnalogHat(RightHatX) < 117) { - Serial.print(F("RightHatX: ")); - Serial.print(BT.getAnalogHat(RightHatX)); - Serial.print("\t"); - } if(BT.getAnalogHat(RightHatY) > 137 || BT.getAnalogHat(RightHatY) < 117) { - Serial.print(F("RightHatY: ")); - Serial.print(BT.getAnalogHat(RightHatY)); - } - Serial.println(""); - } - - //Analog button values can be read from almost all buttons - if(BT.getAnalogButton(L2_ANALOG) > 0 || BT.getAnalogButton(R2_ANALOG) > 0) { - if(BT.getAnalogButton(L2_ANALOG) > 0) { - Serial.print(F("L2: ")); - Serial.print(BT.getAnalogButton(L2_ANALOG)); - Serial.print("\t"); - } if(BT.getAnalogButton(R2_ANALOG) > 0) { - Serial.print(F("R2: ")); - Serial.print(BT.getAnalogButton(R2_ANALOG)); - } - Serial.println(""); - } - - if(BT.buttonPressed) - { - Serial.print(F("PS3 Controller")); - - if(BT.getButton(PS)) { - Serial.print(F(" - PS")); - BT.disconnect(); - } else { - if(BT.getButton(TRIANGLE)) - Serial.print(F(" - Traingle")); - if(BT.getButton(CIRCLE)) - Serial.print(F(" - Circle")); - if(BT.getButton(CROSS)) - Serial.print(F(" - Cross")); - if(BT.getButton(SQUARE)) - Serial.print(F(" - Square")); - - if(BT.getButton(UP)) { - Serial.print(F(" - Up")); - BT.setAllOff(); - BT.setLedOn(LED4); - } if(BT.getButton(RIGHT)) { - Serial.print(F(" - Right")); - BT.setAllOff(); - BT.setLedOn(LED1); - } if(BT.getButton(DOWN)) { - Serial.print(F(" - Down")); - BT.setAllOff(); - BT.setLedOn(LED2); - } if(BT.getButton(LEFT)) { - Serial.print(F(" - Left")); - BT.setAllOff(); - BT.setLedOn(LED3); - } - - if(BT.getButton(L1)) - Serial.print(F(" - L1")); - //if(BT.getButton(L2)) - //Serial.print(F(" - L2")); - if(BT.getButton(L3)) - Serial.print(F(" - L3")); - if(BT.getButton(R1)) - Serial.print(F(" - R1")); - //if(BT.getButton(R2)) - //Serial.print(F(" - R2")); - if(BT.getButton(R3)) - Serial.print(F(" - R3")); - - if(BT.getButton(SELECT)) { - Serial.print(F(" - Select - ")); - Serial.print(BT.getStatusString()); - } if(BT.getButton(START)) { - Serial.print(F(" - Start")); - printAngle = !printAngle; - while(BT.getButton(START)) - Usb.Task(); - } - Serial.println(""); - } - } - if(printAngle) { - Serial.print(F("Pitch: ")); - Serial.print(BT.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.println(BT.getAngle(Roll)); - } - } - else if(BT.PS3MoveBTConnected) - { - if(BT.getAnalogButton(T_MOVE_ANALOG) > 0) { - Serial.print(F("T: ")); - Serial.println(BT.getAnalogButton(T_MOVE_ANALOG)); - } if(BT.buttonPressed) { - Serial.print(F("PS3 Move Controller")); - - if(BT.getButton(PS_MOVE)) { - Serial.print(F(" - PS")); - BT.disconnect(); - } else { - if(BT.getButton(SELECT_MOVE)) { - Serial.print(F(" - Select")); - printTemperature = !printTemperature; - while(BT.getButton(SELECT_MOVE)) - Usb.Task(); - } if(BT.getButton(START_MOVE)) { - Serial.print(F(" - Start")); - printAngle = !printAngle; - while(BT.getButton(START_MOVE)) - Usb.Task(); - } if(BT.getButton(TRIANGLE_MOVE)) { - Serial.print(F(" - Triangle")); - BT.moveSetBulb(Red); - } if(BT.getButton(CIRCLE_MOVE)) { - Serial.print(F(" - Circle")); - BT.moveSetBulb(Green); - } if(BT.getButton(SQUARE_MOVE)) { - Serial.print(F(" - Square")); - BT.moveSetBulb(Blue); - } if(BT.getButton(CROSS_MOVE)) { - Serial.print(F(" - Cross")); - BT.moveSetBulb(Yellow); - } if(BT.getButton(MOVE_MOVE)) { - BT.moveSetBulb(Off); - Serial.print(F(" - Move")); - Serial.print(F(" - ")); - Serial.print(BT.getStatusString()); - } - //if(BT.getButton(T)) - //Serial.print(F(" - T")); - - Serial.println(""); - } - } - if(printAngle) { - Serial.print(F("Pitch: ")); - Serial.print(BT.getAngle(Pitch)); - Serial.print(F("\tRoll: ")); - Serial.println(BT.getAngle(Roll)); - } - else if(printTemperature) { - String templow; - String temphigh; - String input = String(BT.getSensor(tempMove)); - - if (input.length() > 3) { - temphigh = input.substring(0, 2); - templow = input.substring(2); - } else { - temphigh = input.substring(0, 1); - templow = input.substring(1); - } - Serial.print(F("Temperature: ")); - Serial.print(temphigh); - Serial.print(F(".")); - Serial.println(templow); - } - } - delay(1); -} diff --git a/keywords.txt b/keywords.txt index 8b11fbcf..89597cf3 100644 --- a/keywords.txt +++ b/keywords.txt @@ -1,16 +1,17 @@ -################################################ -# Syntax Coloring Map For PS3 Bluetooth Library -################################################ +#################################################### +# Syntax Coloring Map For PS3 Bluetooth/USB Library +#################################################### -################################################ +#################################################### # Datatypes (KEYWORD1) -################################################ +#################################################### PS3BT KEYWORD1 +PS3USB KEYWORD1 -################################################ +#################################################### # Methods and Functions (KEYWORD2) -################################################ +#################################################### setBdaddr KEYWORD2 setMoveBdaddr KEYWORD2 @@ -32,18 +33,18 @@ setLedToggle KEYWORD2 moveSetBulb KEYWORD2 moveSetRumble KEYWORD2 -PS3BTConnected KEYWORD2 -PS3MoveBTConnected KEYWORD2 -PS3NavigationBTConnected KEYWORD2 +PS3Connected KEYWORD2 +PS3MoveConnected KEYWORD2 +PS3NavigationConnected KEYWORD2 buttonChanged KEYWORD2 buttonPressed KEYWORD2 buttonReleased KEYWORD2 isWatingForConnection KEYWORD2 -################################################ +#################################################### # Constants and enums (LITERAL1) -################################################ +#################################################### LED1 LITERAL1 LED2 LITERAL1 LED3 LITERAL1 From a53b3336609b2c8fad6e08bf89b99e2be8bc76fd Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 26 May 2012 01:48:12 +0200 Subject: [PATCH 08/20] Added USB version of the library After several request I decided to port the library to a USB version --- PS3USB.cpp | 605 +++++++++++++++++++++++++++++++++ PS3USB.h | 244 +++++++++++++ examples/PS3/PS3USB/PS3USB.ino | 188 ++++++++++ 3 files changed, 1037 insertions(+) create mode 100644 PS3USB.cpp create mode 100644 PS3USB.h create mode 100644 examples/PS3/PS3USB/PS3USB.ino diff --git a/PS3USB.cpp b/PS3USB.cpp new file mode 100644 index 00000000..ed718110 --- /dev/null +++ b/PS3USB.cpp @@ -0,0 +1,605 @@ +/* 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 + */ + +#include "PS3USB.h" +#define DEBUG // Uncomment to print data for debugging +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers + +prog_char PS3_REPORT_BUFFER[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +prog_char MOVE_REPORT_BUFFER[] PROGMEM = { + 0x02, 0x00, // Always 0x02, 0x00, + 0x00, 0x00, 0x00, // r, g, b, + 0x00, // Always 0x00, + 0x00 // Rumble +}; + +PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0): +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) // don't start polling before dongle is connected +{ + for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry + + my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead + my_bdaddr[4] = btadr4; + my_bdaddr[3] = btadr3; + my_bdaddr[2] = btadr2; + my_bdaddr[1] = btadr1; + my_bdaddr[0] = btadr0; +} + +uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) +{ + uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t PID; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nPS3BT Init")); +#endif + // check if address has already been assigned to an instance + if (bAddress) + { +#ifdef DEBUG + Notify(PSTR("\r\nAddress in use")); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + { +#ifdef DEBUG + Notify(PSTR("\r\nAddress not found")); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if (!p->epinfo) + { +#ifdef DEBUG + Notify(PSTR("\r\nepinfo is null")); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: ")); +#endif + PrintHex(rcode); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: ")); + PrintHex(bAddress); +#endif + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; + + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; + + if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) { + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the PID and VID we will use known values for the + configuration values for device, interface, endpoints and HID for the PS3 Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint + epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint + epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if( rcode ) + goto FailSetDevTblEntry; + + delay(200);//Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); + if( rcode ) + goto FailSetConf; + + if(PID == PS3_PID || PID == PS3NAVIGATION_PID) + { + if(PID == PS3_PID) { +#ifdef DEBUG + Notify(PSTR("\r\nDualshock 3 Controller Connected")); +#endif + PS3Connected = true; + } else { // must be a navigation controller +#ifdef DEBUG + Notify(PSTR("\r\nNavigation Controller Connected")); +#endif + PS3NavigationConnected = true; + } + /* Set internal bluetooth address and request for data */ + setBdaddr(my_bdaddr); + enable_sixaxis(); + + // Needed for PS3 Dualshock and Navigation commands to work + for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); + + for (uint8_t i = 6; i < 10; i++) + readBuf[i] = 0x7F; // Set the analog joystick values to center position + + setLedOn(LED1); + + timer = millis(); + } + else // must be a Motion controller + { +#ifdef DEBUG + Notify(PSTR("\r\nMotion Controller Connected")); +#endif + PS3MoveConnected = true; + setMoveBdaddr(my_bdaddr); // Set internal bluetooth address + moveSetBulb(Red); + + // Needed for Move commands to work + for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); + + timer = millis(); + } + } + else + goto FailUnknownDevice; + + bPollEnable = true; + Notify(PSTR("\r\n")); + return 0; // successful configuration + + /* diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG + Notify(PSTR("\r\ngetDevDescr:")); +#endif + goto Fail; +FailSetDevTblEntry: +#ifdef DEBUG + Notify(PSTR("\r\nsetDevTblEn:")); +#endif + goto Fail; +FailSetConf: +#ifdef DEBUG + Notify(PSTR("\r\nsetConf:")); +#endif + goto Fail; +FailUnknownDevice: +#ifdef DEBUG + Notify(PSTR("\r\nUnknown Device Connected - VID: ")); + PrintHex(VID); + Notify(PSTR(" PID: ")); + PrintHex(PID); +#endif + goto Fail; +Fail: +#ifdef DEBUG + Notify(PSTR("\r\nPS3 Init Failed, error code: ")); + Serial.print(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t PS3USB::Release() +{ + PS3Connected = false; + PS3MoveConnected = false; + PS3NavigationConnected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} +uint8_t PS3USB::Poll() +{ + if (!bPollEnable) + return 0; + + if(PS3Connected || PS3NavigationConnected) { + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + if(millis() - timer > 100) { // Loop 100ms before processing data + readReport(); +#ifdef PRINTREPORT + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers +#endif + } + } + else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + if (millis() - timer > 4000) // Send at least every 4th second + { + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on + timer = millis(); + } + } + return 0; +} + +void PS3USB::readReport() +{ + if (readBuf == NULL) + return; + if(PS3Connected || PS3NavigationConnected) + ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); + + //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; + } + + OldButtonState = ButtonState; +} + +void PS3USB::printReport() //Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers +{ + if (readBuf == NULL) + return; + for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE;i++) + { + PrintHex(readBuf[i]); + Serial.print(" "); + } + Serial.println(""); +} + +bool PS3USB::getButton(Button b) +{ + if (readBuf == NULL) + return false; + if ((readBuf[(uint16_t)b >> 8] & ((uint8_t)b & 0xff)) > 0) + return true; + else + return false; +} +uint8_t PS3USB::getAnalogButton(AnalogButton a) +{ + if (readBuf == NULL) + return 0; + return (uint8_t)(readBuf[(uint16_t)a]); +} +uint8_t PS3USB::getAnalogHat(AnalogHat a) +{ + if (readBuf == NULL) + return 0; + return (uint8_t)(readBuf[(uint16_t)a]); +} +int32_t PS3USB::getSensor(Sensor a) +{ + if (readBuf == NULL) + return 0; + return ((readBuf[(uint16_t)a] << 8) | readBuf[(uint16_t)a + 1]); +} +double PS3USB::getAngle(Angle a) { + double accXval; + double accYval; + double accZval; + + if(PS3Connected) { + // Data for the Kionix KXPC4 used in the DualShock 3 + const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) + accXval = -((double)getSensor(aX)-zeroG); + accYval = -((double)getSensor(aY)-zeroG); + accZval = -((double)getSensor(aZ)-zeroG); + } + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if (a == Pitch) { + double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; + return angle; + } else { + double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; + return angle; + } +} +bool PS3USB::getStatus(Status c) +{ + if (readBuf == NULL) + return false; + if (readBuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff)) + return true; + return false; +} +String PS3USB::getStatusString() +{ + if (PS3Connected || PS3NavigationConnected) + { + char statusOutput[100]; + + strcpy(statusOutput,"ConnectionStatus: "); + + if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); + else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); + else strcat(statusOutput,"Error"); + + + strcat(statusOutput," - PowerRating: "); + if (getStatus(Charging)) strcat(statusOutput,"Charging"); + else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); + else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); + else if (getStatus(Dying)) strcat(statusOutput,"Dying"); + else if (getStatus(Low)) strcat(statusOutput,"Low"); + else if (getStatus(High)) strcat(statusOutput,"High"); + else if (getStatus(Full)) strcat(statusOutput,"Full"); + else strcat(statusOutput,"Error"); + + strcat(statusOutput," - WirelessStatus: "); + + if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); + else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); + else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); + else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); + else strcat(statusOutput,"Error"); + + return statusOutput; + } +} + +/* Playstation Sixaxis Dualshock and Navigation Controller commands */ +void PS3USB::PS3_Command(uint8_t* data, uint16_t nbytes) +{ + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); +} +void PS3USB::setAllOff() +{ + for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) + writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} +void PS3USB::setRumbleOff() +{ + writeBuf[1] = 0x00; + writeBuf[2] = 0x00;//low mode off + writeBuf[3] = 0x00; + writeBuf[4] = 0x00;//high mode off + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} +void PS3USB::setRumbleOn(Rumble mode) +{ + /* Still not totally sure how it works, maybe something like this instead? + * 3 - duration_right + * 4 - power_right + * 5 - duration_left + * 6 - power_left + */ + if ((mode & 0x30) > 0) + { + writeBuf[1] = 0xfe; + writeBuf[3] = 0xfe; + + if (mode == RumbleHigh) + { + writeBuf[2] = 0;//low mode off + writeBuf[4] = 0xff;//high mode on + } + else + { + writeBuf[2] = 0xff;//low mode on + writeBuf[4] = 0;//high mode off + } + + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); + } +} +void PS3USB::setLedOff(LED a) +{ + writeBuf[9] &= ~((uint8_t)(((uint16_t)a & 0x0f) << 1)); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} +void PS3USB::setLedOn(LED a) +{ + writeBuf[9] |= (uint8_t)(((uint16_t)a & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} +void PS3USB::setLedToggle(LED a) +{ + writeBuf[9] ^= (uint8_t)(((uint16_t)a & 0x0f) << 1); + PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); +} +void PS3USB::setBdaddr(uint8_t* BDADDR) +{ + /* Set the internal bluetooth address */ + uint8_t buf[8]; + buf[0] = 0x01; + buf[1] = 0x00; + for (uint8_t i = 0; i < 6; i++) + buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); +#ifdef DEBUG + Notify(PSTR("\r\nBluetooth Address was set to: ")); + for(int8_t i = 5; i > 0; i--) + { + PrintHex(my_bdaddr[i]); + Serial.print(":"); + } + PrintHex(my_bdaddr[0]); +#endif + return; +} +void PS3USB::enable_sixaxis()//Command used to enable the Dualshock 3 and Navigation controller to send data via USB +{ + uint8_t cmd_buf[4]; + cmd_buf[0] = 0x42;// Special PS3 Controller enable commands + cmd_buf[1] = 0x0c; + cmd_buf[2] = 0x00; + cmd_buf[3] = 0x00; + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); +} + +/* Playstation Move Controller commands */ +void PS3USB::Move_Command(uint8_t* data, uint16_t nbytes) +{ + pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); +} + +void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b)//Use this to set the Color using RGB values +{ + // set the Bulb's values into the write buffer + writeBuf[2] = r; + writeBuf[3] = g; + writeBuf[4] = b; + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); +} +void PS3USB::moveSetBulb(Colors color)//Use this to set the Color using the predefined colors in "enums.h" +{ + moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); +} +void PS3USB::moveSetRumble(uint8_t rumble) +{ +#ifdef DEBUG + if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) + Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%")); +#endif + //set the rumble value into the write buffer + writeBuf[6] = rumble; + + Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); +} +void PS3USB::setMoveBdaddr(uint8_t* BDADDR) +{ + /* Set the internal bluetooth address */ + uint8_t buf[11]; + buf[0] = 0x05; + buf[7] = 0x10; + buf[8] = 0x01; + buf[9] = 0x02; + buf[10] = 0x12; + + for (uint8_t i = 0; i < 6; i++) + buf[i + 1] = BDADDR[i]; + + //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) + pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); +#ifdef DEBUG + Notify(PSTR("\r\nBluetooth Address was set to: ")); + for(int8_t i = 5; i > 0; i--) + { + PrintHex(my_bdaddr[i]); + Serial.print(":"); + } + PrintHex(my_bdaddr[0]); +#endif + return; +} \ No newline at end of file diff --git a/PS3USB.h b/PS3USB.h new file mode 100644 index 00000000..fb8fc25f --- /dev/null +++ b/PS3USB.h @@ -0,0 +1,244 @@ +/* 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 _ps3usb_h_ +#define _ps3usb_h_ + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#include "Usb.h" + +/* PS3 data taken from descriptors */ +#define EP_MAXPKTSIZE 64 // max size for data via USB + +/* Endpoint types */ +#define EP_INTERRUPT 0x03 + +/* Names we give to the 3 ps3 pipes - this is only used for setting the bluetooth address into the ps3 controllers */ +#define PS3_CONTROL_PIPE 0 +#define PS3_OUTPUT_PIPE 1 +#define PS3_INPUT_PIPE 2 + +//PID and VID of the different devices +#define PS3_VID 0x054C // Sony Corporation +#define PS3_PID 0x0268 // PS3 Controller DualShock 3 +#define PS3NAVIGATION_PID 0x042F // Navigation controller +#define PS3MOVE_PID 0x03D5 // Motion controller + +#define PS3_REPORT_BUFFER_SIZE 48 // Size of the output report buffer for the Dualshock and Navigation controllers +#define MOVE_REPORT_BUFFER_SIZE 7 // Size of the output report buffer for the Move Controller + +// used in control endpoint header for HCI Commands +#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE + +// used in control endpoint header for HID Commands +#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define HID_REQUEST_SET_REPORT 0x09 + +#define PS3_MAX_ENDPOINTS 3 + +enum LED +{ + LED1 = 0x01, + LED2 = 0x02, + LED3 = 0x04, + LED4 = 0x08, + + LED5 = 0x09, + LED6 = 0x0A, + LED7 = 0x0C, + LED8 = 0x0D, + LED9 = 0x0E, + LED10 = 0x0F, +}; +enum Colors +{ + //Used to set the colors of the move controller + Red = 0xFF0000,//((255 << 16) | (0 << 8) | 0); + Green = 0xFF00,//((0 << 16) | (255 << 8) | 0); + Blue = 0xFF,//((0 << 16) | (0 << 8) | 255); + + Yellow = 0xFFEB04,//((255 << 16) | (235 << 8) | 4); + Lightblue = 0xFFFF,//((0 << 16) | (255 << 8) | 255); + Purble = 0xFF00FF,//((255 << 16) | (0 << 8) | 255); + + White = 0xFFFFFF,//((255 << 16) | (255 << 8) | 255); + Off = 0x00,//((0 << 16) | (0 << 8) | 0); +}; + +enum Button +{ + // byte location | bit location + + //Sixaxis Dualshcock 3 & Navigation controller + SELECT = (2 << 8) | 0x01, + L3 = (2 << 8) | 0x02, + R3 = (2 << 8) | 0x04, + START = (2 << 8) | 0x08, + UP = (2 << 8) | 0x10, + RIGHT = (2 << 8) | 0x20, + DOWN = (2 << 8) | 0x40, + LEFT = (2 << 8) | 0x80, + + L2 = (3 << 8) | 0x01, + R2 = (3 << 8) | 0x02, + L1 = (3 << 8) | 0x04, + R1 = (3 << 8) | 0x08, + TRIANGLE = (3 << 8) | 0x10, + CIRCLE = (3 << 8) | 0x20, + CROSS = (3 << 8) | 0x40, + SQUARE = (3 << 8) | 0x80, + + PS = (4 << 8) | 0x01, +}; +enum AnalogButton +{ + //Sixaxis Dualshcock 3 & Navigation controller + UP_ANALOG = 14, + RIGHT_ANALOG = 15, + DOWN_ANALOG = 16, + LEFT_ANALOG = 17, + + L2_ANALOG = 18, + R2_ANALOG = 19, + L1_ANALOG = 20, + R1_ANALOG = 21, + TRIANGLE_ANALOG = 22, + CIRCLE_ANALOG = 23, + CROSS_ANALOG = 24, + SQUARE_ANALOG = 25, +}; +enum AnalogHat +{ + LeftHatX = 6, + LeftHatY = 7, + RightHatX = 8, + RightHatY = 9, +}; +enum Sensor +{ + // Sensors inside the Sixaxis Dualshock 3 controller + aX = 41, + aY = 43, + aZ = 45, + gZ = 47, +}; +enum Angle +{ + Pitch = 0x01, + Roll = 0x02, +}; +enum Status +{ + // byte location | bit location + Plugged = (29 << 8) | 0x02, + Unplugged = (29 << 8) | 0x03, + + Charging = (30 << 8) | 0xEE, + NotCharging = (30 << 8) | 0xF1, + Shutdown = (30 << 8) | 0x01, + Dying = (30 << 8) | 0x02, + Low = (30 << 8) | 0x03, + High = (30 << 8) | 0x04, + Full = (30 << 8) | 0x05, + + CableRumble = (31 << 8) | 0x10, // Opperating by USB and rumble is turned on + Cable = (31 << 8) | 0x12, // Opperating by USB and rumble is turned off + BluetoothRumble = (31 << 8) | 0x14, // Opperating by bluetooth and rumble is turned on + Bluetooth = (30 << 8) | 0x16, // Opperating by bluetooth and rumble is turned off +}; +enum Rumble +{ + RumbleHigh = 0x10, + RumbleLow = 0x20, +}; + +class PS3USB : public USBDeviceConfig +{ +public: + 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 + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + virtual bool isReady() { return bPollEnable; }; + + void setBdaddr(uint8_t* BDADDR); + void setMoveBdaddr(uint8_t* BDADDR); + + /* PS3 Controller Commands */ + bool getButton(Button b); + uint8_t getAnalogButton(AnalogButton a); + uint8_t getAnalogHat(AnalogHat a); + int32_t getSensor(Sensor a); + double getAngle(Angle a); + bool getStatus(Status c); + String getStatusString(); + + /* Commands for Dualshock 3 and Navigation controller */ + void setAllOff(); + void setRumbleOff(); + void setRumbleOn(Rumble mode); + void setLedOff(LED a); + void setLedOn(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 + void moveSetBulb(Colors color);//Use this to set the Color using the predefined colors in "enum Colors" + 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 + bool PS3NavigationConnected;// Variable used to indicate if the navigation 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 + +protected: + /* mandatory members */ + USB *pUsb; + uint8_t bAddress; // device address + EpInfo epInfo[PS3_MAX_ENDPOINTS]; //endpoint info structure + +private: + bool bPollEnable; + + uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values + + uint32_t ButtonState; + uint32_t OldButtonState; + + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in PS3BT.cpp + 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 PS3_Command(uint8_t* data, uint16_t nbytes); + void enable_sixaxis();//Command used to enable the Dualshock 3 and Navigation controller to send data via USB + void Move_Command(uint8_t* data, uint16_t nbytes); +}; +#endif diff --git a/examples/PS3/PS3USB/PS3USB.ino b/examples/PS3/PS3USB/PS3USB.ino new file mode 100644 index 00000000..0741d220 --- /dev/null +++ b/examples/PS3/PS3USB/PS3USB.ino @@ -0,0 +1,188 @@ +/* + Example sketch for the PS3 USB library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +USB Usb; +/* You can create the instance of the class in two ways */ +PS3USB PS3(&Usb); // This will just create the instance +//PS3USB PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch + +boolean printAngle; +uint8_t state = 0; + +void setup() { + Serial.begin(115200); + + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while(1); //halt + } + Serial.print(F("\r\nPS3 USB Library Started")); +} +void loop() { + Usb.Task(); + + if(PS3.PS3Connected || PS3.PS3NavigationConnected) { + if(PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + if(PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117) { + Serial.print(F("LeftHatX: ")); + Serial.print(PS3.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } + if(PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117) { + Serial.print(F("LeftHatY: ")); + Serial.print(PS3.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } + if(PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117) { + Serial.print(F("RightHatX: ")); + Serial.print(PS3.getAnalogHat(RightHatX)); + Serial.print("\t"); + } + if(PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) { + Serial.print(F("RightHatY: ")); + Serial.print(PS3.getAnalogHat(RightHatY)); + } + Serial.println(""); + } + + // Analog button values can be read from almost all buttons + if(PS3.getAnalogButton(L2_ANALOG) > 0 || PS3.getAnalogButton(R2_ANALOG) > 0) { + if(PS3.getAnalogButton(L2_ANALOG) > 0) { + Serial.print(F("L2: ")); + Serial.print(PS3.getAnalogButton(L2_ANALOG)); + Serial.print("\t"); + } + if(PS3.getAnalogButton(R2_ANALOG) > 0) { + Serial.print(F("R2: ")); + Serial.print(PS3.getAnalogButton(R2_ANALOG)); + } + Serial.println(""); + } + + if(PS3.buttonPressed) + { + Serial.print(F("PS3 Controller")); + + if(PS3.getButton(PS)) + Serial.print(F(" - PS")); + + if(PS3.getButton(TRIANGLE)) + Serial.print(F(" - Traingle")); + if(PS3.getButton(CIRCLE)) + Serial.print(F(" - Circle")); + if(PS3.getButton(CROSS)) + Serial.print(F(" - Cross")); + if(PS3.getButton(SQUARE)) + Serial.print(F(" - Square")); + + if(PS3.getButton(UP)) { + Serial.print(F(" - Up")); + PS3.setAllOff(); + PS3.setLedOn(LED4); + } + if(PS3.getButton(RIGHT)) { + Serial.print(F(" - Right")); + PS3.setAllOff(); + PS3.setLedOn(LED1); + } + if(PS3.getButton(DOWN)) { + Serial.print(F(" - Down")); + PS3.setAllOff(); + PS3.setLedOn(LED2); + } + if(PS3.getButton(LEFT)) { + Serial.print(F(" - Left")); + PS3.setAllOff(); + PS3.setLedOn(LED3); + } + + if(PS3.getButton(L1)) + Serial.print(F(" - L1")); + //if(PS3.getButton(L2)) + //Serial.print(F(" - L2")); + if(PS3.getButton(L3)) + Serial.print(F(" - L3")); + if(PS3.getButton(R1)) + Serial.print(F(" - R1")); + //if(PS3.getButton(R2)) + //Serial.print(F(" - R2")); + if(PS3.getButton(R3)) + Serial.print(F(" - R3")); + + if(PS3.getButton(SELECT)) { + Serial.print(F(" - Select - ")); + Serial.print(PS3.getStatusString()); + } + if(PS3.getButton(START)) { + Serial.print(F(" - Start")); + printAngle = !printAngle; + while(PS3.getButton(START)) + Usb.Task(); + } + Serial.println(""); + } + if(printAngle) { + Serial.print(F("Pitch: ")); + Serial.print(PS3.getAngle(Pitch)); + Serial.print(F("\tRoll: ")); + Serial.println(PS3.getAngle(Roll)); + } + } + else if(PS3.PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB + switch(state) { + case 0: + PS3.moveSetRumble(0); + PS3.moveSetBulb(Off); + state = 1; + break; + + case 1: + PS3.moveSetRumble(75); + PS3.moveSetBulb(Red); + state = 2; + break; + + case 2: + PS3.moveSetRumble(125); + PS3.moveSetBulb(Green); + state = 3; + break; + + case 3: + PS3.moveSetRumble(150); + PS3.moveSetBulb(Blue); + state = 4; + break; + + case 4: + PS3.moveSetRumble(175); + PS3.moveSetBulb(Yellow); + state = 5; + break; + + case 5: + PS3.moveSetRumble(200); + PS3.moveSetBulb(Lightblue); + state = 6; + break; + + case 6: + PS3.moveSetRumble(225); + PS3.moveSetBulb(Purble); + state = 7; + break; + + case 7: + PS3.moveSetRumble(250); + PS3.moveSetBulb(White); + state = 0; + break; + } + delay(1000); + } +} + From d7464b16b4e46ed15644c13abefd5b772c2ee2f0 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 26 May 2012 10:15:56 +0200 Subject: [PATCH 09/20] Updated the readme --- PS3BTREADME => PS3README | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename PS3BTREADME => PS3README (75%) diff --git a/PS3BTREADME b/PS3README similarity index 75% rename from PS3BTREADME rename to PS3README index 2004ef7f..161b1bf8 100644 --- a/PS3BTREADME +++ b/PS3README @@ -1,13 +1,13 @@ -The PS3BT.cpp PS3BT.h was developed by Kristian Lauszus +The PS3BT.cpp, PS3BT.h, PS3USB.cpp, and PS3USB.h were developed by Kristian Lauszus For more information regarding the PS3 protocol etc. visit my blog at: http://blog.tkjelectronics.dk/ or send me an email at kristianl at tkjelectronics dot dk. You could also visit the official wiki: https://github.com/TKJElectronics/USB_Host_Shield_2.0/wiki for information. All three PS3 Controllers are supported (Dualshock 3-, Navigation-, and Motioncontroller). -They communicate with the Arduino via Bluetooth using the USB Host Shield from http://www.circuitsathome.com/ +They communicate with the Arduino via Bluetooth or USB using the USB Host Shield from http://www.circuitsathome.com/ A special thanks go to the following people: -"Richard Ibbotson" who made this guide: http://www.circuitsathome.com/mcu/ps3-and-wiimote-game-controllers-on-the-arduino-host-shield-part-1 +"Richard Ibbotson" who made this excellent guide: http://www.circuitsathome.com/mcu/ps3-and-wiimote-game-controllers-on-the-arduino-host-shield-part-1 - It inspired me to get starting and had a lot of good information for the USB communication "Tomoyuki Tanaka" for releasing his code for the Arduino USB Host shield connected to the wiimote: http://www.circuitsathome.com/mcu/rc-car-controlled-by-wii-remote-on-arduino From 67a89697110d19b0f19d7d7b214eaecf14d1800d Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sun, 27 May 2012 16:12:27 +0200 Subject: [PATCH 10/20] A few minor changes --- PS3USB.cpp | 52 ++++++++++++++++++++++++++-------------------------- PS3USB.h | 7 ++----- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/PS3USB.cpp b/PS3USB.cpp index ed718110..5fa13abd 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -74,7 +74,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) // get memory address of USB device address pool AddressPool &addrPool = pUsb->GetAddressPool(); #ifdef EXTRADEBUG - Notify(PSTR("\r\nPS3BT Init")); + Notify(PSTR("\r\nPS3USB Init")); #endif // check if address has already been assigned to an instance if (bAddress) @@ -209,17 +209,14 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) /* Set internal bluetooth address and request for data */ setBdaddr(my_bdaddr); enable_sixaxis(); + setLedOn(LED1); // Needed for PS3 Dualshock and Navigation commands to work for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); for (uint8_t i = 6; i < 10; i++) - readBuf[i] = 0x7F; // Set the analog joystick values to center position - - setLedOn(LED1); - - timer = millis(); + readBuf[i] = 0x7F; // Set the analog joystick values to center position } else // must be a Motion controller { @@ -232,9 +229,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) // Needed for Move commands to work for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) - writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); - - timer = millis(); + writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); } } else @@ -242,6 +237,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) bPollEnable = true; Notify(PSTR("\r\n")); + timer = millis(); return 0; // successful configuration /* diagnostic messages */ @@ -377,34 +373,37 @@ uint8_t PS3USB::getAnalogHat(AnalogHat a) return 0; return (uint8_t)(readBuf[(uint16_t)a]); } -int32_t PS3USB::getSensor(Sensor a) +uint16_t PS3USB::getSensor(Sensor a) { if (readBuf == NULL) return 0; return ((readBuf[(uint16_t)a] << 8) | readBuf[(uint16_t)a + 1]); } -double PS3USB::getAngle(Angle a) { - double accXval; - double accYval; - double accZval; - +double PS3USB::getAngle(Angle a) { if(PS3Connected) { + double accXval; + double accYval; + double accZval; + // Data for the Kionix KXPC4 used in the DualShock 3 const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) accXval = -((double)getSensor(aX)-zeroG); accYval = -((double)getSensor(aY)-zeroG); accZval = -((double)getSensor(aZ)-zeroG); - } - // Convert to 360 degrees resolution - // atan2 outputs the value of -π to π (radians) - // We are then converting it to 0 to 2π and then to degrees - if (a == Pitch) { - double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; - return angle; - } else { - double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; - return angle; - } + + // Convert to 360 degrees resolution + // atan2 outputs the value of -π to π (radians) + // We are then converting it to 0 to 2π and then to degrees + if (a == Pitch) { + double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; + return angle; + } else { + double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; + return angle; + } + } else + return 0; + } bool PS3USB::getStatus(Status c) { @@ -428,6 +427,7 @@ String PS3USB::getStatusString() strcat(statusOutput," - PowerRating: "); + if (getStatus(Charging)) strcat(statusOutput,"Charging"); else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); diff --git a/PS3USB.h b/PS3USB.h index fb8fc25f..21550aea 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -46,9 +46,6 @@ #define PS3_REPORT_BUFFER_SIZE 48 // Size of the output report buffer for the Dualshock and Navigation controllers #define MOVE_REPORT_BUFFER_SIZE 7 // Size of the output report buffer for the Move Controller -// used in control endpoint header for HCI Commands -#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE - // used in control endpoint header for HID Commands #define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE #define HID_REQUEST_SET_REPORT 0x09 @@ -163,7 +160,7 @@ enum Status CableRumble = (31 << 8) | 0x10, // Opperating by USB and rumble is turned on Cable = (31 << 8) | 0x12, // Opperating by USB and rumble is turned off BluetoothRumble = (31 << 8) | 0x14, // Opperating by bluetooth and rumble is turned on - Bluetooth = (30 << 8) | 0x16, // Opperating by bluetooth and rumble is turned off + Bluetooth = (31 << 8) | 0x16, // Opperating by bluetooth and rumble is turned off }; enum Rumble { @@ -190,7 +187,7 @@ public: bool getButton(Button b); uint8_t getAnalogButton(AnalogButton a); uint8_t getAnalogHat(AnalogHat a); - int32_t getSensor(Sensor a); + uint16_t getSensor(Sensor a); double getAngle(Angle a); bool getStatus(Status c); String getStatusString(); From 91fbbfad3b72349628778514dee48a32765fbce8 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Mon, 28 May 2012 21:02:43 +0200 Subject: [PATCH 11/20] Fixed some errors --- PS3BT.cpp | 34 +++++++++++++++++----------------- PS3BT.h | 2 +- PS3USB.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index 78712b6b..e47db9fe 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -464,25 +464,25 @@ int32_t PS3BT::getSensor(Sensor a) return 0; if (a == aX || a == aY || a == aZ || a == gZ) return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]); - else if (a == mXmove || a == mYmove || a == mZmove) + else if (a == mXmove || a == mYmove || a == mZmove) // These are all 12-bits long { // Might not be correct, haven't tested it yet - if (a == mXmove) + /*if (a == mXmove) return ((l2capinbuf[(uint16_t)a + 1] << 0x04) | (l2capinbuf[(uint16_t)a] << 0x0C)); - //return (((unsigned char)l2capinbuf[(unsigned int)a + 1]) | (((unsigned char)l2capinbuf[(unsigned int)a] & 0x0F)) << 8); else if (a == mYmove) return ((l2capinbuf[(uint16_t)a + 1] & 0xF0) | (l2capinbuf[(uint16_t)a] << 0x08)); - //return (((unsigned char)l2capinbuf[(unsigned int)a + 1]) | (((unsigned char)l2capinbuf[(unsigned int)a] & 0x0F)) << 8); else if (a == mZmove) - return ((l2capinbuf[(uint16_t)a + 1] << 0x0F) | (l2capinbuf[(uint16_t)a] << 0x0C)); - //return ((((unsigned char)l2capinbuf[(unsigned int)a + 1] & 0xF0) >> 4) | ((unsigned char)l2capinbuf[(unsigned int)a] << 4)); - else - return 0; + return ((l2capinbuf[(uint16_t)a + 1] << 0x0F) | (l2capinbuf[(uint16_t)a] << 0x0C)); + */ + if (a == mXmove || a == mYmove) + return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1])); + else // mZmove + return ((l2capinbuf[(uint16_t)a] << 4) | (l2capinbuf[(uint16_t)a + 1] >> 4)); } - else if (a == tempMove) - return (((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4) | (l2capinbuf[(uint16_t)a] << 4)); + else if (a == tempMove) // The tempearature is 12 bits long too + return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4)); else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove - return ((l2capinbuf[(uint16_t)a + 1] << 8) | l2capinbuf[(uint16_t)a]); + return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8)); } double PS3BT::getAngle(Angle a) { double accXval; @@ -946,14 +946,14 @@ void PS3BT::ACL_event_task() Notify(PSTR(" Identifier: ")); PrintHex(l2capinbuf[9]); */ - if ((l2capinbuf[13] | l2capinbuf[12]) == L2CAP_PSM_HID_CTRL) + if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == L2CAP_PSM_HID_CTRL) { identifier = l2capinbuf[9]; control_scid[0] = l2capinbuf[14]; control_scid[1] = l2capinbuf[15]; l2cap_event_flag |= L2CAP_EV_CONTROL_CONNECTION_REQUEST; } - else if ((l2capinbuf[13] | l2capinbuf[12]) == L2CAP_PSM_HID_INTR) + else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == L2CAP_PSM_HID_INTR) { identifier = l2capinbuf[9]; interrupt_scid[0] = l2capinbuf[14]; @@ -1000,7 +1000,7 @@ void PS3BT::ACL_event_task() if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Request: Disconnected Control")); + Notify(PSTR("\r\nDisconnect Request: Control Channel")); #endif identifier = l2capinbuf[9]; l2cap_disconnection_response(identifier,control_dcid,control_scid); @@ -1008,7 +1008,7 @@ void PS3BT::ACL_event_task() else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { #ifdef DEBUG - Notify(PSTR("\r\nDisconnected Request: Disconnected Interrupt")); + Notify(PSTR("\r\nDisconnect Request: Interrupt Channel")); #endif identifier = l2capinbuf[9]; l2cap_disconnection_response(identifier,interrupt_dcid,interrupt_scid); @@ -1018,13 +1018,13 @@ void PS3BT::ACL_event_task() { if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { - //Serial.print("\r\nDisconnected Response: Disconnected Control"); + //Serial.print("\r\nDisconnect Response: Control Channel"); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_EV_CONTROL_DISCONNECT_RESPONSE; } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { - //Serial.print("\r\nDisconnected Response: Disconnected Interrupt"); + //Serial.print("\r\nDisconnect Response: Interrupt Channel"); identifier = l2capinbuf[9]; l2cap_event_flag |= L2CAP_EV_INTERRUPT_DISCONNECT_RESPONSE; } diff --git a/PS3BT.h b/PS3BT.h index 2e0e4fad..db67f9da 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -413,7 +413,7 @@ private: uint32_t timerHID;// timer used see if there has to be a delay before a new HID command uint32_t timerBulbRumble;// used to continuously set PS3 Move controller Bulb and rumble values - uint8_t my_bdaddr[6]; //Change to your dongles Bluetooth address in PS3BT.cpp + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor uint8_t hcibuf[BULK_MAXPKTSIZE];//General purpose buffer for hci data uint8_t l2capinbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap in data uint8_t l2capoutbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap out data diff --git a/PS3USB.h b/PS3USB.h index 21550aea..6e34dba8 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -226,7 +226,7 @@ private: uint32_t ButtonState; uint32_t OldButtonState; - uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in PS3BT.cpp + uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data From 9d6eb2d69bcfc49217296ba5702f7c68037cb7bf Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Mon, 28 May 2012 21:53:20 +0200 Subject: [PATCH 12/20] Created same syntax for Move controller --- PS3BT.cpp | 15 ++++++++--- PS3BT.h | 35 ++++++++++++++---------- PS3USB.h | 22 +++++++-------- examples/PS3/PS3BT/PS3BT.ino | 52 +++++++++++++++++++++--------------- keywords.txt | 13 +++------ 5 files changed, 76 insertions(+), 61 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index e47db9fe..c369e3c9 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -441,10 +441,17 @@ bool PS3BT::getButton(Button b) { if (l2capinbuf == NULL) return false; - if ((l2capinbuf[(uint16_t)b >> 8] & ((uint8_t)b & 0xff)) > 0) - return true; - else - return false; + if(PS3MoveConnected) { + if((l2capinbuf[((uint16_t)b >> 8)-1] & ((uint8_t)b & 0xff))) // All the buttons locations are shifted one back on the Move controller + return true; + else + return false; + } else { + if((l2capinbuf[(uint16_t)b >> 8] & ((uint8_t)b & 0xff))) + return true; + else + return false; + } } uint8_t PS3BT::getAnalogButton(AnalogButton a) { diff --git a/PS3BT.h b/PS3BT.h index db67f9da..3d071dfc 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -179,24 +179,24 @@ enum LED }; enum Colors { - //Used to set the colors of the move controller - Red = 0xFF0000,//((255 << 16) | (0 << 8) | 0); - Green = 0xFF00,//((0 << 16) | (255 << 8) | 0); - Blue = 0xFF,//((0 << 16) | (0 << 8) | 255); + // Used to set the colors of the move controller + Red = 0xFF0000, // r = 255, g = 0, b = 0 + Green = 0xFF00, // r = 0, g = 255, b = 0 + Blue = 0xFF, // r = 0, g = 0, b = 255 - Yellow = 0xFFEB04,//((255 << 16) | (235 << 8) | 4); - Lightblue = 0xFFFF,//((0 << 16) | (255 << 8) | 255); - Purble = 0xFF00FF,//((255 << 16) | (0 << 8) | 255); + Yellow = 0xFFEB04, // r = 255, g = 235, b = 4 + Lightblue = 0xFFFF, // r = 0, g = 255, b = 255 + Purble = 0xFF00FF, // r = 255, g = 0, b = 255 - White = 0xFFFFFF,//((255 << 16) | (255 << 8) | 255); - Off = 0x00,//((0 << 16) | (0 << 8) | 0); + White = 0xFFFFFF, // r = 255, g = 255, b = 255 + Off = 0x00, // r = 0, g = 0, b = 0 }; enum Button { // byte location | bit location - //Sixaxis Dualshcock 3 & Navigation controller + // Sixaxis Dualshcock 3 & Navigation controller SELECT = (11 << 8) | 0x01, L3 = (11 << 8) | 0x02, R3 = (11 << 8) | 0x04, @@ -217,7 +217,13 @@ enum Button PS = (13 << 8) | 0x01, - //Playstation Move Controller + MOVE = (13/*12*/ << 8) | 0x08, // covers 12 bits - we only need to read the top 8 + T = (13/*12*/ << 8) | 0x10, // covers 12 bits - we only need to read the top 8 + + + // These are the true locations for the Move controller, but to make the same syntax for all controllers, it is handled by getButton() +/* + // Playstation Move Controller SELECT_MOVE = (10 << 8) | 0x01, START_MOVE = (10 << 8) | 0x08, @@ -227,8 +233,9 @@ enum Button SQUARE_MOVE = (11 << 8) | 0x80, PS_MOVE = (12 << 8) | 0x01, - MOVE_MOVE = (12 << 8) | 0x08,//covers 12 bits - we only need to read the top 8 - T_MOVE = (12 << 8) | 0x10,//covers 12 bits - we only need to read the top 8 + MOVE_MOVE = (12 << 8) | 0x08, // covers 12 bits - we only need to read the top 8 + T_MOVE = (12 << 8) | 0x10, // covers 12 bits - we only need to read the top 8 + */ }; enum AnalogButton { @@ -248,7 +255,7 @@ enum AnalogButton SQUARE_ANALOG = 34, //Playstation Move Controller - T_MOVE_ANALOG = 15,//Both at byte 14 (last reading) and byte 15 (current reading) + T_ANALOG = 15, // Both at byte 14 (last reading) and byte 15 (current reading) }; enum AnalogHat { diff --git a/PS3USB.h b/PS3USB.h index 6e34dba8..a89faae7 100644 --- a/PS3USB.h +++ b/PS3USB.h @@ -68,24 +68,24 @@ enum LED }; enum Colors { - //Used to set the colors of the move controller - Red = 0xFF0000,//((255 << 16) | (0 << 8) | 0); - Green = 0xFF00,//((0 << 16) | (255 << 8) | 0); - Blue = 0xFF,//((0 << 16) | (0 << 8) | 255); + // Used to set the colors of the move controller + Red = 0xFF0000, // r = 255, g = 0, b = 0 + Green = 0xFF00, // r = 0, g = 255, b = 0 + Blue = 0xFF, // r = 0, g = 0, b = 255 - Yellow = 0xFFEB04,//((255 << 16) | (235 << 8) | 4); - Lightblue = 0xFFFF,//((0 << 16) | (255 << 8) | 255); - Purble = 0xFF00FF,//((255 << 16) | (0 << 8) | 255); + Yellow = 0xFFEB04, // r = 255, g = 235, b = 4 + Lightblue = 0xFFFF, // r = 0, g = 255, b = 255 + Purble = 0xFF00FF, // r = 255, g = 0, b = 255 - White = 0xFFFFFF,//((255 << 16) | (255 << 8) | 255); - Off = 0x00,//((0 << 16) | (0 << 8) | 0); + White = 0xFFFFFF, // r = 255, g = 255, b = 255 + Off = 0x00, // r = 0, g = 0, b = 0 }; enum Button { // byte location | bit location - //Sixaxis Dualshcock 3 & Navigation controller + // Sixaxis Dualshcock 3 & Navigation controller SELECT = (2 << 8) | 0x01, L3 = (2 << 8) | 0x02, R3 = (2 << 8) | 0x04, @@ -108,7 +108,7 @@ enum Button }; enum AnalogButton { - //Sixaxis Dualshcock 3 & Navigation controller + // Sixaxis Dualshcock 3 & Navigation controller UP_ANALOG = 14, RIGHT_ANALOG = 15, DOWN_ANALOG = 16, diff --git a/examples/PS3/PS3BT/PS3BT.ino b/examples/PS3/PS3BT/PS3BT.ino index 7830aa01..74d911f9 100644 --- a/examples/PS3/PS3BT/PS3BT.ino +++ b/examples/PS3/PS3BT/PS3BT.ino @@ -79,21 +79,29 @@ void loop() Serial.print(F(" - Square")); if(PS3.getButton(UP)) { - Serial.print(F(" - Up")); - PS3.setAllOff(); - PS3.setLedOn(LED4); + Serial.print(F(" - Up")); + if(PS3.PS3Connected) { + PS3.setAllOff(); + PS3.setLedOn(LED4); + } } if(PS3.getButton(RIGHT)) { Serial.print(F(" - Right")); - PS3.setAllOff(); - PS3.setLedOn(LED1); + if(PS3.PS3Connected) { + PS3.setAllOff(); + PS3.setLedOn(LED1); + } } if(PS3.getButton(DOWN)) { Serial.print(F(" - Down")); - PS3.setAllOff(); - PS3.setLedOn(LED2); + if(PS3.PS3Connected) { + PS3.setAllOff(); + PS3.setLedOn(LED2); + } } if(PS3.getButton(LEFT)) { - Serial.print(F(" - Left")); - PS3.setAllOff(); - PS3.setLedOn(LED3); + Serial.print(F(" - Left")); + if(PS3.PS3Connected) { + PS3.setAllOff(); + PS3.setLedOn(LED3); + } } if(PS3.getButton(L1)) @@ -130,39 +138,39 @@ void loop() } else if(PS3.PS3MoveConnected) { - if(PS3.getAnalogButton(T_MOVE_ANALOG) > 0) { + if(PS3.getAnalogButton(T_ANALOG) > 0) { Serial.print(F("T: ")); - Serial.println(PS3.getAnalogButton(T_MOVE_ANALOG)); + Serial.println(PS3.getAnalogButton(T_ANALOG)); } if(PS3.buttonPressed) { Serial.print(F("PS3 Move Controller")); - if(PS3.getButton(PS_MOVE)) { + if(PS3.getButton(PS)) { Serial.print(F(" - PS")); PS3.disconnect(); } else { - if(PS3.getButton(SELECT_MOVE)) { + if(PS3.getButton(SELECT)) { Serial.print(F(" - Select")); printTemperature = !printTemperature; - while(PS3.getButton(SELECT_MOVE)) + while(PS3.getButton(SELECT)) Usb.Task(); - } if(PS3.getButton(START_MOVE)) { + } if(PS3.getButton(START)) { Serial.print(F(" - Start")); printAngle = !printAngle; - while(PS3.getButton(START_MOVE)) + while(PS3.getButton(START)) Usb.Task(); - } if(PS3.getButton(TRIANGLE_MOVE)) { + } if(PS3.getButton(TRIANGLE)) { Serial.print(F(" - Triangle")); PS3.moveSetBulb(Red); - } if(PS3.getButton(CIRCLE_MOVE)) { + } if(PS3.getButton(CIRCLE)) { Serial.print(F(" - Circle")); PS3.moveSetBulb(Green); - } if(PS3.getButton(SQUARE_MOVE)) { + } if(PS3.getButton(SQUARE)) { Serial.print(F(" - Square")); PS3.moveSetBulb(Blue); - } if(PS3.getButton(CROSS_MOVE)) { + } if(PS3.getButton(CROSS)) { Serial.print(F(" - Cross")); PS3.moveSetBulb(Yellow); - } if(PS3.getButton(MOVE_MOVE)) { + } if(PS3.getButton(MOVE)) { PS3.moveSetBulb(Off); Serial.print(F(" - Move")); Serial.print(F(" - ")); diff --git a/keywords.txt b/keywords.txt index 89597cf3..20afc467 100644 --- a/keywords.txt +++ b/keywords.txt @@ -82,15 +82,8 @@ CIRCLE LITERAL1 CROSS LITERAL1 SQUARE LITERAL1 PS LITERAL1 -SELECT_MOVE LITERAL1 -START_MOVE LITERAL1 -TRIANGLE_MOVE LITERAL1 -CIRCLE_MOVE LITERAL1 -CROSS_MOVE LITERAL1 -SQUARE_MOVE LITERAL1 -PS_MOVE LITERAL1 -MOVE_MOVE LITERAL1 -T_MOVE LITERAL1 +MOVE LITERAL1 +T LITERAL1 UP_ANALOG LITERAL1 RIGHT_ANALOG LITERAL1 @@ -104,7 +97,7 @@ TRIANGLE_ANALOG LITERAL1 CIRCLE_ANALOG LITERAL1 CROSS_ANALOG LITERAL1 SQUARE_ANALOG LITERAL1 -T_MOVE_ANALOG LITERAL1 +T_ANALOG LITERAL1 LeftHatX LITERAL1 LeftHatY LITERAL1 From b07aac63e1e708bd8fa79bc991627b197e82e973 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Wed, 30 May 2012 23:55:07 +0200 Subject: [PATCH 13/20] Minor update --- PS3USB.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PS3USB.cpp b/PS3USB.cpp index 5fa13abd..26e7f49d 100644 --- a/PS3USB.cpp +++ b/PS3USB.cpp @@ -313,8 +313,8 @@ void PS3USB::readReport() { if (readBuf == NULL) return; - if(PS3Connected || PS3NavigationConnected) - ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); + + ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); //Notify(PSTR("\r\nButtonState"); //PrintHex(ButtonState); From 053786b12510056dd9417211cd92fe63e51604d2 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Fri, 1 Jun 2012 17:27:21 +0200 Subject: [PATCH 14/20] Updated getAngle() function --- PS3BT.cpp | 21 ++++----------------- PS3BT.h | 2 +- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index c369e3c9..a694eec4 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -465,7 +465,7 @@ uint8_t PS3BT::getAnalogHat(AnalogHat a) return 0; return (uint8_t)(l2capinbuf[(uint16_t)a]); } -int32_t PS3BT::getSensor(Sensor a) +int16_t PS3BT::getSensor(Sensor a) { if (l2capinbuf == NULL) return 0; @@ -505,22 +505,9 @@ double PS3BT::getAngle(Angle a) { } else if(PS3MoveConnected) { // It's a Kionix KXSC4 inside the Motion controller const uint16_t zeroG = 0x8000; - accXval = getSensor(aXmove); - accYval = getSensor(aYmove); - accZval = getSensor(aZmove); - - if(accXval < 0) - accXval += zeroG; - else - accXval -= zeroG; - if(accYval < 0) - accYval += zeroG; - else - accYval -= zeroG; - if(accZval < 0) - accZval += zeroG; - else - accZval -= zeroG; + accXval = -(int16_t)(getSensor(aXmove)-zeroG); + accYval = (int16_t)(getSensor(aYmove)-zeroG); + accZval = (int16_t)(getSensor(aZmove)-zeroG); } // Convert to 360 degrees resolution diff --git a/PS3BT.h b/PS3BT.h index 3d071dfc..618747ec 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -349,7 +349,7 @@ public: bool getButton(Button b); uint8_t getAnalogButton(AnalogButton a); uint8_t getAnalogHat(AnalogHat a); - int32_t getSensor(Sensor a); + int16_t getSensor(Sensor a); double getAngle(Angle a); bool getStatus(Status c); String getStatusString(); From d251a48fb1402c0913c3428c9da0a7018faed66b Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Fri, 1 Jun 2012 18:47:15 +0200 Subject: [PATCH 15/20] Added getTemperature() --- PS3BT.cpp | 13 +++++++++++++ PS3BT.h | 1 + examples/PS3/PS3BT/PS3BT.ino | 17 ++--------------- keywords.txt | 1 + 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index a694eec4..d23adb76 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -521,6 +521,19 @@ double PS3BT::getAngle(Angle a) { return angle; } } +String PS3BT::getTemperature() { + if(PS3MoveConnected) { + int16_t input = getSensor(tempMove); + + String output = String(input/100); + output += "."; + if(input%100 < 10) + output += "0"; + output += String(input%100); + + return output; + } +} bool PS3BT::getStatus(Status c) { if (l2capinbuf == NULL) diff --git a/PS3BT.h b/PS3BT.h index 618747ec..ae038dad 100644 --- a/PS3BT.h +++ b/PS3BT.h @@ -353,6 +353,7 @@ public: double getAngle(Angle a); bool getStatus(Status c); String getStatusString(); + String getTemperature(); void disconnect(); // use this void to disconnect any of the controllers /* HID Commands */ diff --git a/examples/PS3/PS3BT/PS3BT.ino b/examples/PS3/PS3BT/PS3BT.ino index 74d911f9..122d984a 100644 --- a/examples/PS3/PS3BT/PS3BT.ino +++ b/examples/PS3/PS3BT/PS3BT.ino @@ -189,21 +189,8 @@ void loop() Serial.println(PS3.getAngle(Roll)); } else if(printTemperature) { - String templow; - String temphigh; - String input = String(PS3.getSensor(tempMove)); - - if (input.length() > 3) { - temphigh = input.substring(0, 2); - templow = input.substring(2); - } else { - temphigh = input.substring(0, 1); - templow = input.substring(1); - } - Serial.print(F("Temperature: ")); - Serial.print(temphigh); - Serial.print(F(".")); - Serial.println(templow); + Serial.print(F("Temperature: ")); + Serial.println(PS3.getTemperature()); } } delay(1); diff --git a/keywords.txt b/keywords.txt index 20afc467..de987ded 100644 --- a/keywords.txt +++ b/keywords.txt @@ -22,6 +22,7 @@ getSensor KEYWORD2 getAngle KEYWORD2 getStatus KEYWORD2 getStatusString KEYWORD2 +getTemperature KEYWORD2 disconnect KEYWORD2 setAllOff KEYWORD2 From 0ccffe946c0a039d0094311c8d0038b487bf0019 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 2 Jun 2012 14:49:55 +0200 Subject: [PATCH 16/20] Added support for Arduino Leonardo The Teensy 2.0 is no longer the default, as both the Leonardo and Teensy 2.0 is using the ATmega32u4. To use the Teensy 2.0 you have to uncomment "#define BOARD_TEENSY" in avrpins.h --- avrpins.h | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/avrpins.h b/avrpins.h index bb41602c..99dbcf7f 100644 --- a/avrpins.h +++ b/avrpins.h @@ -23,6 +23,8 @@ e-mail : support@circuitsathome.com /* Uncomment the following if you have Arduino Mega ADK board with MAX3421e built-in */ //#define BOARD_MEGA_ADK +/* Uncomment the following if you are using a Teensy 2.0 */ +//#define BOARD_TEENSY #include @@ -501,7 +503,47 @@ template #endif // "Classic" Arduino pin numbers -#if defined(__AVR_ATmega32U4__) +#if !defined(BOARD_TEENSY) && defined(__AVR_ATmega32U4__) +// Arduino Leonardo pin numbers + +#define P0 Pd2 // D0 - PD2 +#define P1 Pd3 // D1 - PD3 +#define P2 Pd1 // D2 - PD1 +#define P3 Pd0 // D3 - PD0 +#define P4 Pd4 // D4 - PD4 +#define P5 Pc6 // D5 - PC6 +#define P6 Pd7 // D6 - PD7 +#define P7 Pe6 // D7 - PE6 + +#define P8 Pb4 // D8 - PB4 +#define P9 Pb5 // D9 - PB5 +#define P10 Pb6 // D10 - PB6 +#define P11 Pb7 // D11 - PB7 +#define P12 Pd6 // D12 - PD6 +#define P13 Pc7 // D13 - PC7 + +#define P14 Pb3 // D14 - MISO - PB3 +#define P15 Pb1 // D15 - SCK - PB1 +#define P16 Pb2 // D16 - MOSI - PB2 +#define P17 Pb0 // D17 - SS - PB0 + +#define P18 Pf7 // D18 - A0 - PF7 +#define P19 Pf6 // D19 - A1 - PF6 +#define P20 Pf5 // D20 - A2 - PF5 +#define P21 Pf4 // D21 - A3 - PF4 +#define P22 Pf1 // D22 - A4 - PF1 +#define P23 Pf0 // D23 - A5 - PF0 + +#define P24 Pd4 // D24 / D4 - A6 - PD4 +#define P25 Pd7 // D25 / D6 - A7 - PD7 +#define P26 Pb4 // D26 / D8 - A8 - PB4 +#define P27 Pb5 // D27 / D9 - A9 - PB5 +#define P28 Pb6 // D28 / D10 - A10 - PB6 +#define P29 Pd6 // D29 / D12 - A11 - PD6 + +#endif // Arduino Leonardo pin numbers + +#if defined(BOARD_TEENSY) && defined(__AVR_ATmega32U4__) // Teensy 2.0 pin numbers // http://www.pjrc.com/teensy/pinout.html #define P0 Pb0 From 9460daf941d3db84a9aa33cd30c32be654b29102 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Fri, 22 Jun 2012 22:41:02 +0200 Subject: [PATCH 17/20] Check microcontroller type before defining Mega ADK This allows the users to easily use an ADK and for instance an Uno without needing to edit avrpins.h every time --- avrpins.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avrpins.h b/avrpins.h index 99dbcf7f..df37def9 100644 --- a/avrpins.h +++ b/avrpins.h @@ -20,8 +20,10 @@ e-mail : support@circuitsathome.com #ifndef _avrpins_h_ #define _avrpins_h_ +#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) /* Uncomment the following if you have Arduino Mega ADK board with MAX3421e built-in */ //#define BOARD_MEGA_ADK +#endif /* Uncomment the following if you are using a Teensy 2.0 */ //#define BOARD_TEENSY From 9e22dce46ca336cb37d3797b11316529a48d03a1 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Sat, 23 Jun 2012 00:17:23 +0200 Subject: [PATCH 18/20] Removed prog_char prog_char is deprecated, as described here: http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html --- PS3BT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PS3BT.cpp b/PS3BT.cpp index d23adb76..8f9ae9af 100644 --- a/PS3BT.cpp +++ b/PS3BT.cpp @@ -24,7 +24,7 @@ const uint8_t PS3BT::BTD_EVENT_PIPE = 1; const uint8_t PS3BT::BTD_DATAIN_PIPE = 2; const uint8_t PS3BT::BTD_DATAOUT_PIPE = 3; -prog_char OUTPUT_REPORT_BUFFER[] PROGMEM = { +uint8_t OUTPUT_REPORT_BUFFER[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, From 9d49f803faf5936cdd01e6071cde34e0d8def577 Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Tue, 17 Jul 2012 18:41:05 +0200 Subject: [PATCH 19/20] Added support for the Xbox 360 controller --- PS3README => EXTRAREADME | 6 +- XBOXUSB.cpp | 342 +++++++++++++++++++++++++++++ XBOXUSB.h | 149 +++++++++++++ examples/XBOX360USB/XBOX360USB.ino | 109 +++++++++ keywords.txt | 40 +++- 5 files changed, 644 insertions(+), 2 deletions(-) rename PS3README => EXTRAREADME (81%) create mode 100644 XBOXUSB.cpp create mode 100644 XBOXUSB.h create mode 100644 examples/XBOX360USB/XBOX360USB.ino diff --git a/PS3README b/EXTRAREADME similarity index 81% rename from PS3README rename to EXTRAREADME index 161b1bf8..36515a06 100644 --- a/PS3README +++ b/EXTRAREADME @@ -1,4 +1,4 @@ -The PS3BT.cpp, PS3BT.h, PS3USB.cpp, and PS3USB.h were developed by Kristian Lauszus +The PS3BT.cpp, PS3BT.h, PS3USB.cpp, PS3USB.h, XBOXUSB.cpp, and XBOXUSB.h were developed by Kristian Lauszus For more information regarding the PS3 protocol etc. visit my blog at: http://blog.tkjelectronics.dk/ or send me an email at kristianl at tkjelectronics dot dk. You could also visit the official wiki: https://github.com/TKJElectronics/USB_Host_Shield_2.0/wiki for information. @@ -19,4 +19,8 @@ http://www.copenhagengamecollective.org/unimove/ https://github.com/thp/psmoveapi http://code.google.com/p/moveonpc/ +All the information regarding the Xbox 360 controller protocol are form these two sites: +http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/UsbInfo +http://pingus.seul.org/~grumbel/xboxdrv/ + And at last I would like to thank Oleg from http://www.circuitsathome.com/ for making such an awesome shield! \ No newline at end of file diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp new file mode 100644 index 00000000..a976b686 --- /dev/null +++ b/XBOXUSB.cpp @@ -0,0 +1,342 @@ +/* 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 + */ + +#include "XBOXUSB.h" +#define DEBUG // Uncomment to print data for debugging +//#define EXTRADEBUG // Uncomment to get even more debugging data +//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller + +XBOXUSB::XBOXUSB(USB *p): +pUsb(p), // pointer to USB class instance - mandatory +bAddress(0), // device address - mandatory +bPollEnable(false) { // don't start polling before dongle is connected + for(uint8_t i=0; iRegisterDeviceClass(this); //set devConfig[] entry +} + +uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { + uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; + uint8_t rcode; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint16_t VID; + + // get memory address of USB device address pool + AddressPool &addrPool = pUsb->GetAddressPool(); +#ifdef EXTRADEBUG + Notify(PSTR("\r\nXBOXUSB Init")); +#endif + // check if address has already been assigned to an instance + if (bAddress) + { +#ifdef DEBUG + Notify(PSTR("\r\nAddress in use")); +#endif + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + } + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + { +#ifdef DEBUG + Notify(PSTR("\r\nAddress not found")); +#endif + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + } + + if (!p->epinfo) + { +#ifdef DEBUG + Notify(PSTR("\r\nepinfo is null")); +#endif + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + if(rcode) + goto FailGetDevDescr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr( 0, 0, bAddress ); + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; +#ifdef DEBUG + Notify(PSTR("\r\nsetAddr: ")); +#endif + PrintHex(rcode); + return rcode; + } +#ifdef EXTRADEBUG + Notify(PSTR("\r\nAddr: ")); + PrintHex(bAddress); +#endif + p->lowspeed = false; + + //get pointer to assigned address record + p = addrPool.GetUsbDevicePtr(bAddress); + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign epInfo to epinfo pointer - only EP0 is known + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + if (rcode) + goto FailSetDevTblEntry; + + VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + + if(VID == XBOX_VID) { // We just check if it's a xbox controller using the Vendor ID + /* The application will work in reduced host mode, so we can save program and data + memory space. After verifying the VID we will use known values for the + configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ + + /* Initialize data structures for endpoints of device */ + epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint + epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint + epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; + epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints + epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; + epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; + epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; + + rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); + if( rcode ) + goto FailSetDevTblEntry; + + delay(200);//Give time for address change + + rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); + if( rcode ) + goto FailSetConf; + + + +#ifdef DEBUG + Notify(PSTR("\r\nXbox 360 Controller Connected")); +#endif + setLedMode(ROTATING); + Xbox360Connected = true; + } + else + goto FailUnknownDevice; + + bPollEnable = true; + Notify(PSTR("\r\n")); + return 0; // successful configuration + + /* diagnostic messages */ +FailGetDevDescr: +#ifdef DEBUG + Notify(PSTR("\r\ngetDevDescr:")); +#endif + goto Fail; +FailSetDevTblEntry: +#ifdef DEBUG + Notify(PSTR("\r\nsetDevTblEn:")); +#endif + goto Fail; +FailSetConf: +#ifdef DEBUG + Notify(PSTR("\r\nsetConf:")); +#endif + goto Fail; +FailUnknownDevice: +#ifdef DEBUG + Notify(PSTR("\r\nUnknown Device Connected - VID: ")); + PrintHex(VID); + Notify(PSTR(" PID: ")); + PrintHex(((USB_DEVICE_DESCRIPTOR*)buf)->idProduct); +#endif + goto Fail; +Fail: +#ifdef DEBUG + Notify(PSTR("\r\nXbox 360 Init Failed, error code: ")); + Serial.print(rcode); +#endif + Release(); + return rcode; +} + +/* Performs a cleanup after failed Init() attempt */ +uint8_t XBOXUSB::Release() { + Xbox360Connected = false; + pUsb->GetAddressPool().FreeAddress(bAddress); + bAddress = 0; + bPollEnable = false; + return 0; +} +uint8_t XBOXUSB::Poll() { + if (!bPollEnable) + return 0; + uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; + pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 + readReport(); +#ifdef PRINTREPORT + printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller +#endif + return 0; +} + +void XBOXUSB::readReport() { + if (readBuf == NULL) + return; + if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports + /*for(int i = 0; i < EP_MAXPKTSIZE; i++) + readBuf[i] = 0;*/ + return; + } + + ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16) | ((uint32_t)readBuf[5] << 24)); + + //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; + } + + OldButtonState = ButtonState; +} + +void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller + if (readBuf == NULL) + return; + for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE;i++) { + PrintHex(readBuf[i]); + Serial.print(" "); + } + Serial.println(""); +} + +uint8_t XBOXUSB::getButton(Button b) { + if (readBuf == NULL) + 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; + } +} +int16_t XBOXUSB::getAnalogHat(AnalogHat a) { + if (readBuf == NULL) + return 0; + return (int16_t)(readBuf[(uint8_t)a+1] << 8 | readBuf[(uint8_t)a]); +} + +/* Playstation Sixaxis Dualshock and Navigation 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; + 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; + + XboxCommand(writeBuf, 3); +} +void XBOXUSB::setLedBlink(LED l) { + writeBuf[0] = 0x01; + writeBuf[1] = 0x03; + writeBuf[2] = (uint8_t)l; + + XboxCommand(writeBuf, 3); +} +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::setRumbleOn(uint8_t lValue, uint8_t rValue) { + writeBuf[0] = 0x00; + writeBuf[1] = 0x08; + writeBuf[2] = 0x00; + writeBuf[3] = lValue; // big weight + writeBuf[4] = rValue; // small weight + writeBuf[5] = 0x00; + writeBuf[6] = 0x00; + writeBuf[7] = 0x00; + + XboxCommand(writeBuf, 8); +} \ No newline at end of file diff --git a/XBOXUSB.h b/XBOXUSB.h new file mode 100644 index 00000000..598f3ed4 --- /dev/null +++ b/XBOXUSB.h @@ -0,0 +1,149 @@ +/* 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 _xboxusb_h_ +#define _xboxusb_h_ + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +#include "Usb.h" + +/* Data Xbox 360 taken from descriptors */ +#define EP_MAXPKTSIZE 32 // max size for data via USB + +/* Endpoint types */ +#define EP_INTERRUPT 0x03 + +/* Names we give to the 3 Xbox360 pipes */ +#define XBOX_CONTROL_PIPE 0 +#define XBOX_INPUT_PIPE 1 +#define XBOX_OUTPUT_PIPE 2 + +//PID and VID of the different devices +#define XBOX_VID 0x045E // Microsoft Corporation + +#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer + +// used in control endpoint header for HID Commands +#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define HID_REQUEST_SET_REPORT 0x09 + +#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, +}; + +class XBOXUSB : public USBDeviceConfig +{ +public: + XBOXUSB(USB *pUsb); + + // USBDeviceConfig implementation + virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); + virtual uint8_t Release(); + virtual uint8_t Poll(); + virtual uint8_t GetAddress() { return bAddress; }; + virtual bool isReady() { return bPollEnable; }; + + /* XBOX Controller Readings */ + uint8_t getButton(Button b); + int16_t getAnalogHat(AnalogHat a); + + /* Commands for Dualshock 3 and Navigation controller */ + void setAllOff() { setRumbleOn(0,0); setLedOff(); }; + void setRumbleOff() { setRumbleOn(0,0); }; + void setRumbleOn(uint8_t lValue, uint8_t rValue); + void setLedOff(); + void setLedOn(LED l); + void setLedBlink(LED l); + 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 + +protected: + /* mandatory members */ + USB *pUsb; + uint8_t bAddress; // device address + EpInfo epInfo[XBOX_MAX_ENDPOINTS]; //endpoint info structure + +private: + bool bPollEnable; + + uint32_t ButtonState; + uint32_t OldButtonState; + + 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); +}; +#endif diff --git a/examples/XBOX360USB/XBOX360USB.ino b/examples/XBOX360USB/XBOX360USB.ino new file mode 100644 index 00000000..580129fe --- /dev/null +++ b/examples/XBOX360USB/XBOX360USB.ino @@ -0,0 +1,109 @@ +/* + Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus + For more information visit my blog: http://blog.tkjelectronics.dk/ or + send me an e-mail: kristianl@tkjelectronics.com + */ + +#include +USB Usb; +XBOXUSB Xbox(&Usb); + +void setup() { + Serial.begin(115200); + + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while(1); //halt + } + Serial.print(F("\r\nXBOX USB Library Started")); +} +void loop() { + Usb.Task(); + if(Xbox.Xbox360Connected) { + 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: ")); + Serial.print(Xbox.getAnalogHat(LeftHatX)); + Serial.print("\t"); + } + if(Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) { + Serial.print(F("LeftHatY: ")); + Serial.print(Xbox.getAnalogHat(LeftHatY)); + Serial.print("\t"); + } + if(Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) { + Serial.print(F("RightHatX: ")); + Serial.print(Xbox.getAnalogHat(RightHatX)); + Serial.print("\t"); + } + if(Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) { + 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)); + } + Xbox.setRumbleOn(Xbox.getButton(L2),Xbox.getButton(R2)); + Serial.println(); + } + } + delay(1); +} diff --git a/keywords.txt b/keywords.txt index de987ded..930a08e8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -145,4 +145,42 @@ BluetoothRumble LITERAL1 Bluetooth LITERAL1 RumbleHigh LITERAL1 -RumbleLow LITERAL1 \ No newline at end of file +RumbleLow LITERAL1 + +#################################################### +# Syntax Coloring Map For Xbox 360 USB Library +#################################################### + +#################################################### +# Datatypes (KEYWORD1) +#################################################### + +XBOXUSB KEYWORD1 + +#################################################### +# Methods and Functions (KEYWORD2) +#################################################### + +setLedBlink KEYWORD2 +setLedMode KEYWORD2 +Xbox360Connected KEYWORD2 + +#################################################### +# Constants and enums (LITERAL1) +#################################################### + +ALL LITERAL1 + +ROTATING LITERAL1 +FASTBLINK LITERAL1 +SLOWBLINK LITERAL1 +ALTERNATING LITERAL1 + +BACK LITERAL1 + +XBOX LITERAL1 + +A LITERAL1 +B LITERAL1 +X LITERAL1 +Y LITERAL1 \ No newline at end of file From 3c14815f9b34871139919d995d56af4af6ebde1b Mon Sep 17 00:00:00 2001 From: Kristian Lauszus Date: Wed, 18 Jul 2012 19:27:26 +0200 Subject: [PATCH 20/20] Added error check for wireless controllers and wireless receivers --- XBOXUSB.cpp | 19 ++++++++++++++++--- XBOXUSB.h | 5 ++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/XBOXUSB.cpp b/XBOXUSB.cpp index a976b686..a5411c2b 100644 --- a/XBOXUSB.cpp +++ b/XBOXUSB.cpp @@ -40,6 +40,7 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t rcode; UsbDevice *p = NULL; EpInfo *oldep_ptr = NULL; + uint16_t PID; uint16_t VID; // get memory address of USB device address pool @@ -133,8 +134,22 @@ uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { goto FailSetDevTblEntry; VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; + PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; if(VID == XBOX_VID) { // We just check if it's a xbox controller using the Vendor ID + if(PID == XBOX_WIRELESS_PID) { +#ifdef DEBUG + Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication")); +#endif + return 0; + } + else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { +#ifdef DEBUG + Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB")); +#endif + return 0; + } + /* The application will work in reduced host mode, so we can save program and data memory space. After verifying the VID we will use known values for the configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ @@ -199,7 +214,7 @@ FailUnknownDevice: Notify(PSTR("\r\nUnknown Device Connected - VID: ")); PrintHex(VID); Notify(PSTR(" PID: ")); - PrintHex(((USB_DEVICE_DESCRIPTOR*)buf)->idProduct); + PrintHex(PID); #endif goto Fail; Fail: @@ -235,8 +250,6 @@ void XBOXUSB::readReport() { if (readBuf == NULL) return; if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports - /*for(int i = 0; i < EP_MAXPKTSIZE; i++) - readBuf[i] = 0;*/ return; } diff --git a/XBOXUSB.h b/XBOXUSB.h index 598f3ed4..b688eb0b 100644 --- a/XBOXUSB.h +++ b/XBOXUSB.h @@ -38,7 +38,10 @@ #define XBOX_OUTPUT_PIPE 2 //PID and VID of the different devices -#define XBOX_VID 0x045E // Microsoft Corporation +#define XBOX_VID 0x045E // Microsoft Corporation +#define XBOX_WIRELESS_PID 0x028F // Wireless controller only support charging +#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver +#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver #define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer