Based on Alfredo Guerrero's WiiClassicControllerReader although I had to do additional decoding of packet. KL25Z talking to Wii classic controller.

Dependencies:   CommonTypes WiiClassicControllerLib mbed

Files at this revision

API Documentation at this revision

Comitter:
RichardE
Date:
Sat Jun 29 21:40:31 2013 +0000
Child:
1:5334e20cd2fd
Commit message:
Working I2C communications with genuine Wii classic controller. KL25Z using PTE0 as SDA and PTE1 as SCL.

Changed in this revision

CommonTypes.lib Show annotated file Show diff for this revision Revisions of this file
WiiClassicController.cpp Show annotated file Show diff for this revision Revisions of this file
WiiClassicController.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CommonTypes.lib	Sat Jun 29 21:40:31 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/RichardE/code/CommonTypes/#033e112463bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiiClassicController.cpp	Sat Jun 29 21:40:31 2013 +0000
@@ -0,0 +1,76 @@
+/*
+ * SOURCE FILE : WiiClassicController.cpp
+ *
+ * Definition of class WiiClassicController.
+ * Allows use of a Wii classic controller using an I2C bus.
+ *
+ */
+
+#include "WiiClassicController.h"
+
+// REMOVE THIS!
+extern Serial pc;
+
+/** Constructor.
+ * @param sda pin to use for SDA.
+ * @param scl pin to use for SCL.
+ */
+WiiClassicController::WiiClassicController( PinName sda, PinName scl ) :
+    controllerPort( sda, scl ),
+    initialised( false )
+{
+}
+
+/** Destructor.
+ */
+WiiClassicController::~WiiClassicController() {
+}
+
+/** Read from the controller.
+ * @returns true on success, false on failure.
+ */
+bool WiiClassicController::Read( void ) {
+    // Don't expect client to remember to send an init to the nunchuck
+    // so do it for them here.
+    if( ! initialised ) {
+        initialised = ControllerInit();
+    }
+    // Don't start reading if init failed
+    return initialised && ControllerRead();
+}
+
+/** Initialise the controller.
+ * @returns true on success, false on failure.
+ */
+bool WiiClassicController::ControllerInit( void ) {
+    const UInt8 cmd[] = { CONTROLLER_REGADDR, 0x00 };
+    bool ok = ( controllerPort.write( CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd) ) == 0 );
+    pc.printf( "ControllerInit returned %d\r\n", (int)ok );
+    return ok;
+}
+
+/** Read from the controller, assuming it has been initialised.
+ * @returns true on success, false on failure.
+ */
+bool WiiClassicController::ControllerRead() {
+    // write the address we want to read from
+    const UInt8 cmd[] = { 0x00 };
+    if( controllerPort.write( CONTROLLER_ADDR, (const char*)cmd, sizeof(cmd) ) == 0 ) {
+        // The Wii Classic Controller is non-standard I2C
+        // and can't manage setting the read address and immediately supplying the data
+        // so wait a bit.
+        wait( 0.01 );
+        if( controllerPort.read( CONTROLLER_ADDR, (char*)readBuf, sizeof(readBuf) ) == 0 ) {
+            for( int i = 0; i < CONTROLLER_READLEN; ++i ) {
+                readBuf[ i ] = Decode( readBuf[ i ] );
+            }
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+    else {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WiiClassicController.h	Sat Jun 29 21:40:31 2013 +0000
@@ -0,0 +1,242 @@
+/*
+ * SOURCE FILE : WiiClassicController.h
+ *
+ * Definition of class WiiClassicController.
+ * Allows use of a Wii classic controller using an I2C bus.
+ *
+ */
+
+#ifndef WiiClassicControllerDefined
+
+  #define WiiClassicControllerDefined
+
+  #include <mbed.h>
+  #include "Types.h"
+  
+  #define CONTROLLER_ADDR     0xA4  // I2C library doesn't right shift the address, so provided shifted
+  #define CONTROLLER_REGADDR  0x40  // relevant register address
+  #define CONTROLLER_READLEN  0x06  // always read this many bytes back
+
+  class WiiClassicController {
+
+  public :
+
+    /** Constructor.
+     * @param sda pin to use for SDA.
+     * @param scl pin to use for SCL.
+     */
+    WiiClassicController( PinName sda, PinName scl );
+
+    /** Destructor.
+     */
+    virtual ~WiiClassicController();
+
+    /** Read from the controller.
+     * @returns true on success, false on failure.
+     */
+     bool Read( void );
+    
+    /** Read left joystick X axis.
+     * @returns joystick reading as number between 0 and 63.
+     */
+    UInt8 GetLJoyX( void ) const {
+        return (UInt8)( readBuf[ 0 ] & 0x3F );
+    }
+    
+    /** Read left joystick Y axis.
+     * @returns joystick reading as number between 0 and 63.
+     */
+    UInt8 GetLJoyY( void ) const {
+        return (UInt8)( readBuf[ 1 ] & 0x3F );
+    }
+    
+    /** Read right joystick X axis.
+     * @returns joystick reading as number between 0 and 31.
+     */
+    UInt8 GetRJoyX( void ) const {
+        return (UInt8)(
+            ( ( readBuf[ 2 ] & 0x80 ) >> 7 ) |
+            ( ( readBuf[ 1 ] & 0xC0 ) >> 5 ) |
+            ( ( readBuf[ 0 ] & 0xC0 ) >> 3 )
+        );
+    }
+    
+    /** Read right joystick Y axis.
+     * @returns joystick reading as number between 0 and 31.
+     */
+    UInt8 GetRJoyY( void ) const {
+        return (UInt8)( readBuf[ 2 ] & 0x1F );
+    }
+
+    /** Read X button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonX( void ) const {
+        return ( readBuf[ 5 ] & 0x08 ) ? false : true;
+    }
+    
+    /** Read Y button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonY( void ) const {
+        return ( readBuf[ 5 ] & 0x20 ) ? false : true;
+    }
+    
+    /** Read A button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonA( void ) const {
+        return ( readBuf[ 5 ] & 0x10 ) ? false : true;
+    }
+    
+    /** Read B button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonB( void ) const {
+        return ( readBuf[ 5 ] & 0x40 ) ? false : true;
+    }
+    
+    /** Read left trigger button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonLT( void ) const {
+        return ( readBuf[ 4 ] & 0x20 ) ? false : true;
+    }
+    
+    /** Read right trigger button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonRT( void ) const {
+        return ( readBuf[ 4 ] & 0x02 ) ? false : true;
+    }
+    
+    /** Read left trigger reading.
+     * @returns reading as a number between 0 and 31.
+     */    
+    UInt8 GetLeftTrigger( void ) const {
+        return (UInt8)(
+            ( ( readBuf[ 3 ] & 0xE0 ) >> 5 ) |
+            ( ( readBuf[ 2 ] & 0x60 ) >> 2 )
+        );
+    }
+    
+    /** Read right trigger reading.
+     * @returns reading as a number between 0 and 31.
+     */    
+    UInt8 GetRightTrigger( void ) const {
+        return (UInt8)( readBuf[ 3 ] & 0x1F );
+    }
+    
+    /** Read ZL button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonZL( void ) const {
+        return ( readBuf[ 5 ] & 0x80 ) ? false : true;
+    }
+    
+    /** Read ZR button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonZR( void ) const {
+        return ( readBuf[ 5 ] & 0x04 ) ? false : true;
+    }
+    
+    /** Read select (or minus) button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonSelect( void ) const {
+        return ( readBuf[ 4 ] & 0x10 ) ? false : true;
+    }
+
+    /** Read home button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonHome( void ) const {
+        return ( readBuf[ 4 ] & 0x08 ) ? false : true;
+    }
+    
+    /** Read start (or plus) button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonStart( void ) const {
+        return ( readBuf[ 4 ] & 0x04 ) ? false : true;
+    }
+    
+    /** Read up button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonUp( void ) const {
+        return ( readBuf[ 5 ] & 0x01 ) ? false : true;
+    }
+    
+    /** Read down button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonDown( void ) const {
+        return ( readBuf[ 4 ] & 0x40 ) ? false : true;
+    }
+    
+    /** Read left button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonLeft( void ) const {
+        return ( readBuf[ 5 ] & 0x02 ) ? false : true;
+    }
+    
+    /** Read right button.
+     * @returns true if button is pressed.
+     */    
+    bool GetButtonRight( void ) const {
+        return ( readBuf[ 4 ] & 0x80 ) ? false : true;
+    }
+    
+    /** Get size of read buffer.
+     * @returns size of read buffer.
+     */
+    UInt8 GetReadBufSize( void ) const {
+        return sizeof(readBuf);
+    }
+    
+    /** Get address of read buffer.
+     * @returns pointer to read buffer.
+     */
+    UInt8* GetReadBuf( void ) {
+        return readBuf;
+    }
+
+  private :
+
+    // I2C port used for comms with controller.  
+    I2C controllerPort;
+    
+    // Set to true once controller has been initialised.
+    bool initialised;
+    
+    // Buffer for incoming data.
+    UInt8 readBuf[ CONTROLLER_READLEN ];
+
+    /** Initialise the controller.
+     * @returns true on success, false on failure.
+     */
+    bool ControllerInit( void );
+    
+    /** Read from the controller, assuming it has been initialised.
+     * @returns true on success, false on failure.
+     */
+    bool ControllerRead( void );
+
+    /** Decoder a byte in received packet.
+     * @param x byte to decode
+     * @returns decoded byte
+     */
+    UInt8 Decode( UInt8 x ) {
+        return (x ^ 0x17) + 0x17;
+    }
+    
+  };
+
+#endif
+
+/* END of WiiClassicController.h */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Jun 29 21:40:31 2013 +0000
@@ -0,0 +1,77 @@
+/*
+ * SOURCE FILE : main.cpp
+ *
+ * Test program to test out WiiClassicController class.
+ *
+ */
+ 
+#include "mbed.h"
+#include "WiiClassicController.h"
+
+// Define this to dump packet in hex.
+#define DUMP_PACKET
+
+#define LOOP_DELAY    1    // seconds
+
+// global declarations
+Serial pc(USBTX, USBRX);
+
+/* Read from the Wii classic controller and display results on serial port output.
+ * @param ctrlr Controller to read from.
+ * @param portname Name of port you are reading from.
+ */
+static void ReadAndReport( WiiClassicController* const ctrlr, const char* const portname ) {
+    if( ctrlr->Read() ) {
+
+        pc.printf("%s: ", portname);
+    
+        #ifdef DUMP_PACKET
+            int bufSize = ctrlr->GetReadBufSize();
+            UInt8 *bufPtr = ctrlr->GetReadBuf();
+            for (int i = 0; i < bufSize; i++) {
+                pc.printf("%x ", bufPtr[i]);
+            }
+            pc.printf("\r\n");
+        #endif
+        
+        pc.printf("\r\nA\tB\tX\tY\tZL\tZR\tDU\tDD\tDL\tDR\tH\r\n");
+        pc.printf("%u\t", ctrlr->GetButtonA());
+        pc.printf("%u\t", ctrlr->GetButtonB());
+        pc.printf("%u\t", ctrlr->GetButtonX());
+        pc.printf("%u\t", ctrlr->GetButtonY());
+        pc.printf("%u\t", ctrlr->GetButtonZL());
+        pc.printf("%u\t", ctrlr->GetButtonZR());
+        pc.printf("%u\t", ctrlr->GetButtonUp());
+        pc.printf("%u\t", ctrlr->GetButtonDown());
+        pc.printf("%u\t", ctrlr->GetButtonLeft());
+        pc.printf("%u\t", ctrlr->GetButtonRight());
+        pc.printf("%u\t", ctrlr->GetButtonHome());
+        pc.printf("\r\nSEL\tSTART\tLT\tLC\tRT\tRC\tLX\tLY\tRX\tRY\r\n");
+        pc.printf("%u\t", ctrlr->GetButtonSelect());
+        pc.printf("%u\t", ctrlr->GetButtonStart());
+        pc.printf("%u\t", ctrlr->GetLeftTrigger());
+        pc.printf("%u\t", ctrlr->GetButtonLT());
+        pc.printf("%u\t", ctrlr->GetRightTrigger());
+        pc.printf("%u\t", ctrlr->GetButtonRT());
+        pc.printf("%u\t", ctrlr->GetLJoyX());
+        pc.printf("%u\t", ctrlr->GetLJoyY());
+        pc.printf("%u\t", ctrlr->GetRJoyX());
+        pc.printf("%u\t", ctrlr->GetRJoyY());
+        pc.printf("\r\n\n\n");
+    }
+    else {
+        pc.puts( "READ FAILURE\r\n" );
+    }
+}
+
+/** Main program.
+ */
+int main() {
+    WiiClassicController ctrlrA( PTE0, PTE1 );
+    while (true) {
+        ReadAndReport( &ctrlrA, "PORT A" );
+        wait(LOOP_DELAY);
+    }
+    // Never gets here.
+    // return EXIT_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Jun 29 21:40:31 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b3110cd2dd17
\ No newline at end of file