You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
18 KiB

  1. /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Kristian Lauszus, TKJ Electronics
  11. Web : http://www.tkjelectronics.com
  12. e-mail : kristianl@tkjelectronics.com
  13. IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus
  14. */
  15. #ifndef _wii_h_
  16. #define _wii_h_
  17. #include "BTD.h"
  18. #include "controllerEnums.h"
  19. /* Wii event flags */
  20. #define WII_FLAG_MOTION_PLUS_CONNECTED (1 << 0)
  21. #define WII_FLAG_NUNCHUCK_CONNECTED (1 << 1)
  22. #define WII_FLAG_CALIBRATE_BALANCE_BOARD (1 << 2)
  23. #define wii_check_flag(flag) (wii_event_flag & (flag))
  24. #define wii_set_flag(flag) (wii_event_flag |= (flag))
  25. #define wii_clear_flag(flag) (wii_event_flag &= ~(flag))
  26. /** Enum used to read the joystick on the Nunchuck. */
  27. enum HatEnum {
  28. /** Read the x-axis on the Nunchuck joystick. */
  29. HatX = 0,
  30. /** Read the y-axis on the Nunchuck joystick. */
  31. HatY = 1,
  32. };
  33. /** Enum used to read the weight on Wii Balance Board. */
  34. enum BalanceBoardEnum {
  35. TopRight = 0,
  36. BotRight = 1,
  37. TopLeft = 2,
  38. BotLeft = 3,
  39. };
  40. /**
  41. * This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension.
  42. *
  43. * It also support the Wii U Pro Controller.
  44. */
  45. class WII : public BluetoothService {
  46. public:
  47. /**
  48. * Constructor for the WII class.
  49. * @param p Pointer to BTD class instance.
  50. * @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.
  51. * One can use ::PAIR to set it to true.
  52. */
  53. WII(BTD *p, bool pair = false);
  54. /** @name BluetoothService implementation */
  55. /** Used this to disconnect any of the controllers. */
  56. void disconnect();
  57. /**@}*/
  58. /** @name Wii Controller functions */
  59. /**
  60. * getButtonPress(Button b) will return true as long as the button is held down.
  61. *
  62. * While getButtonClick(Button b) will only return it once.
  63. *
  64. * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
  65. * but if you need to drive a robot forward you would use getButtonPress(Button b).
  66. * @param b ::ButtonEnum to read.
  67. * @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.
  68. */
  69. bool getButtonPress(ButtonEnum b);
  70. bool getButtonClick(ButtonEnum b);
  71. /**@}*/
  72. /** @name Wii Controller functions */
  73. /** Call this to start the paring sequence with a controller */
  74. void pair(void) {
  75. if(pBtd)
  76. pBtd->pairWithWiimote();
  77. };
  78. /**
  79. * Used to read the joystick of the Nunchuck.
  80. * @param a Either ::HatX or ::HatY.
  81. * @return Return the analog value in the range from approximately 25-230.
  82. */
  83. uint8_t getAnalogHat(HatEnum a);
  84. /**
  85. * Used to read the joystick of the Wii U Pro Controller.
  86. * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
  87. * @return Return the analog value in the range from approximately 800-3200.
  88. */
  89. uint16_t getAnalogHat(AnalogHatEnum a);
  90. /**
  91. * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
  92. * @return Pitch in the range from 0-360.
  93. */
  94. double getPitch() {
  95. if(motionPlusConnected)
  96. return compPitch;
  97. return getWiimotePitch();
  98. };
  99. /**
  100. * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
  101. * @return Roll in the range from 0-360.
  102. */
  103. double getRoll() {
  104. if(motionPlusConnected)
  105. return compRoll;
  106. return getWiimoteRoll();
  107. };
  108. /**
  109. * This is the yaw calculated by the gyro.
  110. *
  111. * <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
  112. * @return The angle calculated using the gyro.
  113. */
  114. double getYaw() {
  115. return gyroYaw;
  116. };
  117. /** Used to set all LEDs and rumble off. */
  118. void setAllOff();
  119. /** Turn off rumble. */
  120. void setRumbleOff();
  121. /** Turn on rumble. */
  122. void setRumbleOn();
  123. /** Toggle rumble. */
  124. void setRumbleToggle();
  125. /**
  126. * Set LED value without using the ::LEDEnum.
  127. * @param value See: ::LEDEnum.
  128. */
  129. void setLedRaw(uint8_t value);
  130. /** Turn all LEDs off. */
  131. void setLedOff() {
  132. setLedRaw(0);
  133. };
  134. /**
  135. * Turn the specific ::LEDEnum off.
  136. * @param a The ::LEDEnum to turn off.
  137. */
  138. void setLedOff(LEDEnum a);
  139. /**
  140. * Turn the specific ::LEDEnum on.
  141. * @param a The ::LEDEnum to turn on.
  142. */
  143. void setLedOn(LEDEnum a);
  144. /**
  145. * Toggle the specific ::LEDEnum.
  146. * @param a The ::LEDEnum to toggle.
  147. */
  148. void setLedToggle(LEDEnum a);
  149. /**
  150. * This will set the LEDs, so the user can see which connections are active.
  151. *
  152. * The first ::LEDEnum indicate that the Wiimote is connected,
  153. * the second ::LEDEnum indicate indicate that a Motion Plus is also connected
  154. * the third ::LEDEnum will indicate that a Nunchuck controller is also connected.
  155. */
  156. void setLedStatus();
  157. /**
  158. * Return the battery level of the Wiimote.
  159. * @return The battery level in the range 0-255.
  160. */
  161. uint8_t getBatteryLevel();
  162. /**
  163. * Return the Wiimote state.
  164. * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
  165. */
  166. uint8_t getWiiState() {
  167. return wiiState;
  168. };
  169. /**@}*/
  170. /**@{*/
  171. /** Variable used to indicate if a Wiimote is connected. */
  172. bool wiimoteConnected;
  173. /** Variable used to indicate if a Nunchuck controller is connected. */
  174. bool nunchuckConnected;
  175. /** Variable used to indicate if a Nunchuck controller is connected. */
  176. bool motionPlusConnected;
  177. /** Variable used to indicate if a Wii U Pro controller is connected. */
  178. bool wiiUProControllerConnected;
  179. /** Variable used to indicate if a Wii Balance Board is connected. */
  180. bool wiiBalanceBoardConnected;
  181. /**@}*/
  182. /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
  183. /**@{*/
  184. /** Pitch and roll calculated from the accelerometer inside the Wiimote. */
  185. double getWiimotePitch() {
  186. return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;
  187. };
  188. double getWiimoteRoll() {
  189. return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;
  190. };
  191. /**@}*/
  192. /**@{*/
  193. /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
  194. double getNunchuckPitch() {
  195. return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
  196. };
  197. double getNunchuckRoll() {
  198. return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
  199. };
  200. /**@}*/
  201. /**@{*/
  202. /** Accelerometer values used to calculate pitch and roll. */
  203. int16_t accXwiimote, accYwiimote, accZwiimote;
  204. int16_t accXnunchuck, accYnunchuck, accZnunchuck;
  205. /**@}*/
  206. /* Variables for the gyro inside the Motion Plus */
  207. /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
  208. double gyroPitch;
  209. /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
  210. double gyroRoll;
  211. /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
  212. double gyroYaw;
  213. /**@{*/
  214. /** The speed in deg/s from the gyro. */
  215. double pitchGyroSpeed;
  216. double rollGyroSpeed;
  217. double yawGyroSpeed;
  218. /**@}*/
  219. /**@{*/
  220. /** You might need to fine-tune these values. */
  221. uint16_t pitchGyroScale;
  222. uint16_t rollGyroScale;
  223. uint16_t yawGyroScale;
  224. /**@}*/
  225. /**@{*/
  226. /** Raw value read directly from the Motion Plus. */
  227. int16_t gyroYawRaw;
  228. int16_t gyroRollRaw;
  229. int16_t gyroPitchRaw;
  230. /**@}*/
  231. /**@{*/
  232. /** These values are set when the controller is first initialized. */
  233. int16_t gyroYawZero;
  234. int16_t gyroRollZero;
  235. int16_t gyroPitchZero;
  236. /**@}*/
  237. /** @name Wii Balance Board functions */
  238. /**
  239. * Used to get the weight at the specific position on the Wii Balance Board.
  240. * @param ::BalanceBoardEnum to read from.
  241. * @return Returns the weight in kg.
  242. */
  243. float getWeight(BalanceBoardEnum pos);
  244. /**
  245. * Used to get total weight on the Wii Balance Board.
  246. * @returnReturns the weight in kg.
  247. */
  248. float getTotalWeight();
  249. /**
  250. * Used to get the raw reading at the specific position on the Wii Balance Board.
  251. * @param ::BalanceBoardEnum to read from.
  252. * @return Returns the raw reading.
  253. */
  254. uint16_t getWeightRaw(BalanceBoardEnum pos) {
  255. return wiiBalanceBoardRaw[pos];
  256. };
  257. /**@}*/
  258. #ifdef WIICAMERA
  259. /** @name Wiimote IR camera functions
  260. * You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera.
  261. */
  262. /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */
  263. void IRinitialize();
  264. /**
  265. * IR object 1 x-position read from the Wii IR camera.
  266. * @return The x-position of the object in the range 0-1023.
  267. */
  268. uint16_t getIRx1() {
  269. return IR_object_x1;
  270. };
  271. /**
  272. * IR object 1 y-position read from the Wii IR camera.
  273. * @return The y-position of the object in the range 0-767.
  274. */
  275. uint16_t getIRy1() {
  276. return IR_object_y1;
  277. };
  278. /**
  279. * IR object 1 size read from the Wii IR camera.
  280. * @return The size of the object in the range 0-15.
  281. */
  282. uint8_t getIRs1() {
  283. return IR_object_s1;
  284. };
  285. /**
  286. * IR object 2 x-position read from the Wii IR camera.
  287. * @return The x-position of the object in the range 0-1023.
  288. */
  289. uint16_t getIRx2() {
  290. return IR_object_x2;
  291. };
  292. /**
  293. * IR object 2 y-position read from the Wii IR camera.
  294. * @return The y-position of the object in the range 0-767.
  295. */
  296. uint16_t getIRy2() {
  297. return IR_object_y2;
  298. };
  299. /**
  300. * IR object 2 size read from the Wii IR camera.
  301. * @return The size of the object in the range 0-15.
  302. */
  303. uint8_t getIRs2() {
  304. return IR_object_s2;
  305. };
  306. /**
  307. * IR object 3 x-position read from the Wii IR camera.
  308. * @return The x-position of the object in the range 0-1023.
  309. */
  310. uint16_t getIRx3() {
  311. return IR_object_x3;
  312. };
  313. /**
  314. * IR object 3 y-position read from the Wii IR camera.
  315. * @return The y-position of the object in the range 0-767.
  316. */
  317. uint16_t getIRy3() {
  318. return IR_object_y3;
  319. };
  320. /**
  321. * IR object 3 size read from the Wii IR camera.
  322. * @return The size of the object in the range 0-15.
  323. */
  324. uint8_t getIRs3() {
  325. return IR_object_s3;
  326. };
  327. /**
  328. * IR object 4 x-position read from the Wii IR camera.
  329. * @return The x-position of the object in the range 0-1023.
  330. */
  331. uint16_t getIRx4() {
  332. return IR_object_x4;
  333. };
  334. /**
  335. * IR object 4 y-position read from the Wii IR camera.
  336. * @return The y-position of the object in the range 0-767.
  337. */
  338. uint16_t getIRy4() {
  339. return IR_object_y4;
  340. };
  341. /**
  342. * IR object 4 size read from the Wii IR camera.
  343. * @return The size of the object in the range 0-15.
  344. */
  345. uint8_t getIRs4() {
  346. return IR_object_s4;
  347. };
  348. /**
  349. * Use this to check if the camera is enabled or not.
  350. * If not call WII#IRinitialize to initialize the IR camera.
  351. * @return True if it's enabled, false if not.
  352. */
  353. bool isIRCameraEnabled() {
  354. return (wiiState & 0x08);
  355. };
  356. /**@}*/
  357. #endif
  358. protected:
  359. /** @name BluetoothService implementation */
  360. /**
  361. * Used to pass acldata to the services.
  362. * @param ACLData Incoming acldata.
  363. */
  364. void ACLData(uint8_t* ACLData);
  365. /** Used to run part of the state machine. */
  366. void Run();
  367. /** Use this to reset the service. */
  368. void Reset();
  369. /**
  370. * Called when the controller is successfully initialized.
  371. * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
  372. * This is useful for instance if you want to set the LEDs in a specific way.
  373. */
  374. void onInit();
  375. /**@}*/
  376. private:
  377. void L2CAP_task(); // L2CAP state machine
  378. /* Variables filled from HCI event management */
  379. bool activeConnection; // Used to indicate if it's already has established a connection
  380. /* Variables used by high level L2CAP task */
  381. uint8_t l2cap_state;
  382. uint8_t wii_event_flag; // Used for Wii flags
  383. uint32_t ButtonState;
  384. uint32_t OldButtonState;
  385. uint32_t ButtonClickState;
  386. uint16_t hatValues[4];
  387. uint8_t HIDBuffer[3]; // Used to store HID commands
  388. uint16_t stateCounter;
  389. bool unknownExtensionConnected;
  390. bool extensionConnected;
  391. bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false
  392. bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it
  393. /* L2CAP Channels */
  394. uint8_t control_scid[2]; // L2CAP source CID for HID_Control
  395. uint8_t control_dcid[2]; // 0x0060
  396. uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
  397. uint8_t interrupt_dcid[2]; // 0x0061
  398. /* HID Commands */
  399. void HID_Command(uint8_t* data, uint8_t nbytes);
  400. void setReportMode(bool continuous, uint8_t mode);
  401. void writeData(uint32_t offset, uint8_t size, uint8_t* data);
  402. void initExtension1();
  403. void initExtension2();
  404. void statusRequest(); // Used to update the Wiimote state and battery level
  405. void readData(uint32_t offset, uint16_t size, bool EEPROM);
  406. void readExtensionType();
  407. void readCalData();
  408. void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values
  409. void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
  410. void initMotionPlus();
  411. void activateMotionPlus();
  412. uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values
  413. uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values
  414. double compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
  415. double compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
  416. bool activateNunchuck;
  417. bool motionValuesReset; // This bool is true when the gyro values has been reset
  418. uint32_t timer;
  419. 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)
  420. uint8_t batteryLevel;
  421. #ifdef WIICAMERA
  422. /* Private function and variables for the readings from the IR Camera */
  423. void enableIRCamera1(); // Sets bit 2 of output report 13
  424. void enableIRCamera2(); // Sets bit 2 of output report 1A
  425. void writeSensitivityBlock1();
  426. void writeSensitivityBlock2();
  427. void write0x08Value();
  428. void setWiiModeNumber(uint8_t mode_number);
  429. uint16_t IR_object_x1; // IR x position 10 bits
  430. uint16_t IR_object_y1; // IR y position 10 bits
  431. uint8_t IR_object_s1; // IR size value
  432. uint16_t IR_object_x2;
  433. uint16_t IR_object_y2;
  434. uint8_t IR_object_s2;
  435. uint16_t IR_object_x3; // IR x position 10 bits
  436. uint16_t IR_object_y3; // IR y position 10 bits
  437. uint8_t IR_object_s3; // IR size value
  438. uint16_t IR_object_x4;
  439. uint16_t IR_object_y4;
  440. uint8_t IR_object_s4;
  441. #endif
  442. };
  443. #endif