Introduction: Turn an N64 Controller Into a USB Gamepad Using an Arduino Leonardo
The easiest way to turn an N64 Controller into a USB Gamepad is to buy an N64 Controller Adapter for around £15. However it can also be done if you have an Arduino Leonardo or any other Arduino board with built-in USB communication.
What you will need:
- An Arduino Leonardo (Also possible with other boards but the config will need to be changed)
- An N64 Controller
- 3 Leads
- USB Micro Cable
Background:
This project is an evolution of the excellent instructable by quasse. That project used a standard Arduino Uno to communicate with an N64 Controller and send the state via Serial port to the computer. A processing sketch was then required to be running on the computer to convert the Serial input into keystrokes or mouse movements that could be used to play N64 games on an emulator.
This project varies in a number of crucial steps:
- The Arduino Leonardo can act as a USB Gamepad directly without requiring any drivers or processing sketches to interpret the USB connection.
- Being a gamepad and not a mouse/keyboard it means that the mouse isn't moving across the screen when playing games.
- Now that the gamepad interprets the analog stick rather than a keyboard the controls are analog and not digital - before it didn't matter if the analog stick was left a little bit or a lot the game response was the same, now it is different.
Step 1: Setting Up the Arduino Environment
Unfortunately the Arduino doesn't support USB Gamepads, it only supports mouses and keyboards. So we have to edit the Arduino core files to support Gamepads. Rather than start messing with the files we can define a new board type that uses a different set of core files.
Start by navigating to C:\Program Files (x86)\Arduino\hardware\arduino\avr and open up the boards.txt file. Find the definitions for the Leonardo board and copy all of them. Then at the bottom of the file paste them. Then rename leonardo on every line to leonardon64. Then change the lines:
leonardon64.name=Arduino Leonard leonardon64.build.core=arduino
to:
leonardon64.name=Leonardo N64
leonardon64.build.core=leonardon64
The final product should be:
##############################################################
leonardon64.name=Leonardo N64 leonardon64.vid.0=0x2341 leonardon64.pid.0=0x0036 leonardon64.vid.1=0x2341 leonardon64.pid.1=0x8036 leonardon64.vid.2=0x2A03 leonardon64.pid.2=0x0036 leonardon64.vid.3=0x2A03 leonardon64.pid.3=0x8036 leonardon64.upload.tool=avrdude leonardon64.upload.protocol=avr109 leonardon64.upload.maximum_size=28672 leonardon64.upload.maximum_data_size=2560 leonardon64.upload.speed=57600 leonardon64.upload.disable_flushing=true leonardon64.upload.use_1200bps_touch=true leonardon64.upload.wait_for_upload_port=true leonardon64.bootloader.tool=avrdude leonardon64.bootloader.low_fuses=0xff leonardon64.bootloader.high_fuses=0xd8 leonardon64.bootloader.extended_fuses=0xcb leonardon64.bootloader.file=caterina/Caterina-Leonardo.hex leonardon64.bootloader.unlock_bits=0x3F leonardon64.bootloader.lock_bits=0x2F leonardon64.build.mcu=atmega32u4 leonardon64.build.f_cpu=16000000L leonardon64.build.vid=0x2341 leonardon64.build.pid=0x8036 leonardon64.build.usb_product="Arduino Leonardo" leonardon64.build.board=AVR_LEONARDO leonardon64.build.core=leonardon64 leonardon64.build.variant=leonardo leonardon64.build.extra_flags={build.usb_flags}
Finally enter the folder 'cores' and copy the folder 'arduino' and paste it there renaming it to 'leonardon64'. Then within this folder delete the files 'HID.cpp' and 'USBAPI.h' and replace them with the files of the same name below.
These files effectively define the way that the leonardo creates the gamepad. Further information on creating these two files can be found in a freetronics forum by drake250.
Step 2: Uploading the Program to the Leonardo
Plug the Leonardo into the computer and start up the Arduino IDE. The under the tools menu select the board we have just created 'Leonardo N64'. Then using the attached code upload the project to the Leonardo. The majority of the code here has been lifted from the instructable by quasse and details of how the state of the N64 controller is retrieved can be found there.
Attachments
Step 3: Connect the N64 Controller
Connect the N64 controller using three leads to the three Arduino pins (Ground, Pin2 and 3.3V) in my picture black, yellow and blue respectively. You will need to reset the board to get it working as there is an initialization that occurs at the start of the code.
If done correctly you should be able to go to set up USB Game Controllers in windows and the leonardo should display as a gamepad with 14 buttons and a joystick.
If that works then you're good to go and start using it with an N64 emulator or any other gaming platform that accepts gamepads.
A small note with Project64: I found that N-Rage's input plugin didn't connect to all 14 of the buttons, however Shunyuan's plugin worked perfectly (with a bit of an adjustment for the sensitivity).
Attachments
Step 4: Notes for Using Other Arduino Types or Pins for the Signal
The project should in theory be possible to port to other Arduino types that feature direct-USB communication like the Micro or the Due but the following will need to be done:
- Update Boards.txt to create a new type that mimics the board you want to use just like leonardon64 mimics the leonardo
- In N64_Controller.h change the following section so that N64_PIN refers to the pin you are using and also change 0x02 so that it refers to the correct pin in the port register for that board (more info on port registers available here):
#define N64_PIN 2 #define N64_PIN_REGISTER 0x02
Good Luck!
16 Comments
Tip 4 years ago
I got it up and running today.
Please keep in mind, that since 1.6.12, you will not find the HID.cpp in your core folder and the script may not compile. As it is not searching for the HID.cpp in the core files, it will ignore the newly copied one.
I also received that 'JoyState_t' error message (and several others) ;-)
Solution:
Download a old version of arduino (I downloaded 1.6.0 as a zip), unpack it, follow the instructions and it should work.
Another reason for the "joystate" may be a wrong controller board. Tried a 'nano', but I think it is not able to run that stuff.
Need to find a smaller ( than Leonardo) board to do that. :-)
Reply 4 years ago
What version of windows did you try? to me in windows10 64 bits did not work
Reply 4 years ago
Hi Alejandro,
sorry - have not seen that reply. I got it running in Windows 10 64bit.
Reply 4 years ago
The nano has a ATMEGA328 chip, so it can't do the HID functions, you need an arduino pro micro for example, which has the same chip as the leonardo. As the n64 controller works at 3.3V, you better buy the 3.3V 8MHz pro micro version instead of the 5V one unless you accommodate the voltage.
Question 4 years ago
I get some errors related to the library when I try to compile the program:
N64_Controller.h:16:20: error: 'PIN' was not declared in this scope
#define N64_QUERY (PIN & N64_PIN_REGISTER)
N64_Controller.h:15:17: error: 'DDRD' was not declared in this scope
#define N64_LOW DDRD |= N64_PIN_REGISTER
N64_Controller.cpp:251:15: note: in expansion of macro 'N64_QUERY'
*bitbin = N64_QUERY;
I have all the files included in the same folder as the program, and everything looks fine, I don't know what can it be. The HID and USBAPI seems to work fine too.
Any clue on this?
Question 4 years ago
hi thanks for the project.
but a have a problem, it not works on windows 10 64 bits :c
in windows 7 32 bits works perfect
I dont now if the problem are USB drivers for my Ryzen system or is just windows 10.
Did someone make it works in windows10 64 bits?
7 years ago
If you can't find "Leonardo N64" at ardiuno 1.6.9, Maybe can using this way;
You doing Step 1.
Step 1-2:
Make copying 'C:\Program Files (x86)\Arduino\hardware\arduino\avr\arduino' folder on same place, and Change name to "leonardon64".
Step 1-3(option):
Except for related leonardon64, Delete all board data from "boards.txt".
7 years ago
error:
N64_USB.ino:37:21: fatal error: Arduino.h: No such file or directory
compilation terminated.
Arduino: 1.5.7 (Linux), Board:"Arduino N64"
=/
7 years ago
I keep getting this error any idea?
'JoyState_t' does not name a type
Reply 7 years ago
Looks like the Arduino environment isn't accepting the edited USBAPI.h, are you seeing a new Board under Tools -> Board called Leonardo N64?
Reply 7 years ago
I can't see the board Leonardo N64, however I did all the procedures.
8 years ago on Introduction
This is amazing! Well written and referenced, easy enough for anyone but can be a very complicated project if you wanted to do it "from scratch". And most importantly, you can play N64 on your computer :D
8 years ago on Introduction
What would this be used for?
Reply 8 years ago on Introduction
For playing N64 games using an emulator like Project 64
8 years ago on Introduction
cool
8 years ago on Introduction
Hahaha this is great! Thanks for sharing!