********************************************* * ** * USING the STANDARD PC JOYSTICK *** * *** * *** * Gamecore Group *** * compiled by Brian Eley *** * Last updated March 25, 2002 *** * *** *********************************************** ********************************************** ********************************************* i. CONTENTS ~~~~~~~~~~~~~~~ 1........The Standard PC Joystick 2........Non-standard Joysticks 2.1......Auto-fire 2.2......Extra Buttons 2.3......Digital Joysticks 3........Joystick Pinouts 4........How to Measure the Joystick Position and Button Status 4.1......Reading the Joystick Buttons 4.2......Reading the Joystick Position 4.3......Simpler Circuit for Reading Joystick Position 5........Sampling the Joystick With a FPGA 5.1......RTL Diagram for Sampling Circuit 5.2......VHDL Code for Sampling Circuit 6........References 1. The Standard PC Joystick ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A standard PC joystick is composed of two axes (X & Y) and two buttons. The axes are implemented as variable resistors, and the buttons are normally open momentary SPST switches. Sometimes a standard joystick has 3 or more buttons. In these cases, two buttons may simply be wired in parallel to act as the same button. This is the circuit for a standard joystick: +------------------+ V | +-/\/\/\/\/\/\/\/\/\/\/\ | | (var. resistor Y) | | (0..100 kohms) | | | +5V -----+ +----------------+ | | V | | +-/\/\/\/\/\/\/\/\/\/\/\ | | (var. resistor X) | | (0..100 kohms) | | | | X-Axis ----------------------------+ | | Y-Axis ---------------------------------+ / Button1 -----------------------/ ---+ (switch 1) | | / | Button2 -----------------------/ ---+ (switch 2) | | Ground ------------------------------+ A standard PC joystick port has support for two joysticks (4 axes, 4 buttons). Some gamepads, such as the Gravis Gamepad, use fixed resistors to implement the direction control. Thus, only 3 distinct points are available on each axis. These joysticks still behave as standard joysticks. 2. Non-standard Joysticks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Over the years, many non-standard joysticks have been produced. Examples are the CH Flight Stick and Microsoft Sidewinder. While these joysticks may offer additional buttons and/or increased precision, beware that these joysticks use non-standard means to communicate with a PC. Often, the button inputs are used to communicate with the PC using either a digital encoding of the buttons, or a digital synchronous bit stream (one button input acts as data, another as a clock). A joystick is likely non-standard if it has many buttons, or more than 2 axes (which may come in the form of a rudder or throttle controls). While there are advantages to non-standard joysticks, standard joysticks are inexpensive, still available, and are easy to interface to. And everyone has an old PC joystick sitting in their basement that they wouldn't mind donating to an EE-552 project. 2.1. Auto-Fire ~~~~~~~~~~~~~~~~ Auto-fire is a joystick feature that has been around since the early days of PC games. The idea is that holding down a joystick button will pulse the button line as if you were clicking the button really fast (10-20 Hz). This was an advantage in some games. Watch out for auto-fire since the button pins do not behave as switches. The +5V supply must be present for the button pins to do anything as they are driven by active circuits, even when the auto-fire is turend off. 2.2. Exra Buttons ~~~~~~~~~~~~~~~~~~~ Some joysticks support more than the two standard joystick buttons. Of these multi-button joysticks, some simply use the four buttons normally allocated to 2 joysticks (thus robbing any chance to use two joysticks on the standard joystick port). Others use proprietary digital means to transfer button status to the PC. For instance, the CH Flightstick encodes 15 buttons and a no button active state into four bits using all four button pins. 2.3. Digital Joysticks ~~~~~~~~~~~~~~~~~~~~~~~~ Some joysticks (such as the Microsoft Sidewinder) use optical means of measuring the joystick position instead of variable resistors, and they use proprietary, entirely digital means of transfering joystick position and button information to the PC. For instance, the Microsoft Sidewinder uses one button pin to send a serial bit stream and a second button pin to send a clock. 3. Joystick Pinouts ~~~~~~~~~~~~~~~~~~~~~~~ The PC joystick port uses a 15-pint D connector. Usually, a Y-splitter cable is required to use two joysticks. On newer joystick ports that are integrated with sound cards, the joystick port usually doubles as a MIDI port. Theses are the pinouts for the joystick port: (Pins on joystick port) __________________________ \ 1 2 3 4 5 6 7 8 / \ 9 10 11 12 13 14 15 / ---------------------- +-------------------------------+ | Pin # Function | | ~~~~~ ~~~~~~~~ | | 1. +5V (To POTs) | | 2. Joystick A Button 1 | | 3. Joystick A X-Axis | | 4. Ground | | 5. Ground | | 6. Joystick A Y-Axis | | 7. Joystick A Button 2 | | 8. N.C. | | 9. +5V (To POTs) | | 10. Joystick B Button 1 | | 11. Joystick B X-Axis | | 12. MIDI TXD | | 13. Joystick B Y-Axis | | 14. Joystick B Button 2 | | 15. MIDI RXD | +-------------------------------+ If you're lucky enough to have an old PC (pre Pentium) sitting around, you may be able to steal the joystick connector from the parallel port/joystick face plate. These cables are great because you have the 15 pin joystick jack on one end, and a ribbon cable with a 16 pin header on the other end. 4. How to Measure the Joystick Position and Button Status ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Since the joystick buttons are the easiest to read, I will start with them and then move onto the axes. 4.1. Reading the Joystick Buttons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reading the joystick buttons is easily done by connecting the button pins to +5V through pullup resistors, and then measuring the voltage on the button pins. This way, when the buttons are inactive, the pin voltages sit at +5V, and when the buttons are pressed, the pin voltages drop to ground. The joystick buttons can be debounced by sampling the voltage with a sampling interval big enough to absorb any bouncing. I found that 30 Hz worked quite well. This equates to a sampling interval of 33.3 ms which should be sufficient to absorb any button bounce, and it is very unlikely that the user can press the buttons faster than 15 times a second. Here is a circuit for measuring the joystick buttons: Measurement Circuit Cable Joystick =================== ===== ======== +5V ------------+---+ \ \ / / 10k \ \ 10k pullup / / pullup \ \ (SW 1) / / / Button 1 o-----+---)---------------------------/ --------+ | / | Button 2 o---------+---------------------------/ ----+ | (SW 2) | | Ground ------------------------------------------------+---+ 4.2. Reading the Joystick Position ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Several techniques can be used to measure the joystick position. The problem of measuring the joystick position is simply a problem of measuring a resistance. The joystick position is proportional to this resistance. One simple (yet wasteful) approach is to connect the variable joystick resistance in series with a fixed resistor to create a voltage divider. Then you could apply a fixed voltage across the divider, and read the voltage in the middle using an ADC. This method is probably easiest to understand, but it wastes an expensive analog to digital converter, not to mention all the extra wiring. A simpler approach is to convert the joystick resistance to pulse width using a monostable multivibrator. The width of a pulse can be easily measured using a counter. A monostable multivibrator is a circuit that can be triggered to start outputting a pulse based on an input pin, and the width of the output pulse is based on the charging of a capacitor through a resistance. A threshold circuit indicates when the capacitor has charged to the threshold voltage. If we choose a fixed capacitor and charge it through the joystick variable resistor, the output pulse will depend on the resistance. The nice thing about this circuit is that the width of the pulse is directly proportional to the RC time constant, and therefor is directly proportional to the chosen fixed capacitor and to the resistance presented by the joystick axis. A 555 timer can be used to create the monostable multivibrator. I have tested and have had good results with the 74LS123 Retrigerable Monostable Multivibrator chip. Note the fixed resistor to prevent a short to ground that would occur when the joystick axis resistance is zero and the monostable is trying to drain the capacitor. Here is the circuit (you need one for each axis): +5V --------------------/\/\/\/\/\/\-----------+ Fixed 5k resistor | + +------+ / +---------------+ | | \ | | | +--->/ Variable Trigger --->| Monostable |<-----+ \ Joystick Output <----| Multivibrator | | / Resistance | | --- C1 \ (0-100 kohms) +---------------+ --- / | \ | + Ground ----------------------------+ C1 = 100 nF approx. When the trigger input is asserted, the capacitor is drained by the monostable. At this point the monostable output goes low. The capacitor begins charging through the variable resistor, and when the threshold voltage is crossed, the monostable's output returns high. Here's a waveform: Trigger Input: ---------+ +--------------------------- | | | | <-- Width of pulse not important +--+ Monostable Output: ---------+ +------- | <-- depends on RC -> | | | +----------------------+ 4.3. Simpler Circuit for Reading Joystick Position ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A simpler circuit for measuring the joystick resistance uses the same approach as the monostable multivibrator, but only requires a series resistor and a capacitor to interface the joystick variable resistor with a FPGA. Here's the circuit: +5V -------------------/\/\/\/\/\/----------+ Fixed 5K | resistor | + / +----------------+ \ | |<-+---+----+ / Variable | FPGA | | | | \ Joystick | ==== | | | +-> / Resistance | | | | \ (0-100 kohms) | 3-state buf. | | --- C1 / | |\ | | --- \ | GND >-| >----|--+ | + | |/ | | +----------------+ m (Ground) C1 = 100 nF approx. To measure the joystick position (resistance), the FPGA enables the output tristate buffer and places a low vow voltage at the output. The capacitor drains through the FPGA pin. Next, the tristate buffer output is changed to high impedance. The capacitor begins charging through the joystick variable resistor, and the FPGA input pin is sampled until the voltage goes high. The input will read as high when the threshold voltage of the FPGA pin is exceeded. This threshold voltage is not well know, but it is constant. The particular switching voltage is not important because the FPGA pulse width measurement circuit can be calibrated to work with the particular capacitor value, joystick resistance range, and pin threshold voltage. I chose the monostable method over this method partly because I was afraid of damaging the FPGA output pin by discharging a capacitor through it, and I thought the monostable circuit might possible give better range and linearity. However, this was not tested. Please feel free to update this appnote if you test this circuit. Also, if you use this circuit, it is extremely important to include the fixed resistor or else you have a short from power to ground (through the FPGA pin) when the joystick resistance goes to zero. 5. Sampling the Joystick With a FPGA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here I will present a method for sampling the position and button status for two joysticks (4 axes, 4 buttons) using the above described monostable multivibrator circuit and button connections. There are likely better implementations, but this one is rather simple and easy to understand. The circuit in the FPGA requires a clock and an enable signal to generate an effective 1MHz clock that is used for timing everything. A 15-bit free-running counter is clocked at 1MHz. The counter wraps at approximately 30.5 Hz. Each time the counter wraps, the buttons are sampled and stored in a register, and the monostables are triggered. The counter continues counting up from zero, and the value of the counter is latched for each axis at the time when the axis' monostable output returns to the stable (high) state. The capacitor values can be adjusted until the pulse width is set to give a good range of counter values for the entire joystick range of motion. Idealy, you would like near zero pulse widths when the joystick is in the top left corner, and pulses nearly as long as the sampling interval when the joystick is in the lower right corner. Most likely, you will only be interested in the most significant 8 bits of the axes counts since the joystick is usually quite noisy and the readings will jump around somewhat. If you experience a lot of trouble, some sort of filtering may need to be performed on the readings. 5.1. RTL Diagram for Sampling Circuit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is an RTL Diagram of the measurement circuit: +-----------+ +--------+ | 15-bit | 15 | Zero | | Counter |>-/-+--->| Detect |>-+------->|NOT|------------> Trigger | (1MHz) | | +--------+ | +-----------+ | | | | +------------+ +---------------+ | Load | Button |<-------o Button 0 | +----->| Register |<-------o Button 1 | | | |<-------o Button 2 | +----------------------+ | |<-------o Button 3 | | +------------+ | | | | +---------+ +-------------------------o Axis 0 | +--->| Axis 0 | | | sync. clear | Flag | +--->| | sync. set | Reg. | |AND|---+ | +------>| |>--->|NOT|---->| | | | +---------+ | | | | | +-----------------------------------------+ | | | | load +---------+ | 15 +------>| Axis 0 | +-/----------->| Count | | Count | Reg. | | +---------+ | . . . . . . . . . . . . . . . . (Repeat for remaining 3 axes) 5.2. VHDL Code for Sampling Circuit ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VHDL code to implement this circuit is distributed with this file. Please refer to: joystick_pkg.vhd 6. References ~~~~~~~~~~~~~~~~~ ePanorama.net http://www.epanorama.net/documents/joystick/pc_joystick.html Joystick programming Guide from PC-Game Programmer's Encyclopedia http://brand107.home.attbi.com/pc-gpe/joystick.txt