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

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
snatch59
Date:
Sun Dec 13 12:19:31 2009 +0000
Commit message:

Changed in this revision

I2CConfig.h Show annotated file Show diff for this revision Revisions of this file
WiiNunchuckDefs.h Show annotated file Show diff for this revision Revisions of this file
WiiNunchuckReader.cpp Show annotated file Show diff for this revision Revisions of this file
WiiNunchuckReader.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r d51f5e2478c1 I2CConfig.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2CConfig.h	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,50 @@
+/*
+* 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/>.
+*/
+
+#ifndef SNATCH59_I2CCONFIG_H
+#define SNATCH59_I2CCONFIG_H
+
+#include <mbed.h>
+
+class I2CPort_A
+{
+public:
+    static const PinName SDA;
+    static const PinName SCL;
+};
+
+    
+class I2CPort_B
+{
+public:
+    static const PinName SDA;
+    static const PinName SCL;
+};
+
+const PinName I2CPort_A::SDA = p9;
+const PinName I2CPort_A::SCL = p10;
+
+const PinName I2CPort_B::SDA = p28;
+const PinName I2CPort_B::SCL = p27;
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r d51f5e2478c1 WiiNunchuckDefs.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiiNunchuckDefs.h	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,55 @@
+/*
+* 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/>.
+*/
+
+#ifndef SNATCH59_WIINUNCHUCKDEFS_H
+#define SNATCH59_WIINUNCHUCKDEFS_H
+
+// I2C
+#define NUNCHUCK_ADDR     0xA4  // I2C library doesn't right shift the address, so provided shifted
+#define NUNCHUCK_REGADDR  0x40  // relevant register address
+#define NUNCHUCK_READLEN  0x06  // always read this many bytes back
+
+// received byte position
+#define JOY_X      0
+#define JOY_Y      1
+#define ACCEL_X    2
+#define ACCEL_Y    3
+#define ACCEL_Z    4
+#define ADDITIONAL 5
+
+// bitmasks for addition info byte
+#define MASK_CZ      0x03
+#define MASK_ACCLX1  0x04
+#define MASK_ACCLX2  0x08
+#define MASK_ACCLY1  0x10
+#define MASK_ACCLY2  0x20
+#define MASK_ACCLZ1  0x40
+#define MASK_ACCLZ2  0x80
+
+// timing
+#define I2C_READ_DELAY  0.01
+
+// I2C status
+#define I2C_OK        0    // zero on success (ACK), non-zero on fail (NACK) for read or write
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r d51f5e2478c1 WiiNunchuckReader.cpp
--- /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
diff -r 000000000000 -r d51f5e2478c1 WiiNunchuckReader.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiiNunchuckReader.h	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,78 @@
+/*
+* 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/>.
+*/
+
+#ifndef SNATCH59_WIINUNCHUCKREADER_H
+#define SNATCH59_WIINUNCHUCKREADER_H
+
+#include <mbed.h>
+#include "WiiNunchuckDefs.h"
+
+typedef unsigned char BYTE;
+
+class WiiNunchuckReader
+{
+public:
+    // constructors
+    WiiNunchuckReader(PinName sda, PinName scl);
+    
+    // functions
+    void RequestRead();
+    
+    // accessors
+    int getJoyX() const { return joyX; }
+    int getJoyY() const { return joyY; }
+    int getAccelX() const { return accelX; }
+    int getAccelY() const { return accelY; }
+    int getAccelZ() const { return accelZ; }
+    int getButtonC() const { return buttonC; }
+    int getButtonZ() const { return buttonZ; }
+    int getBufferSize() const { return sizeof(readBuf); }
+    char* getReadBuf() { return readBuf; }
+    
+private:
+    // nunchuck controls states
+    int joyX;
+    int joyY;
+    int accelX;
+    int accelY;
+    int accelZ;
+    int buttonC;
+    int buttonZ;
+    
+    // nunchuck init state
+    bool nunchuckInit;
+    
+    // nunchuck I2C port
+    I2C nunchuckPort;
+    
+    // read data
+    char readBuf[NUNCHUCK_READLEN];
+    
+    // functions    
+    bool NunchuckInit();
+    bool NunchuckRead();
+    void NunchuckDecode();
+    void DecodeAdditional();
+};
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r d51f5e2478c1 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,79 @@
+/*
+* 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 "I2CConfig.h"
+#include "WiiNunchuckReader.h"
+
+#define LOOP_DELAY    1    // seconds
+
+// global declarations
+Serial serial(USBTX, USBRX);
+
+void ReadAndReport(WiiNunchuckReader* const nchk, const char* const portname)
+{
+    int bufSize = 0;
+    char* bufPtr = NULL;
+    bool debug = true;
+
+    nchk->RequestRead();
+    serial.printf("%s: ", portname);
+        
+    if (debug)
+    {
+        bufSize = nchk->getBufferSize();
+        bufPtr = nchk->getReadBuf();
+        if (bufPtr != NULL)
+        {
+            for (int i = 0; i < bufSize; i++)
+            {
+                serial.printf("%x ", bufPtr[i]);
+            }
+            serial.printf("\r\n");
+        }
+    }
+        
+    serial.printf("%d\t", nchk->getButtonZ());
+    serial.printf("%d\t", nchk->getButtonC());
+    serial.printf("%d\t", nchk->getAccelX());
+    serial.printf("%d\t", nchk->getAccelY());
+    serial.printf("%d\t", nchk->getAccelZ());
+    serial.printf("%d\t", nchk->getJoyX());
+    serial.printf("%d\r\n", nchk->getJoyY());
+    serial.printf("\r\n");
+}
+
+int main() 
+{
+    WiiNunchuckReader nchkA(I2CPort_A::SDA, I2CPort_A::SCL);
+    WiiNunchuckReader nchkB(I2CPort_B::SDA, I2CPort_B::SCL);
+    
+    while (true)
+    {
+        ReadAndReport(&nchkA, "PORT A");
+        ReadAndReport(&nchkB, "PORT B");
+                
+        wait(LOOP_DELAY);
+    }
+    
+    return EXIT_SUCCESS;
+}
diff -r 000000000000 -r d51f5e2478c1 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Dec 13 12:19:31 2009 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/32af5db564d4