From b1902b2a5509a5149fbe9b7d64002da6e380327f Mon Sep 17 00:00:00 2001 From: Kristian Sloth Lauszus Date: Thu, 16 Apr 2015 01:57:00 +0200 Subject: [PATCH] Initial support for Wii Balance Board Still need to convert readings into something meaningful --- BTD.cpp | 55 ++++++++++--------- BTD.h | 2 + README.md | 6 +- Wii.cpp | 35 +++++++++++- Wii.h | 2 + .../WiiBalanceBoard/WiiBalanceBoard.ino | 44 +++++++++++++++ keywords.txt | 1 + 7 files changed, 113 insertions(+), 32 deletions(-) create mode 100644 examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino diff --git a/BTD.cpp b/BTD.cpp index 42cf3d62..5c470bab 100755 --- a/BTD.cpp +++ b/BTD.cpp @@ -445,11 +445,17 @@ void BTD::HCI_event_task() { for(uint8_t j = 0; j < 3; j++) classOfDevice[j] = hcibuf[j + 4 + offset]; +#ifdef EXTRADEBUG + Notify(PSTR("\r\nClass of device: "), 0x80); + D_PrintHex (classOfDevice[2], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[1], 0x80); + Notify(PSTR(" "), 0x80); + D_PrintHex (classOfDevice[0], 0x80); +#endif + if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information - if(classOfDevice[0] & 0x08) // Check if it's the new Wiimote with motion plus inside that was detected - motionPlusInside = true; - else - motionPlusInside = false; + checkRemoteName = true; // Check remote name to distinguish between the different controllers for(uint8_t j = 0; j < 6; j++) disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; @@ -472,16 +478,6 @@ void BTD::HCI_event_task() { hci_set_flag(HCI_FLAG_DEVICE_FOUND); break; } -#ifdef EXTRADEBUG - else { - Notify(PSTR("\r\nClass of device: "), 0x80); - D_PrintHex (classOfDevice[2], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[1], 0x80); - Notify(PSTR(" "), 0x80); - D_PrintHex (classOfDevice[0], 0x80); - } -#endif } } break; @@ -555,7 +551,7 @@ void BTD::HCI_event_task() { case EV_PIN_CODE_REQUEST: if(pairWithWii) { #ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nPairing with wiimote"), 0x80); + Notify(PSTR("\r\nPairing with Wiimote"), 0x80); #endif hci_pin_code_request_reply(); } else if(btdPin != NULL) { @@ -705,7 +701,7 @@ void BTD::HCI_task() { if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote #ifdef DEBUG_USB_HOST if(pairWithWii) - Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80); + Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or Wii Balance Board"), 0x80); else Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80); #endif @@ -736,8 +732,8 @@ void BTD::HCI_task() { else Notify(PSTR("device"), 0x80); #endif - if(motionPlusInside) { - hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller + if(checkRemoteName) { + hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board hci_state = HCI_REMOTE_NAME_STATE; } else hci_state = HCI_CONNECT_DEVICE_STATE; @@ -752,6 +748,7 @@ void BTD::HCI_task() { else Notify(PSTR("\r\nConnecting to HID device"), 0x80); #endif + checkRemoteName = false; hci_connect(); hci_state = HCI_CONNECTED_DEVICE_STATE; } @@ -809,6 +806,9 @@ void BTD::HCI_task() { #endif if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) { incomingWii = true; + motionPlusInside = false; + wiiUProController = false; + pairWiiUsingSync = false; #ifdef DEBUG_USB_HOST Notify(PSTR("\r\nWiimote is connecting"), 0x80); #endif @@ -821,11 +821,12 @@ void BTD::HCI_task() { #ifdef DEBUG_USB_HOST Notify(PSTR(" - Wii U Pro Controller"), 0x80); #endif - motionPlusInside = true; - wiiUProController = true; - } else { - motionPlusInside = false; - wiiUProController = false; + wiiUProController = motionPlusInside = pairWiiUsingSync = true; + } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) { +#ifdef DEBUG_USB_HOST + Notify(PSTR(" - Wii Balance Board"), 0x80); +#endif + pairWiiUsingSync = true; } } if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) { @@ -834,7 +835,7 @@ void BTD::HCI_task() { #endif incomingPS4 = true; } - if(pairWithWii && motionPlusInside) + if(pairWithWii && checkRemoteName) hci_state = HCI_CONNECT_DEVICE_STATE; else { hci_accept_connection(); @@ -886,7 +887,7 @@ void BTD::HCI_task() { memset(l2capinbuf, 0, BULK_MAXPKTSIZE); connectToWii = incomingWii = pairWithWii = false; - connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false; + connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false; incomingPS4 = false; hci_state = HCI_SCANNING_STATE; @@ -1085,9 +1086,9 @@ void BTD::hci_pin_code_request_reply() { hcibuf[8] = disc_bdaddr[5]; if(pairWithWii) { hcibuf[9] = 6; // Pin length is the length of the Bluetooth address - if(wiiUProController) { + if(pairWiiUsingSync) { #ifdef DEBUG_USB_HOST - Notify(PSTR("\r\nParing with Wii U Pro Controller"), 0x80); + Notify(PSTR("\r\nParing with Wii controller via SYNC"), 0x80); #endif for(uint8_t i = 0; i < 6; i++) hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards diff --git a/BTD.h b/BTD.h index b7683f65..312e45f7 100755 --- a/BTD.h +++ b/BTD.h @@ -535,6 +535,8 @@ private: uint8_t pollInterval; bool bPollEnable; + bool pairWiiUsingSync; // True if paring was done using the SYNC button. + bool checkRemoteName; // Used to check remote device's name before connecting. bool incomingPS4; // True if a PS4 controller is connecting uint8_t classOfDevice[3]; // Class of device of last device diff --git a/README.md b/README.md index 3efcfb03..60877437 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. ### [Wii library](Wii.cpp) -The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller is also supported via Bluetooth. +The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth. First you have to pair with the controller, this is done automatically by the library if you create the instance like so: @@ -253,7 +253,7 @@ First you have to pair with the controller, this is done automatically by the li WII Wii(&Btd, PAIR); ``` -And then press 1 & 2 at once on the Wiimote or press sync if you are using a Wii U Pro Controller. +And then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board. After that you can simply create the instance like so: @@ -273,13 +273,13 @@ The Wii IR camera can also be used, but you will have to activate the code for i The [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used. - All the information about the Wii controllers are from these sites: * * * * +* * The old library created by _Tomoyuki Tanaka_: also helped a lot. ### [PS Buzz Library](PSBuzz.cpp) diff --git a/Wii.cpp b/Wii.cpp index 008e5329..a0aa9d53 100755 --- a/Wii.cpp +++ b/Wii.cpp @@ -108,6 +108,7 @@ void WII::Reset() { motionPlusInside = false; pBtd->wiiUProController = false; wiiUProControllerConnected = false; + wiiBalanceBoardConnected = false; l2cap_event_flag = 0; // Reset flags l2cap_state = L2CAP_WAIT; } @@ -380,6 +381,12 @@ void WII::ACLData(uint8_t* l2capinbuf) { Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); #endif wiiUProControllerConnected = true; + } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) { +#ifdef DEBUG_USB_HOST + Notify(PSTR("\r\nWii Balance Board connected"), 0x80); +#endif + setReportMode(false, 0x32); // Read the Wii Balance Board extension + wiiBalanceBoardConnected = true; } #ifdef DEBUG_USB_HOST else { @@ -414,8 +421,32 @@ void WII::ACLData(uint8_t* l2capinbuf) { break; case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA break; - case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE - break; + case 0x32: { // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE +#if 1 + uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); + Notify(PSTR("\r\nLength: "), 0x80); + D_PrintHex (length - 2, 0x80); + Notify(PSTR("\tData: "), 0x80); + for(uint8_t i = 0; i < length - 2; i++) { + D_PrintHex (l2capinbuf[10 + i], 0x80); + Notify(PSTR(" "), 0x80); + } + + uint16_t topRight = (l2capinbuf[13] | l2capinbuf[12] << 8); + uint16_t botRight = (l2capinbuf[15] | l2capinbuf[14] << 8); + uint16_t topLeft = (l2capinbuf[17] | l2capinbuf[16] << 8); + uint16_t botleft = (l2capinbuf[19] | l2capinbuf[18] << 8); + + Notify(PSTR("\ttopRight: "), 0x80); + Notify(topRight, 0x80); + Notify(PSTR("\tbotRight: "), 0x80); + Notify(botRight, 0x80); + Notify(PSTR("\ttopLeft: "), 0x80); + Notify(topLeft, 0x80); + Notify(PSTR("\tbotleft: "), 0x80); + Notify(botleft, 0x80); +#endif + } break; case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II #ifdef WIICAMERA // Read the IR data diff --git a/Wii.h b/Wii.h index 13ba8d50..c8a477aa 100755 --- a/Wii.h +++ b/Wii.h @@ -191,6 +191,8 @@ public: bool motionPlusConnected; /** Variable used to indicate if a Wii U Pro controller is connected. */ bool wiiUProControllerConnected; + /** Variable used to indicate if a Wii Balance Board is connected. */ + bool wiiBalanceBoardConnected; /**@}*/ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ diff --git a/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino b/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino new file mode 100644 index 00000000..af8a78bf --- /dev/null +++ b/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino @@ -0,0 +1,44 @@ +/* + Example sketch for the Wii Balance Board 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 +#include + +// Satisfy the IDE, which needs to see the include statment in the ino too. +#ifdef dobogusinclude +#include +#include +#endif + +USB Usb; +//USBHub Hub1(&Usb); // Some dongles have a hub inside + +BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so +/* You can create the instance of the class in two ways */ +WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once +//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board + +void setup() { + Serial.begin(115200); +#if !defined(__MIPSEL__) + while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection +#endif + if (Usb.Init() == -1) { + Serial.print(F("\r\nOSC did not start")); + while (1); //halt + } + Serial.print(F("\r\nWii Balance Board Bluetooth Library Started")); +} +void loop() { + Usb.Task(); + if (Wii.wiiBalanceBoardConnected) { + if (Wii.getButtonClick(A)) { + Serial.print(F("\r\nA")); + Wii.setLedToggle(LED1); + //Wii.disconnect(); + } + } +} diff --git a/keywords.txt b/keywords.txt index bbbfb03e..ade71b28 100644 --- a/keywords.txt +++ b/keywords.txt @@ -269,6 +269,7 @@ wiimoteConnected KEYWORD2 nunchuckConnected KEYWORD2 motionPlusConnected KEYWORD2 wiiUProControllerConnected KEYWORD2 +wiiBalanceBoardConnected KEYWORD2 setRumbleToggle KEYWORD2 getPitch KEYWORD2 getRoll KEYWORD2