1 #include "OISConfig.h" 2 #ifdef OIS_WIN32_WIIMOTE_SUPPORT 3 //cWiimote 0.2 by Kevin Forbes (http://simulatedcomicproduct.com) 4 //This code is public domain, and comes with no warranty. The user takes full responsibility for anything that happens as a result from using this code. 5 6 //Edited for Toshiba Stack support (hopefully also all others) by 7 //Sean Stellingwerff (http://sean.stellingwerff.com) using information 8 //gathered from http://www.lvr.com/hidpage.htm (Thanks a million! :D) 9 10 //#include "stdafx.h" 11 #include "wiimote.h" 12 #include <stdio.h> 13 14 //output channels 15 const unsigned char OUTPUT_CHANNEL_FORCE_FEEDBACK = 0x13; 16 const unsigned char OUTPUT_CHANNEL_LED = 0x11; 17 const unsigned char OUTPUT_CHANNEL_REPORT = 0x12; 18 const unsigned char OUTPUT_READ_MEMORY = 0x17; 19 const unsigned char OUTPUT_WRITE_MEMORY = 0x16; 20 21 const unsigned char OUTPUT_ENABLE_IR = 0x13; 22 const unsigned char OUTPUT_ENABLE_IR2 = 0x1a; 23 24 //report request types 25 const unsigned char REQUEST_CONTINUOUS_REPORTS = 0x4; 26 const unsigned char REQUEST_SINGLE_REPORTS = 0x0; 27 28 //input channels 29 const unsigned char INPUT_CHANNEL_BUTTONS_ONLY = 0x30; 30 const unsigned char INPUT_CHANNEL_BUTTONS_MOTION = 0x31; 31 const unsigned char INPUT_CHANNEL_WRITE_CONFIRM = 0x22; 32 const unsigned char INPUT_CHANNEL_EXPANSION_PORT = 0x20; 33 34 const unsigned char INPUT_CHANNEL_MOTION_IR = 0x33; 35 const unsigned char INPUT_CHANNEL_MOTION_CHUCK_IR = 0x37; 36 const unsigned char INPUT_CHANNEL_MOTION_CHUCK = 0x35; 37 38 //the ID values for a wiimote 39 const unsigned short mVendorID = 0x057E; 40 const unsigned short mDeviceID = 0x0306; 41 42 //how to find the calibration data for the wiimote 43 const unsigned short CALIBRATION_ADDRESS = 0x16; 44 const unsigned short CALIBRATION_DATA_LENGTH = 7; 45 46 //nunchuck constants 47 const unsigned long NUNCHUCK_STATUS_ADDRESS = 0x04A40000; 48 const unsigned long NUNCHUCK_CALIBRATION_ADDRESS = 0x04A40020; 49 const unsigned long NUNCHUCK_CALIBRATION_ADDRESS_2 = 0x04A40030; 50 const unsigned long NUNCHUCK_INIT_ADDRESS= 0x04A40040; 51 const unsigned long NUNCHUK_ID_ADDRESS = 0x04a400f0; 52 const unsigned char NUNCHUCK_INIT_VAL= 0x0; 53 54 //IR constants 55 const unsigned long IR_REG_1 = 0x04b00030; 56 const unsigned long IR_REG_2 = 0x04b00033; 57 const unsigned long IR_SENS_ADDR_1 = 0x04b00000; 58 const unsigned long IR_SENS_ADDR_2 = 0x04b0001a; 59 60 const unsigned char IR_SENS_MIDRANGE_PART1[] = {0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xaa, 0x00, 0x64}; 61 const unsigned char IR_SENS_MIDRANGE_PART2[] = {0x63, 0x03}; 62 63 const unsigned char IR_MODE_OFF = 0; 64 const unsigned char IR_MODE_STD = 1; 65 const unsigned char IR_MODE_EXP = 3; 66 const unsigned char IR_MODE_FULL = 5; 67 68 cWiiMote::cWiiMote() 69 { 70 Init(); 71 } 72 73 cWiiMote::~cWiiMote() 74 { 75 Disconnect(); 76 } 77 78 void cWiiMote::Init() 79 { 80 mReportMode = REPORT_MODE_EVENT_BUTTONS; 81 mLastButtonStatus.Init(); 82 mLastExpansionReport.Init(); 83 mLastMotionReport.Init(); 84 mOutputControls.Init(); 85 mReadInfo.Init(); 86 mAccelCalibrationData.Init(); 87 mNunchuckAccelCalibrationData.Init(); 88 mNunchuckStickCalibrationData.Init(); 89 mLastIRReport.Init(); 90 mNunchuckAttached = false; 91 mIRRunning = false; 92 mDataStreamRunning = false; 93 } 94 95 bool cWiiMote::SetReportMode(eReportMode mode) 96 { 97 mReportMode = mode; 98 return SendReportMode(); 99 } 100 101 bool cWiiMote::SendReportMode() 102 { 103 bool continuous = true; 104 unsigned char channel = INPUT_CHANNEL_BUTTONS_ONLY; 105 bool check_chuck = false; 106 107 switch (mReportMode) 108 { 109 case REPORT_MODE_MOTION_IR: 110 channel = INPUT_CHANNEL_MOTION_IR; 111 break; 112 case REPORT_MODE_MOTION_CHUCK_IR: 113 channel = INPUT_CHANNEL_MOTION_CHUCK_IR; 114 check_chuck = true; 115 break; 116 case REPORT_MODE_MOTION_CHUCK: 117 channel = INPUT_CHANNEL_MOTION_CHUCK; 118 check_chuck = true; 119 break; 120 case REPORT_MODE_MOTION: 121 channel = INPUT_CHANNEL_BUTTONS_MOTION; 122 break; 123 case REPORT_MODE_EVENT_BUTTONS: 124 channel = INPUT_CHANNEL_BUTTONS_ONLY; 125 continuous = false; 126 break; 127 default: 128 break; 129 } 130 131 //check to make sure that there is a chuck attached 132 // if (check_chuck && !mNunchuckAttached) 133 // { 134 // printf("Supposed to check for nunchuck, but couldn't find one!"); 135 // return false; 136 // } 137 138 bool retval = SelectInputChannel(continuous,channel); 139 return retval; 140 } 141 142 bool cWiiMote::ConnectToDevice(int index) 143 { 144 Init(); 145 const bool retval = mHIDDevice.Connect(mDeviceID,mVendorID,index) && 146 SetReportMode(REPORT_MODE_MOTION_CHUCK_IR) && 147 UpdateOutput() && 148 ReadCalibrationData(); 149 150 if (retval) 151 { 152 InitNunchuck(); 153 } 154 return retval; 155 } 156 157 bool cWiiMote::Disconnect() 158 { 159 bool retval = false; 160 StopDataStream(); 161 162 if (mHIDDevice.IsConnected()) 163 { 164 retval = mHIDDevice.Disconnect(); 165 } 166 167 return retval; 168 } 169 170 bool cWiiMote::SetVibration(bool vib_on) 171 { 172 bool retval = true; 173 if (mOutputControls.mVibration != vib_on) 174 { 175 mOutputControls.mVibration = vib_on; 176 retval = UpdateOutput(); 177 } 178 return retval; 179 } 180 181 void cWiiMote::ClearBuffer() 182 { 183 memset(mOutputBuffer,0, mOutputBufferSize); 184 } 185 186 bool cWiiMote::SetLEDs(bool led1, bool led2, bool led3, bool led4) 187 { 188 const bool no_change = mOutputControls.mLED1 == led1 && 189 mOutputControls.mLED2 == led2 && 190 mOutputControls.mLED3 == led3 && 191 mOutputControls.mLED4 == led4; 192 193 if (no_change) 194 { 195 return true; 196 } 197 198 mOutputControls.mLED1 = led1; 199 mOutputControls.mLED2 = led2; 200 mOutputControls.mLED3 = led3; 201 mOutputControls.mLED4 = led4; 202 return UpdateOutput(); 203 } 204 205 bool cWiiMote::UpdateOutput() 206 { 207 ClearBuffer(); 208 mOutputBuffer[0] = OUTPUT_CHANNEL_LED; 209 mOutputBuffer[1] = (mOutputControls.mVibration ? 0x1 : 0x0) | 210 (mOutputControls.mLED1 ? 0x1 : 0x0) << 4 | 211 (mOutputControls.mLED2 ? 0x1 : 0x0) << 5 | 212 (mOutputControls.mLED3 ? 0x1 : 0x0) << 6 | 213 (mOutputControls.mLED4 ? 0x1 : 0x0) << 7; 214 return mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 215 } 216 217 bool cWiiMote::HeartBeat(int timeout) 218 { 219 bool retval = true; 220 int bytes_read = 0; 221 222 223 //most of these reports aren't implemented yet. I don't have a sensor bar or a nunchuck :) 224 if (mHIDDevice.ReadFromDevice(mInputBuffer,mInputBufferSize,bytes_read) && (bytes_read > 0,timeout)) 225 { 226 const int channel = mInputBuffer[0]; 227 switch (channel) 228 { 229 case INPUT_CHANNEL_EXPANSION_PORT:// 6 Expansion Port change 230 { 231 ParseButtonReport(&mInputBuffer[1]); 232 ParseExpansionReport(&mInputBuffer[2]); 233 bool restart = mDataStreamRunning; 234 StopDataStream(); 235 InitNunchuck(); 236 237 if (restart) 238 { 239 retval = StartDataStream(); 240 } 241 } 242 break; 243 244 case INPUT_CHANNEL_BUTTONS_ONLY:// 2 Buttons only 245 ParseButtonReport(&mInputBuffer[1]); 246 break; 247 248 case 0x21:// 21 Read data 249 ParseButtonReport(&mInputBuffer[1]); 250 ParseReadData(&mInputBuffer[3]); 251 break; 252 253 case INPUT_CHANNEL_WRITE_CONFIRM:// 4 Write data 254 break; 255 256 case 0x31:// 5 Buttons | Motion Sensing Report 257 ParseButtonReport(&mInputBuffer[1]); 258 ParseMotionReport(&mInputBuffer[3]); 259 break; 260 261 case 0x32:// 16 Buttons | Expansion Port | IR?? 262 ParseButtonReport(&mInputBuffer[1]); 263 break; 264 265 case INPUT_CHANNEL_MOTION_IR: 266 ParseButtonReport(&mInputBuffer[1]); 267 ParseMotionReport(&mInputBuffer[3]); 268 ParseIRReport(&mInputBuffer[6]); 269 break; 270 271 case INPUT_CHANNEL_MOTION_CHUCK_IR: 272 ParseButtonReport(&mInputBuffer[1]); 273 ParseMotionReport(&mInputBuffer[3]); 274 ParseIRReport(&mInputBuffer[6]); 275 ParseChuckReport(&mInputBuffer[16]); 276 break; 277 278 case INPUT_CHANNEL_MOTION_CHUCK: 279 ParseButtonReport(&mInputBuffer[1]); 280 ParseMotionReport(&mInputBuffer[3]); 281 ParseChuckReport(&mInputBuffer[6]); 282 283 break; 284 285 case 0x34:// 21 Buttons | Expansion Port | IR?? 286 case 0x3d:// 21 Buttons | Expansion Port | IR?? 287 ParseButtonReport(&mInputBuffer[1]); 288 break; 289 290 case 0x3e:// 21 Buttons | Motion Sensing Report | IR?? 291 case 0x3f:// 21 Buttons | Motion Sensing Report | IR?? 292 ParseButtonReport(&mInputBuffer[1]); 293 break; 294 default: 295 retval = false; 296 //unknown report 297 break; 298 } 299 } 300 return retval; 301 } 302 303 void cWiiMote::ParseExpansionReport(const unsigned char *data) 304 { 305 //four bytes long 306 mLastExpansionReport.mAttachmentPluggedIn = (data[0] & 0x02) != 0; 307 mLastExpansionReport.mIREnabled = (data[0] & 0x08) != 0; 308 mLastExpansionReport.mSpeakerEnabled = (data[0] & 0x04) != 0; 309 mLastExpansionReport.mLED1On = (data[0] & 0x10) != 0; 310 mLastExpansionReport.mLED2On = (data[0] & 0x20) != 0; 311 mLastExpansionReport.mLED3On = (data[0] & 0x40) != 0; 312 mLastExpansionReport.mLED4On = (data[0] & 0x80) != 0; 313 314 //two unknown bytes 315 mLastExpansionReport.mBatteryLevel = data[3]; 316 } 317 318 void cWiiMote::ParseButtonReport(const unsigned char * data) 319 { 320 //two bytes long 321 mLastButtonStatus.mA = (data[1] & 0x08) != 0; 322 mLastButtonStatus.mB = (data[1] & 0x04) != 0; 323 mLastButtonStatus.m1 = (data[1] & 0x02) != 0; 324 mLastButtonStatus.m2 = (data[1] & 0x01) != 0; 325 mLastButtonStatus.mPlus = (data[0] & 0x10) != 0; 326 mLastButtonStatus.mMinus = (data[1] & 0x10) != 0; 327 mLastButtonStatus.mHome = (data[1] & 0x80) != 0; 328 mLastButtonStatus.mUp = (data[0] & 0x08) != 0; 329 mLastButtonStatus.mDown = (data[0] & 0x04) != 0; 330 mLastButtonStatus.mLeft = (data[0] & 0x01) != 0; 331 mLastButtonStatus.mRight = (data[0] & 0x02) != 0; 332 } 333 334 void cWiiMote::ParseMotionReport(const unsigned char * data) 335 { 336 //three bytes long 337 mLastMotionReport.mX = data[0]; 338 mLastMotionReport.mY = data[1]; 339 mLastMotionReport.mZ = data[2]; 340 } 341 342 void cWiiMote::PrintStatus() const 343 { 344 float wX,wY,wZ; 345 float cX,cY,cZ; 346 float sX,sY; 347 float irX,irY; 348 349 wX =wY=wZ=cX=cY=cZ=sX=sY=irX=irY=0.f; 350 351 GetCalibratedAcceleration(wX,wY,wZ); 352 printf("W:[%+1.2f %+1.2f %+1.2f] ",wX,wY,wZ); 353 354 if (mNunchuckAttached) 355 { 356 GetCalibratedChuckAcceleration(cX,cY,cZ); 357 printf("N:[%+1.2f %+1.2f %+1.2f] ",cX,cY,cZ); 358 359 GetCalibratedChuckStick(sX,sY); 360 printf("S:[%+1.2f %+1.2f] ",sX,sY); 361 } 362 363 if (mIRRunning) 364 { 365 if (GetIRP1(irX,irY)) 366 { 367 printf("P1:[%+1.2f %+1.2f]",irX,irY); 368 } 369 if (GetIRP2(irX,irY)) 370 { 371 printf("P2:[%+1.2f %+1.2f]",irX,irY); 372 } 373 } 374 375 376 //print the button status 377 if (mLastButtonStatus.m1) 378 printf("1"); 379 if (mLastButtonStatus.m2) 380 printf("2"); 381 if (mLastButtonStatus.mA) 382 printf("A"); 383 if (mLastButtonStatus.mB) 384 printf("B"); 385 if (mLastButtonStatus.mPlus) 386 printf("+"); 387 if (mLastButtonStatus.mMinus) 388 printf("-"); 389 if (mLastButtonStatus.mUp) 390 printf("U"); 391 if (mLastButtonStatus.mDown) 392 printf("D"); 393 if (mLastButtonStatus.mLeft) 394 printf("L"); 395 if (mLastButtonStatus.mRight) 396 printf("R"); 397 if (mLastButtonStatus.mHome) 398 printf("H"); 399 400 if (mNunchuckAttached) 401 { 402 if (mLastChuckReport.mButtonZ) 403 printf("Z"); 404 if (mLastChuckReport.mButtonC) 405 printf("C"); 406 } 407 408 printf("\n"); 409 410 } 411 412 413 bool cWiiMote::SelectInputChannel(bool continuous, unsigned char channel) 414 { 415 ClearBuffer(); 416 mOutputBuffer[0] = OUTPUT_CHANNEL_REPORT; 417 mOutputBuffer[1] = (continuous ? REQUEST_CONTINUOUS_REPORTS : REQUEST_SINGLE_REPORTS) | (mOutputControls.mVibration ? 0x1 : 0x0); 418 mOutputBuffer[2] = channel; 419 return mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 420 } 421 422 423 //this may or may not work to read buffers greater than 16 bytes. . . . 424 bool cWiiMote::IssueReadRequest(unsigned int address, unsigned short size, unsigned char * buffer) 425 { 426 bool retval = false; 427 if (mReadInfo.mReadStatus != tMemReadInfo::READ_PENDING) 428 { 429 ClearBuffer(); 430 mOutputBuffer[0] = OUTPUT_READ_MEMORY; 431 mOutputBuffer[1] = (((address & 0xff000000) >> 24) & 0xFE) | (mOutputControls.mVibration ? 0x1 : 0x0); 432 mOutputBuffer[2] = (address & 0x00ff0000) >> 16; 433 mOutputBuffer[3] = (address & 0x0000ff00) >> 8; 434 mOutputBuffer[4] = (address & 0xff); 435 436 mOutputBuffer[5] = (size & 0xff00) >> 8; 437 mOutputBuffer[6] = (size & 0xff); 438 439 if (mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize)) 440 { 441 mReadInfo.mReadStatus = tMemReadInfo::READ_PENDING; 442 mReadInfo.mReadBuffer = buffer; 443 mReadInfo.mTotalBytesToRead = size; 444 mReadInfo.mBytesRead =0; 445 mReadInfo.mBaseAddress = (unsigned short)(address & 0xFFFF); 446 retval = true; 447 } 448 } 449 450 return retval; 451 } 452 453 void cWiiMote::ParseReadData(const unsigned char * data) 454 { 455 if(mReadInfo.mReadStatus == tMemReadInfo::READ_PENDING) 456 { 457 const bool error = (data[0] & 0x0F) != 0; 458 if (error) 459 { 460 mReadInfo.mReadStatus = tMemReadInfo::READ_ERROR; 461 } 462 else 463 { 464 unsigned char bytes = (data[0] >> 4)+1; 465 unsigned short offset = ((unsigned short)data[1] << 8) + data[2]; 466 unsigned int space_left_in_buffer = mReadInfo.mTotalBytesToRead - mReadInfo.mBytesRead; 467 if (offset == mReadInfo.mBytesRead + mReadInfo.mBaseAddress && 468 space_left_in_buffer >= bytes) 469 { 470 memcpy(&mReadInfo.mReadBuffer[mReadInfo.mBytesRead],&data[3],bytes); 471 472 mReadInfo.mBytesRead+= bytes; 473 if (mReadInfo.mBytesRead >= mReadInfo.mTotalBytesToRead) 474 { 475 mReadInfo.mReadStatus = tMemReadInfo::READ_COMPLETE; 476 } 477 } 478 } 479 } 480 481 } 482 483 bool cWiiMote::ReadData(unsigned int address, unsigned short size, unsigned char * buffer) 484 { 485 if (IssueReadRequest(address, size,buffer)) 486 { 487 while (mReadInfo.mReadStatus == tMemReadInfo::READ_PENDING) 488 { 489 if (!HeartBeat(1000)) 490 { 491 break; 492 } 493 } 494 } 495 return mReadInfo.mReadStatus == tMemReadInfo::READ_COMPLETE; 496 } 497 498 bool cWiiMote::ReadCalibrationData() 499 { 500 bool retval = false; 501 unsigned char buffer[CALIBRATION_DATA_LENGTH]; 502 if (ReadData(CALIBRATION_ADDRESS, CALIBRATION_DATA_LENGTH,buffer)) 503 { 504 mAccelCalibrationData.mXZero = buffer[0]; 505 mAccelCalibrationData.mYZero = buffer[1]; 506 mAccelCalibrationData.mZZero = buffer[2]; 507 mAccelCalibrationData.mXG = buffer[4]; 508 mAccelCalibrationData.mYG = buffer[5]; 509 mAccelCalibrationData.mZG = buffer[6]; 510 retval = true; 511 } 512 513 return retval; 514 } 515 516 void cWiiMote::GetCalibratedAcceleration(float & x, float & y, float &z) const 517 { 518 x = (mLastMotionReport.mX - mAccelCalibrationData.mXZero) / (float)(mAccelCalibrationData.mXG- mAccelCalibrationData.mXZero); 519 y = (mLastMotionReport.mY - mAccelCalibrationData.mYZero) / (float)(mAccelCalibrationData.mYG- mAccelCalibrationData.mYZero); 520 z = (mLastMotionReport.mZ - mAccelCalibrationData.mZZero) / (float)(mAccelCalibrationData.mZG- mAccelCalibrationData.mZZero); 521 } 522 523 void cWiiMote::GetCalibratedChuckAcceleration(float & x, float & y, float &z) const 524 { 525 if (!mNunchuckAttached) 526 { 527 x = y = z = 0.f; 528 return; 529 } 530 531 x = (mLastChuckReport.mAccelX - mNunchuckAccelCalibrationData.mXZero) / (float)(mNunchuckAccelCalibrationData.mXG- mNunchuckAccelCalibrationData.mXZero); 532 y = (mLastChuckReport.mAccelY - mNunchuckAccelCalibrationData.mYZero) / (float)(mNunchuckAccelCalibrationData.mYG- mNunchuckAccelCalibrationData.mYZero); 533 z = (mLastChuckReport.mAccelZ - mNunchuckAccelCalibrationData.mZZero) / (float)(mNunchuckAccelCalibrationData.mZG- mNunchuckAccelCalibrationData.mZZero); 534 } 535 void cWiiMote::GetCalibratedChuckStick(float & x, float & y) const 536 { 537 if (!mNunchuckAttached) 538 { 539 x = y = 0.f; 540 return; 541 } 542 543 if (mLastChuckReport.mStickX < mNunchuckStickCalibrationData.mXmid) 544 { 545 x = ((mLastChuckReport.mStickX - mNunchuckStickCalibrationData.mXmin) / (float)(mNunchuckStickCalibrationData.mXmid - mNunchuckStickCalibrationData.mXmin)) - 1.f; 546 } 547 else 548 { 549 x = ((mLastChuckReport.mStickX - mNunchuckStickCalibrationData.mXmid) / (float)(mNunchuckStickCalibrationData.mXmax - mNunchuckStickCalibrationData.mXmid)); 550 } 551 552 if (mLastChuckReport.mStickY < mNunchuckStickCalibrationData.mYmid) 553 { 554 y = ((mLastChuckReport.mStickY - mNunchuckStickCalibrationData.mYmin) / (float)(mNunchuckStickCalibrationData.mYmid - mNunchuckStickCalibrationData.mYmin)) - 1.f; 555 } 556 else 557 { 558 y = ((mLastChuckReport.mStickY - mNunchuckStickCalibrationData.mYmid) / (float)(mNunchuckStickCalibrationData.mYmax - mNunchuckStickCalibrationData.mYmid)); 559 } 560 } 561 562 563 bool cWiiMote::WriteMemory(unsigned int address, unsigned char size, const unsigned char * buffer) 564 { 565 bool retval = false; 566 if (size <= 16) 567 { 568 ClearBuffer(); 569 mOutputBuffer[0] = OUTPUT_WRITE_MEMORY; 570 mOutputBuffer[1] = (address & 0xff000000) >> 24 | (mOutputControls.mVibration ? 0x1 : 0x0); 571 mOutputBuffer[2] = (address & 0x00ff0000) >> 16; 572 mOutputBuffer[3] = (address & 0x0000ff00) >> 8; 573 mOutputBuffer[4] = (address & 0xff); 574 mOutputBuffer[5] = size; 575 memcpy(&mOutputBuffer[6],buffer,size); 576 retval = mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 577 } 578 579 return retval; 580 } 581 582 bool cWiiMote::InitNunchuck() 583 { 584 585 bool retval = false; 586 587 //first init the nunchuck, if it is present 588 if (WriteMemory(NUNCHUCK_INIT_ADDRESS,1,&NUNCHUCK_INIT_VAL)) 589 { 590 591 unsigned char buffer[16]; 592 //now try to read the nunchuck's calibration data 593 if (ReadData(NUNCHUCK_CALIBRATION_ADDRESS,16,buffer)) 594 { 595 596 //note that this hasn't worked properly for me yet (I get all 0xff). 597 /*mNunchuckAccelCalibrationData.mXZero = NunChuckByte(buffer[0]); 598 mNunchuckAccelCalibrationData.mYZero = NunChuckByte(buffer[1]); 599 mNunchuckAccelCalibrationData.mZZero = NunChuckByte(buffer[2]); 600 601 mNunchuckAccelCalibrationData.mXG = NunChuckByte(buffer[4]); 602 mNunchuckAccelCalibrationData.mYG = NunChuckByte(buffer[5]); 603 mNunchuckAccelCalibrationData.mZG = NunChuckByte(buffer[6]); 604 605 mNunchuckStickCalibrationData.mXmax = NunChuckByte(buffer[8]); 606 mNunchuckStickCalibrationData.mXmin = NunChuckByte(buffer[9]); 607 mNunchuckStickCalibrationData.mXmid = NunChuckByte(buffer[10]); 608 mNunchuckStickCalibrationData.mYmax = NunChuckByte(buffer[11]); 609 mNunchuckStickCalibrationData.mYmin = NunChuckByte(buffer[12]); 610 mNunchuckStickCalibrationData.mYmid = NunChuckByte(buffer[13]);*/ 611 612 //these are default values from the wiili wiki 613 mNunchuckAccelCalibrationData.mXZero = 0x7E; 614 mNunchuckAccelCalibrationData.mYZero = 0x7A; 615 mNunchuckAccelCalibrationData.mZZero = 0x7D; 616 mNunchuckAccelCalibrationData.mXG = 0xB0; 617 mNunchuckAccelCalibrationData.mYG = 0xAF; 618 mNunchuckAccelCalibrationData.mZG = 0xB1; 619 mNunchuckStickCalibrationData.mXmax = 0xe5; 620 mNunchuckStickCalibrationData.mXmin = 0x21; 621 mNunchuckStickCalibrationData.mXmid = 0x7c; 622 mNunchuckStickCalibrationData.mYmax = 0xe7; 623 mNunchuckStickCalibrationData.mYmin = 0x23; 624 mNunchuckStickCalibrationData.mYmid = 0x7a; 625 retval = true; 626 627 } 628 } 629 mNunchuckAttached = retval; 630 return retval; 631 } 632 633 void cWiiMote::ParseChuckReport(const unsigned char * data) 634 { 635 mLastChuckReport.mStickX = NunChuckByte(data[0]); 636 mLastChuckReport.mStickY = NunChuckByte(data[1]); 637 mLastChuckReport.mAccelX = NunChuckByte(data[2]); 638 mLastChuckReport.mAccelY = NunChuckByte(data[3]); 639 mLastChuckReport.mAccelZ = NunChuckByte(data[4]); 640 mLastChuckReport.mButtonC = (NunChuckByte(data[5]) & 0x2) == 0; 641 mLastChuckReport.mButtonZ = (NunChuckByte(data[5]) & 0x1) == 0; 642 } 643 644 bool cWiiMote::EnableIR() 645 { 646 bool retval = false; 647 648 DisableIR(); 649 650 if (!mIRRunning) 651 { 652 ClearBuffer(); 653 mOutputBuffer[0] = OUTPUT_ENABLE_IR; 654 mOutputBuffer[1] = 0x4 | (mOutputControls.mVibration ? 0x1 : 0x0); 655 retval = mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 656 657 if (retval) 658 { 659 mOutputBuffer[0] = OUTPUT_ENABLE_IR2; 660 mOutputBuffer[1] = 0x4 | (mOutputControls.mVibration ? 0x1 : 0x0); 661 retval = mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 662 } 663 664 if (retval) 665 { 666 unsigned char val = 0x1; 667 retval = WriteMemory(IR_REG_1,1,&val); 668 } 669 670 if (retval) 671 { 672 retval = WriteMemory(IR_SENS_ADDR_1,9,IR_SENS_MIDRANGE_PART1); 673 } 674 675 if (retval) 676 { 677 retval = WriteMemory(IR_SENS_ADDR_2,2,IR_SENS_MIDRANGE_PART2); 678 } 679 680 681 if (retval) 682 { 683 retval = WriteMemory(IR_REG_2,1,&IR_MODE_EXP); 684 } 685 686 if (retval) 687 { 688 unsigned char val = 0x8; 689 retval = WriteMemory(IR_REG_1,1,&val); 690 } 691 692 693 mIRRunning = retval; 694 } 695 return retval; 696 697 } 698 699 bool cWiiMote::DisableIR() 700 { 701 bool retval = false; 702 703 if (mIRRunning) 704 { 705 ClearBuffer(); 706 mOutputBuffer[0] = OUTPUT_ENABLE_IR; 707 mOutputBuffer[1] = (mOutputControls.mVibration ? 0x1 : 0x0); 708 retval = mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 709 710 if (retval) 711 { 712 mOutputBuffer[0] = OUTPUT_ENABLE_IR2; 713 mOutputBuffer[1] = (mOutputControls.mVibration ? 0x1 : 0x0); 714 retval = mHIDDevice.WriteToDevice(mOutputBuffer,mOutputBufferSize); 715 } 716 717 mIRRunning = false; 718 } 719 return retval; 720 721 } 722 723 void cWiiMote::ParseIRReport(const unsigned char * data) 724 { 725 mLastIRReport.mP1X = data[0] << 2 | (data[2] & 0x30) >>4; 726 mLastIRReport.mP1Y = data[1] << 2 | (data[2] & 0xc0) >>6; 727 mLastIRReport.mP1Size = data[2] & 0xf; 728 729 mLastIRReport.mP2X = data[3] << 2 | (data[5] & 0x30) >>4; 730 mLastIRReport.mP2Y = data[4] << 2 | (data[5] & 0xc0) >>6; 731 mLastIRReport.mP2Size = data[5] & 0xf; 732 733 mLastIRReport.mP1Found = !(data[0] == 0xff && data[1] == 0xff && data[2] == 0xff); 734 mLastIRReport.mP2Found = !(data[3] == 0xff && data[4] == 0xff && data[5] == 0xff); 735 } 736 737 bool cWiiMote::GetIRP1(float &x, float &y) const 738 { 739 bool retval = false; 740 if (mIRRunning && mLastIRReport.mP1Found) 741 { 742 x = mLastIRReport.mP1X / 1024.f; 743 y = mLastIRReport.mP1Y / 1024.f; 744 retval = true; 745 } 746 return retval; 747 } 748 749 750 bool cWiiMote::GetIRP2(float &x, float &y) const 751 { 752 bool retval = false; 753 if (mIRRunning && mLastIRReport.mP2Found) 754 { 755 x = mLastIRReport.mP2X / 1024.f; 756 y = mLastIRReport.mP2Y / 1024.f; 757 retval = true; 758 } 759 return retval; 760 761 } 762 763 bool cWiiMote::StartDataStream() 764 { 765 bool retval = false; 766 767 StopDataStream(); 768 769 if (mNunchuckAttached) 770 { 771 retval =SetReportMode(REPORT_MODE_MOTION_CHUCK_IR); 772 } 773 else 774 { 775 retval = SetReportMode(REPORT_MODE_MOTION_IR); 776 } 777 EnableIR(); 778 779 mDataStreamRunning = retval; 780 return retval; 781 } 782 783 784 bool cWiiMote::StopDataStream() 785 { 786 if (mDataStreamRunning) 787 { 788 mDataStreamRunning = false; 789 DisableIR(); 790 SetReportMode(REPORT_MODE_EVENT_BUTTONS); 791 } 792 return true;; 793 } 794 #endif 795