Gravis Interface Protocol

Posted by pulkomandy on Wed Dec 2 18:47:36 2020  •  Comments (7)  • 

This article has been revised to include fixed and up to date information after I actually plugged the gamepad to an oscilloscope. Now it should be error-free.

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
(the other pins are axis 0, 1, 2, 3, they are not used in GrIP mode).

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:

011111
0SelectStartR2Blue
0L2GreenYellowRed
0L1R1DownUp
0RightLeft
The 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 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.

gravatar Comment

Posted by brad on Wed Feb 26 19:24:59 2020

I love these old gamepads, perfect for retrogaming on dosbox - except for the 15-pin connector!

Did you ever get around to implementing an STM converter?

I'm working on an atmega32u4 (on an Arduino) implementation to adapt these old gamepads to USB. I've implemented decoding so far, the hard part. There are libraries available to make the USB output easy. A few more days and it'll be good to go. Your writeup here and the linux source were invaluable.

https://github.com/prosper00/GRiP-duino

gravatar Comment

Posted by Pulko on Wed Feb 26 20:07:17 2020

Glad it could help :)

I got them somewhat working on STM32, then switched to AT90USB and did something too ambitious where I attempted to drive 4 of them at the same time and it turned out the CPU was not fast enough for that. So I need a new plan now. They are still on my desk patiently waiting after a few years...

With an appropriate HID descriptor it should be possible to copy the 4 bytes from the pad straight into the USB HID report (including the always-0 bits) ) and let the host computer care about parsing it further and that would work.

Does the atmega32 use V-USB, or does it have some hardware USB support? I fear the latter would be needed (because V-USB is also CPU intensive and interrupt driven, so not sure both can run at the same time), but I'm interested if you get it working without that.

gravatar Comment

Posted by brad on Fri Feb 28 06:12:30 2020

oooo! I hadn't thought of just dumping the packet into the descriptor.

The atmega 32u4 has hardware USB support. The Arduino Leonardo and the Chinese 'Pro Micro' clones use the 32u4.

My code is complete and working now. I'm working on a way to measure the performance, but it looks that it takes about 2.2-2.4ms to process two gamepads running at once, which is sufficient IMO.

gravatar Comment

Posted by brad on Fri Feb 28 06:24:18 2020

I should also note that I implemented this as a *keyboard* that sends keypresses, instead of a gamepad device. Mostly because I intend to use it with Commander Keen and Duke Nukem and other old platformers on dosbox, and I really find joysticks with dosbox to be fussy.

gravatar Comment

Posted by desu on Wed Dec 2 18:37:09 2020

The link "a textfile with some info" pointing to http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/specs.txt is dead. A copy is available on archive dot org so you might want to update the link.

gravatar Comment

Posted by Plk on Wed Dec 2 18:48:12 2020

Thanks, fixed the link, now pointing to a local copy.

gravatar Comment

Posted by Hyratel on Sun Feb 20 09:56:55 2022

I got the more-complex XT protocol working with a Blackhawk Digital but it's pushing an arduino 32U4 right to its limits on timing tolerances

Leave a comment

Name: Mail: