USBASP, a cheap retro controller adapter?

Intro

Long ago, I stared at my trusty USBASP and asked myself if it was possible to convert it to a USB adapter for a Mega Drive(Genesis) controller. At the time I still did not even know about V-USB or that the USBASP used it. As I write this, I got it working recently, with a SNES controller tough.  In this article I will talk about how I made it work, as well a little about USB. Be warned that this is an article about how I hacked an USBASP ( with software USB) to work as an USB converter for retro controllers. Still, I know is 2017 and native USB is getting popular on many microcontrollers and there are other ways of creating USB adapters.

Because the USBASP has 6 GPIOS easily available, it can be used to connect many old devices, as retro controllers, mice, keyboards, or even custom joypads and controllers (for arcade games or simulators) with help of external chips.

If you are comfortable already with creating USB devices with V-USB, maybe this article can be a bit boring for you. Anyway, feel free to stick around.

USBASP

The usbasp is an open source AVR programmer by Thomas Fischl. I have the popular version showed in the picture below. The schematic for it is easily obtained online.

USBASP programmer
USBASP programmer
USBASP schematic
USBASP schematic

This picture above is from the manual of the programmer I have. It was colorized before, that’s why some wires look grey.

This programmer uses V-USB, by objective development,  a software-only implementation of a low speed USB device for AVR microcontrollers. If you don’t know V-USB, there are some really good tutorials for V-USB in Code and Life for getting started. The USBASP has six GPIOs available at the ICSP header, so there is no need to make any mod to the programmer itself. Also, it can be programmed by the ICSP header, just connect other programmer, short JP2 on the target one and you’re good to go.

I wanted to use a USBASP here because it can be bought for around 1,65USD on eBay. I have some  USB homemade devices here, but they were made with perfboard and lots of wires and solder and probably costed more than 1,65. Unfortunately, I still dont have easy access to a laser printer or CNC mill to make pretty boards.

HID and the SNES Joypad

You can’t compare USB to the simpler protocols used with microcontrollers in general. It is very complex, but thankfully there are people out there willing to make it easier to understand. There is a document called “USB in a Nutshell” by Beyond Logic that helps a lot in this matter.

You probably heard of HID already, it is used by a ton of input devices and it does not need specific drivers. HID uses report descriptors to send data that is interpreted by the computer. HID descriptors are not easy to understand either, but there is a fantastic article on the subject by Eleccelerator.

I chose a SNES controller as I have some fake ones here I could use for testing and spare if I made any mistake. However, this easily works with Genesis, Master System, Atari, NES, PlayStation I guess, and others. The Nintendo 64 and Nintendo Game cube controllers have a serial one wire protocol that is a PIA, They can be adapted to USB, but not easily. The SNES controller has a D-PAD and 8 buttons (X, Y, A, B, L, R, Select and Start).

The SNES joypad only needs three GPIO, and two of them can be shared. I mean n controllers use 2+n GPIOS (If you don’t use external chips, of course). That means the USBASP with 6 GPIOs on the ICSP header can easily have 4 SNES controllers attached to itself.

Poorly drawn front view of the joypad connector
Poorly drawn front view of the joypad connector

Joypad adapter

I made a super simple adapter to connect the SNES controller to the ICSP header. Just wired the SNES joypad buttons to the header on the USBASP. I used two standard male header pins for each controller pin and a 2×5 female header for connecting the board to the ICSP port.

 

That’s it. Some wires,perfboard and a bit of solder.

Code

First, I had to edit usbconfig.h, the configuration file for V-USB. These defines were there already in the HID example, I just edited them to match the schematic above. This is basically it for the configuration file, as I used the one in the HID example. In this file is also possible to change VID and PID or rename the device.

As I said before. A HID device needs a report descriptor, the descriptor is an array of bytes that tell the computer how to read the data the device sends to the computer. I this case, I imagined the data,which must be defined as a report_t struct in main.c, as follows:

You may be imagining why in the earth I need two axes on a SNES controller. Yeah, I thought this at first, as every tutorial I found online used axes for directions.  I read that devices implementing real D-pads are troublesome and sometimes not recognized. I even analyzed the descriptor for a USB controller I have here and it uses axes too. So I went with axis for now.

I used the HID toll from usb.org and built the following descriptor. Spoiler! It is wrong and the program did not let me fix it. It is missing a END_COLLECTION, that I added later by hand. If you have no idea how to read the descriptor below, you may need to have a read at the link from Eleccelerator I mentioned previously.

The HID tool from usb.org. Unfortunately, I haven’t tried to run it on Linux, but later I read it works fine with wine.

 

Anyway, I tried to plug the thing to the  USB port. Just to see what happened. The device was not recognized, but I ran dmesg and got the following:

Brilliant. The driver even reported the problem. I fixed the report descriptor as follows. The USBASP is reported as “Mouse” because this is the default name for the HID example and I had not changed it at the time.

The report descriptor size must be updated in the usbconfig.h file

So, now I tested and the device was recognized, but I still needed to send the button presses correctly. For this, I just needed to fill a report_t struct with the data from the SNES controller.

The SNES controller has a very well known protocol, it can’t even be called a protocol. Is just a chip that works like a 74hc165 and sends the buttons pressed serially.

Accordingly to a file on Game FAQs

And the button sequence:

Then, it is simple to read the button states.

CLOCK, LATCH and DATA are the pins of PORTB where the SNES controller is connected(these pins are available at the ISCP header).

And, to fill the struct with the button states:

Then the struct is sent whenever the USB interrupt is ready.

The complete code is available on my github.

Conclusions

It works. I tested in both Linux and Windows. As I said before about HID, it does not need custom drivers.

Joypad test on Windows 10
Joypad test on Ubuntu with jstest-gtk

I am happy I could understand USB better, but I still have a lot to study and try. Hope that this post and the links I provide below will be helpful to you.

I may use this with a Raspberry Pi zero in the future to make a emulation machine with genuine SNES or NES controllers.The good thing is I only need a USB port to connect up to four controllers anyway.

How about Digispark? It should be not only cheaper, as smaller. I thought about this, but a Attiny85 only has 6 pins available, and this only if you disable the reset pin, two of these are used for USB, so it cuts down the number of devices that can be connected right to the micro. Also it has a bootloader for Arduino and does not have a ICSP header, so I went with the USBASP for this project.

That is it for now. Thanks for reading!

See ya next post.

Sources

The following articles were very helpful while writing this text:

Code and Life V-USB Tutorials

USB in a Nutshell

HID Report Descriptor Tutorial by Eleccelerator

Super Nintendo Pinouts and Protocol at Game FAQs

USBASP manual

 

 

Robson Couto

I am a Electrical Engineering student. I should be studying motors or transmission lines right now, but instead I am probably reading about computer history, microcontrollers, buses and protocols. My life is basically I having trouble because of this. God help me please.

6 thoughts on “USBASP, a cheap retro controller adapter?

  1. Hi,

    Thanks to sharing it with us :)
    A question : you said “That means the USBASP with 6 GPIOs on the ICSP header can easily have 4 SNES controllers attached to itself.”. So I presume it is possible to create 4 HID too ?
    I would like to use my USBASP for 2 gamepad in a first time, do you have some advices ?

    Thank you :)

    1. Hello Shcmurtz.
      Sorry for the late reply, wordpress isn’t notifying my email correctly.
      To use 2 gamepads, you basically have to expand the code to two collections and report descriptors. Ufortunately I did not implement it, but it is explained on the Eleccelerator website.
      http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/
      You have to program the next GPIO to read the other controller as well.
      Any trouble you can leave another comment here.

      Robson

Leave a Reply

Your email address will not be published. Required fields are marked *