I bought a Super Advantage joystick on eBay with the intent of making it a USB stick for my computer.  This isnt as hard as it sounds.

The SNES controller is a very simple device that uses shift registers to get the state of all the buttons from the pad into the SNES using only 3 wires.

Heres how that works, in a nutshell.

You have 12 buttons, XYBALR Start Select, and the 4 directions on the D-Pad.  These buttons are connected to a shift register that takes all those individual buttons and turns it into 2 bytes; 16 bits of information, of which 4 bits are not used.

In code, it looks like this

So our little shift register has 3 lines that we care about (plus power, but that’s going to be a given); these are the CLOCK, DATA and LATCH/STROBE lines.  The way these are used is quite simple.  The CLOCK is always ticking, HIGH,LOW,HIGH,LOW, etc.  each tick of the clock will push one bit out of the shift register down the DATA line.  The LATCH tells the shift register to ‘latch’ or store all the states that are currently present into its internal buffer so they can be shifted out.

So the entire procedure is this, LATCH pulse, then 16 CLOCK pulses, for each you read the DATA line, a 0 means a button is pressed, a 1 means it isn’t, then you start over.  The order of the buttons is always the same, B, Y, SELECT, START, Up, DOWN, LEFT, RIGHT, A, X, L, R.  Using the microcontroller, we can actually just store that into an int.  There’s a library for arduino that can do all this for you.  Grab it here.

Now comes the fun part; making that work as a USB joystick.  I’m using an arduino pro micro.  It has an ATmega 32u4 microcontroller on it that has USB functionality.  Unfortunately, the defualt arduino configuration does not allow for joystick type HID devices, so I’ve used the information from http://www.imaginaryindustries.com/blog/?p=80 (UPDATE: READ BELOW)to add that capability.  Now we just need some glue code.

Thats about it really.


 

UPDATE:  Apparently that blog is down, so I’ll mirror that information here. Original by Connor.

I recently bought a Arduino Leonardo in the interest of updating the interface in an old arcade-style controller I occasionally use to playMAME games.

As such, I needed to figure out how to get the leonardo to properly act like a joystick.
Anyways, this is heavily based on drake250’s work, which is on the freetronics forum here. HelmPCB’s USB Joystick (BAD LINK) site was also a useful reference.
There is a useful list of HID descriptors here.
Also, the “HID Descriptor Tool” from usb.org is also very useful for seeing how HID descriptors are put together. Get it here.

In the end, I wound up rewriting most of the drake250’s HID descriptor myself, based on some of the USB.org docs, and the HID Descriptor Tool.

Anyways, here are my modified files you would need to turn your own leonardo into a joystick. These files support an 8-axis joystick, with two hat-switches, and 32 buttons.
If you want fewer buttons/axes/whatever, you can either just ignore the things you don’t need, or modify the HID descriptor yourself. As it is, for everything the HID descriptor currently specifies, it only needs 12 bytes per PC-update, so I’m not too worried about the extra axes causing issues or slowing things down.

leoJoy-Arduino-1.01
The windows joystick info dialog only seems to be able to display 7 axes. I’m fairly sure the eighth axis there. However, since the built-in windows dialog works almost the time, I have not found any tools for looking at joystick readouts other then the built-in windows dialog. I mean, how may people have an 8-axis joystick anyways?
Also, the HID documents seem to also support the belief that the HID spec allows a maximum of 63 buttons. However, again, the windows tools for inspecting a joystick only support 32. You could add more quite easily, but you would have to test their functionality yourself.

Modified arduino files (replace the files in {arduino executable dir}\hardware\arduino\cores\arduino\ with these):

USBAPI.h
HID.cpp

And the main source file:

 leoJoy.ino 

It’s contents:

The interesting thing here is JoyState_t, which is a struct that stores the state for all the joystick controls.

The struct is defined in USBAPI.h as such:

Continuing on with the contents of leoJoy.ino:

This section just generates random values and sets the analog axes to them. Each bit in buttons is also set in sequence, using bit-shifting.
It also steps through the different hat-switch positions. It steps hatSw1 fowards, and hatSw2 backwards. Lastly, the throttle axis it linearly ramped.

The last (and most important thing) here is

This is the function that actually sends the values in the joySt struct to the computer.

At this point, all that is needed to make a useable joystick is to replace the contents of loop() with something that actually reads hardware buttons.


Anyways, everything is under the arduino license (I think it’s GPL, but the only file I edited with a license actually looks to be BSD-ish. Anyways, do whatever, just don’t be an ass).

 

snes3

SNES2

snes1

I decided to upgrade my G27 shifter.  I’m not using it with a G27 wheel, so it’s possible to do a few things with it. The shift registers inside the stick are configured for 16 buttons; the 4 red, the 4 black in the top quad, the Dpad counts as 4 and the reverse pushdown takes one, that leaves 3 buttons that can be counted, but are not present.  I was never able to trace one of them out, so I was only able to add 2 buttons to my stick.
IMG_0717

Heres the button I’m gonna put in.  Its the horn button left over from my custom wheel mod.

 

IMG_0718

I made a hole!  actually, It was bigger than it was supposed to be so I had to cut even more.  It’s flush mount instead of being proud of the surface like I had wanted.

 

IMG_0719

A bit of a gap, but not too terribly noticeable.  I’ll make some ABS cement later to fill it, but the hot glue on the backside is doing a decent job.

 

IMG_0721

Here is the circuit board, note the unpopulated J12 connector location.  This is where the large button connector will go.  On the G25, this is where the mode switch connects.  I went ahead and drilled a hole in the face for the mode LED to poke through, and added that as well.  It doesn’t have any real functionality apart from blinky lights when you press the button.

 

IMG_0722

The bottom of R109 and the lower pad of R76 on the far left (white wire) are the connection points for the other button.  The black connector was added.  It has 3 pin in it, but only 2 are connected; I’m fresh out of 2 pin connectors.

 

IMG_0723

Everything fits nicely.

 

IMG_0724

And here it is all reassembled.  Not too bad, I don’t think.  I’m thinking of using these as Engine Start/Nitrous buttons.

 

IMG_0726

Obligatory Blinkenlights.

I’ve been teaching a friend of mine to drive a manual transmission.  Neither of us actually have a manual transmission vehicle, so I’ve been teaching him in the safe environment of the sim.  My first thought was ‘Well, at least he will get a general feel for pedal layout and shift points’.  Suprisingly the sims I had chosen (Live for Speed demo and City Car Driving) react pretty well to the clutch being abused.  In both, if you don’t feather the clutch properly on a standing start, the car bogs down and the engine stalls.  LFS has the added bonus of actually simulating the clutch plate itself, in that you can completely burn it up if you aren’t careful.  CCD has extra bonuses like general driving rules and penalizes you if you forget to do something.

All this training is being done with my race setup, comprised of my customized Driving Force Pro and it’s pdeals, as well as the shifter from a G27 and the converted rockband clutch, controlled by a microcontroller.

iPhoneUpload

These pedals are stuck to the mat with high strength double-stick tape.  The good stuff by 3M.  You can see the controller box in the top left.

IMG_20140603_102212_473

This is the shifter.  Nothing fancy apart from whats controlling it.

iPhoneUpload

And the wheel itself.  This has had the most work done to it.  The factory plastic was replaced with heavy-duty c-clamps, and the wheel itself was replaced with a momo knock-off I got for $30 on eBay.  It’s a full sized car steering wheel and the force-feedback works great.  For most games/sims, I have the sequential shifter bound to the handbrake, for mad skids.

 

Anyone who knows me knows I love my driving sims. The one thing I haven’t had, is a clutch pedal. What I do have, however, is an old rock band pedal, and a semi-wonkey Saitek ST290 Pro joystick (The y-axis drifts, and it’s not in hardware, it’s a firmware for which there is no fix).

IMG_0302

You may notice that the rockband pedal has a layer of plywood on it.  These things tend to crack when you really start to get into your drumming, so I reinforced it.  I don’t have the game any more, so it will work perfectly for this project.

 

IMG_0303

I’m going to use the throttle pot from the saitek, as it has the largest range of motion.

 

IMG_0304

This should fit rather nicely I think.  It’s important to choose a location that will afford the greatest amount of rotation to the pot, so the closer I can get to that orange bit, the better.

 

IMG_0305

I need to remove the hinge pin from the pedal, easily achieved with a punch.

 

IMG_0306

I did have to remove the bit of wall here as the pot will be sitting in there.  A dremel and some pliers make quick work of that.

 

IMG_0307

Using my digital calipers, I measured and marked where I am going to have to drill.

 

IMG_0308IMG_0309

This should work out rather well.  Now to remove the pot and slot it for the steel rod.

 

IMG_0310

With the steel rod affixed and the pot re-installed, the orange bit actuates the pot quite nicely, but I still need to have it return.  I had considered a spring but I couldn’t find one.

 

IMG_0311

 

So I’m going to use a paperclip.

 

IMG_0312IMG_0313

Up, and down.

 

IMG_0314

All that’s left is wiring up to the microcontroller and adding the code to send it as the z axis.  I won’t bother with the whole thing just now, but the code part was as simple as the single line Joystick.Z(analogRead(40));

 

A quick calibration in the control panel and it works.  Video later.