Parody's Parodies  Sluggy Freelance  Commodore 8-bits  Personal Info

Joystick Port Networking

...or at least a bunch of musings while watching an LED turn on and off at my command while the LED is sitting in a Radio Shack box connected to my joystick port...

**WARNING: I don't have all the original stuff for this anymore; too many moves have caused it to disappear on me. I also don't have the box anymore, so I can't test this right offhand. Plus I don't remember how much current you can slap through a CIA chip. Hopefully it will be helpful, but if your Commodore fries messing around with this, I will not be responsible. I didn't fry my Commie doing this, so you probably won't have any trouble.

This text is copyright (C)1996 Michael Jay Miller. You may freely distribute, print, etc. this text, so long as this message remains intact. If you make something useful out of this information, and you're releasing it for free, please credit me; if you are using this information for a commercial product, I would appreciate credit in the documentation and one copy of the product.

The basic theory behind using the joystick ports lies in the 6526 CIA 1/A chip that controls the keyboard, joystick ports, and is used for tape and serial timing. For my simple tests, only 4 memory locations in that chip's registers are actually used: $DC00-$DC03 (56320-56323).

If you have the book "Programming the Commodore 64" by Raeto Colin West, open to page 125 for a nice diagram of how the CIA looks in memory. If not, open to pages 328 & 329 of your Commodore 64 Programmer's Reference Guide. Here's a quick summary:

$DC00 is Joystick Port 2  ("CIA Port A")
$DC01 is Joystick Port 1  ("CIA Port B")
Bit 4=Fire, Bit 3=E/Right, Bit 2=W/Left, Bit 1=S/Down, Bit 0=N/Up

$DC02 is "Port A Data Direction Register"
$DC03 is "Port B Data Direction Register"

To read bits coming in (for a joystick, for example), you set the bits you want to read to 0 in the appropriate Data Direction Register, and then read the appropriate bits in the Port.

The practical upshot of all this: if you disable the interrupts (because the keyboard runs off this as well), reset the Data Direction Registers to how you want to read or write, and then put the right bits into the two ports, whatever is connected to the other side can read or write to this. This may be easier to see with an example:

"The Box, Mark 1"

Parts: 1 joystick extension cable (or end from a broken joystick), 1 project box, 1 or more LEDs, 1 or more switches, one of those speaker-wire clip 8-packs (the things you can clip wires into), and connection methods (clip leads, solder, etc.) + a monitor and assembler.

In the Commodore 64 Programmer's Reference Guide, page 395, they show the pinout for the two joystick ports. Something like this:

-------------------------    1=Bit 0    7=5 volt
!   o   o   o   o   o   !    2=Bit 1    8=GND
 !  1   2   3   4   5  !     3=Bit 2
  !   o   o   o   o   !      4=Bit 3    5=POT Y
   !  6   7   8   9  !       6=Bit 5    9=POT X
   ------------------- 

What you want to do is wire up pins 1-4 to 4 ends of the speaker wire things, pin 7 to one of the speaker wire things, pin 8 to one of them, and maybe wire a couple switches in as well. Hook up an LED between pins 7 and 8: plug it in a joystick port, and turn on the computer. Hopefully it lights. If not, turn the LED around, check connections, etc. Once you know which way the LED works, remember which pin goes to 7 and which goes to 8; these remain the same throughout the experiments.

Once you know which way to plug in your LED, hook it between pins 0 and 8. Turn the computer off, plug it into Joystick Port 2, and turn it back on. It should light up, since port 2 is set to all outputs, and the system is constantly looking for input there. Then try hooking it up to pins 7 and 0, and plugging it into port 1. It should light up as well. Either of these may cause characters to run across the screen, just like if you were holding up on the joystick in the appropriate port.

Now try hooking up a few LEDs to pins 1-4 and 8. For sake of example, I'll work with pins 1 and 2. Hook your box to port 1, and turn on the computer. The LEDs should be off. Now load up your favorite monitor (or assembler, I guess) and type in this:

A C000 sei       ; disable keyboard
lda #0           ; initialize
sta $DC01        ; joyport 1
sta $DC03        ; and its DDR : 4321 pins
lda #07          ; that's   0000 1111=bits 0-3, pins 1-4 outputs
sta $DC03        ; that's DDR B, setting pins 1-4 to output
lda #01          ; pin 1 on
sta $DC01        ; and get it going
here jmp here    ; here is the address your monitor gave for this line.
G C000

Hopefully the LED turned on and the computer seems to lock up. Press RESTORE a few times to get back to the monitor (at least, my monitor does that.) By editing the line

lda #01          ; pin 1 on

to anything from 0 to 15, you can control the lights via their appropriate bits. Have fun.

By changing the LEDs to being hooked between pins 7 and 1-4, with a switch wired in, and a nice BASIC program, you can read the status (just like a joystick). Page 344 of the Programmer's Reference Guide has a program you can adapt: just get rid of all the stuff about North and South and just PRINT the value in 56320 (port 2) or 56321 (port 1). Push the switch, the value should change. Yay!

Now, hook an LED between pins 1 and 2. Put the voltage side (pin 7) on pin 1. Get back into your monitor, and try this:

A C000
sei
lda #00     ; init
sta $DC01
sta $DC03
lda #01     ; output for pin 1, input for pin 2
sta $DC03
sta $DC01   ; activate
nop         ; pause
nop
nop
nop
nop
lda $DC01   ; read
sta $FE     ; temp
lda $00     ; reset
sta $DC03   ; normally all reads
cli         ; back to normal
lda $FE     ; reload acc
brk         ; exit to monitor
G C000

Hopefully, the accumulator now holds $03. The pause may take longer, or may not be needed (my notes don't indicate). By setting the appropriate bits, you can now read and write through the port. If you have two boxes, you can read and write between joystick ports (much safer). "But," you ask, "I can't do much in the way of input..." Well, that's why you need:

"The Box, Mark 2"

Parts: "The Box, Mark 1", Other end of joystick extension cable or similar 9-pin Male port, 1351 mouse or compatible, good ML skills.

Remember we didn't use pin 6/bit 5, the fire button? This is why: if you wire in an extra joystick port with pins 5-9 attached, you can hook a 1351 up to it and read that from the SID chip, with the fire button running from pin 6 (bit 5) on the CIA. You don't want to hook up pins 1-4 because the other fire buttons run off there.

Also, you want to make sure you set the CIA appropriately: $DC00 bits 7 and 6 control which paddle you're reading:

10xx xxxx = Paddles in Joyport 1
01xx xxxx = Paddles in Joyport 2

I'm sorry I don't have much in the way of specific examples for this, because this is where I stopped doing things and just wrote down ideas. If I can find that box again, I should be able to do a full-blown writeup for C=Hacking or something.

A MikeNet Cable

To set up an actual cable to hook between two Commies and still allow one of them to use a mouse (for, say, selecting files from an on-screen directory list and menu?), you want to hook lines 1-4 direct connect, and pins 5-9 to pins 5-9 of a male 9-pin port or cable to hook to your 1351-compatible.

File transfer

The direct-connect file transfer protocol I had in mind would use pins 1 and 2 to send 2 bits at a time, pin 3 for a RDY line from the sending machine, and pin 4 for an ACK line from the receiving machine. Basically, the RDY line would change level when the sending computer had the appropriate bits on pins 1 and 2, and the ACK line would change every time the receiving computer got it. Or something like that. Or do like Craig Bruce and junk all that kind of ACKing for speed. Whatever.

Network setup

I had two basic ideas for network setups, a Ring style (not too great) and a Server style (cool, but requires lots of hardware).

RingNet

Each computer would be hooked from their joyport 2 to the next computer's joyport 1. One machine is designated "Master". This machine would send "I'm number 1, you're a Slave, take the next number and pass it along" until the Master received something like "I'm number 8, you're a Slave, take the next number and pass it along". Of course, the Master knows it isn't a Slave. Then it sends out something like "There's 8 computers in the ring. We're open for business."

Then, each computer can pass messages to each computer by number, and if you get a message that isn't your number, you pass it along. The master computer double-checks that the ring is working, and resets it if necessary.

How can the computer keep working? Well, Craig Bruce has that 3-key rollover routine that also checks to see if the joystick ports are being used: if so, just trigger a routine to handle the message, pass it along if necessary, then clear the ports and continue. That's why I designated an RDY line: if that's up, the previous computer has a message to send.

As long as the messages aren't sent very often, the system shouldn't slow down too much, and you may even be able to do other things in the meantime. Or you could go to where I got the idea from, the Atari ST program MIDIMaze, and write a fun game like that. Of course, you have to use the mouse to control it, but something could be arranged.

Server Setup

With a server, my design has a box hooked between the server and the other systems in the network. This box has its own processor (it might be a 64 only running this program) that has lines running to each system. Data pins 1 and 2 are hooked up to all systems and the box. Each system gets its own RDY and ACK line (from somewhere!) The server and the box have a standard 1/2/RDY/ACK that the box echos to the appropriate system. Each system has a number; the server is 0.

Basically, when a system has a request for the server, it raises its ACK line; when the box and server are ready to process, the box raises the RDY line for that system, and then they transfer messages. If the system is sending a message to another system (like talk or ping in unix) the box handles sending that along. Otherwise, the box calls up the server, and sends messages to there to be handled.

The messages would be queued, to avoid deadlocks--whenever a system is sending a message, the box would check to see if that system had any messages it needs to receive, and send them.

That's basically all I have right now...feel free to comment on this, send me messages, design better systems, etc.


Back to Commodore Information