Reading Color Computer Joysticks

In the CoCo 1 and 2, the joysticks are read by looking at the single bit output of a comparator; one input to that comparator is one of the joystick values, the other is the output of a digital-to-analog (D/A) converter under software control. When the selected joystick value exceeds the output of the D/A converter, the comparator outputs a one, any other time, if outputs a zero. So the joystick value itself isn't just sitting in memory anywhere; you have to select which joystick to use as input to the comparator, vary the input to the D/A converter, and then check the output of the comparator to see when it changes from a one to a zero or visa-versa.

The input to the D/A is the most-significant 6 bits at address $FF20; write $FC to that address to set the analog value as high as it will go. The comparator output can be read as the most-significant bit at address $FF00; when it's a one, the joystick value is higher than the D/A output.

Note that the remaining bits at those addresses are used for other things: $FF20 also has a bit going to the serial port output, and a bit coming in from the cassette port; while the rest of $FF00 is input from the keyboard matrix and joystick fire-buttons. So you should strip out the bits you need by doing the appropriate ANDs. Ignoring extraneous input bits causes no problem, and (in this case) setting the remaining output bits to zero should be okay. (Though you might want to leave the serial output line high; for that, just OR in $02 before writing the D/A value).

To select which joystick value gets compared (ie: left or right, and X or Y axis), you have to control a pair of special PIA outputs; CA2 and CB2. Each of the four possible values of these bits selects a different joystick line to compare. These are controlled by writing to the PIA control registers, which is a little complicated because they also control a bunch of other things. The control registers you want are at addresses $FF01 (for CA2) and $FF03 (for CB2). For each address, I *think* you want to write the value $3F to set the output to a one, and $37 to set it to zero. These settings enable interrupts that (I think) the CoCo normally uses, and triggers them on the rising edge of the input signals, which I also think is the normal setting. If these are wrong, please let me know!

Another possibility is that the PIA control registers might be readable. In that case, you would just want to read the control register, mask out the bits controlling the select line by ANDing against $C7, and the fill in the new control values for those bits by ORing against $38 (for high output) or against $30 (for low).

Of course, the easiest way to do this is from BASIC is with the JOYSTK(I) function, where I is a joystick axis number. There are four axes you might want to read: each of the two joysticks has a left-right axis and an up-down axis.

The second easiest way is to call a ROM routine which will read all four joystick values and leave them sitting in memory. This routine lives in the Color BASIC ROM at address $A00A, and leaves its results in the four bytes at addresses $015A through $015D.

More information on these "easy" ways can be found on my Color Basic Summary web page.

Back to my top-level CoCo page

(remove all "x"s to get a valid address)