2012-08-21 14:31:11 +02:00
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2013-03-28 09:46:43 +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:46:43 +01:00
2012-08-21 14:31:11 +02:00
Contact information
- - - - - - - - - - - - - - - - - - -
2013-03-28 09:46:43 +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
*/
# ifndef _wii_h_
# define _wii_h_
# include "BTD.h"
2013-01-27 21:25:50 +01:00
# include "controllerEnums.h"
2012-08-21 14:31:11 +02:00
2012-08-23 23:10:12 +02:00
/* Wii event flags */
2013-12-11 09:29:38 +01:00
# define WII_FLAG_MOTION_PLUS_CONNECTED 0x01
# define WII_FLAG_NUNCHUCK_CONNECTED 0x02
2012-08-23 23:10:12 +02:00
2013-12-13 11:27:05 +01:00
# define wii_check_flag(flag) (wii_event_flag & (flag))
# define wii_set_flag(flag) (wii_event_flag |= (flag))
# define wii_clear_flag(flag) (wii_event_flag &= ~(flag))
2012-08-23 23:10:12 +02:00
2013-02-05 19:51:45 +01:00
/** Enum used to read the joystick on the Nunchuck. */
2014-01-04 13:43:49 +01:00
enum HatEnum {
2013-03-28 09:46:43 +01:00
/** Read the x-axis on the Nunchuck joystick. */
HatX = 0 ,
/** Read the y-axis on the Nunchuck joystick. */
HatY = 1 ,
2012-08-21 14:31:11 +02:00
} ;
2013-02-05 19:51:45 +01:00
/**
* This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension .
*
* It also support the Wii U Pro Controller .
*/
2012-08-21 14:31:11 +02:00
class WII : public BluetoothService {
public :
2013-03-28 09:46:43 +01:00
/**
* Constructor for the WII class .
* @ param p Pointer to BTD class instance .
* @ param pair Set this to true in order to pair with the Wiimote . If the argument is omitted then it won ' t pair with it .
* One can use : : PAIR to set it to true .
*/
WII ( BTD * p , bool pair = false ) ;
/** @name BluetoothService implementation */
/**
* Used to pass acldata to the services .
* @ param ACLData Incoming acldata .
*/
virtual void ACLData ( uint8_t * ACLData ) ;
2013-12-30 16:05:50 +01:00
/** Used to run part of the state machine. */
2013-03-28 09:46:43 +01:00
virtual void Run ( ) ;
/** Use this to reset the service. */
virtual void Reset ( ) ;
/** Used this to disconnect any of the controllers. */
virtual void disconnect ( ) ;
/**@}*/
/** @name Wii Controller functions */
/**
* getButtonPress ( Button b ) will return true as long as the button is held down .
*
* While getButtonClick ( Button b ) will only return it once .
*
* So you instance if you need to increase a variable once you would use getButtonClick ( Button b ) ,
* but if you need to drive a robot forward you would use getButtonPress ( Button b ) .
2014-01-04 13:43:49 +01:00
* @ param b : : ButtonEnum to read .
* @ return getButtonPress ( ButtonEnum b ) will return a true as long as a button is held down , while getButtonClick ( ButtonEnum b ) will return true once for each button press .
2013-03-28 09:46:43 +01:00
*/
2014-01-04 13:43:49 +01:00
bool getButtonPress ( ButtonEnum b ) ;
bool getButtonClick ( ButtonEnum b ) ;
2013-03-28 09:46:43 +01:00
/**@}*/
/** @name Wii Controller functions */
2013-12-25 11:09:57 +01:00
2013-05-06 23:32:00 +02:00
/** Call this to start the paring sequence with a controller */
void pair ( void ) {
if ( pBtd )
pBtd - > pairWithWiimote ( ) ;
2013-12-30 16:05:50 +01:00
} ;
2013-03-28 09:46:43 +01:00
/**
* Used to read the joystick of the Nunchuck .
* @ param a Either : : HatX or : : HatY .
* @ return Return the analog value in the range from approximately 25 - 230.
*/
2014-01-04 13:43:49 +01:00
uint8_t getAnalogHat ( HatEnum a ) ;
2013-03-28 09:46:43 +01:00
/**
* Used to read the joystick of the Wii U Pro Controller .
* @ param a Either : : LeftHatX , : : LeftHatY , : : RightHatX or : : RightHatY .
* @ return Return the analog value in the range from approximately 800 - 3200.
*/
2014-01-04 13:43:49 +01:00
uint16_t getAnalogHat ( AnalogHatEnum a ) ;
2013-03-28 09:46:43 +01:00
/**
* Pitch calculated from the Wiimote . A complimentary filter is used if the Motion Plus is connected .
* @ return Pitch in the range from 0 - 360.
*/
double getPitch ( ) {
2013-12-25 11:09:57 +01:00
if ( motionPlusConnected )
2013-10-21 18:41:47 +02:00
return compPitch ;
return getWiimotePitch ( ) ;
2013-03-28 09:46:43 +01:00
} ;
/**
* Roll calculated from the Wiimote . A complimentary filter is used if the Motion Plus is connected .
* @ return Roll in the range from 0 - 360.
*/
double getRoll ( ) {
2013-12-25 11:09:57 +01:00
if ( motionPlusConnected )
2013-10-21 18:41:47 +02:00
return compRoll ;
return getWiimoteRoll ( ) ;
2013-03-28 09:46:43 +01:00
} ;
/**
* This is the yaw calculated by the gyro .
*
* < B > NOTE : < / B > This angle will drift a lot and is only available if the Motion Plus extension is connected .
* @ return The angle calculated using the gyro .
*/
double getYaw ( ) {
return gyroYaw ;
} ;
/** Used to set all LEDs and rumble off. */
void setAllOff ( ) ;
/** Turn off rumble. */
void setRumbleOff ( ) ;
/** Turn on rumble. */
void setRumbleOn ( ) ;
/** Toggle rumble. */
void setRumbleToggle ( ) ;
2013-04-01 15:38:15 +02:00
/**
2014-01-04 13:43:49 +01:00
* Set LED value without using the : : LEDEnum .
* @ param value See : : : LEDEnum .
2013-04-01 15:38:15 +02:00
*/
void setLedRaw ( uint8_t value ) ;
2013-12-25 11:09:57 +01:00
2013-11-15 23:19:10 +01:00
/** Turn all LEDs off. */
void setLedOff ( ) {
setLedRaw ( 0 ) ;
2013-12-30 16:05:50 +01:00
} ;
2013-03-28 09:46:43 +01:00
/**
2014-01-04 13:43:49 +01:00
* Turn the specific : : LEDEnum off .
* @ param a The : : LEDEnum to turn off .
2013-03-28 09:46:43 +01:00
*/
2014-01-04 13:43:49 +01:00
void setLedOff ( LEDEnum a ) ;
2013-03-28 09:46:43 +01:00
/**
2014-01-04 13:43:49 +01:00
* Turn the specific : : LEDEnum on .
* @ param a The : : LEDEnum to turn on .
2013-03-28 09:46:43 +01:00
*/
2014-01-04 13:43:49 +01:00
void setLedOn ( LEDEnum a ) ;
2013-03-28 09:46:43 +01:00
/**
2014-01-04 13:43:49 +01:00
* Toggle the specific : : LEDEnum .
* @ param a The : : LEDEnum to toggle .
2013-03-28 09:46:43 +01:00
*/
2014-01-04 13:43:49 +01:00
void setLedToggle ( LEDEnum a ) ;
2013-03-28 09:46:43 +01:00
/**
* This will set the LEDs , so the user can see which connections are active .
*
2014-01-04 13:43:49 +01:00
* The first : : LEDEnum indicate that the Wiimote is connected ,
* the second : : LEDEnum indicate indicate that a Motion Plus is also connected
* the third : : LEDEnum will indicate that a Nunchuck controller is also connected .
2013-03-28 09:46:43 +01:00
*/
void setLedStatus ( ) ;
/**
* Return the battery level of the Wiimote .
* @ return The battery level in the range 0 - 255.
*/
2013-07-18 19:43:21 +02:00
uint8_t getBatteryLevel ( ) ;
2013-12-25 11:09:57 +01:00
2013-03-28 09:46:43 +01:00
/**
* Return the Wiimote state .
* @ return See : http : //wiibrew.org/wiki/Wiimote#0x20:_Status.
*/
uint8_t getWiiState ( ) {
return wiiState ;
} ;
2013-07-14 00:43:35 +02:00
/**
* Used to call your own function when the controller is successfully initialized .
* @ param funcOnInit Function to call .
*/
void attachOnInit ( void ( * funcOnInit ) ( void ) ) {
pFuncOnInit = funcOnInit ;
} ;
2013-03-28 09:46:43 +01:00
/**@}*/
/**@{*/
/** Variable used to indicate if a Wiimote is connected. */
bool wiimoteConnected ;
/** Variable used to indicate if a Nunchuck controller is connected. */
bool nunchuckConnected ;
/** Variable used to indicate if a Nunchuck controller is connected. */
bool motionPlusConnected ;
/** Variable used to indicate if a Wii U Pro controller is connected. */
bool wiiUProControllerConnected ;
/**@}*/
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
/**@{*/
2013-12-25 11:09:57 +01:00
2013-03-28 09:46:43 +01:00
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */
2013-10-21 18:41:47 +02:00
double getWiimotePitch ( ) {
return ( atan2 ( accYwiimote , accZwiimote ) + PI ) * RAD_TO_DEG ;
} ;
2013-12-25 11:09:57 +01:00
2013-10-21 18:41:47 +02:00
double getWiimoteRoll ( ) {
return ( atan2 ( accXwiimote , accZwiimote ) + PI ) * RAD_TO_DEG ;
} ;
2013-03-28 09:46:43 +01:00
/**@}*/
/**@{*/
2013-12-25 11:09:57 +01:00
2013-03-28 09:46:43 +01:00
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
2013-10-21 18:41:47 +02:00
double getNunchuckPitch ( ) {
return ( atan2 ( accYnunchuck , accZnunchuck ) + PI ) * RAD_TO_DEG ;
} ;
2013-12-25 11:09:57 +01:00
2013-10-21 18:41:47 +02:00
double getNunchuckRoll ( ) {
return ( atan2 ( accXnunchuck , accZnunchuck ) + PI ) * RAD_TO_DEG ;
} ;
2013-03-28 09:46:43 +01:00
/**@}*/
/**@{*/
/** Accelerometer values used to calculate pitch and roll. */
2013-10-21 18:41:47 +02:00
int16_t accXwiimote , accYwiimote , accZwiimote ;
int16_t accXnunchuck , accYnunchuck , accZnunchuck ;
2013-03-28 09:46:43 +01:00
/**@}*/
/* Variables for the gyro inside the Motion Plus */
/** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
double gyroPitch ;
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
double gyroRoll ;
/** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
double gyroYaw ;
/**@{*/
/** The speed in deg/s from the gyro. */
double pitchGyroSpeed ;
double rollGyroSpeed ;
double yawGyroSpeed ;
/**@}*/
/**@{*/
/** You might need to fine-tune these values. */
uint16_t pitchGyroScale ;
uint16_t rollGyroScale ;
uint16_t yawGyroScale ;
/**@}*/
/**@{*/
/** Raw value read directly from the Motion Plus. */
int16_t gyroYawRaw ;
int16_t gyroRollRaw ;
int16_t gyroPitchRaw ;
/**@}*/
/**@{*/
/** These values are set when the controller is first initialized. */
int16_t gyroYawZero ;
int16_t gyroRollZero ;
int16_t gyroPitchZero ;
/**@}*/
2013-01-17 00:07:56 +01:00
# ifdef WIICAMERA
2013-03-28 09:46:43 +01:00
/** @name Wiimote IR camera functions
2013-12-30 16:19:34 +01:00
* You will have to set ENABLE_WII_IR_CAMERA in settings . h to 1 in order use the IR camera .
2013-03-28 09:46:43 +01:00
*/
/** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */
void IRinitialize ( ) ;
/**
* IR object 1 x - position read from the Wii IR camera .
* @ return The x - position of the object in the range 0 - 1023.
*/
uint16_t getIRx1 ( ) {
return IR_object_x1 ;
} ;
/**
* IR object 1 y - position read from the Wii IR camera .
* @ return The y - position of the object in the range 0 - 767.
*/
uint16_t getIRy1 ( ) {
return IR_object_y1 ;
} ;
/**
* IR object 1 size read from the Wii IR camera .
* @ return The size of the object in the range 0 - 15.
*/
uint8_t getIRs1 ( ) {
return IR_object_s1 ;
} ;
/**
* IR object 2 x - position read from the Wii IR camera .
* @ return The x - position of the object in the range 0 - 1023.
*/
uint16_t getIRx2 ( ) {
return IR_object_x2 ;
} ;
/**
* IR object 2 y - position read from the Wii IR camera .
* @ return The y - position of the object in the range 0 - 767.
*/
uint16_t getIRy2 ( ) {
return IR_object_y2 ;
} ;
/**
* IR object 2 size read from the Wii IR camera .
* @ return The size of the object in the range 0 - 15.
*/
uint8_t getIRs2 ( ) {
return IR_object_s2 ;
} ;
/**
* IR object 3 x - position read from the Wii IR camera .
* @ return The x - position of the object in the range 0 - 1023.
*/
uint16_t getIRx3 ( ) {
return IR_object_x3 ;
} ;
/**
* IR object 3 y - position read from the Wii IR camera .
* @ return The y - position of the object in the range 0 - 767.
*/
uint16_t getIRy3 ( ) {
return IR_object_y3 ;
} ;
/**
* IR object 3 size read from the Wii IR camera .
* @ return The size of the object in the range 0 - 15.
*/
uint8_t getIRs3 ( ) {
return IR_object_s3 ;
} ;
/**
* IR object 4 x - position read from the Wii IR camera .
* @ return The x - position of the object in the range 0 - 1023.
*/
uint16_t getIRx4 ( ) {
return IR_object_x4 ;
} ;
/**
* IR object 4 y - position read from the Wii IR camera .
* @ return The y - position of the object in the range 0 - 767.
*/
uint16_t getIRy4 ( ) {
return IR_object_y4 ;
} ;
/**
* IR object 4 size read from the Wii IR camera .
* @ return The size of the object in the range 0 - 15.
*/
uint8_t getIRs4 ( ) {
return IR_object_s4 ;
} ;
/**
* Use this to check if the camera is enabled or not .
* If not call WII # IRinitialize to initialize the IR camera .
* @ return True if it ' s enabled , false if not .
*/
bool isIRCameraEnabled ( ) {
2013-12-25 11:09:57 +01:00
return ( wiiState & 0x08 ) ;
2013-03-28 09:46:43 +01:00
} ;
/**@}*/
2013-01-17 00:07:56 +01:00
# endif
2013-03-28 09:46:43 +01:00
2012-08-21 14:31:11 +02:00
private :
2013-07-14 00:43:35 +02:00
BTD * pBtd ; // Pointer to BTD instance
/**
* Called when the controller is successfully initialized .
* Use attachOnInit ( void ( * funcOnInit ) ( void ) ) to call your own function .
* This is useful for instance if you want to set the LEDs in a specific way .
*/
void onInit ( ) ;
void ( * pFuncOnInit ) ( void ) ; // Pointer to function called in onInit()
2013-03-28 09:46:43 +01:00
void L2CAP_task ( ) ; // L2CAP state machine
/* Variables filled from HCI event management */
uint16_t hci_handle ;
bool activeConnection ; // Used to indicate if it's already has established a connection
2013-07-14 00:43:35 +02:00
/* Variables used by high level L2CAP task */
2013-03-28 09:46:43 +01:00
uint8_t l2cap_state ;
2013-12-11 09:29:38 +01:00
uint32_t l2cap_event_flag ; // L2CAP flags of received Bluetooth events
uint8_t wii_event_flag ; // Used for Wii flags
2013-03-28 09:46:43 +01:00
uint32_t ButtonState ;
uint32_t OldButtonState ;
uint32_t ButtonClickState ;
uint16_t hatValues [ 4 ] ;
uint8_t HIDBuffer [ 3 ] ; // Used to store HID commands
uint16_t stateCounter ;
bool unknownExtensionConnected ;
bool extensionConnected ;
2013-07-18 19:43:21 +02:00
bool checkExtension ; // Set to false when getBatteryLevel() is called otherwise if should be true
bool motionPlusInside ; // True if it's a new Wiimote with the Motion Plus extension build into it
2013-03-28 09:46:43 +01:00
/* L2CAP Channels */
uint8_t control_scid [ 2 ] ; // L2CAP source CID for HID_Control
uint8_t control_dcid [ 2 ] ; // 0x0060
uint8_t interrupt_scid [ 2 ] ; // L2CAP source CID for HID_Interrupt
uint8_t interrupt_dcid [ 2 ] ; // 0x0061
uint8_t identifier ; // Identifier for connection
/* HID Commands */
void HID_Command ( uint8_t * data , uint8_t nbytes ) ;
void setReportMode ( bool continuous , uint8_t mode ) ;
void writeData ( uint32_t offset , uint8_t size , uint8_t * data ) ;
void initExtension1 ( ) ;
void initExtension2 ( ) ;
2013-07-18 19:43:21 +02:00
void statusRequest ( ) ; // Used to update the Wiimote state and battery level
2013-03-28 09:46:43 +01:00
void readData ( uint32_t offset , uint16_t size , bool EEPROM ) ;
void readExtensionType ( ) ;
void readCalData ( ) ;
void checkMotionPresent ( ) ; // Used to see if a Motion Plus is connected to the Wiimote
void initMotionPlus ( ) ;
void activateMotionPlus ( ) ;
2013-10-21 18:41:47 +02:00
double compPitch ; // Fusioned angle using a complimentary filter if the Motion Plus is connected
double compRoll ; // Fusioned angle using a complimentary filter if the Motion Plus is connected
2013-03-28 09:46:43 +01:00
bool activateNunchuck ;
bool motionValuesReset ; // This bool is true when the gyro values has been reset
unsigned long timer ;
uint8_t wiiState ; // Stores the value in 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)
uint8_t batteryLevel ;
2013-01-17 00:47:19 +01:00
# ifdef WIICAMERA
2013-07-18 19:43:21 +02:00
/* Private function and variables for the readings from the IR Camera */
2013-03-28 09:46:43 +01:00
void enableIRCamera1 ( ) ; // Sets bit 2 of output report 13
void enableIRCamera2 ( ) ; // Sets bit 2 of output report 1A
void writeSensitivityBlock1 ( ) ;
void writeSensitivityBlock2 ( ) ;
void write0x08Value ( ) ;
void setWiiModeNumber ( uint8_t mode_number ) ;
uint16_t IR_object_x1 ; // IR x position 10 bits
uint16_t IR_object_y1 ; // IR y position 10 bits
uint8_t IR_object_s1 ; // IR size value
uint16_t IR_object_x2 ;
uint16_t IR_object_y2 ;
uint8_t IR_object_s2 ;
uint16_t IR_object_x3 ; // IR x position 10 bits
uint16_t IR_object_y3 ; // IR y position 10 bits
uint8_t IR_object_s3 ; // IR size value
uint16_t IR_object_x4 ;
uint16_t IR_object_y4 ;
uint8_t IR_object_s4 ;
2013-01-17 00:47:19 +01:00
# endif
2012-08-21 14:31:11 +02:00
} ;
2013-12-25 11:09:57 +01:00
# endif