Shinichiro Nakamura
/
Drive2ChoroQ
This is a demonstration of two Choro Q Hybrid cars.
Diff: extlib/WiiNunchuck/WiiNunchuckReader.cpp
- Revision:
- 0:d825f8dae2be
diff -r 000000000000 -r d825f8dae2be extlib/WiiNunchuck/WiiNunchuckReader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extlib/WiiNunchuck/WiiNunchuckReader.cpp Mon Nov 22 12:23:23 2010 +0000 @@ -0,0 +1,118 @@ +/* +* WiiNunchuckReader. A program allowing the output of one or two +* Wii Nunchucks to be read via I2C and decoded for use, using the mbed +* microcontroller and its associated libraries. +* +* Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk> +* +* This file is part of WiiNunchuckReader. +* +* WiiNunchuckReader is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* WiiNunchuckReader is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with WiiNunchuckReader. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "WiiNunchuckReader.h" + +// constructor +WiiNunchuckReader::WiiNunchuckReader(PinName sda, PinName scl) : + joyX(0), joyY(0), accelX(0), accelY(0), accelZ(0), + buttonC(0), buttonZ(0), nunchuckInit(false), + nunchuckPort(sda, scl) { +} + +void WiiNunchuckReader::RequestRead() { + // don't expect client to remember to send an init to the nunchuck + // so do it for them here + if (!nunchuckInit) { + nunchuckInit = NunchuckInit(); + } + + if (nunchuckInit) { // don't start reading if init failed + if (NunchuckRead()) { + // only decode successful reads + NunchuckDecode(); + } + } +} + +bool WiiNunchuckReader::NunchuckInit() { + bool success = false; + + const BYTE cmd[] = {NUNCHUCK_REGADDR, 0x00}; + if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) success = true; + + return success; +} + +bool WiiNunchuckReader::NunchuckRead() { + bool success = false; + + // write the address we want to read from + const BYTE cmd[] = {0x00}; + if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) { + // the Wii Nunchuck is non-standard I2C + // and can't manage setting the read address and immediately supplying the data + // so wait a bit + wait(I2C_READ_DELAY); + + if (I2C_OK == nunchuckPort.read(NUNCHUCK_ADDR, readBuf, sizeof(readBuf))) success = true; + } + + return success; +} + +void WiiNunchuckReader::NunchuckDecode() { + joyX = (int)readBuf[JOY_X]; + joyY = (int)readBuf[JOY_Y]; + + // the accelerometer axis values are really 10 bit values + // so shift the 8 bit values read from the nunchuck + // 2 bits to the right + accelX = (int)readBuf[ACCEL_X] << 2; + accelY = (int)readBuf[ACCEL_Y] << 2; + accelZ = (int)readBuf[ACCEL_Z] << 2; + + DecodeAdditional(); +} + +void WiiNunchuckReader::DecodeAdditional() { + // the nunchcuk buttons have their own idea of state + int buttonState = readBuf[ADDITIONAL] & MASK_CZ; + switch (buttonState) { + case 3: + buttonZ = 0; + buttonC = 0; + break; + case 2: + buttonZ = 1; + buttonC = 1; + break; + case 1: + buttonZ = 0; + buttonC = 1; + break; + case 0: + buttonZ = 1; + buttonC = 0; + break; + } + + // and the accelerometer axis - for each axis value add bit 1 and bit 0 + // as required + if (readBuf[ADDITIONAL] & MASK_ACCLX1) accelX += 2; + if (readBuf[ADDITIONAL] & MASK_ACCLX2) accelX += 1; + if (readBuf[ADDITIONAL] & MASK_ACCLY1) accelY += 2; + if (readBuf[ADDITIONAL] & MASK_ACCLY2) accelY += 1; + if (readBuf[ADDITIONAL] & MASK_ACCLZ1) accelZ += 2; + if (readBuf[ADDITIONAL] & MASK_ACCLZ2) accelZ += 1; +} \ No newline at end of file