Gravis Interface Protocol
Ever heard of the Gravis Gamepad Pro ? It's a gamepad using the old-fashioned PC gameport. It looks quite like the original Playstation controller and has a very solid build quality.
Those of you who know about the gameport limitations will quickly notice that there must be something non-standard about it: there are 10 buttons, while the gameport only allows 4. Even better, you can actually use 2 gamepads at the same time on a single port.
There are several modes accessible with a switch under the gamepad. These are 1-player, 2-player, and GrIP. In 1 player mode, you get 2 axis and 4 buttons. In 2 player mode, you get 2 axis and 2 buttons, and you can use 2 gamepads. In GrIP mode, each gamepad can use all 10 buttons, but this is not compatible with the games expecting a standard joystick.
I have some of these gamepads around, but my PC don't have a gamepad anymore. Since I'm not very happy with replacement hardware (I tried the Logitech Precision USB gamepad, but it doesn't look as nice and colourful), I'm thinking about building an adapter for these gamepads to plug them on an USB port. Of course, without opening and rewiring them. Not only this would void the long expired warranty, but I may still want to plug these gamepads to the system they were intended for (my 1995 Pentium 166 MMX).
There is some information on the internet about the protocol, but it's not easy to find. Heer is what I could get : a textfile with some info and the Linux driver for these joysticks. Since the textfile does not say everything the driver does, here are some notes that duplicate the text file and add the info from the driver.
First, the gameport pinout. It's a SUB-E 15 connector. The following pins are relevant:
- 1,8,9,15: 5V power
- 4,5,12: GND
- 2,7,10,14: buttons 0,1,2,3
When you use only one gamepad, buttons 0 and 1 are used as data lines. Button 0 is a 20kHz clock. On each rising edge of this, you can read the state of button 1. Frames are 24 bits long and holmd data as follows:
0 1 1 1 1 1 0 Select Start R2 Blue 0 L2 Green Yellow Red 0 L1 R1 Down Up 0 Left RightThe frame starts with a start bit, then 5 bits set high. Since the button data is split in 4-bit words with a 0 interleaved, there can't possibly be 5 set bits anywhere else, this makes it possible to detect the start of a frame.
Transmitting a full frame at 20KHz will take exactly 1.2ms. This is more than fast enough. It's likely that Gravis drivers on windows only polled the gameport only 20 or 25 times per second (or even less), and waited up to 2ms for a frame start. This was the only way for them, because these gameport buttons are not triggering interrupts.
When there are 2 joysticks connected, the second one uses buttons 2 and 3 exactly the same way. The Gamepad Pro has a pass through connector that swaps buttons 2 and 3 with 0 and 1 for the second device, like any Y-doubler joystick cable does.
My plan is to use a Stellaris Launchpad LM4F120 as an adapter. Why ? Because I have one and want to try playing with it. More interesting, this board has 4 SSI/SPI channels and they can be configured for up to 16 bit frames (where an AVR can only do 8 bits). Since our frames are actually 24 bits here, we'll have to cheat a bit. The plan is to use 2 12-bit frames. Another problem is since the bits come in in a continuous flow, there's a risk of getting out of sync. What I will try is configuring the SSI, reading 2 frames, and see if one of them starts with 0111110. If so, the system is in sync and should stay so forever. Else, wait for 1/20ms, reset the SSI and try again. This should shift by one bit until we get it right. If this approach fails, I'll have to revert to using GPIO and external interrupts. At 20kHz I think the Launchpad can handle it, even with 4 gamepads plugged in. Since the USB is handled in hardware I shouldn't run into as much problems as my amiga keyboard to USB adapter.

