This is a modified version of the Wii Classic Controller? library by Tim Hirzel to be compatible with Arduino 1.0. I (Robbert Brandsma/brandrob) also added a define (REPORT_ON_HOLD) that will modify the behaviour of a button that is pressed for two or more updates. When defined (the behaviour of the original library), a button press will only be reported once. When not defined, a button press will be reported for as long as the button is held.

The sample code by Tim Hirzel is unmodified; only the library itself was modified.

  • Test Code by Tim Hirzel

/*
WiiClassic Test Code

This code prints the current controller status to the serial port.
Button pressed calls poll whether the button was pressed since the last update call.
as a result, it will just briefly print the last button pressed once.

Tim Hirzel May 2008

*/


#include "Wire.h"

#include "WiiClassic.h"

WiiClassic wiiClassy = WiiClassic();

void setup() {
Wire.begin();
Serial.begin(9600);
wiiClassy.begin();
wiiClassy.update();
}

void loop() {
delay(100); // 1ms is enough to not overload the wii Classic, 100ms seems to ease the serial terminal a little
wiiClassy.update();

//
/*
// PRINT RAW BYTES FOR DEBUG
// STATUS IS FIRST FOUR BYTES
for (int i = 0; i < 4; i ++) {
for (int j = 7; j >= 0; j--) {
if ((wiiClassy.getRawStatus()[i] & (1 << j)) == 0) {
Serial.print("0");
}
else{
Serial.print("1");
}
}
Serial.println();
}
// BUTTONS IS NEXT TWO BYTES
for (int i = 0; i < 2; i ++) {
for (int j = 7; j >= 0; j--) {
if ((wiiClassy.getRawButtons()[i] & (1 << j)) == 0) {
Serial.print("0");
}
else{
Serial.print("1");
}
}
Serial.println();
}
Serial.println("---");
*/

Serial.print("Buttons:");


if (wiiClassy.leftShoulderPressed()) {
Serial.print("LS.");
}
if (wiiClassy.rightShoulderPressed()) {
Serial.print("RS.");
}
if (wiiClassy.lzPressed()) {
Serial.print("lz.");
}
if (wiiClassy.rzPressed()) {
Serial.print("rz.");
}
if (wiiClassy.leftDPressed()) {
Serial.print("LD.");
}

if (wiiClassy.rightDPressed()) {
Serial.print("RD.");
}

if (wiiClassy.upDPressed()) {
Serial.print("UD.");
}
if (wiiClassy.downDPressed()) {
Serial.print("DD.");
}

if (wiiClassy.selectPressed()) {
Serial.print("select.");
}

if (wiiClassy.homePressed()) {
Serial.print("home.");
}
if (wiiClassy.startPressed()) {
Serial.print("start.");
}

if (wiiClassy.xPressed()) {
Serial.print("x.");
}

if (wiiClassy.yPressed()) {
Serial.print("y.");
}

if (wiiClassy.aPressed()) {
Serial.print("a.");
}

if (wiiClassy.bPressed()) {
Serial.print("b.");
}

Serial.println();
Serial.print("right shoulder: ");
Serial.println(wiiClassy.rightShouldPressure());
Serial.print(" left shoulder: ");

Serial.println(wiiClassy.leftShouldPressure());
Serial.print(" left stick x: ");

Serial.println(wiiClassy.leftStickX());
Serial.print(" left stick y: ");

Serial.println(wiiClassy.leftStickY());
Serial.print(" right stick x: ");

Serial.println(wiiClassy.rightStickX());
Serial.print(" right stick y: ");

Serial.println(wiiClassy.rightStickY());
Serial.println("---");

//pulse = (int)500+8*wiiClassy.leftStickX();
//updateServo();
}

  • WiiClassic.h library code by Tim Hirzel, modified by Robbert Brandsma

/*
  * Wii Classic -- Use a Wii Classic Controller
  * by Tim Hirzel http://www.growdown.com
  *
  * Modified by Robbert Brandsma (21-3-2012) for Arduino 1.0 compatibility
  * and to add the REPORT_ON_HOLD define.
  *
  * This code owes thanks to the code by these authors:
  * Tod E. Kurt, http://todbot.com/blog/
  *
  * The Wii Nunchuck reading code is taken from Windmeadow Labs
  * http://www.windmeadow.com/node/42
  *
  * and the reference document on the wii linux site:
  * http://www.wiili.org/index.php/Wiimote/Extension_Controllers/Classic_Controller
  */


#ifndef WiiClassic_h
#define WiiClassic_h

#include <Arduino.h>

//#define REPORT_ON_HOLD

class WiiClassic {    
     private:
         byte cnt;
         uint8_t status[4];              // array to store wiichuck output
         byte averageCounter;
         //int accelArray[3][AVERAGE_N];  // X,Y,Z

        uint8_t buttons[2];
         uint8_t lastButtons[2];


    public:

        void begin()
        {
             Wire.begin();
             cnt = 0;
             averageCounter = 0;
             Wire.beginTransmission ((byte)0x52);      // transmit to device (byte)0x52
             Wire.write ((byte)0x40);           // writes memory address
             Wire.write ((byte)0x00);           // writes memory address
             Wire.endTransmission ();    // stop transmitting
             lastButtons[0] = (byte)0xff;
             lastButtons[1] = (byte)0xff;
             buttons[0] = (byte)0xff;
             buttons[1] = (byte)0xff;

            update();        

        }


        void update() {

            Wire.requestFrom (0x52, 6); // request data from nunchuck
             while (Wire.available ()) {
                 // read byte as an integer
                 if (cnt < 4) {
                     status[cnt] = _nunchuk_decode_byte (Wire.read()); //_nunchuk_decode_byte ()
                } else {
                     lastButtons[cnt-4] = buttons[cnt-4];
                     buttons[cnt-4] =_nunchuk_decode_byte (Wire.read());
                 }
                 cnt++;
             }
             if (cnt > 5) {
                 _write_zero(); // write the request for next bytes
                 cnt = 0;                  
            }
         }

        byte * getRawStatus() {
             return status;
         }

        byte * getRawButtons() {
             return buttons;
         }

        boolean leftShoulderPressed() {
             return _PressedRowBit(0,5);
         }

        boolean rightShoulderPressed() {
             return _PressedRowBit(0,1);
         }

        boolean lzPressed() {
             return _PressedRowBit(1,7);
         }

        boolean rzPressed() {
             return _PressedRowBit(1,2);
         }

        boolean leftDPressed() {
             return _PressedRowBit(1,1);
         }

        boolean rightDPressed() {
             return _PressedRowBit(0,7);
         }

        boolean upDPressed() {
             return _PressedRowBit(1,0);
         }

        boolean downDPressed() {
             return _PressedRowBit(0,6);
         }

        boolean selectPressed() {
             return _PressedRowBit(0,4);
         }

        boolean homePressed() {
             return _PressedRowBit(0,3);
         }

        boolean startPressed() {
             return _PressedRowBit(0,2);
         }

        boolean xPressed() {
             return _PressedRowBit(1,3);
         }

        boolean yPressed() {
             return _PressedRowBit(1,5);
         }

        boolean aPressed() {
             return _PressedRowBit(1,4);
         }

        boolean bPressed() {
             return _PressedRowBit(1,6);
         }

        int rightShouldPressure() {
             return status[3] & (byte)0x1f; //rightmost 5 bits
         }

        int leftShouldPressure() {
             return ((status[2] & (byte)0x60) >> 2) + ((status[3] & (byte)0xe0) >> 5); //rightmost 5 bits
         }

        int leftStickX() {
             return  ( (status[0] & (byte)0x3f) );
         }

        int leftStickY() {
             return  ((status[1] & (byte)0x3f));      
        }

        int rightStickX() {
             return ((status[0] & (byte)0xc0) >> 3) + ((status[1] & (byte)0xc0) >> 5) +  ((status[2] & (byte)0x80) >> 7);

        }

        int rightStickY() {
             return status[2] & (byte)0x1f;    
        }


    private:
         boolean _PressedRowBit(byte row, byte bit) {
             byte mask = (1 << bit);
             #ifdef REPORT_ON_HOLD
             return (!(buttons[row] & mask )) && (lastButtons[row] & mask);
             #else
             return (!(buttons[row] & mask ));
             #endif
         }


        byte _nunchuk_decode_byte (byte x)
         {
             x = (x ^ (byte)0x17) + (byte)0x17;
             return x;
         }

        void _write_zero()
         {
             Wire.beginTransmission ((byte)0x52);      // transmit to device (byte)0x52
             Wire.write ((byte)0x00);           // writes one byte
             Wire.endTransmission ();    // stop transmitting
         }

};



#endif
 

Share