2012-08-21 14:31:11 +02:00
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
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 " ) .
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
Contact information
- - - - - - - - - - - - - - - - - - -
2013-03-28 09:37:09 +01:00
2012-08-21 14:31:11 +02:00
Kristian Lauszus , TKJ Electronics
Web : http : //www.tkjelectronics.com
e - mail : kristianl @ tkjelectronics . com
2013-01-17 00:07:56 +01:00
2013-07-18 19:43:21 +02:00
IR camera support added by Allan Glover ( adglover9 .81 @ gmail . com ) and Kristian Lauszus
2012-08-21 14:31:11 +02:00
*/
# include "Wii.h"
2013-11-11 11:48:09 +01:00
// To enable serial debugging see "settings.h"
2012-08-21 14:31:11 +02:00
//#define EXTRADEBUG // Uncomment to get even more debugging data
2012-08-22 23:41:38 +02:00
//#define PRINTREPORT // Uncomment to print the report send by the Wii controllers
2012-08-21 14:31:11 +02:00
2013-01-27 21:25:50 +01:00
const uint8_t LEDS [ ] PROGMEM = {
2013-03-28 09:46:43 +01:00
0x10 , // LED1
0x20 , // LED2
0x40 , // LED3
0x80 , // LED4
0x90 , // LED5
0xA0 , // LED6
0xC0 , // LED7
0xD0 , // LED8
0xE0 , // LED9
0xF0 // LED10
} ;
2013-01-27 21:25:50 +01:00
const uint32_t BUTTONS [ ] PROGMEM = {
2013-03-28 09:46:43 +01:00
0x00008 , // UP
0x00002 , // RIGHT
0x00004 , // DOWN
0x00001 , // LEFT
0 , // Skip
0x00010 , // PLUS
0x00100 , // TWO
0x00200 , // ONE
0x01000 , // MINUS
0x08000 , // HOME
0x10000 , // Z
0x20000 , // C
0x00400 , // B
0x00800 // A
2013-01-27 21:25:50 +01:00
} ;
2013-02-02 22:14:01 +01:00
const uint32_t PROCONTROLLERBUTTONS [ ] PROGMEM = {
2013-03-28 09:46:43 +01:00
0x00100 , // UP
0x00080 , // RIGHT
0x00040 , // DOWN
0x00200 , // LEFT
0 , // Skip
0x00004 , // PLUS
0x20000 , // L3
0x10000 , // R3
0x00010 , // MINUS
0x00008 , // HOME
0 , 0 , // Skip
0x04000 , // B
0x01000 , // A
0x00800 , // X
0x02000 , // Y
0x00020 , // L
0x00002 , // R
0x08000 , // ZL
0x00400 // ZR
2013-02-02 22:14:01 +01:00
} ;
2013-01-27 21:25:50 +01:00
2013-03-28 09:46:43 +01:00
WII : : WII ( BTD * p , bool pair ) :
2012-08-21 14:31:11 +02:00
pBtd ( p ) // pointer to USB class instance - mandatory
{
2013-03-28 09:46:43 +01:00
if ( pBtd )
pBtd - > registerServiceClass ( this ) ; // Register it as a Bluetooth service
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
pBtd - > pairWithWii = pair ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
HIDBuffer [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
/* Set device cid for the control and intterrupt channelse - LSB */
control_dcid [ 0 ] = 0x60 ; //0x0060
control_dcid [ 1 ] = 0x00 ;
interrupt_dcid [ 0 ] = 0x61 ; //0x0061
interrupt_dcid [ 1 ] = 0x00 ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
Reset ( ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : Reset ( ) {
2013-03-28 09:46:43 +01:00
wiimoteConnected = false ;
nunchuckConnected = false ;
motionPlusConnected = false ;
activateNunchuck = false ;
motionValuesReset = false ;
activeConnection = false ;
2013-07-18 19:43:21 +02:00
motionPlusInside = false ;
2013-03-28 09:46:43 +01:00
pBtd - > wiiUProController = false ;
wiiUProControllerConnected = false ;
l2cap_event_flag = 0 ; // Reset flags
l2cap_state = L2CAP_WAIT ;
2012-08-21 14:31:11 +02:00
}
void WII : : disconnect ( ) { // Use this void to disconnect any of the controllers
2013-07-18 19:43:21 +02:00
if ( ! motionPlusInside ) { // The old Wiimote needs a delay after the first command or it will automatically reconnect
if ( motionPlusConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:43:21 +02:00
Notify ( PSTR ( " \r \n Deactivating Motion Plus " ) , 0x80 ) ;
2013-03-05 18:51:44 +01:00
# endif
2013-07-18 19:43:21 +02:00
initExtension1 ( ) ; // This will disable the Motion Plus extension
}
timer = millis ( ) + 1000 ; // We have to wait for the message before the rest of the channels can be deactivated
} else
timer = millis ( ) ; // Don't wait
// First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
2013-03-28 09:46:43 +01:00
pBtd - > l2cap_disconnection_request ( hci_handle , 0x0A , interrupt_scid , interrupt_dcid ) ;
Reset ( ) ;
l2cap_state = L2CAP_INTERRUPT_DISCONNECT ;
2012-08-21 14:31:11 +02:00
}
void WII : : ACLData ( uint8_t * l2capinbuf ) {
2013-03-28 09:46:43 +01:00
if ( ! pBtd - > l2capConnectionClaimed & & pBtd - > incomingWii & & ! wiimoteConnected & & ! activeConnection ) {
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_CTRL_PSM ) {
2013-07-18 19:43:21 +02:00
motionPlusInside = pBtd - > motionPlusInside ;
2013-03-28 09:46:43 +01:00
pBtd - > incomingWii = false ;
pBtd - > l2capConnectionClaimed = true ; // Claim that the incoming connection belongs to this service
activeConnection = true ;
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_state = L2CAP_WAIT ;
}
}
2013-01-31 21:58:13 +01:00
}
2013-03-28 09:46:43 +01:00
if ( ( l2capinbuf [ 0 ] | ( l2capinbuf [ 1 ] < < 8 ) ) = = ( hci_handle | 0x2000 ) ) { // acl_handle_ok or it's a new connection
if ( ( l2capinbuf [ 6 ] | ( l2capinbuf [ 7 ] < < 8 ) ) = = 0x0001 ) { //l2cap_control - Channel ID for ACL-U
if ( l2capinbuf [ 8 ] = = L2CAP_CMD_COMMAND_REJECT ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n L2CAP Command Rejected - Reason: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 17 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 16 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_RESPONSE ) {
if ( ( ( l2capinbuf [ 16 ] | ( l2capinbuf [ 17 ] < < 8 ) ) = = 0x0000 ) & & ( ( l2capinbuf [ 18 ] | ( l2capinbuf [ 19 ] < < 8 ) ) = = SUCCESSFUL ) ) { // Success
2013-11-25 18:46:10 +01:00
if ( l2capinbuf [ 14 ] = = control_dcid [ 0 ] & & l2capinbuf [ 15 ] = = control_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
control_scid [ 0 ] = l2capinbuf [ 12 ] ;
control_scid [ 1 ] = l2capinbuf [ 13 ] ;
l2cap_event_flag | = L2CAP_FLAG_CONTROL_CONNECTED ;
} else if ( l2capinbuf [ 14 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 15 ] = = interrupt_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
interrupt_scid [ 0 ] = l2capinbuf [ 12 ] ;
interrupt_scid [ 1 ] = l2capinbuf [ 13 ] ;
l2cap_event_flag | = L2CAP_FLAG_INTERRUPT_CONNECTED ;
}
}
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONNECTION_REQUEST ) {
2012-10-07 14:50:51 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n L2CAP Connection Request - PSM: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " SCID: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 15 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " Identifier: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 9 ] , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2013-03-28 09:46:43 +01:00
if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_CTRL_PSM ) {
identifier = l2capinbuf [ 9 ] ;
control_scid [ 0 ] = l2capinbuf [ 14 ] ;
control_scid [ 1 ] = l2capinbuf [ 15 ] ;
l2cap_event_flag | = L2CAP_FLAG_CONNECTION_CONTROL_REQUEST ;
} else if ( ( l2capinbuf [ 12 ] | ( l2capinbuf [ 13 ] < < 8 ) ) = = HID_INTR_PSM ) {
identifier = l2capinbuf [ 9 ] ;
interrupt_scid [ 0 ] = l2capinbuf [ 14 ] ;
interrupt_scid [ 1 ] = l2capinbuf [ 15 ] ;
l2cap_event_flag | = L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST ;
}
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONFIG_RESPONSE ) {
if ( ( l2capinbuf [ 16 ] | ( l2capinbuf [ 17 ] < < 8 ) ) = = 0x0000 ) { // Success
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
l2cap_event_flag | = L2CAP_FLAG_CONFIG_CONTROL_SUCCESS ;
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
l2cap_event_flag | = L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS ;
}
}
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_CONFIG_REQUEST ) {
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
2013-03-28 09:46:43 +01:00
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , control_scid ) ;
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
2013-03-28 09:46:43 +01:00
pBtd - > l2cap_config_response ( hci_handle , l2capinbuf [ 9 ] , interrupt_scid ) ;
}
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_REQUEST ) {
if ( l2capinbuf [ 12 ] = = control_dcid [ 0 ] & & l2capinbuf [ 13 ] = = control_dcid [ 1 ] ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Disconnect Request: Control Channel " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , control_dcid , control_scid ) ;
Reset ( ) ;
} else if ( l2capinbuf [ 12 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_dcid [ 1 ] ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Disconnect Request: Interrupt Channel " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
pBtd - > l2cap_disconnection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid ) ;
Reset ( ) ;
}
} else if ( l2capinbuf [ 8 ] = = L2CAP_CMD_DISCONNECT_RESPONSE ) {
if ( l2capinbuf [ 12 ] = = control_scid [ 0 ] & & l2capinbuf [ 13 ] = = control_scid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
l2cap_event_flag | = L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE ;
} else if ( l2capinbuf [ 12 ] = = interrupt_scid [ 0 ] & & l2capinbuf [ 13 ] = = interrupt_scid [ 1 ] ) {
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
2013-03-28 09:46:43 +01:00
identifier = l2capinbuf [ 9 ] ;
l2cap_event_flag | = L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE ;
}
}
2012-08-21 14:31:11 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
else {
identifier = l2capinbuf [ 9 ] ;
Notify ( PSTR ( " \r \n L2CAP Unknown Signaling Command: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 8 ] , 0x80 ) ;
2012-08-23 23:10:12 +02:00
}
2013-03-28 09:46:43 +01:00
# endif
} else if ( l2capinbuf [ 6 ] = = interrupt_dcid [ 0 ] & & l2capinbuf [ 7 ] = = interrupt_dcid [ 1 ] ) { // l2cap_interrupt
2013-04-26 23:50:39 +02:00
//Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
2013-07-18 19:53:18 +02:00
if ( l2capinbuf [ 8 ] = = 0xA1 ) { // HID_THDR_DATA_INPUT
if ( ( l2capinbuf [ 9 ] > = 0x20 & & l2capinbuf [ 9 ] < = 0x22 ) | | ( l2capinbuf [ 9 ] > = 0x30 & & l2capinbuf [ 9 ] < = 0x37 ) | | l2capinbuf [ 9 ] = = 0x3e | | l2capinbuf [ 9 ] = = 0x3f ) { // These reports include the buttons
if ( ( l2capinbuf [ 9 ] > = 0x20 & & l2capinbuf [ 9 ] < = 0x22 ) | | l2capinbuf [ 9 ] = = 0x31 | | l2capinbuf [ 9 ] = = 0x33 ) // These reports have no extensions bytes
ButtonState = ( uint32_t ) ( ( l2capinbuf [ 10 ] & 0x1F ) | ( ( uint16_t ) ( l2capinbuf [ 11 ] & 0x9F ) < < 8 ) ) ;
else if ( wiiUProControllerConnected )
ButtonState = ( uint32_t ) ( ( ( ~ l2capinbuf [ 23 ] ) & 0xFE ) | ( ( uint16_t ) ( ~ l2capinbuf [ 24 ] ) < < 8 ) | ( ( uint32_t ) ( ( ~ l2capinbuf [ 25 ] ) & 0x03 ) < < 16 ) ) ;
else if ( motionPlusConnected ) {
if ( l2capinbuf [ 20 ] & 0x02 ) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus
ButtonState = ( uint32_t ) ( ( l2capinbuf [ 10 ] & 0x1F ) | ( ( uint16_t ) ( l2capinbuf [ 11 ] & 0x9F ) < < 8 ) | ( ( uint32_t ) ( ButtonState & 0xFFFF0000 ) ) ) ;
else if ( nunchuckConnected ) // Update if it's a report from the Nunchuck
ButtonState = ( uint32_t ) ( ( l2capinbuf [ 10 ] & 0x1F ) | ( ( uint16_t ) ( l2capinbuf [ 11 ] & 0x9F ) < < 8 ) | ( ( uint32_t ) ( ( ~ l2capinbuf [ 20 ] ) & 0x0C ) < < 14 ) ) ;
//else if(classicControllerConnected) // Update if it's a report from the Classic Controller
} else if ( nunchuckConnected ) // The Nunchuck is directly connected
ButtonState = ( uint32_t ) ( ( l2capinbuf [ 10 ] & 0x1F ) | ( ( uint16_t ) ( l2capinbuf [ 11 ] & 0x9F ) < < 8 ) | ( ( uint32_t ) ( ( ~ l2capinbuf [ 20 ] ) & 0x03 ) < < 16 ) ) ;
//else if(classicControllerConnected) // The Classic Controller is directly connected
else if ( ! unknownExtensionConnected )
ButtonState = ( uint32_t ) ( ( l2capinbuf [ 10 ] & 0x1F ) | ( ( uint16_t ) ( l2capinbuf [ 11 ] & 0x9F ) < < 8 ) ) ;
2012-08-21 17:36:37 +02:00
# ifdef PRINTREPORT
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " ButtonState: " ) , 0x80 ) ;
D_PrintHex < uint32_t > ( ButtonState , 0x80 ) ;
Notify ( PSTR ( " \r \n " ) , 0x80 ) ;
2012-08-21 17:36:37 +02:00
# endif
2013-07-18 19:53:18 +02:00
if ( ButtonState ! = OldButtonState ) {
ButtonClickState = ButtonState & ~ OldButtonState ; // Update click state variable
OldButtonState = ButtonState ;
2013-03-28 09:46:43 +01:00
}
2013-07-18 19:53:18 +02:00
}
if ( l2capinbuf [ 9 ] = = 0x31 | | l2capinbuf [ 9 ] = = 0x33 | | l2capinbuf [ 9 ] = = 0x35 | | l2capinbuf [ 9 ] = = 0x37 ) { // Read the accelerometer
2013-10-21 18:41:47 +02:00
accXwiimote = ( ( l2capinbuf [ 12 ] < < 2 ) | ( l2capinbuf [ 10 ] & 0x60 > > 5 ) ) - 500 ;
accYwiimote = ( ( l2capinbuf [ 13 ] < < 2 ) | ( l2capinbuf [ 11 ] & 0x20 > > 4 ) ) - 500 ;
accZwiimote = ( ( l2capinbuf [ 14 ] < < 2 ) | ( l2capinbuf [ 11 ] & 0x40 > > 5 ) ) - 500 ;
2013-07-18 19:53:18 +02:00
}
switch ( l2capinbuf [ 9 ] ) {
case 0x20 : // Status Information - (a1) 20 BB BB LF 00 00 VV
2013-07-18 19:43:21 +02:00
# ifdef EXTRADEBUG
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Status report was received " ) , 0x80 ) ;
2013-07-18 19:43:21 +02:00
# endif
2013-07-18 19:53:18 +02:00
wiiState = l2capinbuf [ 12 ] ; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
batteryLevel = l2capinbuf [ 15 ] ; // Update battery level
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
if ( l2capinbuf [ 12 ] & 0x01 )
Notify ( PSTR ( " \r \n WARNING: Battery is nearly empty " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-07-18 19:53:18 +02:00
if ( checkExtension ) { // If this is false it means that the user must have called getBatteryLevel()
if ( l2capinbuf [ 12 ] & 0x02 ) { // Check if a extension is connected
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
if ( ! unknownExtensionConnected )
Notify ( PSTR ( " \r \n Extension connected " ) , 0x80 ) ;
2012-08-22 23:41:38 +02:00
# endif
2013-07-18 19:53:18 +02:00
unknownExtensionConnected = true ;
2013-01-24 00:23:09 +01:00
# ifdef WIICAMERA
2013-07-18 19:53:18 +02:00
if ( ! isIRCameraEnabled ( ) ) // Don't activate the Motion Plus if we are trying to initialize the IR camera
2013-03-28 09:37:09 +01:00
# endif
2013-07-18 19:53:18 +02:00
setReportMode ( false , 0x35 ) ; // Also read the extension
} else {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Extension disconnected " ) , 0x80 ) ;
2012-08-22 23:41:38 +02:00
# endif
2013-07-18 19:53:18 +02:00
if ( motionPlusConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " - from Motion Plus " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
l2cap_event_flag & = ~ WII_FLAG_NUNCHUCK_CONNECTED ;
if ( ! activateNunchuck ) // If it's already trying to initialize the Nunchuck don't set it to false
nunchuckConnected = false ;
//else if(classicControllerConnected)
} else if ( nunchuckConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " - Nunchuck " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
nunchuckConnected = false ; // It must be the Nunchuck controller then
l2cap_event_flag & = ~ WII_FLAG_NUNCHUCK_CONNECTED ;
onInit ( ) ;
setReportMode ( false , 0x31 ) ; // If there is no extension connected we will read the buttons and accelerometer
} else
setReportMode ( false , 0x31 ) ; // If there is no extension connected we will read the buttons and accelerometer
}
} else
checkExtension = true ; // Check for extensions by default
break ;
case 0x21 : // Read Memory Data
if ( ( l2capinbuf [ 12 ] & 0x0F ) = = 0 ) { // No error
// See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
if ( l2capinbuf [ 16 ] = = 0x00 & & l2capinbuf [ 17 ] = = 0xA4 & & l2capinbuf [ 18 ] = = 0x20 & & l2capinbuf [ 19 ] = = 0x00 & & l2capinbuf [ 20 ] = = 0x00 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Nunchuck connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
l2cap_event_flag | = WII_FLAG_NUNCHUCK_CONNECTED ;
} else if ( l2capinbuf [ 16 ] = = 0x00 & & ( l2capinbuf [ 17 ] = = 0xA6 | | l2capinbuf [ 17 ] = = 0xA4 ) & & l2capinbuf [ 18 ] = = 0x20 & & l2capinbuf [ 19 ] = = 0x00 & & l2capinbuf [ 20 ] = = 0x05 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Motion Plus connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
l2cap_event_flag | = WII_FLAG_MOTION_PLUS_CONNECTED ;
} else if ( l2capinbuf [ 16 ] = = 0x00 & & l2capinbuf [ 17 ] = = 0xA4 & & l2capinbuf [ 18 ] = = 0x20 & & l2capinbuf [ 19 ] = = 0x04 & & l2capinbuf [ 20 ] = = 0x05 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Motion Plus activated in normal mode " ) , 0x80 ) ;
2012-08-22 23:41:38 +02:00
# endif
2013-07-18 19:53:18 +02:00
motionPlusConnected = true ;
2013-08-13 22:31:51 +02:00
# ifdef WIICAMERA
if ( ! isIRCameraEnabled ( ) ) // Don't activate the Motion Plus if we are trying to initialize the IR camera
# endif
setReportMode ( false , 0x35 ) ; // Also read the extension
2013-07-18 19:53:18 +02:00
} else if ( l2capinbuf [ 16 ] = = 0x00 & & l2capinbuf [ 17 ] = = 0xA4 & & l2capinbuf [ 18 ] = = 0x20 & & l2capinbuf [ 19 ] = = 0x05 & & l2capinbuf [ 20 ] = = 0x05 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Motion Plus activated in Nunchuck pass-through mode " ) , 0x80 ) ;
2012-08-22 23:41:38 +02:00
# endif
2013-07-18 19:53:18 +02:00
activateNunchuck = false ;
motionPlusConnected = true ;
nunchuckConnected = true ;
2013-08-13 22:31:51 +02:00
# ifdef WIICAMERA
if ( ! isIRCameraEnabled ( ) ) // Don't activate the Motion Plus if we are trying to initialize the IR camera
# endif
setReportMode ( false , 0x35 ) ; // Also read the extension
2013-07-18 19:53:18 +02:00
} else if ( l2capinbuf [ 16 ] = = 0x00 & & l2capinbuf [ 17 ] = = 0xA6 & & l2capinbuf [ 18 ] = = 0x20 & & ( l2capinbuf [ 19 ] = = 0x00 | | l2capinbuf [ 19 ] = = 0x04 | | l2capinbuf [ 19 ] = = 0x05 | | l2capinbuf [ 19 ] = = 0x07 ) & & l2capinbuf [ 20 ] = = 0x05 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Inactive Wii Motion Plus " ) , 0x80 ) ;
Notify ( PSTR ( " \r \n Please unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension " ) , 0x80 ) ;
2012-10-07 20:07:48 +02:00
# endif
2013-07-18 19:53:18 +02:00
stateCounter = 300 ; // Skip the rest in "L2CAP_CHECK_MOTION_PLUS_STATE"
} else if ( l2capinbuf [ 16 ] = = 0x00 & & l2capinbuf [ 17 ] = = 0xA4 & & l2capinbuf [ 18 ] = = 0x20 & & l2capinbuf [ 19 ] = = 0x01 & & l2capinbuf [ 20 ] = = 0x20 ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Wii U Pro Controller connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
wiiUProControllerConnected = true ;
2013-03-28 09:46:43 +01:00
}
2013-07-18 19:53:18 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
else {
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Unknown Device: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Data: " ) , 0x80 ) ;
for ( uint8_t i = 0 ; i < ( ( l2capinbuf [ 12 ] > > 4 ) + 1 ) ; i + + ) { // bit 4-7 is the length-1
D_PrintHex < uint8_t > ( l2capinbuf [ 15 + i ] , 0x80 ) ;
Notify ( PSTR ( " " ) , 0x80 ) ;
}
2013-03-28 09:46:43 +01:00
}
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
}
# ifdef EXTRADEBUG
else {
Notify ( PSTR ( " \r \n Report Error: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 13 ] , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 14 ] , 0x80 ) ;
}
# endif
break ;
case 0x22 : // Acknowledge output report, return function result
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
if ( l2capinbuf [ 13 ] ! = 0x00 ) { // Check if there is an error
Notify ( PSTR ( " \r \n Command failed: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 12 ] , 0x80 ) ;
}
2013-03-28 09:37:09 +01:00
# endif
2013-07-18 19:53:18 +02:00
break ;
case 0x30 : // Core buttons - (a1) 30 BB BB
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 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
2013-01-17 00:07:56 +01:00
# ifdef WIICAMERA
2013-07-18 19:53:18 +02:00
// Read the IR data
IR_object_x1 = ( l2capinbuf [ 15 ] | ( ( uint16_t ) ( l2capinbuf [ 17 ] & 0x30 ) < < 4 ) ) ; // x position
IR_object_y1 = ( l2capinbuf [ 16 ] | ( ( uint16_t ) ( l2capinbuf [ 17 ] & 0xC0 ) < < 2 ) ) ; // y position
IR_object_s1 = ( l2capinbuf [ 17 ] & 0x0F ) ; // size value, 0-15
IR_object_x2 = ( l2capinbuf [ 18 ] | ( ( uint16_t ) ( l2capinbuf [ 20 ] & 0x30 ) < < 4 ) ) ;
IR_object_y2 = ( l2capinbuf [ 19 ] | ( ( uint16_t ) ( l2capinbuf [ 20 ] & 0xC0 ) < < 2 ) ) ;
IR_object_s2 = ( l2capinbuf [ 20 ] & 0x0F ) ;
IR_object_x3 = ( l2capinbuf [ 21 ] | ( ( uint16_t ) ( l2capinbuf [ 23 ] & 0x30 ) < < 4 ) ) ;
IR_object_y3 = ( l2capinbuf [ 22 ] | ( ( uint16_t ) ( l2capinbuf [ 23 ] & 0xC0 ) < < 2 ) ) ;
IR_object_s3 = ( l2capinbuf [ 23 ] & 0x0F ) ;
IR_object_x4 = ( l2capinbuf [ 24 ] | ( ( uint16_t ) ( l2capinbuf [ 26 ] & 0x30 ) < < 4 ) ) ;
IR_object_y4 = ( l2capinbuf [ 25 ] | ( ( uint16_t ) ( l2capinbuf [ 26 ] & 0xC0 ) < < 2 ) ) ;
IR_object_s4 = ( l2capinbuf [ 26 ] & 0x0F ) ;
2013-01-17 00:07:56 +01:00
# endif
2013-07-18 19:53:18 +02:00
break ;
case 0x34 : // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
break ;
/* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */
case 0x3E : // Core Buttons with Accelerometer and 32 IR bytes
// (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II
// corresponds to output report mode 0x3e
/**** for reading in full mode: DOES NOT WORK YET ****/
/* When it works it will also have intensity and bounding box data */
/*
IR_object_x1 = ( l2capinbuf [ 13 ] | ( ( uint16_t ) ( l2capinbuf [ 15 ] & 0x30 ) < < 4 ) ) ;
IR_object_y1 = ( l2capinbuf [ 14 ] | ( ( uint16_t ) ( l2capinbuf [ 15 ] & 0xC0 ) < < 2 ) ) ;
IR_object_s1 = ( l2capinbuf [ 15 ] & 0x0F ) ;
*/
break ;
case 0x3F :
/*
IR_object_x1 = ( l2capinbuf [ 13 ] | ( ( uint16_t ) ( l2capinbuf [ 15 ] & 0x30 ) < < 4 ) ) ;
IR_object_y1 = ( l2capinbuf [ 14 ] | ( ( uint16_t ) ( l2capinbuf [ 15 ] & 0xC0 ) < < 2 ) ) ;
IR_object_s1 = ( l2capinbuf [ 15 ] & 0x0F ) ;
*/
break ;
case 0x35 : // Core Buttons and Accelerometer with 16 Extension Bytes
// (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
if ( motionPlusConnected ) {
if ( l2capinbuf [ 20 ] & 0x02 ) { // Check if it's a report from the Motion controller or the extension
if ( motionValuesReset ) { // We will only use the values when the gyro value has been set
gyroYawRaw = ( ( l2capinbuf [ 15 ] | ( ( l2capinbuf [ 18 ] & 0xFC ) < < 6 ) ) - gyroYawZero ) ;
gyroRollRaw = ( ( l2capinbuf [ 16 ] | ( ( l2capinbuf [ 19 ] & 0xFC ) < < 6 ) ) - gyroRollZero ) ;
gyroPitchRaw = ( ( l2capinbuf [ 17 ] | ( ( l2capinbuf [ 20 ] & 0xFC ) < < 6 ) ) - gyroPitchZero ) ;
yawGyroSpeed = ( double ) gyroYawRaw / ( ( double ) gyroYawZero / yawGyroScale ) ;
rollGyroSpeed = - ( double ) gyroRollRaw / ( ( double ) gyroRollZero / rollGyroScale ) ; // We invert these values so they will fit the acc values
pitchGyroSpeed = ( double ) gyroPitchRaw / ( ( double ) gyroPitchZero / pitchGyroScale ) ;
/* The onboard gyro has two ranges for slow and fast mode */
2013-11-12 19:38:18 +01:00
if ( ! ( l2capinbuf [ 18 ] & 0x02 ) ) // Check if fast mode is used
2013-07-18 19:53:18 +02:00
yawGyroSpeed * = 4.545 ;
2013-11-12 19:38:18 +01:00
if ( ! ( l2capinbuf [ 18 ] & 0x01 ) ) // Check if fast mode is used
2013-07-18 19:53:18 +02:00
pitchGyroSpeed * = 4.545 ;
2013-11-12 19:38:18 +01:00
if ( ! ( l2capinbuf [ 19 ] & 0x02 ) ) // Check if fast mode is used
2013-07-18 19:53:18 +02:00
rollGyroSpeed * = 4.545 ;
2013-10-21 18:41:47 +02:00
compPitch = ( 0.93 * ( compPitch + ( pitchGyroSpeed * ( double ) ( micros ( ) - timer ) / 1000000 ) ) ) + ( 0.07 * getWiimotePitch ( ) ) ; // Use a complimentary filter to calculate the angle
compRoll = ( 0.93 * ( compRoll + ( rollGyroSpeed * ( double ) ( micros ( ) - timer ) / 1000000 ) ) ) + ( 0.07 * getWiimoteRoll ( ) ) ;
2013-07-18 19:53:18 +02:00
gyroYaw + = ( yawGyroSpeed * ( ( double ) ( micros ( ) - timer ) / 1000000 ) ) ;
gyroRoll + = ( rollGyroSpeed * ( ( double ) ( micros ( ) - timer ) / 1000000 ) ) ;
gyroPitch + = ( pitchGyroSpeed * ( ( double ) ( micros ( ) - timer ) / 1000000 ) ) ;
timer = micros ( ) ;
/*
// Uncomment these lines to tune the gyro scale variabels
Notify ( PSTR ( " \r \n gyroYaw: " ) , 0x80 ) ;
Notify ( gyroYaw , 0x80 ) ;
Notify ( PSTR ( " \t gyroRoll: " ) , 0x80 ) ;
Notify ( gyroRoll , 0x80 ) ;
Notify ( PSTR ( " \t gyroPitch: " ) , 0x80 ) ;
Notify ( gyroPitch , 0x80 ) ;
*/
/*
Notify ( PSTR ( " \t wiimoteRoll: " ) , 0x80 ) ;
Notify ( wiimoteRoll , 0x80 ) ;
Notify ( PSTR ( " \t wiimotePitch: " ) , 0x80 ) ;
Notify ( wiimotePitch , 0x80 ) ;
*/
} else {
if ( ( micros ( ) - timer ) > 1000000 ) { // Loop for 1 sec before resetting the values
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n The gyro values has been reset " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-07-18 19:53:18 +02:00
gyroYawZero = ( l2capinbuf [ 15 ] | ( ( l2capinbuf [ 18 ] & 0xFC ) < < 6 ) ) ;
gyroRollZero = ( l2capinbuf [ 16 ] | ( ( l2capinbuf [ 19 ] & 0xFC ) < < 6 ) ) ;
gyroPitchZero = ( l2capinbuf [ 17 ] | ( ( l2capinbuf [ 20 ] & 0xFC ) < < 6 ) ) ;
2013-03-28 09:46:43 +01:00
2013-07-18 19:53:18 +02:00
rollGyroScale = 500 ; // You might need to adjust these
pitchGyroScale = 400 ;
yawGyroScale = 415 ;
2013-03-28 09:46:43 +01:00
2013-07-18 19:53:18 +02:00
gyroYaw = 0 ;
gyroRoll = 0 ;
gyroPitch = 0 ;
2013-03-28 09:46:43 +01:00
2013-07-18 19:53:18 +02:00
motionValuesReset = true ;
timer = micros ( ) ;
2013-03-28 09:46:43 +01:00
}
}
2013-07-18 19:53:18 +02:00
} else {
if ( nunchuckConnected ) {
hatValues [ HatX ] = l2capinbuf [ 15 ] ;
hatValues [ HatY ] = l2capinbuf [ 16 ] ;
2013-10-21 18:41:47 +02:00
accXnunchuck = ( ( l2capinbuf [ 17 ] < < 2 ) | ( l2capinbuf [ 20 ] & 0x10 > > 3 ) ) - 416 ;
accYnunchuck = ( ( l2capinbuf [ 18 ] < < 2 ) | ( l2capinbuf [ 20 ] & 0x20 > > 4 ) ) - 416 ;
accZnunchuck = ( ( ( l2capinbuf [ 19 ] & 0xFE ) < < 2 ) | ( l2capinbuf [ 20 ] & 0xC0 > > 5 ) ) - 416 ;
2013-07-18 19:53:18 +02:00
}
//else if(classicControllerConnected) { }
}
if ( l2capinbuf [ 19 ] & 0x01 ) {
if ( ! extensionConnected ) {
extensionConnected = true ;
unknownExtensionConnected = true ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Extension connected to Motion Plus " ) , 0x80 ) ;
2012-08-24 00:59:43 +02:00
# endif
2013-07-18 19:53:18 +02:00
}
} else {
if ( extensionConnected & & ! unknownExtensionConnected ) {
extensionConnected = false ;
unknownExtensionConnected = true ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
Notify ( PSTR ( " \r \n Extension disconnected from Motion Plus " ) , 0x80 ) ;
2012-08-24 00:59:43 +02:00
# endif
2013-07-18 19:53:18 +02:00
nunchuckConnected = false ; // There is no extension connected to the Motion Plus if this report is sent
2013-03-28 09:46:43 +01:00
}
}
2013-07-18 19:53:18 +02:00
} else if ( nunchuckConnected ) {
hatValues [ HatX ] = l2capinbuf [ 15 ] ;
hatValues [ HatY ] = l2capinbuf [ 16 ] ;
2013-10-21 18:41:47 +02:00
accXnunchuck = ( ( l2capinbuf [ 17 ] < < 2 ) | ( l2capinbuf [ 20 ] & 0x0C > > 2 ) ) - 416 ;
accYnunchuck = ( ( l2capinbuf [ 18 ] < < 2 ) | ( l2capinbuf [ 20 ] & 0x30 > > 4 ) ) - 416 ;
accZnunchuck = ( ( l2capinbuf [ 19 ] < < 2 ) | ( l2capinbuf [ 20 ] & 0xC0 > > 6 ) ) - 416 ;
2013-07-18 19:53:18 +02:00
} else if ( wiiUProControllerConnected ) {
hatValues [ LeftHatX ] = ( l2capinbuf [ 15 ] | l2capinbuf [ 16 ] < < 8 ) ;
hatValues [ RightHatX ] = ( l2capinbuf [ 17 ] | l2capinbuf [ 18 ] < < 8 ) ;
hatValues [ LeftHatY ] = ( l2capinbuf [ 19 ] | l2capinbuf [ 20 ] < < 8 ) ;
hatValues [ RightHatY ] = ( l2capinbuf [ 21 ] | l2capinbuf [ 22 ] < < 8 ) ;
}
break ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-18 19:53:18 +02:00
default :
Notify ( PSTR ( " \r \n Unknown Report type: " ) , 0x80 ) ;
D_PrintHex < uint8_t > ( l2capinbuf [ 9 ] , 0x80 ) ;
break ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
}
2013-07-18 19:53:18 +02:00
}
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
L2CAP_task ( ) ;
2012-08-21 14:31:11 +02:00
}
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : L2CAP_task ( ) {
2013-03-28 09:46:43 +01:00
switch ( l2cap_state ) {
/* These states are used if the Wiimote is the host */
case L2CAP_CONTROL_SUCCESS :
if ( l2cap_config_success_control_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n HID Control Successfully Configured " ) , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2013-03-28 09:46:43 +01:00
l2cap_state = L2CAP_INTERRUPT_SETUP ;
}
break ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
case L2CAP_INTERRUPT_SETUP :
if ( l2cap_connection_request_interrupt_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n HID Interrupt Incoming Connection Request " ) , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2013-03-28 09:46:43 +01:00
pBtd - > l2cap_connection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , interrupt_dcid , interrupt_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , interrupt_scid ) ;
l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST ;
}
break ;
/* These states are used if the Arduino is the host */
case L2CAP_CONTROL_CONNECT_REQUEST :
if ( l2cap_connected_control_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send HID Control Config Request " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier + + ;
pBtd - > l2cap_config_request ( hci_handle , identifier , control_scid ) ;
l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST ;
}
break ;
case L2CAP_CONTROL_CONFIG_REQUEST :
if ( l2cap_config_success_control_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send HID Interrupt Connection Request " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier + + ;
pBtd - > l2cap_connection_request ( hci_handle , identifier , interrupt_dcid , HID_INTR_PSM ) ;
l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST ;
}
break ;
case L2CAP_INTERRUPT_CONNECT_REQUEST :
if ( l2cap_connected_interrupt_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send HID Interrupt Config Request " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier + + ;
pBtd - > l2cap_config_request ( hci_handle , identifier , interrupt_scid ) ;
l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST ;
}
break ;
case L2CAP_INTERRUPT_CONFIG_REQUEST :
if ( l2cap_config_success_interrupt_flag ) { // Now the HID channels is established
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n HID Channels Established " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
pBtd - > connectToWii = false ;
pBtd - > pairWithWii = false ;
stateCounter = 0 ;
l2cap_state = L2CAP_CHECK_MOTION_PLUS_STATE ;
}
break ;
/* The next states are in run() */
case L2CAP_INTERRUPT_DISCONNECT :
2013-07-18 19:43:21 +02:00
if ( l2cap_disconnect_response_interrupt_flag & & millis ( ) > timer ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Disconnected Interrupt Channel " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
identifier + + ;
pBtd - > l2cap_disconnection_request ( hci_handle , identifier , control_scid , control_dcid ) ;
l2cap_state = L2CAP_CONTROL_DISCONNECT ;
}
break ;
case L2CAP_CONTROL_DISCONNECT :
if ( l2cap_disconnect_response_control_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Disconnected Control Channel " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
pBtd - > hci_disconnect ( hci_handle ) ;
hci_handle = - 1 ; // Reset handle
l2cap_event_flag = 0 ; // Reset flags
l2cap_state = L2CAP_WAIT ;
}
break ;
}
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : Run ( ) {
2013-07-18 19:43:21 +02:00
if ( l2cap_state = = L2CAP_INTERRUPT_DISCONNECT & & millis ( ) > timer )
L2CAP_task ( ) ; // Call the rest of the disconnection routine after we have waited long enough
2013-03-28 09:46:43 +01:00
switch ( l2cap_state ) {
case L2CAP_WAIT :
if ( pBtd - > connectToWii & & ! pBtd - > l2capConnectionClaimed & & ! wiimoteConnected & & ! activeConnection ) {
pBtd - > l2capConnectionClaimed = true ;
activeConnection = true ;
2013-07-18 19:43:21 +02:00
motionPlusInside = pBtd - > motionPlusInside ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Send HID Control Connection Request " ) , 0x80 ) ;
2012-08-21 14:31:11 +02:00
# endif
2013-03-28 09:46:43 +01:00
hci_handle = pBtd - > hci_handle ; // Store the HCI Handle for the connection
l2cap_event_flag = 0 ; // Reset flags
identifier = 0 ;
pBtd - > l2cap_connection_request ( hci_handle , identifier , control_dcid , HID_CTRL_PSM ) ;
l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST ;
} else if ( l2cap_connection_request_control_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n HID Control Incoming Connection Request " ) , 0x80 ) ;
2012-10-07 14:50:51 +02:00
# endif
2013-03-28 09:46:43 +01:00
pBtd - > l2cap_connection_response ( hci_handle , identifier , control_dcid , control_scid , PENDING ) ;
delay ( 1 ) ;
pBtd - > l2cap_connection_response ( hci_handle , identifier , control_dcid , control_scid , SUCCESSFUL ) ;
identifier + + ;
delay ( 1 ) ;
pBtd - > l2cap_config_request ( hci_handle , identifier , control_scid ) ;
l2cap_state = L2CAP_CONTROL_SUCCESS ;
}
break ;
case L2CAP_CHECK_MOTION_PLUS_STATE :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
if ( stateCounter = = 0 ) // Only print onnce
Notify ( PSTR ( " \r \n Checking if a Motion Plus is connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
stateCounter + + ;
if ( stateCounter % 200 = = 0 )
checkMotionPresent ( ) ; // Check if there is a motion plus connected
if ( motion_plus_connected_flag ) {
stateCounter = 0 ;
l2cap_state = L2CAP_INIT_MOTION_PLUS_STATE ;
timer = micros ( ) ;
if ( unknownExtensionConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n A extension is also connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
activateNunchuck = true ; // For we will just set this to true as this the only extension supported so far
}
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
} else if ( stateCounter = = 601 ) { // We will try three times to check for the motion plus
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n No Motion Plus was detected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
stateCounter = 0 ;
l2cap_state = L2CAP_CHECK_EXTENSION_STATE ;
}
break ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
case L2CAP_CHECK_EXTENSION_STATE : // This is used to check if there is anything plugged in to the extension port
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
if ( stateCounter = = 0 ) // Only print onnce
Notify ( PSTR ( " \r \n Checking if there is any extension connected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
stateCounter + + ; // We use this counter as there has to be a short delay between the commands
if ( stateCounter = = 1 )
statusRequest ( ) ; // See if a new device has connected
if ( stateCounter = = 100 ) {
if ( unknownExtensionConnected ) // Check if there is a extension is connected to the port
initExtension1 ( ) ;
else
stateCounter = 399 ;
} else if ( stateCounter = = 200 )
initExtension2 ( ) ;
else if ( stateCounter = = 300 ) {
readExtensionType ( ) ;
unknownExtensionConnected = false ;
} else if ( stateCounter = = 400 ) {
stateCounter = 0 ;
l2cap_state = L2CAP_LED_STATE ;
}
break ;
case L2CAP_INIT_MOTION_PLUS_STATE :
stateCounter + + ;
if ( stateCounter = = 1 )
initMotionPlus ( ) ;
else if ( stateCounter = = 100 )
activateMotionPlus ( ) ;
else if ( stateCounter = = 200 )
readExtensionType ( ) ; // Check if it has been activated
else if ( stateCounter = = 300 ) {
stateCounter = 0 ;
unknownExtensionConnected = false ; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus
l2cap_state = L2CAP_LED_STATE ;
}
break ;
case L2CAP_LED_STATE :
if ( nunchuck_connected_flag )
nunchuckConnected = true ;
2013-07-18 19:43:21 +02:00
wiimoteConnected = true ;
2013-07-14 00:43:35 +02:00
onInit ( ) ;
2013-03-28 09:46:43 +01:00
l2cap_state = L2CAP_DONE ;
break ;
case L2CAP_DONE :
if ( unknownExtensionConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
if ( stateCounter = = 0 ) // Only print once
Notify ( PSTR ( " \r \n Checking extension port " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
stateCounter + + ; // We will use this counter as there has to be a short delay between the commands
if ( stateCounter = = 50 )
statusRequest ( ) ;
else if ( stateCounter = = 100 )
initExtension1 ( ) ;
else if ( stateCounter = = 150 )
if ( ( extensionConnected & & motionPlusConnected ) | | ( unknownExtensionConnected & & ! motionPlusConnected ) )
initExtension2 ( ) ;
else
stateCounter = 299 ; // There is no extension connected
else if ( stateCounter = = 200 )
readExtensionType ( ) ;
else if ( stateCounter = = 250 ) {
if ( nunchuck_connected_flag ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Nunchuck was reconnected " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
activateNunchuck = true ;
nunchuckConnected = true ;
}
if ( ! motionPlusConnected )
stateCounter = 449 ;
} else if ( stateCounter = = 300 ) {
if ( motionPlusConnected ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Reactivating the Motion Plus " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
initMotionPlus ( ) ;
} else
stateCounter = 449 ;
} else if ( stateCounter = = 350 )
activateMotionPlus ( ) ;
else if ( stateCounter = = 400 )
readExtensionType ( ) ; // Check if it has been activated
else if ( stateCounter = = 450 ) {
2013-07-14 00:43:35 +02:00
onInit ( ) ;
2013-03-28 09:46:43 +01:00
stateCounter = 0 ;
unknownExtensionConnected = false ;
}
} else
stateCounter = 0 ;
break ;
}
2012-08-21 14:31:11 +02:00
}
/************************************************************/
/* HID Commands */
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
/************************************************************/
void WII : : HID_Command ( uint8_t * data , uint8_t nbytes ) {
2013-07-18 19:43:21 +02:00
if ( motionPlusInside )
2013-03-28 09:46:43 +01:00
pBtd - > L2CAP_Command ( hci_handle , data , nbytes , interrupt_scid [ 0 ] , interrupt_scid [ 1 ] ) ; // It's the new wiimote with the Motion Plus Inside
else
pBtd - > L2CAP_Command ( hci_handle , data , nbytes , control_scid [ 0 ] , control_scid [ 1 ] ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setAllOff ( ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] = 0x00 ;
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setRumbleOff ( ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] & = ~ 0x01 ; // Bit 0 control the rumble
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setRumbleOn ( ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] | = 0x01 ; // Bit 0 control the rumble
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setRumbleToggle ( ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] ^ = 0x01 ; // Bit 0 control the rumble
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2013-04-01 15:38:15 +02:00
void WII : : setLedRaw ( uint8_t value ) {
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] = value | ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit
HID_Command ( HIDBuffer , 3 ) ;
}
2012-08-21 14:31:11 +02:00
void WII : : setLedOff ( LED a ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] & = ~ ( pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) ) ;
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setLedOn ( LED a ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] | = pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) ;
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
void WII : : setLedToggle ( LED a ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] ^ = pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) ;
HID_Command ( HIDBuffer , 3 ) ;
2012-08-21 17:36:37 +02:00
}
2013-03-28 09:46:43 +01:00
2012-10-06 16:42:00 +02:00
void WII : : setLedStatus ( ) {
2013-03-28 09:46:43 +01:00
HIDBuffer [ 1 ] = 0x11 ;
HIDBuffer [ 2 ] = ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit
if ( wiimoteConnected )
HIDBuffer [ 2 ] | = 0x10 ; // If it's connected LED1 will light up
if ( motionPlusConnected )
HIDBuffer [ 2 ] | = 0x20 ; // If it's connected LED2 will light up
if ( nunchuckConnected )
HIDBuffer [ 2 ] | = 0x40 ; // If it's connected LED3 will light up
HID_Command ( HIDBuffer , 3 ) ;
2012-10-06 16:42:00 +02:00
}
2013-03-28 09:46:43 +01:00
2013-07-18 19:43:21 +02:00
uint8_t WII : : getBatteryLevel ( ) {
checkExtension = false ; // This is needed so the library knows that the status response is a response to this function
statusRequest ( ) ; // This will update the battery level
return batteryLevel ;
} ;
2012-08-21 17:36:37 +02:00
void WII : : setReportMode ( bool continuous , uint8_t mode ) {
2013-03-28 09:46:43 +01:00
uint8_t cmd_buf [ 4 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x12 ;
if ( continuous )
cmd_buf [ 2 ] = 0x04 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit
else
cmd_buf [ 2 ] = 0x00 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit
cmd_buf [ 3 ] = mode ;
HID_Command ( cmd_buf , 4 ) ;
2012-08-21 17:36:37 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-21 17:36:37 +02:00
void WII : : statusRequest ( ) {
2013-03-28 09:46:43 +01:00
uint8_t cmd_buf [ 3 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x15 ;
cmd_buf [ 2 ] = ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit
HID_Command ( cmd_buf , 3 ) ;
2012-08-21 14:31:11 +02:00
}
2012-08-22 23:41:38 +02:00
/************************************************************/
/* Memmory Commands */
2013-03-28 09:46:43 +01:00
2012-08-22 23:41:38 +02:00
/************************************************************/
void WII : : writeData ( uint32_t offset , uint8_t size , uint8_t * data ) {
2013-03-28 09:46:43 +01:00
uint8_t cmd_buf [ 23 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x16 ; // Write data
cmd_buf [ 2 ] = 0x04 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Write to memory, clear bit 2 to write to EEPROM
cmd_buf [ 3 ] = ( uint8_t ) ( ( offset & 0xFF0000 ) > > 16 ) ;
cmd_buf [ 4 ] = ( uint8_t ) ( ( offset & 0xFF00 ) > > 8 ) ;
cmd_buf [ 5 ] = ( uint8_t ) ( offset & 0xFF ) ;
cmd_buf [ 6 ] = size ;
uint8_t i = 0 ;
for ( ; i < size ; i + + )
cmd_buf [ 7 + i ] = data [ i ] ;
for ( ; i < 16 ; i + + ) // Set the rest to zero
cmd_buf [ 7 + i ] = 0x00 ;
HID_Command ( cmd_buf , 23 ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-23 23:10:12 +02:00
void WII : : initExtension1 ( ) {
2013-03-28 09:46:43 +01:00
uint8_t buf [ 1 ] ;
buf [ 0 ] = 0x55 ;
writeData ( 0xA400F0 , 1 , buf ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-23 23:10:12 +02:00
void WII : : initExtension2 ( ) {
2013-03-28 09:46:43 +01:00
uint8_t buf [ 1 ] ;
buf [ 0 ] = 0x00 ;
writeData ( 0xA400FB , 1 , buf ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-23 23:10:12 +02:00
void WII : : initMotionPlus ( ) {
2013-03-28 09:46:43 +01:00
uint8_t buf [ 1 ] ;
buf [ 0 ] = 0x55 ;
writeData ( 0xA600F0 , 1 , buf ) ;
2012-08-23 23:10:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-23 23:10:12 +02:00
void WII : : activateMotionPlus ( ) {
2013-03-28 09:46:43 +01:00
uint8_t buf [ 1 ] ;
if ( pBtd - > wiiUProController ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Activating Wii U Pro Controller " ) , 0x80 ) ;
2013-02-02 22:14:01 +01:00
# endif
2013-03-28 09:46:43 +01:00
buf [ 0 ] = 0x00 ; // It seems like you can send anything but 0x04, 0x05, and 0x07
} else if ( activateNunchuck ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Activating Motion Plus in pass-through mode " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
buf [ 0 ] = 0x05 ; // Activate nunchuck pass-through mode
} //else if(classicControllerConnected && extensionConnected)
//buf[0] = 0x07;
else {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Activating Motion Plus in normal mode " ) , 0x80 ) ;
2012-08-23 23:10:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
buf [ 0 ] = 0x04 ; // Don't use any extension
}
writeData ( 0xA600FE , 1 , buf ) ;
2012-08-23 23:10:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-22 23:41:38 +02:00
void WII : : readData ( uint32_t offset , uint16_t size , bool EEPROM ) {
2013-03-28 09:46:43 +01:00
uint8_t cmd_buf [ 8 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x17 ; // Read data
if ( EEPROM )
cmd_buf [ 2 ] = 0x00 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Read from EEPROM
else
cmd_buf [ 2 ] = 0x04 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Read from memory
cmd_buf [ 3 ] = ( uint8_t ) ( ( offset & 0xFF0000 ) > > 16 ) ;
cmd_buf [ 4 ] = ( uint8_t ) ( ( offset & 0xFF00 ) > > 8 ) ;
cmd_buf [ 5 ] = ( uint8_t ) ( offset & 0xFF ) ;
cmd_buf [ 6 ] = ( uint8_t ) ( ( size & 0xFF00 ) > > 8 ) ;
cmd_buf [ 7 ] = ( uint8_t ) ( size & 0xFF ) ;
HID_Command ( cmd_buf , 8 ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-22 23:41:38 +02:00
void WII : : readExtensionType ( ) {
2013-03-28 09:46:43 +01:00
readData ( 0xA400FA , 6 , false ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-22 23:41:38 +02:00
void WII : : readCalData ( ) {
2013-03-28 09:46:43 +01:00
readData ( 0x0016 , 8 , true ) ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-23 23:10:12 +02:00
void WII : : checkMotionPresent ( ) {
2013-03-28 09:46:43 +01:00
readData ( 0xA600FA , 6 , false ) ;
2012-08-23 23:10:12 +02:00
}
2012-08-22 23:41:38 +02:00
2012-08-21 14:31:11 +02:00
/************************************************************/
/* WII Commands */
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
/************************************************************/
2012-08-22 23:41:38 +02:00
bool WII : : getButtonPress ( Button b ) { // Return true when a button is pressed
2013-03-28 09:46:43 +01:00
if ( wiiUProControllerConnected )
return ( ButtonState & pgm_read_dword ( & PROCONTROLLERBUTTONS [ ( uint8_t ) b ] ) ) ;
else
return ( ButtonState & pgm_read_dword ( & BUTTONS [ ( uint8_t ) b ] ) ) ;
2012-08-21 14:31:11 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-22 23:41:38 +02:00
bool WII : : getButtonClick ( Button b ) { // Only return true when a button is clicked
2013-03-28 09:46:43 +01:00
uint32_t button ;
if ( wiiUProControllerConnected )
button = pgm_read_dword ( & PROCONTROLLERBUTTONS [ ( uint8_t ) b ] ) ;
else
button = pgm_read_dword ( & BUTTONS [ ( uint8_t ) b ] ) ;
bool click = ( ButtonClickState & button ) ;
ButtonClickState & = ~ button ; // clear "click" event
return click ;
2012-08-22 23:41:38 +02:00
}
2013-03-28 09:46:43 +01:00
2013-01-27 21:25:50 +01:00
uint8_t WII : : getAnalogHat ( Hat a ) {
2013-03-28 09:46:43 +01:00
if ( ! nunchuckConnected )
return 127 ; // Return center position
else {
uint8_t output = hatValues [ ( uint8_t ) a ] ;
if ( output = = 0xFF | | output = = 0x00 ) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position
return 127 ;
else
return output ;
}
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
2013-02-02 22:14:01 +01:00
uint16_t WII : : getAnalogHat ( AnalogHat a ) {
2013-03-28 09:46:43 +01:00
if ( ! wiiUProControllerConnected )
return 2000 ;
else {
uint16_t output = hatValues [ ( uint8_t ) a ] ;
if ( output = = 0x00 ) // The joystick will only read 0 when it is first initializing, so we will just return the center position
return 2000 ;
else
return output ;
}
2013-02-02 22:14:01 +01:00
}
2013-07-14 00:43:35 +02:00
void WII : : onInit ( ) {
if ( pFuncOnInit )
pFuncOnInit ( ) ; // Call the user function
else
setLedStatus ( ) ;
}
2013-01-17 00:07:56 +01:00
/************************************************************/
/* The following functions are for the IR camera */
/************************************************************/
# ifdef WIICAMERA
2013-03-28 09:46:43 +01:00
void WII : : IRinitialize ( ) { // Turns on and initialises the IR camera
2013-03-28 09:37:09 +01:00
2013-01-17 00:47:19 +01:00
enableIRCamera1 ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Enable IR Camera1 Complete " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-17 00:47:19 +01:00
enableIRCamera2 ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Enable IR Camera2 Complete " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-17 00:07:56 +01:00
write0x08Value ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wrote hex number 0x08 " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-17 00:47:19 +01:00
writeSensitivityBlock1 ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wrote Sensitivity Block 1 " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-17 00:47:19 +01:00
writeSensitivityBlock2 ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wrote Sensitivity Block 2 " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-01-17 00:47:19 +01:00
uint8_t mode_num = 0x03 ;
setWiiModeNumber ( mode_num ) ; // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Set Wii Mode Number To 0x " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( mode_num , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-17 00:07:56 +01:00
write0x08Value ( ) ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Wrote Hex Number 0x08 " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
delay ( 80 ) ;
2013-01-23 22:28:40 +01:00
setReportMode ( false , 0x33 ) ;
2013-01-17 00:47:19 +01:00
//setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n Set Report Mode to 0x33 " ) , 0x80 ) ;
2013-01-17 00:07:56 +01:00
# endif
2013-01-23 22:28:40 +01:00
delay ( 80 ) ;
2013-03-28 09:37:09 +01:00
2013-01-23 22:28:40 +01:00
statusRequest ( ) ; // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:37:09 +01:00
Notify ( PSTR ( " \r \n IR Initialized " ) , 0x80 ) ;
# endif
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : enableIRCamera1 ( ) {
uint8_t cmd_buf [ 3 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x13 ; // Output report 13
cmd_buf [ 2 ] = 0x04 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit and sets bit 2
HID_Command ( cmd_buf , 3 ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : enableIRCamera2 ( ) {
uint8_t cmd_buf [ 3 ] ;
cmd_buf [ 0 ] = 0xA2 ; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf [ 1 ] = 0x1A ; // Output report 1A
cmd_buf [ 2 ] = 0x04 | ( HIDBuffer [ 2 ] & 0x01 ) ; // Keep the rumble bit and sets bit 2
HID_Command ( cmd_buf , 3 ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : writeSensitivityBlock1 ( ) {
uint8_t buf [ 9 ] ;
buf [ 0 ] = 0x00 ;
buf [ 1 ] = 0x00 ;
buf [ 2 ] = 0x00 ;
buf [ 3 ] = 0x00 ;
buf [ 4 ] = 0x00 ;
buf [ 5 ] = 0x00 ;
buf [ 6 ] = 0x90 ;
buf [ 7 ] = 0x00 ;
buf [ 8 ] = 0x41 ;
writeData ( 0xB00000 , 9 , buf ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : writeSensitivityBlock2 ( ) {
uint8_t buf [ 2 ] ;
buf [ 0 ] = 0x40 ;
buf [ 1 ] = 0x00 ;
2013-01-17 00:07:56 +01:00
2013-03-28 09:46:43 +01:00
writeData ( 0xB0001A , 2 , buf ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : write0x08Value ( ) {
uint8_t cmd = 0x08 ;
writeData ( 0xb00030 , 1 , & cmd ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:46:43 +01:00
void WII : : setWiiModeNumber ( uint8_t mode_number ) { // mode_number in hex i.e. 0x03 for extended mode
writeData ( 0xb00033 , 1 , & mode_number ) ;
2013-01-17 00:07:56 +01:00
}
2013-03-28 09:37:09 +01:00
# endif