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

Dependencies:   mbed

Revision:
0:d51f5e2478c1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiiNunchuckReader.cpp	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,129 @@
+/*
+* 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) : 
+    nunchuckPort(sda, scl),
+    joyX(0), joyY(0), accelX(0), accelY(0), accelZ(0),
+    buttonC(0), buttonZ(0), nunchuckInit(false)
+{
+}
+
+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