This is a demonstration of two Choro Q Hybrid cars.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WiiNunchuckReader.cpp Source File

WiiNunchuckReader.cpp

00001 /*
00002 * WiiNunchuckReader. A program allowing the output of one or two
00003 * Wii Nunchucks to be read via I2C and decoded for use, using the mbed
00004 * microcontroller and its associated libraries.
00005 *
00006 * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
00007 *
00008 * This file is part of WiiNunchuckReader.
00009 *
00010 * WiiNunchuckReader is free software: you can redistribute it and/or modify
00011 * it under the terms of the GNU General Public License as published by
00012 * the Free Software Foundation, either version 3 of the License, or
00013 * (at your option) any later version.
00014 *
00015 * WiiNunchuckReader is distributed in the hope that it will be useful,
00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 * GNU General Public License for more details.
00019 *
00020 * You should have received a copy of the GNU General Public License
00021 * along with WiiNunchuckReader.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 
00024 #include "WiiNunchuckReader.h"
00025 
00026 // constructor
00027 WiiNunchuckReader::WiiNunchuckReader(PinName sda, PinName scl) :
00028         joyX(0), joyY(0), accelX(0), accelY(0), accelZ(0),
00029         buttonC(0), buttonZ(0), nunchuckInit(false),
00030         nunchuckPort(sda, scl) {
00031 }
00032 
00033 void WiiNunchuckReader::RequestRead() {
00034     // don't expect client to remember to send an init to the nunchuck
00035     // so do it for them here
00036     if (!nunchuckInit) {
00037         nunchuckInit = NunchuckInit();
00038     }
00039 
00040     if (nunchuckInit) {  // don't start reading if init failed
00041         if (NunchuckRead()) {
00042             // only decode successful reads
00043             NunchuckDecode();
00044         }
00045     }
00046 }
00047 
00048 bool WiiNunchuckReader::NunchuckInit() {
00049     bool success = false;
00050 
00051     const BYTE cmd[] = {NUNCHUCK_REGADDR, 0x00};
00052     if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) success = true;
00053 
00054     return success;
00055 }
00056 
00057 bool WiiNunchuckReader::NunchuckRead() {
00058     bool success = false;
00059 
00060     // write the address we want to read from
00061     const BYTE cmd[] = {0x00};
00062     if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) {
00063         // the Wii Nunchuck is non-standard I2C
00064         // and can't manage setting the read address and immediately supplying the data
00065         // so wait a bit
00066         wait(I2C_READ_DELAY);
00067 
00068         if (I2C_OK == nunchuckPort.read(NUNCHUCK_ADDR, readBuf, sizeof(readBuf))) success = true;
00069     }
00070 
00071     return success;
00072 }
00073 
00074 void WiiNunchuckReader::NunchuckDecode() {
00075     joyX = (int)readBuf[JOY_X];
00076     joyY = (int)readBuf[JOY_Y];
00077 
00078     // the accelerometer axis values are really 10 bit values
00079     // so shift the 8 bit values read from the nunchuck
00080     // 2 bits to the right
00081     accelX = (int)readBuf[ACCEL_X] << 2;
00082     accelY = (int)readBuf[ACCEL_Y] << 2;
00083     accelZ = (int)readBuf[ACCEL_Z] << 2;
00084 
00085     DecodeAdditional();
00086 }
00087 
00088 void WiiNunchuckReader::DecodeAdditional() {
00089     // the nunchcuk buttons have their own idea of state
00090     int buttonState = readBuf[ADDITIONAL] & MASK_CZ;
00091     switch (buttonState) {
00092         case 3:
00093             buttonZ = 0;
00094             buttonC = 0;
00095             break;
00096         case 2:
00097             buttonZ = 1;
00098             buttonC = 1;
00099             break;
00100         case 1:
00101             buttonZ = 0;
00102             buttonC = 1;
00103             break;
00104         case 0:
00105             buttonZ = 1;
00106             buttonC = 0;
00107             break;
00108     }
00109 
00110     // and the accelerometer axis - for each axis value add bit 1 and bit 0
00111     // as required
00112     if (readBuf[ADDITIONAL] & MASK_ACCLX1) accelX += 2;
00113     if (readBuf[ADDITIONAL] & MASK_ACCLX2) accelX += 1;
00114     if (readBuf[ADDITIONAL] & MASK_ACCLY1) accelY += 2;
00115     if (readBuf[ADDITIONAL] & MASK_ACCLY2) accelY += 1;
00116     if (readBuf[ADDITIONAL] & MASK_ACCLZ1) accelZ += 2;
00117     if (readBuf[ADDITIONAL] & MASK_ACCLZ2) accelZ += 1;
00118 }