
API for interfacing with a game cube controller
Homepage
Gamecube Controller Interface¶
This is a library to interface the Gamecube Controller to the mbed. The goal of this project is to read input data from the controller.
Introduction¶
This library lets you read data from a Gamecube Controller. It allows you to use two pins to get 6+ buttons, a D-pad (up/down/left/right), two variable triggers, and two joysticks. The controller was stripped of its connector and this wiki shows the subsequent steps to wire the controller to the mbed and code needed to read data through a serial connection. Assembly was used because the timing for the controller needs to have microsecond accuracy. The shortest wait found using wait_us(...) was 1.5us.
Pinout¶
Color | Function |
---|---|
Yellow | 5V power supply (rumble) |
Red | Data: bi-directional / 3.3V |
Green | Ground |
White | Ground |
Blue | 3.3V power supply |
*Note this pinout is for the latest Gamecube controller
Wiring¶
The Gamecube controller was cut to expose the wires. Seperate them and solder other wires on to them for stability and consistency.
Color (Gamecube) | mbed Pin |
---|---|
Yellow | VOUT |
Red | p9 and p10 |
Green | Ground |
White | Ground |
Blue | VU |
Gamecube Controller Protocol¶
The Gamecube controller uses 3.3V logic (bidirectional), 3.3V to power the controller, and 5V for the rumble motor.
The 5V power used by the rumble motor is always on, and the motor is controlled by a command sent to the controller.
The controller uses one bi-directional data line to communicate with the console. This is an active high 3.3V logic signal, using a 10K pull-up resistor to 3.3V to hold the line high. Communication is initiated by the console sending a 24-bit string to the controller, after which the controller responds with 64-bits of button state and joystick data.
The transfer speed is fast at around 4 microseconds per bit. .A low bit is signaled by a 3us low followed by 1us high, and a high bit is signaled by 1us low followed by 3us high.
Here is a 0 followed by a 1
The last bit of the command is the 'rumble' control. Setting this bit to one enables the rumble motor, and clearing it disables the motor.
Polling for Data¶
When the Gamecube or the controller sends a string of bits, it terminates it with a single (high) stop bit. Therefore, in order to send the string 00000000, the Gamecube would send 000000001.
There is a typical interval of about 6ms between successive updates. The real time update time would depend on the game being played or the video frame update rate. The sequence starts with a 24-bit command from the console:
0100 0000 0000 0011 0000 000 (0*) *rumble
After the 24-bit command, the controller responds with a string of bits that contain the state of all the buttons along with joystick position data. The sequence of the returned data is shown in the table below. The buttons are listed in transmission order, from left to right.
Byte 0 | 0 | 0 | 0 | Start | Y | X | B | A |
Byte 1 | 1 | L | R | Z | D-Up | D-Down | D-Right | D-Left |
Byte 2 | Joystick X Value (8 bit) |
Byte 3 | Joystick Y Value (8 bit) |
Byte 4 | C-Stick X Value (8 bit) |
Byte 5 | C-Stick Y Value (8 bit) |
Byte 6 | Left Button Value (8 bit) |
Byte 7 | Right Button Value (8 bit) |
Example Code¶
Basic program to use with library
// #include "mbed.h" #include "Gamecube.h" Serial pc1(USBTX, USBRX); // tx, rx DigitalOut myled(LED1); int main() { Gamecube g(p9); // gamecube controller connected to pin 9 int device_id = g.get_device_id(); if (device_id != NINTENDO_DEVICE_GC_WIRED) { // device id for controller is 0x0900 pc1.printf("this device is not a nintendo gamecube wired controller!, it returned an ID of %d\n", device_id); } while(1) { g.update(); pc1.printf("A: %d \n\rB: %d \n\rX: %d \n\rY: %d \n\rL: %d \n\rR: %d \n\rZ: %d \n\rSTART: %d \n\rD_UP: %d \n\rD_LEFT: %d \n\rD_DOWN: %d \n\rD_RIGHT: %d \n\rJOYSTICK_X: %d \n\rJOYSTICK_Y: %d \n\rC_STICK_X: %d \n\rC_STICK_Y: %d \n\rLEFT_TRIGGER: %d \n\rRIGHT_TRIGGER: %d \n\r", g.A, g.B, g.X, g.Y, g.L, g.R, g.Z, g.START, g.D_UP, g.D_LEFT, g.D_DOWN, g.D_RIGHT, g.JOYSTICK_X, g.JOYSTICK_Y, g.C_STICK_X, g.C_STICK_Y, g.LEFT_TRIGGER, g.RIGHT_TRIGGER); wait(1); g.rumble(true); // rumble working myled = 1; wait(1); myled = 0; g.rumble(false); wait(.2); } }
Functions¶
Functions
// constructor Gamecube(PinName _data_line); // gets the device id int get_device_id(); // call this to update public variables in header file void update(void);
Library¶
Import programgamecube_controller
API for interfacing with a game cube controller