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 gameport 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), and the USB version of the Gravis Gamepad is impossible to find (and less beautiful with the black plastic, 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. Here is what I could get : a textfile with some info and (originally from http://atrey.karlin.mff.cuni.cz/~vojtech/joystick_specs.txt, which is now offline) 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.
I checked this with an oscilloscope, so I believe the information to be correct. But I may have missed something.
First, the gameport pinout. It's a SUB-E 15 connector. The following pins are relevant:
- 1,8,9,15: 5V power (my gamepad accepted down to 3V, below that it stops generating the clock signal)
- 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 20 to 25kHz clock. On each falling edge of this, you can read the state of button 1. Frames are 24 bits long and is formatted as follows:
0 | 1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|
0 | Select | Start | R2 | Blue | |
0 | L2 | Green | Yellow | Red | |
0 | L1 | R1 | Down | Up | |
0 | Right | Left |
Transmitting a full frame at 20KHz will take about 1.2ms (slightly more than 1.5ms on my test gamepad). 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.
I'm planning to use an STM32f3 microcontroller to decode this. The protocol is close to SPI, unfortunately microcontrollers able to handle 24-bit SPI frames are not common. Moreover, the start of frame is hard to detect so synchronization could be a problem. Bit banging the protocol is a better solution, we just have to use the clock line as an external interrupt and read the bits in the interrupt handler.