Am sure this has been done 100 times before, but I've recently acquired two relic computers and I want them to control my trains. They both have ports consisting of 8 digital I/O pins and I'll utilise these to control a throttle, direction and points. I'll also use them to read sensors.
Having only 8 pins provides a nice challenge... but nothing a few shift registers cannot handle!
First step, LEDs
Let's get started very simply by switching a LED on and off. One might think that, as that LEDs are synonymous with digital electronics, that one can just hook it up to a digital pin and set the output to HIGH. One could... but the current draw would likely kill the 'controller' that the parallel port relies on!
Due to this, you must make sure that you provide sufficient safeguards to prevent damage to your delicate hardware. Once you trash a parallel port in a system (especially of this vintage), you cannot go back.
The trick we'll use is known as opto-coupling or opto-isolation. The goal is to use ICs that have both a LED and a light sensor inside them. When you trigger a HIGH state on the LED side, the light sensor is activated and the associated HIGH state is seen on the output side.
This effectively isolates the electrical circuits and prevents any unweildly voltages on the 'peripheral' side from trashing your valuable hardware.
Thanks to Ian Stedman, we can use the circuit he has provided to hook up LEDs and opto-couplers.
The Amiga port provides a lower current than most PC Parallel ports, so we'll use it as the lowest denominator when creating this circuit so that we can use this hardware across multiple platforms.
(Excuse the paint-brush infancy!)
A 74HC7404 Hex Inverter is used to 'sink' the current used by the LED or Opto-coupler. This IC is much more capable of handling the current and will link the GND wires together internally rather than sending the GND signal back through the parallel port to be linked inside the Amiga (or other device that you've plugged this in to.) This provides a secondary level of protection.
The circuit was built on a crappy prototype board; I seem to have misplaced my breadboard. I used ribbon cable and a standard DB-25 male printer port plug. I've left room for future expansion. I had some spare RGB leds, so the red light is showing that 5v is available and green indicates a 'LOW' output from D0 (or pin 2 of the parallel port.)
Controlling it via code
This sample provides a compiled version of 'Pario' which is a C program to test the parallel port on the Amiga. This code is for the console, so extract it and then run the PARIO/PARcode binary.
Excuse the quality of the photos... haven't learnt how to take screen captures on the Amiga and photographing an LCD TV isn't easy.
Either way, once the program is loaded you'll get a list of options... Press 1 then enter then set the ports to output. Then Press 2 and enter either FF or 00. This is a blanket 'all on' or 'all off' for the 8 data pins.
Doing this made my LED successfully light up and turn off! Winner!
Cross-platform: PC test on Windows 7
This wasn't fun. First I had to re-image my Lenovo X61 as it had a huge amount of spyware on it after lending it to a friend. Then I had to make LPT1 work. Device Manager indicated that all was swell, but the sample code from Code Project just didn't work. On reboot, the green LED would flicker, so I knew that the port was live and communicating.
I dug deeper and tried a second example, using TVicPort, but this also didn't work. I went into the BIOS and found the port disabled!?! Why did Windows tell me it was fine?
After enabling it, there was still no dice. I dug through the sample code and it all seemed to set the port into ECP mode. Was this the same as "bi-directional" which was the default setting in the BIOS? Had no clue.. so back into the BIOS where this could be changed to ECP. Had to be it!
And blam! It works. Hitting D0 on the first sample app works a treat!
Cross-platform: Making this work from the Commodore 64!
With the hardware hooked up, I ran the following sample to control the LEDs. A thanks to Coronax for the initial example.
Originally the code was to test all values up to 255, or 11111111b. We only need to test the first three pins in our case, so going to 7 (or 111b) will iterate through the values as expected.
Line 20 sets the magical address 56579 to 11111111b. This means that all 8 pins are '1' or 'output'. 56577 is then the I/O for the port and setting a 0 or a 1 provides a digital LOW or HIGH respectively.
10 PRINT "USER PORT EXAMPLE" 20 POKE 56579, 255 30 FOR I = 0 TO 7 40 POKE 56577, I 50 FOR J = 1 TO 150: NEXT J 60 NEXT I 70 GOTO 30
Does it work? Yes... Check out more on coding the User Port here.
Next is a shift register... with the ultimate goal being a minimal-pin-usage 12v throttle for the railway. Stay Tuned.