Parallel port documentation for IBM PC compatibles is inconsistent. Most sources quote other sources, and little information is based on first-hand experience. This is meant to remedy this shortfall.
The parallel port outputs TTL-level logic signals, although in many modern computers, the signal levels are much closer to 5 volts than ordinary TTL circuits generate. This is no cause for alarm.
There are three basic types of parallel ports: standard, EPP and ECP. My personal experience so far has only been with the standard parallel port, although I may be able to provide some EPP data in the future. The difference is that the standard port provides eleven outputs and five inputs (a state which caters towards output-only devices such as parallel printers), where the enhanced parallel ports (EPP) provide an eight-bit wide bidirectional data path, plus some enhancements associated with bidirectional communication. The ECP is in a class of its own, providing protocols for multiple devices, ultra-fast and efficient transmission with compression, et cetra.
The connector on the back of the computer is a male 25 pin job. You need a female 25 pin connector to interface. You can use an IDC connector (crimps onto ribbon cable), or you can be sensible and get some wire and solder it to a DB-25F connector (<$3 at Radio Shack). I find that UTP wire (4 twisted pairs, approx. 28 gauge) works nicely. You will need several doubled lengths, fastened at regular intervals.
| Pins on DB-25 on computer side | |||
| Pin # | Function | Direction | Inverted |
|---|---|---|---|
| 1 | *Strobe | out | yes |
| 2 | Bit 0 | out | no |
| 3 | Bit 1 | out | no |
| 4 | Bit 2 | out | no |
| 5 | Bit 3 | out | no |
| 6 | Bit 4 | out | no |
| 7 | Bit 5 | out | no |
| 8 | Bit 6 | out | no |
| 9 | Bit 7 | out | no |
| 10 | *Ack | in | no |
| 11 | Busy | in | yes |
| 12 | PE | in | no |
| 13 | Select | in | no |
| 14 | *AutoFd | out | yes |
| 15 | *Error | in | no |
| 16 | *Init | out | no |
| 17 | *Select | out | yes |
| 18-25 | Ground | ||
These pins have special meaning if you are planning to use the port through special interfaces such as the BIOS or your OS's printer devices. Usually, one uses direct port output and ignores the services tailored to printer-type devices (unless, of course, you are building a printer-like device).
In the names above, a leading asterisk denotes a signal which the printer interprets as "active low".
In case you're interested, here are the meanings of the signal names. "*Strobe" is the signal which indicates to the printer that the data is valid. "*Ack" is acknowledge, "Busy" is obvious, "PE" indicates a "paper empty" condition, "Select" (the incoming signal) would normally mirror the "online" light on a printer, indicating that the printer is ready, "*Select" goes high to prevent a printer from acting on data, but printers usually have a dip switch to override this signal. "*AutoFd" has to do with whether a line feed is added after a carriage return, "*Fault" indicates a general error, "*Error" is obvious, and "*Init" resets the printer.
Port address assignments are a bit unusual. The BIOS searches in a predetermined order, and assigns numbers (in the range 0-2 in a usual setup) only to ports which exist. Restated, if you have a port at 0x3BC and a port at 0x278, they are numbered 0 and 1 respectively, regardless of the fact that there is no port at 0x378 (which is usually assigned 0 or 1, depending on the existence of a port at address 0x3BC). DOS device names are formed by appending the BIOS number, plus one, to "LPT". LPT1 is also designated "PRN" for convenience.
The rationale is this: address 0x3BC is reserved for parallel ports integrated into the motherboard or on a display adapter (usually only on obselete ones such as the Hercules Graphics Card or IBM's veritable Monochrome Display Adapter). Multifunction add-on boards usually use the next two sets of addresses.
If you program for an operating system which allows access to the BIOS data tables (ie DOS, or a DOS emulator), you can examine memory at segment 0x40, offsets 0x8, 0xA and 0xC, which are hex words with the base port addresses of BIOS printers numbers 0, 1 and 2 respectively.
| Port numbers | IRQ |
|---|---|
| 0x3BC-0x3BE | ? |
| 0x378-0x37A | 7 |
| 0x278-0x27A | 5 |
To test if the port exists, write a zero to the first address given. If it returns zero, you might have a parallel port. If it returns anything else, you either don't have a parallel port at that address, or it is too broken to use. A hex value of "FF" usually means that you've got a wrong number and nobody lives there. This is because the TTL buffers used on the address busses interpret a lack of a device as a "high" value (hence 0xFF, or all high bits).
These are the pins controlled by the three port locations. The "base" value is the first port listed in the list above.
| Dir. | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
|---|---|---|---|---|---|---|---|---|---|
| base+0 | out | p.9 | p.8 | p.7 | p.6 | p.5 | p.4 | p.3 | p.2 |
| base+1 | in | p.11 | p.10 | p.12 | p.13 | p.15 | n/c | n/c | n/c |
| base+2 | out | n/c | n/c | n/c | I.E. | p.17 | p.16 | p.14 | p.1 |
| value | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Where "n/c" stands for "no connection" and "I.E." stands for "interrupt enable". The interrupt occurs on the negative-going transition of the *Ack pin if bit 5 of (base+2) is on. The interrupt number is the IRQ number plus 8, and the IRQ is listed in the table above.
When you read from (base+0), you get either zero or what you wrote before, depending on the port. When you read from (base+2), you usually get what you wrote before. In any case, the output bits are all latched, and the input bits are not debounced. To keep track of the status of the output ports, keep their values in global variables in your program. This way, you do not need to read the ports (which might return zero on some machines) to find what has been latched at the outputs.
Here are some miscellaneous points to keep in mind.
/dev/port device in Linux.
/dev/port or other such silliness. I no
longer use a PC as my primary desktop machine, so I have
not tried this library myself. YMMV.
The EPP uses eight control ports as opposed to the three ports used by standard parallel ports. The first three are the same as those used by the standard port, and the next is used as an address port to send a device address out over the port. The next four ports can be written to as a double-word, word or byte port, and the port's driver chip sends four, two or one bytes with corresponding strobe signals. This allows for much faster transfer than if the program must manually pulse *Strobe low then high after every character. Unfortunately, there is very little documentation available for this version. Maybe next time.