USB_Host_Shield_2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Wii.h
Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16 
17  IR camera support added by:
18  Allan Glover
19  adglover9.81@gmail.com
20  */
21 
22 #ifndef _wii_h_
23 #define _wii_h_
24 
25 #include "BTD.h"
26 #include "controllerEnums.h"
27 
28 //#define WIICAMERA //uncomment to enable IR camera
29 
30 /* Bluetooth L2CAP states for L2CAP_task() */
31 #define L2CAP_WAIT 0
32 
33 // These states are used if the Wiimote is the host
34 #define L2CAP_CONTROL_SUCCESS 1
35 #define L2CAP_INTERRUPT_SETUP 2
36 
37 // These states are used if the Arduino is the host
38 #define L2CAP_CONTROL_CONNECT_REQUEST 3
39 #define L2CAP_CONTROL_CONFIG_REQUEST 4
40 #define L2CAP_INTERRUPT_CONNECT_REQUEST 5
41 
42 #define L2CAP_INTERRUPT_CONFIG_REQUEST 6
43 
44 #define L2CAP_CHECK_MOTION_PLUS_STATE 7
45 #define L2CAP_CHECK_EXTENSION_STATE 8
46 #define L2CAP_INIT_MOTION_PLUS_STATE 9
47 #define L2CAP_LED_STATE 10
48 #define L2CAP_DONE 11
49 
50 #define L2CAP_INTERRUPT_DISCONNECT 12
51 #define L2CAP_CONTROL_DISCONNECT 13
52 
53 /* L2CAP event flags */
54 #define L2CAP_FLAG_CONTROL_CONNECTED 0x001
55 #define L2CAP_FLAG_INTERRUPT_CONNECTED 0x002
56 #define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS 0x004
57 #define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS 0x008
58 #define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE 0x040
59 #define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE 0x080
60 #define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST 0x100
61 #define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST 0x200
62 
63 /* Macros for L2CAP event flag tests */
64 #define l2cap_connected_control_flag (l2cap_event_flag & L2CAP_FLAG_CONTROL_CONNECTED)
65 #define l2cap_connected_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_INTERRUPT_CONNECTED)
66 #define l2cap_config_success_control_flag (l2cap_event_flag & L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)
67 #define l2cap_config_success_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)
68 #define l2cap_disconnect_response_control_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)
69 #define l2cap_disconnect_response_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)
70 #define l2cap_connection_request_control_flag (l2cap_event_flag & L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)
71 #define l2cap_connection_request_interrupt_flag (l2cap_event_flag & L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)
72 
73 /* Wii event flags */
74 #define WII_FLAG_MOTION_PLUS_CONNECTED 0x400
75 #define WII_FLAG_NUNCHUCK_CONNECTED 0x800
76 
77 #define motion_plus_connected_flag (l2cap_event_flag & WII_FLAG_MOTION_PLUS_CONNECTED)
78 #define nunchuck_connected_flag (l2cap_event_flag & WII_FLAG_NUNCHUCK_CONNECTED)
79 
80 #define PAIR 1
81 
82 enum Hat {
83  HatX = 0,
84  HatY = 1,
85 };
86 
87 class WII : public BluetoothService {
88 public:
89  WII(BTD *p, bool pair=false);
90 
91  // BluetoothService implementation
92  virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services
93  virtual void Run(); // Used to run part of the state maschine
94  virtual void Reset(); // Use this to reset the service
95  virtual void disconnect(); // Use this void to disconnect any of the controllers
96 
97  /*
98  getButtonPress will return true as long as the button is held down
99  While getButtonClick will only return it once
100  So you instance if you need to increase a variable once you would use getButtonClick,
101  but if you need to drive a robot forward you would use getButtonPress
102  */
103  bool getButtonPress(Button b); // This will read true as long as the button is held down
104  bool getButtonClick(Button b); // This will only be true when the button is clicked the first time
105 
106  uint8_t getAnalogHat(Hat a); // Used to read the joystick of the Nunchuck
107 
108  double getPitch() { return pitch; }; // Fusioned angle using a complimentary filter if the Motion Plus is connected
109  double getRoll() { return roll; }; // Fusioned angle using a complimentary filter if the Motion Plus is connected
110  double getYaw() { return gyroYaw; }; // This is the yaw calculated by the gyro
111 
112  void setAllOff(); // Turn both rumble and all LEDs off
113  void setRumbleOff();
114  void setRumbleOn();
115  void setRumbleToggle();
116  void setLedOff(LED a);
117  void setLedOn(LED a);
118  void setLedToggle(LED a);
119  void setLedStatus(); // This will set the LEDs, so the user can see which connections are active
120 
121  bool wiimoteConnected; // Variable used to indicate if a Wiimote is connected
122  bool nunchuckConnected; // Variable used to indicate if a Nunchuck controller is connected
123  bool motionPlusConnected; // Variable used to indicate if a Nunchuck controller is connected
124 
125  /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
126 
127  double wiiMotePitch; // Pitch and roll calculated from the accelerometer inside the Wiimote
128  double wiiMoteRoll;
129  double nunchuckPitch; // Pitch and roll calculated from the accelerometer inside the Nunchuck
130  double nunchuckRoll;
131 
132  int16_t accX; // Accelerometer values used to calculate pitch and roll
133  int16_t accY;
134  int16_t accZ;
135 
136  /* Variables for the gyro inside the Motion Plus */
137  double gyroPitch; // This is the pitch calculated by the gyro - use this to tune pitchGyroScale
138  double gyroRoll; // This is the roll calculated by the gyro - use this to tune rollGyroScale
139  double gyroYaw; // This is the yaw calculated by the gyro - use this to tune yawGyroScale
140 
141  double pitchGyroSpeed; // The speed in deg/s from the gyro
143  double yawGyroSpeed;
144 
145  uint16_t pitchGyroScale; // You might need to fine-tune these values
146  uint16_t rollGyroScale;
147  uint16_t yawGyroScale;
148 
149  int16_t gyroYawRaw; // Raw value read directly from the Motion Plus
150  int16_t gyroRollRaw;
151  int16_t gyroPitchRaw;
152 
153  int16_t gyroYawZero; // These values are set when the controller is first initialized
154  int16_t gyroRollZero;
155  int16_t gyroPitchZero;
156 
157  uint8_t getBatteryLevel() { return batteryLevel; };
158  uint8_t getWiiState() { return wiiState; };
159 
160 #ifdef WIICAMERA
161  /* These are functions for the IR camera */
162  void IRinitialize(); // Initialises the camera as per the steps from http://wiibrew.org/wiki/Wiimote#IR_Camera
163 
164  uint16_t getIRx1() { return IR_object_x1; }; // IR object 1 x position (0-1023)
165  uint16_t getIRy1() { return IR_object_y1; }; // IR object 1 y position (0-767)
166  uint8_t getIRs1() { return IR_object_s1; }; // IR object 1 size (0-15)
167 
168  uint16_t getIRx2() { return IR_object_x2; };
169  uint16_t getIRy2() { return IR_object_y2; };
170  uint8_t getIRs2() { return IR_object_s2; };
171 
172  uint16_t getIRx3() { return IR_object_x3; };
173  uint16_t getIRy3() { return IR_object_y3; };
174  uint8_t getIRs3() { return IR_object_s3; };
175 
176  uint16_t getIRx4() { return IR_object_x4; };
177  uint16_t getIRy4() { return IR_object_y4; };
178  uint8_t getIRs4() { return IR_object_s4; };
179 
180  bool isIRCameraEnabled() { return (wiiState & 0x08); };
181 #endif
182 
183 private:
184  /* Mandatory members */
185  BTD *pBtd;
186 
187  void L2CAP_task(); // L2CAP state machine
188 
189  /* Variables filled from HCI event management */
190  uint16_t hci_handle;
191  bool activeConnection; // Used to indicate if it's already has established a connection
192 
193  /* variables used by high level L2CAP task */
194  uint8_t l2cap_state;
195  uint16_t l2cap_event_flag;// l2cap flags of received bluetooth events
196 
197  uint32_t ButtonState;
198  uint32_t OldButtonState;
199  uint32_t ButtonClickState;
200  uint8_t hatValues[2];
201 
202  uint8_t HIDBuffer[3];// Used to store HID commands
203 
204  uint16_t stateCounter;
205  bool unknownExtensionConnected;
206  bool extensionConnected;
207 
208  /* L2CAP Channels */
209  uint8_t control_scid[2]; // L2CAP source CID for HID_Control
210  uint8_t control_dcid[2]; // 0x0060
211  uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
212  uint8_t interrupt_dcid[2]; // 0x0061
213  uint8_t identifier; // Identifier for connection
214 
215  /* HID Commands */
216  void HID_Command(uint8_t* data, uint8_t nbytes);
217  void setReportMode(bool continuous, uint8_t mode);
218  void statusRequest();
219 
220  void writeData(uint32_t offset, uint8_t size, uint8_t* data);
221  void initExtension1();
222  void initExtension2();
223 
224  void readData(uint32_t offset, uint16_t size, bool EEPROM);
225  void readExtensionType();
226  void readCalData();
227 
228  void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
229  void initMotionPlus();
230  void activateMotionPlus();
231 
232  double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
233  double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
234 
235  bool activateNunchuck;
236  bool motionValuesReset; // This bool is true when the gyro values has been reset
237  unsigned long timer;
238 
239  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)
240  uint8_t batteryLevel;
241 
242 #ifdef WIICAMERA
243  /* Private function and variables for the readings from teh IR Camera */
244  void enableIRCamera1(); // Sets bit 2 of output report 13
245  void enableIRCamera2(); // Sets bit 2 of output report 1A
246  void writeSensitivityBlock1();
247  void writeSensitivityBlock2();
248  void write0x08Value();
249  void setWiiModeNumber(uint8_t mode_number);
250 
251  uint16_t IR_object_x1; // IR x position 10 bits
252  uint16_t IR_object_y1; // IR y position 10 bits
253  uint8_t IR_object_s1; // IR size value
254  uint16_t IR_object_x2;
255  uint16_t IR_object_y2;
256  uint8_t IR_object_s2;
257  uint16_t IR_object_x3; // IR x position 10 bits
258  uint16_t IR_object_y3; // IR y position 10 bits
259  uint8_t IR_object_s3; // IR size value
260  uint16_t IR_object_x4;
261  uint16_t IR_object_y4;
262  uint8_t IR_object_s4;
263 #endif
264 };
265 #endif