A program allowing the output of one or two Wii Nunchucks to be read via I2C and decoded for use.

Dependencies:   mbed

Committer:
snatch59
Date:
Sun Dec 13 12:19:31 2009 +0000
Revision:
0:d51f5e2478c1

        

Who changed what in which revision?

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