Hardware articles index > Programmable Joystick Controller project from Hobby Electronics 1983

Hobby Electronics August 1983 page 11
Joystick Controller
Paul Moody and Chris Lloyd
Set your fingers free! Banish keyboard cramp! Play action
games as they were always meant to be played, with the
HE Joystick Controller!
This project is a completely new idea in Joystick design
because it is fully programmable and can be used with
any games software for the ZX81, Spectrum or Jupiter Ace.

THE ZX81, Spectrum and Jupiter Ace keyboards are excellent for entering programs, but they are very difficult to use for playing any fast moving games. This is a great pity because there is a wide range of excellent games software writ-ten for the ZX81 and Spectrum. The Ace has perhaps been a little slower to catch on, but now that its versatility and speed are being appreciated, a number of good games have appeared for it.
    The Joystick Controller described here can transform your
computer from a toy into a true arcade style machine, and its unique design allows its use on all software. You won't need to buy software especially written for a joystick, because all your existing programs will work with it.
Basic Ideas
The way most joysticks work is to mimic the action of the keyboard, so that when the joystick is moved, the computer is fooled into believing that a key has been pressed. The problem that arises is simply this: which keys should
the joystick mimic? One convention is to use the "arrow" keys
— 5, 6, 7 and 8 for left, down, up and right, and 9 for fire. But unfortunately only a limited amount of software uses these keys — mainly because it is very awkward to use keys so close together. The result is that many people buy a joystick and then find that they can't use it on any of their old software, or that many programs that they would like to buy won't work with the joystick.
 This article describes a completely

Hobby Electronics August 1983 page 12

Although this drawing was produced by a Computer Aided Design package, similar 'sketches' could easily be made using the joystick and a simple drawing programme. The 'fire' buttons could also be used, for example to delete points back along the plotted track and, on the Spectrum, to change the foreground colour.

Some games, such as the flight simulator shown, use more than the six functions available on the joystick. However the keyboard can still be used for flaps, undercarriage etc provided the joystick controls are not operated simultaneously.

it sends A10 low with A8, 9, 11, 12, 13, 14, 15 all high. Now if none of the keys on that row are pressed, the outputs labeled KBDO-4 will all be at logic 1 — because they are all tied via resistors to +5 volts. But now consider what happens when key "W" is pressed: it connects A10 to KBD1, pulling KBD1 low and sending a logic 0 to the ULA (or to a tristate buffer in the case of the Ace, which has no ULA). So, by scanning through each row in turn the computer is able to build up a complete picture of the keyboard, and it does this every 1/50th of a second.
  If you are wondering what those diodes are doing in the address lines, consider what would happen if they were not there and two keys in the same column were pressed at the same time; address lines would be shorted together and the computer would crash instantly!

But how does the CPU distinguish between reading the keyboard and reading memory? In both cases it puts out an address, but for reading the keyboard it sends out a low on IORQ instead of on MREQ. This signal, combined with a low on A0, tells the ULA (or tristate buffer, in the case of the Ace) that it is reading the keyboard, and it transfers the values of KBDO-4 to the lower data lines, D0-4.
In A Nutshell
To explain the operation of the Joystick Controller, We'll use the very simplified (and highly schematic) circuit diagram of Figure 2. It consists of five basic blocks, plus a certain amount of control circuitry, represented here by a single two-input or gate.
  The joystick itself is a simple array of six micro switches operated by the control lever; the output lines are connected to a +5V when one or more switches are closed.
  An 8-into-3 line encoder operates on the CPU's address lines, A8 - A15, that are consecutively taken low during a Keyboard Read operation. The encoder simply reduces the number of address lines required for the memory by utilising the fact that only one of A8 to Al 5 will be low at any one time during a keyboard read. Since there are only eight possible states for A8-A1 5 at these times, only three lines (2 3 = 8) are needed to contain this information.
  These three lines become the top three address lines to the Controller's Random Access Memory. The lower order address lines are derived from one of two sources, depending on whether the Controller.is being programmed for use, or is in use. The address lines are selected by an electronic switch, operated by the CPU's Write Enable line, WE. When the controller is being programmed (this is further explained, later), WE is taken to logic 0 and the
new idea in joystick design — the joystick is actually programmable and can mimic the action of any keys. To make things even easier for you, a program is included which remembers which games use which keys, so if you want to play a game that you've played before then you don't need to reprogram the joystick — simply give it the name of the program and it will do the rest.
  To understand how the joystick works let's first take a look at the Sinclair keyboard.
The Keyboard

The keyboard consists of a five by eight grid of wires, with a key over each crossing point (Figure 1). When a key is pressed, it connects together the two wires passing beneath it. The keyboard is read, one row at a time, by taking each of the eight address lines low, in turn, leaving the other. - seven high. Say, for instance, that the computer wishes to read the row containing the letters "QWERT", then

Hobby Electronics August 1983 page 13
'switches' are in the position shown, connecting the RAM's low-order address lines to the CPU's address lines. At the same time WE enables the RAM so that data can be written to it, and simultaneously connects the RAM's data lines to accept information from the CPU's data lines (this is actually done not by a switch as shown in Figure 2 — but this will be explained in a moment!).
  Now the keyboard is not actually located at a single address; in fact any time A0 is low and an IN instruction has been issued (either by the CPU's Monitor program or by a user program — the Sinclair ULA can't tell the difference) the computer is performing a keyboard read operation. So, when programming the Controller, the keyboard is read by the program written for the purpose and the CPU will return, on data lines D0 - D4, a five-bit 'word' corresponding to whichever key has been pressed, if any. This data now has to be stored in the Controller RAM, and the location in RAM at which it is stored is determined by the CPU's address lines A1 - A7. This address is set up by a single number, entered as part of the set-up routine, which corresponds to a particular joystick position. What happens, in effect, is that the data corresponding to a particular key —'Q', say, — is stored in the Controller RAM at a location which corresponds to a certain joystick position.
  Now when a game is being played, the joystick output lines are connected to the RAM via the electronic switch (because WE is kept high).

Figure 1. The keyboard circuit shown is typical of the ZX81, Spectrum and Ace, with minor variations between them. Each square over a pair of crossed wires represents a switch which, when closed, pulls a KBD line to logic 0 when the corresponding address line is at 0. The Monitor programme performs a keyboard scan about once every 20 milliseconds by consecutively pulling each address line to 0. The diodes prevent two address lines being shorted if two keys are pressed together. The keyboard is also scanned by an INKEY instruction in a user programme.

  Normally the ZX81 monitor performs a keyboard read about 50 times per second, and during these times both IORQ and AO will be low, so the Controller RAM Chip Select pin will be enabled and data will be read from it, as well as from the keyboard. The RAM address, now depends on the physical joystick position, rather than a number representing it, and at that location will be found data corresponding to a particular keyboard letter!
  As mentioned before, the RAM data lines are connected to the CPU's data lines by a 'switch' that
is not really a switch. In fact 'it' is five high-power tri-state buffers, each bypassed by a resistor. When the buffer outputs are in a high impedance condition ('off') the resistors allow data to be written to the Controller RAM. However when the WE input is high the buffers are active (the 'switches' are then in the - opposite position to that show in Figure 2) and they have sufficient 'muscle' to override the CPU data. Thus the computer receives data corresponding to the joystick position, rather than the actual keyboard data, whatever it maybe. And, since the joystick position

Figure 2. A highly representational block diagram of the Controller. When it is being programmed, the memory address lines are connected to the computer's address bus and data is accepted from the data bus, as shown. In use the "switches" are reversed; the joystick provides the addresses and previously programmed information is forced onto the data bus, overwriting information from the keyboard.

Hobby Electronics August 1983 page 14
Figure 3. The full circuit of the Controller. ICs 3 and 4 are the "memory address switch" while 1C7 controls the data direction.
has been set-up to correspond to a particular key, the computer receives the appropriate command — unless the Invaders have just bombed you out of the game!

The Complete Circuit
Figure 3 gives the complete circuit for the joystick interface. As before, A8 to Al 5 are encoded by 1 C5 to give three address lines for the memory, IC6, a 6116 2K by 8-bit static CMOS RAM. IC3 and IC4 are 2-into-1 multiplexers connected as electronic switches — when SELECT (S) is at logic 0 the A inputs are connected to the outputs, and when at logic 1 the B inputs are selected.
  First consider how the memory is programmed. To do this, an OUT command is given along with an address (on the ZX81 this command can only be given in machine code —there is no OUT command in ZX81 BASIC). The address must have both AO and A7 low; AO is always low for a keyboard read while A7 must be held low to avoid the Joystick memory being accidentally written to by the CPU when it gives control
signals to the logic circuitry.
  The OUT command sends both IORQ and WE low. Since WE is connected to the select line on the multiplexers IC3 and 4, the A inputs are selected, and in particular Y1 is connected to A7 and is thus at logic 0. This means that ICI a has all zero inputs and so gives out a logic 1. Then, since one of the inputs to IC2a is WE, at logic 0, its output is at logic 1; therefore IC2b has both inputs at logic 1 and so it gives a 0 output. Thus IC6's CS pin is taken low, enabling the RAM. And, since the output of IC2c is a 1, BUF is 0 and the buffer outputs, are open circuit, this allows data to be read into the memory from the data lines via R2 -R6.
  Now consider what happens when the computer tries to read the keyboard. When the joystick is not being used it is important that the keyboard functions normally, and it is the function of ICI b to detect whether or not the joystick is being used. When the joystick is not being used,
IC1b has all zero inputs and so gives a 1 output. D1 and R1 are included because IC1b has only five inputs while the joystick has six outputs; D1 and R1 form a hardware OR gate, thereby reducing the number of inputs to the ICI b. So, when the CPU tried to read the keyboard IORQ is 0 and WE is at 1; this, combined with the 1 from IC1b, gives a 0 on IC2a which gives a 1 at the output of IC2b. This takes the BUF line to 0 and the buffers are not selected, allowing the keyboard to be read normally.
  When the joystick is being used, at least one of the inputs to IC1b is high and so its output is low, and this gives a 1 at the output of IC2a. Now, because WE is 1 during a keyboard read Y1 is connected to 1B and hence is at logic 0. Thus all the inputs to IC1 a are 0 and so its output is at logic 1. Then the two 1 inputs at IC2b give a 0 output, selecting the memory, IC6. And, since IC2c is outputting a 0, BUF . is at logic 1 and the output from the

Hobby Electronics August 1983 page 15
Figure 4. The component layout shown over the double-sided PCB patterns (the component-side tracks are in red). The Controller PCB plugs into a motherboard which carries the correct edge connector for whichever computer is being used. The Spectrum motherboard (not shown) also carries a 5V regulator circuit.
Parts List

R1 - R6 ....................... 470R

C1 - C7 ....................... 100n
disc ceramic

C8, C9 ....................... 22u 16V
radial electro

IC1 ............ 74LS260
dual 5-in NOR

IC2 ....................... 74LS00
quad 2-in NAND

IC3, 4 ....................... 74LS157
quad 2-in selector

IC5 ....................... 74LS148
8-into-3 decoder

IC6 ....................... 6116
2K x 8-bit CMOS static RAM

IC7 ....................... 74LS365
hex tri-state buffer

IC8 ....................... 7805
+5V regulator

PCB; motherboard, wire, solder etc.
memory is buffered onto the data lines, overwriting the keyboard data.

The interface is built on two double sided PCBs. The main board plugs vertically into a smaller motherboard, which plugs into the edge connector; the main board is the same for the ZX81, Spectrum and Jupiter Ace, while the three motherboard's are different. The ZX81 and Ace motherboard's provide their own edge connectors so that RAMpacks may be plugged on, while the Spectrum motherboard has its own power supply — this is needed because the 48K Spectrum cannot supply enough current for the joystick interface. The interface actually needs very little power, but even the little that it does draw would be enough to make the Spectrum unreliable if the extra supply were not provided.
  Construction of the main board is relatively easy but take care with the 6116 memory. Since it is a CMOS IC it can be damaged quite easily by static charges. It has internal protection diodes which are effective up to about 4,000V, but since you can quite easily generate over 10,000V simply by walking on a nylon
carpet you can destroy it simply by touching the pins! To avoid damage make sure that you don't remove the chip from its protective conductive foam until you are ready to use it, and earth yourself (eg by touching a water tap) before handling it.

When you have finished building the main board, plug it into the motherboard, plug the motherboard onto the computer edge connector and plug the joystick into the DIN socket in the main board. Now switch on the computer — it should behave normally. Now move the joystick into the UP position and try the keyboard. The keyboard should be completely inoperative, since it is being overruled by the joystick. Test the other joystick positions to make sure that the keyboard remains inoperative.

Consider the BASIC program given in Program 1 written for the Spectrum. It is a much simplified version of the complete joystick program, but it clearly demonstrates the ideas involved.
  The program first accepts an

Hobby Electronics August 1983 page 16
input, number between 1 and 6, corresponding to the joystick position which is to be programmed — 1 corresponds to UP, 2 to DOWN, 3 to LEFT, 4 to RIGHT, 5 to FIRE 1, and 6 to FIRE 2. It then asks you to press a key, so that when the joystick is moved into the appropriate position it will be as though that key has been pressed. Say, for instance, that you enter 1 for the joystick position and then press "Q." for the key. Then, whenever the joystick is moved into the up position, the computer will believe that "Q" has been pressed.
  Line 40 simply waits for you to press the key before entering the next section, a FOR/NEXT loop which reads the keyboard and then transfers the data to the joystick memory. The variable N counts through each row of the keyboard in turn; let's consider the case where J = 1 and it is the first time through the loop, when N = 8. Then the address, A in line 60 is equal to 65280 - 2^J + 2, which in binary is 1,111 1110 0000 0010. This address has A0 = 0, which it must have for a keyboard read, and in addition the higher address lines (A8 to A15) are set to read the row SHIFT to V on the keyboard (see Figure 1 again!). So, in line 70, "IN A" reads this line on the keyboard and "OUT A" transfers this to the joystick memory — and puts it into the memory location which has A1 = 1. So later,

10 INPUT "Which joystick
position?", J
20 PAUSE 50
30 PRINT "Press the key corresponding to this position —
and keep your finger on the key"
50 For N = 8 TO 15
60 LET A = 65280 - 2^N + 2^J
70 OUT A, IN A
90 CLS
100 PRINT "Now take your finger off the key"
110 IF INKEYS<> "" THEN GOTO 100
120 CLS
130 GOTO 10

when the computer tries to read this line of the keyboard and the joystick is in the up position, Al will again be 1 (since it is coming from the joystick) and the joystick memory will output the data that had been transferred to it during the OUT operation. The counter N scans through the entire keyboard, making each of the address lines A8 to A15 low in turn, and transferring the keyboard data to the joystick. The overall result is that the joystick saves a copy of the keyboard which it will later output when the joystick is moved into the appropriate position.
  This program seems to do
everything we require, but it does suffer from two faults. The first problem is simply that it won't work with the BREAK key; as soon as this key is pressed the Sinclair BASIC monitor breaks out of the program and data is not transferred to the joystick. The only solution is to write the program in machine code, where it is safe from the BASIC monitor. The second problem is more difficult to cure. It arises whenever two or more functions are used on the joystick at the same time, for example when the joystick is moved into the UP position. and FIRE button 1 is pressed. This sends both Al and A5 high at the same time, but since the memory location this corresponds to has not been programmed, the joystick will not work. The answer is to rewrite the simple program, making it into two parts; the first part reads the keyboard, line by line, and saves the data for the second part which transfers the data to the joystick, filling up every memory location with the appropriate data. The software tape which is being supplied with the Joystick kit (see Buylines for details) actually contains three complete programs, one each for the ZX81, Spectrum and Ace. They are all very easy to use and are able to remember which keys are used by which programs, so you need only program the Joystick once for each game.