Introduction: Turn a GameCube Controller Into a USB MIDI Instrument

This project will walk you through the steps to build an adapter that you can plug a stock GameCube controller into and use as a USB MIDI device. No permanent modifications need to be made to the controller at all, so you can keep yours as pristine as possible. This is a super straight forward project and could probably be completed in a single night if you had all the parts.

Some possible applications of this could be for chip-tune music creation/performance or controlling various things via MIDI. Why did I build this? Well, I came across someone on asking if a GameCube controller could be used as a MIDI controller and I thought that it sounded like a fun project.

The high level description of the project is that we'll take a GameCube controller extension cable and chop it up for the female port. Then we'll take the 3.3V dataline, pass it through a level shifter to bring it up to the 5V logic that the pro micro uses and get the two of them talking. After that, the pro micro takes the GameCube controller data and converts it into USB MIDI data packets and sends them to the computer.

Supplies

There is a relatively short component list needed for this project. There are two versions of the Pro Micro you can buy, a 3.3V version and a 5V version. If you buy the 3.3V variant, you can eliminate two parts but I only had the 5V version on hand so I haven't tested the build with the 3.3V variant.

The GameCube controller runs at 3.3V so if you connect 5V to it, you could kill it. This build is perfectly safe when built properly, but be careful and double check your connections before you plug in the controller.

Note: When you program the Pro Micro in the Arduino IDE, the board and voltage must be set properly otherwise you will brick it. If you program the 3.3V board with 5V settings, it will be bricked. The Arduino Leonardo settings used in this tutorial are for the 5V board only. Unfortunately, I do not have a 3.3V version and so this tutorial will assume that you are using a 5V version.

Tools

  1. Soldering Iron
  2. Wire strippers
  3. Bread board or Proto board
  4. Wire


5V Variant Parts List

  1. GameCube Controller Extension cable (We're only after the female port, so you could pull this off a dead GameCube or Wii if you have one laying around)
  2. Pro Micro micro-controller
  3. Logic Level Shifter
  4. 3.3V Voltage Regulator
  5. 1k-ish Ohm resistor

Note: The Level shifter, 3.3V regulator, and the 1k Ohm resistor are not particularly precise component selections. If you have something that says it does the same job, theres a very good chance it'll work just fine.

3.3V Variant Parts List

  1. GameCube Controller Extension cable (We're only after the female port side of it, so you could pull this off a dead GameCube or Wii if you have one laying around)
  2. Pro Micro micro-controller
  3. 1k-ish Ohm resistor

Step 1: Wiring the Controller to the Bread Board

The very first step is to cut your extension cable in half and strip the wires. I would recommend soldering them down to a proto board to make them easier to work with. Don't worry about adding the wires and the resistor yet, we'll do that in the next step

Step 2: Determine Your Cables Pinout

An unfortunate side effect of cutting up a random extension cable is that the wire colours may not match between brands. So the next step is to figure out how your cable is wired. The first image is a female GameCube controller port, looking into it. The colors in that diagram correspond to the wires in my cable but it might be different for you.

Another thing to notice is that my cable only has five wires, but there is 7 pins in the connector. My cable left two of the redundant wires out to save some money. Those are the pins with the blue X's over them.

Once you figure out which pins correspond to which wire, you can go ahead and wire it into your bread board with the following connections.

  1. White - 5V (Only used for the rumble motors so is optional)
  2. Red - Data
  3. Black - Ground
  4. Yellow - Ground
  5. Purple - Not connected
  6. Teal - 3.3V
  7. Purple - Cable Shielding/Not Connected

The last connection you need to make is to put the 1k-ish Ohm pull up resistor on the data line of the controller. So just put the resistor between the data line and the 3.3V rail.

Credit to https://simplecontrollers.bigcartel.com/gamecube-protocol for documenting the port pinout

Step 3: Connecting the Controller to the Pro Micro

The next step is to connect the Pro Micro to the GameCube controller and get the two of them talking! You'll have to consult the wiring diagrams for the specific level shifter and voltage regulator boards that you have, but this is what it looks like for my set of boards.

The basic jist of it is that you want to connect the digital pin 2 of the Pro Micro and the 5V rail to the high voltage side of the level shifter. Then, you want to connect the GameCube data line and the 3.3V rail to the low voltage side of the level shifter.

After that is completed, you're done with the hardware for this build!

Step 4: Setting Up the Arduino IDE

The first thing we need to do for the software is to download and configure the Arduino IDE. There are a ton of great resources available for getting started with the Arduino IDE so I wont cover things in to great of detail here.

Download the latest version from the arduino website and run through the regular setup.

Once the IDE is open, connect your Pro Micro to the computer via a USB cable. You should see it pop up on one of the com ports under Tools -> Port: -> COMXX (Arduino Leonardo).

Click on the port to select it.

Next, go back to Tools -> Board and select the Arduino Leonardo.

Now the IDE should be ready to program your board. If you would like to test it to make sure everything is working properly, open File -> Examples -> 01. Basics -> Blink. Then click on the upload button (The sideways arrow beside the check mark near the top). If everything is working as intended, the board should program and start blinking its LED

Step 5: Adding Libraries Needed to Arduino IDE

There are two external libraries needed for this project. They are

  • Nintendo
  • MIDIUSB

Luckily, the Arduino IDE makes it very easy to add new libraries. Open Tools -> Manager Libraries and type in Nintendo and hit enter. Then just click on the little install button near the bottom.

You can repeat the same steps for MIDI USB as well.

Step 6: Downloading the Code

I've created a GitHub to host the code as there are two files and Instructables doesn't allow uploading of .zip files. You can find the repo HERE.

The easiest way to download everything is to click on the green "Code" button and select "Download as ZIP".

Once thats downloaded, go ahead and extract the files to somewhere convenient.

Then open up the GameCube-MIDI-Controller.ino file with the Arduino IDE

Step 7: Uploading the Code

The next step is to compile and upload the final code to the board!

Once the project is open in the Arduino IDE, double check the board and port settings are configured properly

If they are, then you can hit the upload button and program the Pro Micro.

Windows will probably make the USB device connected and disconnected sound a couple of times during the programming but that's normal.

Step 8: Configuring It As a MIDI Device

One the Pro Micro is programmed, it should immedately begin acting as a MIDI device. If you open a piece of software that uses MIDI, it should show up as "Arduino Leonardo"

If you would like to change this name, you can check out this video by Nerd Musician

By default, each of the buttons on the controller is mapped to a certain key on the piano while each of the analog values (left analog stick X and Y, C stick X and Y, Left and Right triggers) is mapped to a MIDI control surface. The default configuration is as follows

  • A -> C3
  • B -> D3
  • X -> E3
  • Y -> F3
  • Start -> G3
  • D-pad Up -> A3
  • D-pad Down -> B3
  • D-pad Left -> C4
  • D-pad Right -> D4
  • Z -> E4
  • L -> F4
  • R -> G4

While the analog controls are mapped

  • Analog stick X Axis -> Control 0
  • Analog stick Y Axis -> Control 1
  • C stick X Axis -> Control 2
  • C stick Y Axis -> Control 3
  • Right Trigger Axis -> Control 4
  • Left Trigger Axis -> Control 5


These are very straight forward to change in the code if you would like to. There is a section right at the very top of the code that defines these values under the comment "USER CONFIGURABLE VALUES".

The line

//                                     A   B   X   Y   S   Dup Ddo Dl  Dr  Z   L   R
const byte notePitches[NUM_BUTTONS] = {C3, D3, E3, F3, G3, A3, B3, C4, D4, E4, F4, G4}; //Pitches sent by each button

is the one that defines the note pitches sent for each button. So for example, if you would like the A button to play D2 instead of C3, all you have to do is change the C3 underneath the A to D2. Like this

//                                     A   B   X   Y   S   Dup Ddo Dl  Dr  Z   L   R
const byte notePitches[NUM_BUTTONS] = {D2, D3, E3, F3, G3, A3, B3, C4, D4, E4, F4, G4}; //Pitches sent by each button


By default, the code uses the right analog trigger to define the note intensity. If you would like to have all notes sent at a medium intensity and ignore the analog trigger, simply change the following line to false

const bool SHOULDER_AS_INTESITY = true; //Change to false if you dont want the note intensity to be controlled by the right shoulder trigger


The final configuration option is the control slider number in this section.

const uint8_t control0 = 0; //xAxis mapped to control surface0 (change the 0 after the = to change the surface number)
const uint8_t control1 = 1; //yAxis mapped to control surface1 (change the 1 after the = to change the surface number)
const uint8_t control2 = 2; //cxAxis mapped to control surface2 
const uint8_t control3 = 3; //cyAxis mapped to control surface3 
const uint8_t control4 = 4; //right slider mapped to control surface4 
const uint8_t control5 = 5; //left slider mapped to control surface5 

So right now, the xAxis of the joy stick is mapped to MIDI control surface 0. To change it to another number, say 13, simply edit the line so it becomes

const uint8_t control0 = 13; //xAxis mapped to control surface13