David Rimer / Mbed OS Gigatron_Emulator
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WiiClassicControllerReader.cpp Source File

WiiClassicControllerReader.cpp

00001 /*
00002 * WiiClassicControllerReader. A program allowing the output of one or two
00003 * Wii Classic Controllers to be read via I2C and decoded for use, using the mbed 
00004 * microcontroller and its associated libraries.
00005 *
00006 * Written by Alfredo Guerrero <alfredog83@gmail.com> for the mbedGC open-source 
00007 * game console <http://www.mbedgc.com>. Based on the original code for
00008 * the WiiNunchuckReader written by Petras Saduikis <petras@petras.co.uk>.
00009 *
00010 * This file is part of WiiClassicControllerReader.
00011 *
00012 * WiiClassicControllerReader is free software: you can redistribute it and/or modify
00013 * it under the terms of the GNU General Public License as published by
00014 * the Free Software Foundation, either version 3 of the License, or
00015 * (at your option) any later version.
00016 * 
00017 * WiiClassicControllerReader is distributed in the hope that it will be useful,
00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 * GNU General Public License for more details.
00021 *
00022 * You can find a copy of the GNU General Public License at <http://www.gnu.org/licenses/>.
00023 */
00024 
00025 #include "WiiClassicControllerReader.h"
00026 
00027 // constructor
00028 WiiClassicControllerReader::WiiClassicControllerReader(PinName sda, PinName scl) : 
00029     controllerPort(sda, scl),
00030     ljoyX(0), ljoyY(0), rjoyX(0), rjoyY(0), buttonX(0), buttonY(0), buttonA(0),
00031     buttonB(0), buttonZL(0), buttonZR(0), buttonLT(0), buttonRT(0), buttonLC(0), 
00032     buttonRC(0), buttonHOME(0), buttonSELECT(0), buttonSTART(0), buttonDU(0), 
00033     buttonDD(0), buttonDL(0), buttonDR(0), controllerInit(false)
00034 {
00035 }
00036 
00037 void WiiClassicControllerReader::RequestRead()
00038 {
00039     // don't expect client to remember to send an init to the nunchuck
00040     // so do it for them here
00041     if (!controllerInit)
00042     {
00043         controllerInit = ControllerInit();
00044     }
00045     
00046     if (controllerInit)    // don't start reading if init failed
00047     {
00048         if (ControllerRead())
00049         {
00050             // only decode successful reads
00051             ControllerDecode();
00052         }
00053     }
00054 }
00055 
00056 bool WiiClassicControllerReader::ControllerInit()
00057 {
00058     bool success = false;
00059     
00060     const BYTE cmd[] = {CONTROLLER_REGADDR, 0x00};    
00061     if (I2C_OK == controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd))) success = true;
00062     
00063     return success;
00064 }
00065 
00066 bool WiiClassicControllerReader::ControllerRead()
00067 {
00068     bool success = false;
00069     
00070     // write the address we want to read from
00071     const BYTE cmd[] = {0x00};
00072     if (I2C_OK ==  controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd)))
00073     {
00074         // the Wii Classic Controller is non-standard I2C
00075         // and can't manage setting the read address and immediately supplying the data
00076         // so wait a bit
00077         wait(I2C_READ_DELAY);
00078         
00079         if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf))) success = true;
00080     }
00081     
00082     return success;
00083 }
00084 
00085 bool WiiClassicControllerReader::ControllerWriteCmd()
00086 {
00087     bool success = false;
00088     
00089     // write the address we want to read from
00090     const BYTE cmd[] = {0x00};
00091     if (I2C_OK ==  controllerPort.write(CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd)))
00092     {
00093         success = true;
00094     }
00095     
00096     return success;
00097 }
00098 
00099 bool WiiClassicControllerReader::ControllerReadCmd()
00100 {
00101     bool success = false;
00102     
00103     if (I2C_OK == controllerPort.read(CONTROLLER_ADDR, readBuf, sizeof(readBuf)))
00104     {
00105         success = true;
00106     }
00107     
00108     return success;
00109 }
00110 
00111 void WiiClassicControllerReader::ControllerDecode()
00112 {
00113     ljoyX = (int)readBuf[0] & MASK_LX;
00114     ljoyY = (int)readBuf[1] & MASK_LY;
00115     rjoyY = (int)readBuf[2] & MASK_RY;
00116     buttonRT = (int)readBuf[3] & MASK_RT;
00117     buttonRC = (int)readBuf[4] & MASK_RC_DL;
00118     buttonSTART = (int)readBuf[4] & MASK_BSTART_ZR;
00119     buttonHOME = (int)readBuf[4] & MASK_BHOME_X;
00120     buttonSELECT = (int)readBuf[4] & MASK_BSELECT_A;
00121     buttonLC = (int)readBuf[4] & MASK_LC_Y;
00122     buttonDD = (int)readBuf[4] & MASK_BDD_B;
00123     buttonDR = (int)readBuf[4] & MASK_BDR_ZL;
00124     buttonDU = (int)readBuf[5] & MASK_BDU;
00125     buttonDL = (int)readBuf[5] & MASK_RC_DL;
00126     buttonZR = (int)readBuf[5] & MASK_BSTART_ZR;
00127     buttonX = (int)readBuf[5] & MASK_BHOME_X;
00128     buttonA = (int)readBuf[5] & MASK_BSELECT_A;
00129     buttonY = (int)readBuf[5] & MASK_LC_Y;
00130     buttonB = (int)readBuf[5] & MASK_BDD_B;
00131     buttonZL = (int)readBuf[5] & MASK_BDR_ZL;
00132     
00133     // the RjoyX axis and LT values are really 5 bit values
00134     // so shift the 2 bit values read from the controller
00135     // 3 bits to the right
00136     rjoyX = ( (int)readBuf[0] & MASK_RX34 ) << 3;
00137     buttonLT = ( (int)readBuf[2] & MASK_LT34 ) << 3;
00138     
00139     // and for each value add bit 2, bit 1, and bit 0
00140     // as required    
00141     if (readBuf[2] & MASK_BDR_ZL) rjoyX += 1;
00142     if (readBuf[1] & MASK_BDD_B) rjoyX += 2;
00143     if (readBuf[1] & MASK_BDR_ZL) rjoyX += 4;
00144     if (readBuf[3] & MASK_LC_Y) buttonLT += 1;
00145     if (readBuf[3] & MASK_BDD_B) buttonLT += 2;
00146     if (readBuf[3] & MASK_BDR_ZL) buttonLT += 4;
00147 
00148 }