This is a demonstration of two Choro Q Hybrid cars.

Committer:
shintamainjp
Date:
Mon Nov 22 12:23:23 2010 +0000
Revision:
0:d825f8dae2be
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shintamainjp 0:d825f8dae2be 1 /*
shintamainjp 0:d825f8dae2be 2 * WiiNunchuckReader. A program allowing the output of one or two
shintamainjp 0:d825f8dae2be 3 * Wii Nunchucks to be read via I2C and decoded for use, using the mbed
shintamainjp 0:d825f8dae2be 4 * microcontroller and its associated libraries.
shintamainjp 0:d825f8dae2be 5 *
shintamainjp 0:d825f8dae2be 6 * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
shintamainjp 0:d825f8dae2be 7 *
shintamainjp 0:d825f8dae2be 8 * This file is part of WiiNunchuckReader.
shintamainjp 0:d825f8dae2be 9 *
shintamainjp 0:d825f8dae2be 10 * WiiNunchuckReader is free software: you can redistribute it and/or modify
shintamainjp 0:d825f8dae2be 11 * it under the terms of the GNU General Public License as published by
shintamainjp 0:d825f8dae2be 12 * the Free Software Foundation, either version 3 of the License, or
shintamainjp 0:d825f8dae2be 13 * (at your option) any later version.
shintamainjp 0:d825f8dae2be 14 *
shintamainjp 0:d825f8dae2be 15 * WiiNunchuckReader is distributed in the hope that it will be useful,
shintamainjp 0:d825f8dae2be 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
shintamainjp 0:d825f8dae2be 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
shintamainjp 0:d825f8dae2be 18 * GNU General Public License for more details.
shintamainjp 0:d825f8dae2be 19 *
shintamainjp 0:d825f8dae2be 20 * You should have received a copy of the GNU General Public License
shintamainjp 0:d825f8dae2be 21 * along with WiiNunchuckReader. If not, see <http://www.gnu.org/licenses/>.
shintamainjp 0:d825f8dae2be 22 */
shintamainjp 0:d825f8dae2be 23
shintamainjp 0:d825f8dae2be 24 #include "WiiNunchuckReader.h"
shintamainjp 0:d825f8dae2be 25
shintamainjp 0:d825f8dae2be 26 // constructor
shintamainjp 0:d825f8dae2be 27 WiiNunchuckReader::WiiNunchuckReader(PinName sda, PinName scl) :
shintamainjp 0:d825f8dae2be 28 joyX(0), joyY(0), accelX(0), accelY(0), accelZ(0),
shintamainjp 0:d825f8dae2be 29 buttonC(0), buttonZ(0), nunchuckInit(false),
shintamainjp 0:d825f8dae2be 30 nunchuckPort(sda, scl) {
shintamainjp 0:d825f8dae2be 31 }
shintamainjp 0:d825f8dae2be 32
shintamainjp 0:d825f8dae2be 33 void WiiNunchuckReader::RequestRead() {
shintamainjp 0:d825f8dae2be 34 // don't expect client to remember to send an init to the nunchuck
shintamainjp 0:d825f8dae2be 35 // so do it for them here
shintamainjp 0:d825f8dae2be 36 if (!nunchuckInit) {
shintamainjp 0:d825f8dae2be 37 nunchuckInit = NunchuckInit();
shintamainjp 0:d825f8dae2be 38 }
shintamainjp 0:d825f8dae2be 39
shintamainjp 0:d825f8dae2be 40 if (nunchuckInit) { // don't start reading if init failed
shintamainjp 0:d825f8dae2be 41 if (NunchuckRead()) {
shintamainjp 0:d825f8dae2be 42 // only decode successful reads
shintamainjp 0:d825f8dae2be 43 NunchuckDecode();
shintamainjp 0:d825f8dae2be 44 }
shintamainjp 0:d825f8dae2be 45 }
shintamainjp 0:d825f8dae2be 46 }
shintamainjp 0:d825f8dae2be 47
shintamainjp 0:d825f8dae2be 48 bool WiiNunchuckReader::NunchuckInit() {
shintamainjp 0:d825f8dae2be 49 bool success = false;
shintamainjp 0:d825f8dae2be 50
shintamainjp 0:d825f8dae2be 51 const BYTE cmd[] = {NUNCHUCK_REGADDR, 0x00};
shintamainjp 0:d825f8dae2be 52 if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) success = true;
shintamainjp 0:d825f8dae2be 53
shintamainjp 0:d825f8dae2be 54 return success;
shintamainjp 0:d825f8dae2be 55 }
shintamainjp 0:d825f8dae2be 56
shintamainjp 0:d825f8dae2be 57 bool WiiNunchuckReader::NunchuckRead() {
shintamainjp 0:d825f8dae2be 58 bool success = false;
shintamainjp 0:d825f8dae2be 59
shintamainjp 0:d825f8dae2be 60 // write the address we want to read from
shintamainjp 0:d825f8dae2be 61 const BYTE cmd[] = {0x00};
shintamainjp 0:d825f8dae2be 62 if (I2C_OK == nunchuckPort.write(NUNCHUCK_ADDR, (const char*)cmd, sizeof(cmd))) {
shintamainjp 0:d825f8dae2be 63 // the Wii Nunchuck is non-standard I2C
shintamainjp 0:d825f8dae2be 64 // and can't manage setting the read address and immediately supplying the data
shintamainjp 0:d825f8dae2be 65 // so wait a bit
shintamainjp 0:d825f8dae2be 66 wait(I2C_READ_DELAY);
shintamainjp 0:d825f8dae2be 67
shintamainjp 0:d825f8dae2be 68 if (I2C_OK == nunchuckPort.read(NUNCHUCK_ADDR, readBuf, sizeof(readBuf))) success = true;
shintamainjp 0:d825f8dae2be 69 }
shintamainjp 0:d825f8dae2be 70
shintamainjp 0:d825f8dae2be 71 return success;
shintamainjp 0:d825f8dae2be 72 }
shintamainjp 0:d825f8dae2be 73
shintamainjp 0:d825f8dae2be 74 void WiiNunchuckReader::NunchuckDecode() {
shintamainjp 0:d825f8dae2be 75 joyX = (int)readBuf[JOY_X];
shintamainjp 0:d825f8dae2be 76 joyY = (int)readBuf[JOY_Y];
shintamainjp 0:d825f8dae2be 77
shintamainjp 0:d825f8dae2be 78 // the accelerometer axis values are really 10 bit values
shintamainjp 0:d825f8dae2be 79 // so shift the 8 bit values read from the nunchuck
shintamainjp 0:d825f8dae2be 80 // 2 bits to the right
shintamainjp 0:d825f8dae2be 81 accelX = (int)readBuf[ACCEL_X] << 2;
shintamainjp 0:d825f8dae2be 82 accelY = (int)readBuf[ACCEL_Y] << 2;
shintamainjp 0:d825f8dae2be 83 accelZ = (int)readBuf[ACCEL_Z] << 2;
shintamainjp 0:d825f8dae2be 84
shintamainjp 0:d825f8dae2be 85 DecodeAdditional();
shintamainjp 0:d825f8dae2be 86 }
shintamainjp 0:d825f8dae2be 87
shintamainjp 0:d825f8dae2be 88 void WiiNunchuckReader::DecodeAdditional() {
shintamainjp 0:d825f8dae2be 89 // the nunchcuk buttons have their own idea of state
shintamainjp 0:d825f8dae2be 90 int buttonState = readBuf[ADDITIONAL] & MASK_CZ;
shintamainjp 0:d825f8dae2be 91 switch (buttonState) {
shintamainjp 0:d825f8dae2be 92 case 3:
shintamainjp 0:d825f8dae2be 93 buttonZ = 0;
shintamainjp 0:d825f8dae2be 94 buttonC = 0;
shintamainjp 0:d825f8dae2be 95 break;
shintamainjp 0:d825f8dae2be 96 case 2:
shintamainjp 0:d825f8dae2be 97 buttonZ = 1;
shintamainjp 0:d825f8dae2be 98 buttonC = 1;
shintamainjp 0:d825f8dae2be 99 break;
shintamainjp 0:d825f8dae2be 100 case 1:
shintamainjp 0:d825f8dae2be 101 buttonZ = 0;
shintamainjp 0:d825f8dae2be 102 buttonC = 1;
shintamainjp 0:d825f8dae2be 103 break;
shintamainjp 0:d825f8dae2be 104 case 0:
shintamainjp 0:d825f8dae2be 105 buttonZ = 1;
shintamainjp 0:d825f8dae2be 106 buttonC = 0;
shintamainjp 0:d825f8dae2be 107 break;
shintamainjp 0:d825f8dae2be 108 }
shintamainjp 0:d825f8dae2be 109
shintamainjp 0:d825f8dae2be 110 // and the accelerometer axis - for each axis value add bit 1 and bit 0
shintamainjp 0:d825f8dae2be 111 // as required
shintamainjp 0:d825f8dae2be 112 if (readBuf[ADDITIONAL] & MASK_ACCLX1) accelX += 2;
shintamainjp 0:d825f8dae2be 113 if (readBuf[ADDITIONAL] & MASK_ACCLX2) accelX += 1;
shintamainjp 0:d825f8dae2be 114 if (readBuf[ADDITIONAL] & MASK_ACCLY1) accelY += 2;
shintamainjp 0:d825f8dae2be 115 if (readBuf[ADDITIONAL] & MASK_ACCLY2) accelY += 1;
shintamainjp 0:d825f8dae2be 116 if (readBuf[ADDITIONAL] & MASK_ACCLZ1) accelZ += 2;
shintamainjp 0:d825f8dae2be 117 if (readBuf[ADDITIONAL] & MASK_ACCLZ2) accelZ += 1;
shintamainjp 0:d825f8dae2be 118 }