N64 To USB, or how to turn your Arduino in a USB HID joystick w/ N64 controllers

Hello everyone, I'm Mick and I managed to turn my Arduino UNO rev3 in a USB HID joystick with 4 axes and 32 buttons, which maps input from two N64 controllers to these axes and buttons; it is composed of two parts, a .ino sketch for the ATmega328p which sends a command to two N64 controllers and reads 4 bytes from each controller; the first two bytes represent the x and y axes value, which range from -128 to 127; the other two bytes represent the status for each button in each bit (0 means no pressure, 1 means button pressed); there are actually 14 buttons on a N64 controller, which means that 2 bits are unused; after reading the status of the two controllers, the sketch writes on the serial port the two statuses; the other part is an .hex file for the ATmega16u2 which let the Arduino enumerate as an HID USB joystick with 4 axes and 32 buttons , named "Arduino Joystick"; all I did was actually taking some code from this Instructable for the sketch, and from this page for the USB HID firmware; on the sketch, I just removed the unused code (it was originally meant to be also used on a GCN controller, which is a pain in the a** to connect with unless you want to tear apart a standard GCN connector from your GCN), and turned it to probe two controllers instead of only one (cos I happen to have 2 N64 controllers, and playing with a friend is much more fun!)... on the firmware code, I modified the USB descriptor part in Descriptor.c or .h , don't remember, to my specs (which is, I repeat, 4 axes and 32 buttons). So all the original credit goes to these two guys :)

Btw, the cool thing of this is that, not only you could use your spare N64 controllers to play with your favourite game/emulator/whateveryouwant on your PC, which is super cool by itself, but also, you could easily make your own sketch for the ATmega328p that converts some input (say 2 arcade joysticks and 32 buttons...) into two N64-like statutes (2x8 bit values, 16x1 bit values) and use it to control something on your PC! Of course, you should be aware that this sketch first writes 2 axes and 16 buttons values on the serial port, then writes 2 other axes and 16 more buttons, so don't mess up the order of the things to write on the serial port.

Here I'm also adding a Github repository I use for this code with some brief explanation of what to do to get the whole thing up and running: MickMad N64-To-USB

For future reference, I also added this github repository link in the "Interfacing with Hardware / Gamepads" section of the Arduino Playground page.

Cheers and go get your N64 controllers NOW!!


Ps: this is my first ever post on this forum, yay!

can you please provide me some help in building the hex file from usbserial sources that come with the arduino code and produce the .hex file identical to Arduino-usbserial-atmega16u2-Uno-Rev3.hex file?

Once I have this, I'd like to modify the source for my project.

So far I have managed to compile the usbserial sources to produce the .hex file identical to the Arduino-usbserial-uno.hex included in the arduino code. However this does not work on my arduino.

Thanks in advance

Supposing you are working on a Windows enviroment, you should download and install CYGWIN, which enables some UNIX commands for your Windows command line, and then you have to invoke the "make" command in the folder containing source code and makefile.

Example: if you downloaded my n64-to-usb and wanted to modify the serial part thingy, you get the n64-to-usb-atmega16u2 from my GitHub, you uncompress it, you modify it then you "make" it. Done :)

BTW, if it doesn't work, well it's probably because there are some errors (I recompiled many times before getting the right USB descriptor configuration).

Nauman048: Hi all I am trying to communicate using SPI protocol between two arduino uno boards. I have writthen a very simple code to transfer a single character from master. The code is as following [...]

Please correct the code if its not right. And I really want to know that how to recieve that character on arduino uno in slave mode. There is a command SPI.transfer() to send data on SPI where as I haven't seen any command to recieve it.

Thanks and regards

First, this topic is NOT about the SPI protocol, nor about how to interface two Arduinos together; there are sooo many detailed guides and topics for that; Second, you can't simply ask people to correct your code; because, if you do that once, the second time you have some problems, you'll ask someone else to correct that for you, and so on; this way, you annoy people, and you don't learn how to code properly and how to debug/solve problems.

Your post has been reported.

is there a sample code that just simulates button presses and joystick movements? I wrote a sample program to toggle some of the buttons but it keeps moving one of the joystick axis.

I don't know what i am doing wrong.

The test program can simulate button presses sequentially with a delay (100) in between them. this way I can look in the joystick calibration dialog in windows.


sorry, all the testing I did was made during debug; btw, you can achieve your goal by modifing my n64-to-usb sketch file; in the main loop, you can comment all the lines needed to poll data from n64 controllers and to fill input buffers, so that you just need to write the buttons/axes data you need for your testing to the serial port of your arduino. In fact, all the main loop does is reading 4 bytes status data from 2 n64 controllers, and then writes these 8 bytes to the serial port;

as you can see in the head of the sketch:

struct state{
    char stick_x;
    char stick_y;
    // bits: 0, 0, 0, start, y, x, b, a
    unsigned char data1;
    // bits: 1, L, R, Z, Dup, Ddown, Dright, Dleft
    unsigned char data2;
} N64_status, N64_status2;

these are the 2 buffers that are used to store the status of both controllers; the difference between the use of char for the axes, and unsigned char for the data, is that the axes values range from -128 to +127, while the unsigned char is used as a buffer to store single bits, so that every bit is assigned to the status of the corresponding button (the buttons are mapped as they are written in the struct, left to right means MSB to LSB); so the only lines you need in the main loop are the last 3 lines (they HAVE to be at the end of the loop). Good testing to you :)