Initial support for Wii Balance Board

Still need to convert readings into something meaningful
This commit is contained in:
Kristian Sloth Lauszus 2015-04-16 01:57:00 +02:00
parent 3d5b46d055
commit b1902b2a55
7 changed files with 113 additions and 32 deletions

55
BTD.cpp
View file

@ -445,11 +445,17 @@ void BTD::HCI_event_task() {
for(uint8_t j = 0; j < 3; j++) for(uint8_t j = 0; j < 3; j++)
classOfDevice[j] = hcibuf[j + 4 + offset]; classOfDevice[j] = hcibuf[j + 4 + offset];
#ifdef EXTRADEBUG
Notify(PSTR("\r\nClass of device: "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
#endif
if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information 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 checkRemoteName = true; // Check remote name to distinguish between the different controllers
motionPlusInside = true;
else
motionPlusInside = false;
for(uint8_t j = 0; j < 6; j++) for(uint8_t j = 0; j < 6; j++)
disc_bdaddr[j] = hcibuf[j + 3 + 6 * i]; disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
@ -472,16 +478,6 @@ void BTD::HCI_event_task() {
hci_set_flag(HCI_FLAG_DEVICE_FOUND); hci_set_flag(HCI_FLAG_DEVICE_FOUND);
break; break;
} }
#ifdef EXTRADEBUG
else {
Notify(PSTR("\r\nClass of device: "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
}
#endif
} }
} }
break; break;
@ -555,7 +551,7 @@ void BTD::HCI_event_task() {
case EV_PIN_CODE_REQUEST: case EV_PIN_CODE_REQUEST:
if(pairWithWii) { if(pairWithWii) {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing with wiimote"), 0x80); Notify(PSTR("\r\nPairing with Wiimote"), 0x80);
#endif #endif
hci_pin_code_request_reply(); hci_pin_code_request_reply();
} else if(btdPin != NULL) { } 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 if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
if(pairWithWii) 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 else
Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80); Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
#endif #endif
@ -736,8 +732,8 @@ void BTD::HCI_task() {
else else
Notify(PSTR("device"), 0x80); Notify(PSTR("device"), 0x80);
#endif #endif
if(motionPlusInside) { if(checkRemoteName) {
hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller 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; hci_state = HCI_REMOTE_NAME_STATE;
} else } else
hci_state = HCI_CONNECT_DEVICE_STATE; hci_state = HCI_CONNECT_DEVICE_STATE;
@ -752,6 +748,7 @@ void BTD::HCI_task() {
else else
Notify(PSTR("\r\nConnecting to HID device"), 0x80); Notify(PSTR("\r\nConnecting to HID device"), 0x80);
#endif #endif
checkRemoteName = false;
hci_connect(); hci_connect();
hci_state = HCI_CONNECTED_DEVICE_STATE; hci_state = HCI_CONNECTED_DEVICE_STATE;
} }
@ -809,6 +806,9 @@ void BTD::HCI_task() {
#endif #endif
if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) { if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
incomingWii = true; incomingWii = true;
motionPlusInside = false;
wiiUProController = false;
pairWiiUsingSync = false;
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWiimote is connecting"), 0x80); Notify(PSTR("\r\nWiimote is connecting"), 0x80);
#endif #endif
@ -821,11 +821,12 @@ void BTD::HCI_task() {
#ifdef DEBUG_USB_HOST #ifdef DEBUG_USB_HOST
Notify(PSTR(" - Wii U Pro Controller"), 0x80); Notify(PSTR(" - Wii U Pro Controller"), 0x80);
#endif #endif
motionPlusInside = true; wiiUProController = motionPlusInside = pairWiiUsingSync = true;
wiiUProController = true; } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) {
} else { #ifdef DEBUG_USB_HOST
motionPlusInside = false; Notify(PSTR(" - Wii Balance Board"), 0x80);
wiiUProController = false; #endif
pairWiiUsingSync = true;
} }
} }
if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) { 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 #endif
incomingPS4 = true; incomingPS4 = true;
} }
if(pairWithWii && motionPlusInside) if(pairWithWii && checkRemoteName)
hci_state = HCI_CONNECT_DEVICE_STATE; hci_state = HCI_CONNECT_DEVICE_STATE;
else { else {
hci_accept_connection(); hci_accept_connection();
@ -886,7 +887,7 @@ void BTD::HCI_task() {
memset(l2capinbuf, 0, BULK_MAXPKTSIZE); memset(l2capinbuf, 0, BULK_MAXPKTSIZE);
connectToWii = incomingWii = pairWithWii = false; connectToWii = incomingWii = pairWithWii = false;
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false; connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
incomingPS4 = false; incomingPS4 = false;
hci_state = HCI_SCANNING_STATE; hci_state = HCI_SCANNING_STATE;
@ -1085,9 +1086,9 @@ void BTD::hci_pin_code_request_reply() {
hcibuf[8] = disc_bdaddr[5]; hcibuf[8] = disc_bdaddr[5];
if(pairWithWii) { if(pairWithWii) {
hcibuf[9] = 6; // Pin length is the length of the Bluetooth address hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
if(wiiUProController) { if(pairWiiUsingSync) {
#ifdef DEBUG_USB_HOST #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 #endif
for(uint8_t i = 0; i < 6; i++) for(uint8_t i = 0; i < 6; i++)
hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards

2
BTD.h
View file

@ -535,6 +535,8 @@ private:
uint8_t pollInterval; uint8_t pollInterval;
bool bPollEnable; 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 bool incomingPS4; // True if a PS4 controller is connecting
uint8_t classOfDevice[3]; // Class of device of last device uint8_t classOfDevice[3]; // Class of device of last device

View file

@ -245,7 +245,7 @@ An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class.
### [Wii library](Wii.cpp) ### [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: 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); 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: 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. 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: All the information about the Wii controllers are from these sites:
* <http://wiibrew.org/wiki/Wiimote> * <http://wiibrew.org/wiki/Wiimote>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers> * <http://wiibrew.org/wiki/Wiimote/Extension_Controllers>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck> * <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus> * <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus>
* <http://wiibrew.org/wiki/Wii_Balance_Board>
* The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot. * The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot.
### [PS Buzz Library](PSBuzz.cpp) ### [PS Buzz Library](PSBuzz.cpp)

35
Wii.cpp
View file

@ -108,6 +108,7 @@ void WII::Reset() {
motionPlusInside = false; motionPlusInside = false;
pBtd->wiiUProController = false; pBtd->wiiUProController = false;
wiiUProControllerConnected = false; wiiUProControllerConnected = false;
wiiBalanceBoardConnected = false;
l2cap_event_flag = 0; // Reset flags l2cap_event_flag = 0; // Reset flags
l2cap_state = L2CAP_WAIT; l2cap_state = L2CAP_WAIT;
} }
@ -380,6 +381,12 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80); Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
#endif #endif
wiiUProControllerConnected = true; 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 #ifdef DEBUG_USB_HOST
else { else {
@ -414,8 +421,32 @@ void WII::ACLData(uint8_t* l2capinbuf) {
break; break;
case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
break; break;
case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE case 0x32: { // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
break; #if 1
uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
Notify(PSTR("\r\nLength: "), 0x80);
D_PrintHex<uint16_t > (length - 2, 0x80);
Notify(PSTR("\tData: "), 0x80);
for(uint8_t i = 0; i < length - 2; i++) {
D_PrintHex<uint8_t > (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 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 #ifdef WIICAMERA
// Read the IR data // Read the IR data

2
Wii.h
View file

@ -191,6 +191,8 @@ public:
bool motionPlusConnected; bool motionPlusConnected;
/** Variable used to indicate if a Wii U Pro controller is connected. */ /** Variable used to indicate if a Wii U Pro controller is connected. */
bool wiiUProControllerConnected; 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 */ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */

View file

@ -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 <Wii.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#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();
}
}
}

View file

@ -269,6 +269,7 @@ wiimoteConnected KEYWORD2
nunchuckConnected KEYWORD2 nunchuckConnected KEYWORD2
motionPlusConnected KEYWORD2 motionPlusConnected KEYWORD2
wiiUProControllerConnected KEYWORD2 wiiUProControllerConnected KEYWORD2
wiiBalanceBoardConnected KEYWORD2
setRumbleToggle KEYWORD2 setRumbleToggle KEYWORD2
getPitch KEYWORD2 getPitch KEYWORD2
getRoll KEYWORD2 getRoll KEYWORD2