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
Revision 0:3c7f660dbc34, committed 2013-06-29
- 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
--- /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