by Zhahai Stewart
parport@hisys.com
plain ASCII version at ftp://ftp.rmii.com/pub2/hisys/parport
Addr MDPA no MDPA 0x3BC LPT1 n/a Monochrome Display and Printer Adapter (MDPA) 0x378 LPT2 LPT1 Primary Printer Adapter 0x278 LPT3 LPT2 Secondary Printer Adapter Name MDPA no MDPA LPT1 0x3BC 0x378 LPT2 0x378 0x278 LPT3 0x278 n/a
Port R/W IOAddr Bits Function
---------- ------ ----- ----------------
Data Out W Base+0 D0-D7 8 LS TTL outputs
Status In R Base+1 S3-S7 5 LS TTL inputs
Control Out W Base+2 C0-C3 4 TTL Open Collector outputs
" " " C4 internal, IRQ enable
" " " C5 internal, Tristate data [PS/2]
Data Feedback R Base+0 D0-D7 matches Data Out
Control Feedbk R Base+2 C0-C3 matches Control Out
" " " C4 internal, IRQ enable readback
The Feedback registers are for diagnostic purposes (except in bidirectional
ports, where Data Feedback is used for data input; and the IRQ enable C4).
<= in DB25 Cent Name of Reg
=> out pin pin Signal Bit Function Notes
------ ---- ---- -------- --- -----------------------------
=> 1 1 -Strobe C0- Set Low pulse >0.5 us to send
=> 2 2 Data 0 D0 Set to least significant data
=> 3 3 Data 1 D1 ...
=> 4 4 Data 2 D2 ...
=> 5 5 Data 3 D3 ...
=> 6 6 Data 4 D4 ...
=> 7 7 Data 5 D5 ...
=> 8 8 Data 6 D6 ...
=> 9 9 Data 7 D7 Set to most significant data
<= 10 10 -Ack S6+ IRQ Low Pulse ~ 5 uS, after accept
<= 11 11 +Busy S7- High for Busy/Offline/Error
<= 12 12 +PaperEnd S5+ High for out of paper
<= 13 13 +SelectIn S4+ High for printer selected
=> 14 14 -AutoFd C1- Set Low to autofeed one line
<= 15 32 -Error S3+ Low for Error/Offline/PaperEnd
=> 16 31 -Init C2+ Set Low pulse > 50uS to init
=> 17 36 -Select C3- Set Low to select printer
== 18-25 19-30, Ground
33,17,16
Note: Some cables, ports, or connectors may not connect all grounds.
Centronics pins 19-30 and 33 are "twisted pair return" grounds, while
17 is "chassis ground" and 16 is "logic ground".
"<= In" and "=> Out" are defined from the viewpoint of the PC, not the
printer. The IRQ line (-Ack/S6+) is positive edge triggered, but only
enabled if C4 is 1.
Here's the same data grouped for ease of reference by Control Out and Status
In registers and pins. (Data Out is straightforward in previous table).
<= in DB25 Cent Name of Reg => out pin pin Signal Bit Function Notes ------ ---- ---- -------- --- ------------------------------ => 17 36 -Select C3- Set Low to select printer => 16 31 -Init C2+ Set Low pulse > 50uS to init => 14 14 -AutoFd C1- Set Low to autofeed one line => 1 1 -Strobe C0- Set Low pulse > 0.5 us to send <= 11 11 +Busy S7- High for Busy/Offline/Error <= 10 10 -Ack S6+ IRQ Low Pulse ~ 5 uS, after accept <= 12 12 +PaperEnd S5+ High for out of paper <= 13 13 +SelectIn S4+ High for printer selected <= 15 32 -Error S3+ Low for Error/Offline/PaperEnd
Wait for not +Busy (+Busy low)
Set Data Out bits
at least 0.5 uS delay
Pulse -Strobe low for at least 0.5 uS
hold Data Out for at least 0.5 uS after end of -Strobe pulse
Some time later, printer will pulse -Ack low for at least 5 uS
Printer may lower +Busy when it raises -Ack at end of pulse
Set other Control outputs or check Status inputs as desired.
AH = 0: print the character in AL AH = 1: reinitialize the port, return status in AH AH = 2: return status in AHBIOS operation notes follow.
The BIOS normally keeps the Control register value as 0x0C:
C5 = 0 => output enabled (for bidirectional only)
C4 = 0 => IRQ disabled
C3 = 1 => -Select pin low (Printer Selected)
C2 = 1 => -Init pin high (Printer not being initialized)
C1 = 0 => -AutoFeed pin high (No Auto Feed)
C0 = 0 => -Strobe pin high (No Stobe)
The BIOS prints a character (function AH = 0) as follows:__________________________________ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | | | | | not used |___ 1 = "Time Out" (software) | | | | |________________ 1 = "I/O Error" (inv C3+; -Error pin low) | | | |____________________ 1 = "Selected" (C4+; +SelectIn pin high) | | |________________________ 1 = "Paper Out" (C5+; +PaperEnd pin high) | |____________________________ 1 = "Acknowledge" (inv C6+; -Ack pin low) |________________________________ 1 = "Not Busy" (C7-; +Busy pin low)The high 5 bits of this are essentially the Status In register from the printer port, with bits 6 and 3 inverted (ie: XORed with 0x48). The low bit is generated by BIOS software after a timeout. In the original PC, timeout delays were generated by delay loops.
Different Parallel Ports on NSC Parts -------------------------------------------------------- PC87311 Bidirectional Parallel Port (16450 UARTS) PC87312 Bidirectional Parallel Port (16550 UARTS) PC87322 Enhanced Parallel Port (EPP) (16550 UARTS)* PC87332 Enhanced Capabilities Port (ECP) also EPP 1.7 and 1.9 (16550 UARTS)* *Floppy controller signals can be redirected out the parallel port pins via an internal multiplexor. This feature is used in some sub-notebooks with external floppy drives
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D0 2 => 15 S3+ direct
D1 3 => 13 S4+ direct
D2 4 => 12 S5+ direct
D3 5 => 10 S6+ direct
D4 6 => 11 S7- inverted
S7- 11 <= 6 D4 inverted
S6+ 10 <= 5 D3 direct
S5+ 12 <= 4 D2 direct
S4+ 13 <= 3 D1 direct
S3+ 15 <= 2 D0 direct
Gnd 25 === 25 Gnd (ground)
Mode 1B: nibble mode, using Data Out to Status In connection
This version works with all parallel ports; bit positions matched.
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D3 5 => 15 S3+ direct
D4 6 => 13 S4+ direct
D5 7 => 12 S5+ direct
D6 8 => 10 S6+ direct
D7 9 => 11 S7- inverted
S7- 11 <= 9 D7 inverted
S6+ 10 <= 8 D6 direct
S5+ 12 <= 7 D5 direct
S4+ 13 <= 6 D4 direct
S3+ 15 <= 5 D3 direct
Gnd 25 === 25 Gnd (ground)
Mode 1C: nibble mode, using Data Out to Status In connection; Controls wired
for additional interfaces. This version works with all parallel ports.
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D3 5 => 15 S3+ direct
D4 6 => 13 S4+ direct
D5 7 => 12 S5+ direct
D6 8 => 10 S6+ direct
D7 9 => 11 S7- inverted
S7- 11 <= 9 D7 inverted
S6+ 10 <= 8 D6 direct
S5+ 12 <= 7 D5 direct
S4+ 13 <= 6 D4 direct
S3+ 15 <= 5 D3 direct
C0- 1 <=>* 1 C0- direct
C1- 14 <=>* 14 C1- direct
C2+ 16 <=>* 16 C2+ direct
C3- 17 <=>* 17 C3- direct
Gnd 25 === 25 Gnd (ground)
* Note: Control Out bits on receiver set high (including inversion, ie:
C0,C1,C3=0; C2=1). Control feedback on receiver can read control out from
sender. Can use some lines each way, and could switch C0 - C2 and C1 - C3
for symmetry if we want two lines each way, or other variations.
Mode 2: 8 bits, using bidirectional parallel port
This version works only with bidirectional parallel port whose Data Out
can be tristated; the receiving side must tristate its Data Out port to
use its feedback register as an 8 bit input port.
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D0 2 <=>* 2 D0 direct
D1 3 <=>* 3 D1 direct
D2 4 <=>* 4 D2 direct
D3 5 <=>* 5 D3 direct
D4 6 <=>* 6 D4 direct
D5 7 <=>* 7 D5 direct
D6 8 <=>* 8 D6 direct
D7 9 <=>* 9 D7 direct
C0- 1 => 13 S4+ inverted
C1- 14 => 12 S5+ inverted
C2+ 16 => 10 S6+ direct
C3- 17 => 11 S7- direct
S4+ 13 <= 1 C0- inverted
S5+ 12 <= 14 C1- inverted
S6+ 10 <= 16 C2+ direct
S7- 11 <= 17 C3- direct
Gnd 25 === 25 Gnd (ground)
* Note: bidirectional cards only; receiving side must tri-state with C5=1
If a two bidirectional ports are left connected in this fashion, and they
are both enabled (eg: after powerup or reset) with different data outputs,
then the 74LS374 driver chips could be "fighting". Just to be careful,
when I created a cable like this (actually, a DB25 jumper box usually sold
for RS-232 jumpering, along with straight through 25 line DB-25 cables), I
used 8 10K resistors between the corresponding Data lines, to limit current
in this case. (Actually, a DIP resistor pack fit perfectly on the PC board
inside the DB-25 jumper box). The resistors are large enough to keep TTL
output from overstressing another one if both enabled, but when one is
disabled and the other enabled, the resistors are low enough to allow the
TTL output to drive a TTL input well enough.
Mode 3A: 8 bits, using Open Collector Control Outputs as inputs
This version uses 4 control outputs as inputs, plus 4 status inputs.
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D0 2 =>* 1 C0- inverted
D1 3 =>* 14 C1- inverted
D2 4 =>* 16 C2+ direct
D3 5 =>* 17 C3- inverted
D4 6 => 13 S4+ direct
D5 7 => 12 S5+ direct
D6 8 => 10 S6+ direct
D7 9 => 11 S7- inverted
C0- 1 <=* 2 D0 inverted
C1- 14 <=* 3 D1 inverted
C2+ 16 <=* 4 D2 direct
C3- 17 <=* 5 D3 inverted
S4+ 13 <= 6 D4 direct
S5+ 12 <= 7 D5 direct
S6+ 10 <= 8 D6 direct
S7- 11 <= 9 D7 inverted
Gnd 25 === 25 Gnd (ground)
* Note: Control outputs used as inputs must be programmed high:
C0, C1, C3 = 0 and C2 = 1
Mode 3B: 8 bits, using Open Collector Control Outputs as inputs
This version uses 3 control outputs as inputs, plus 5 status inputs;
remaining control output is bidirectional - if left high by default,
either side can pull low (remember inverted logic).
Side 1 Pin dir Pin Side 2 connection
------ --- --- --- ------ ----------
D0 2 =>* 1 C0- inverted
D1 3 =>* 14 C1- inverted
D2 4 =>* 16 C2+ direct
D3 5 =>* 15 S3+ direct
D4 6 => 13 S4+ direct
D5 7 => 12 S5+ direct
D6 8 => 10 S6+ direct
D7 9 => 11 S7- inverted
C0- 1 <=* 2 D0 inverted
C1- 14 <=* 3 D1 inverted
C2+ 16 <=* 4 D2 direct
S3+ 15 <=* 5 D3 direct
S4+ 13 <= 6 D4 direct
S5+ 12 <= 7 D5 direct
S6+ 10 <= 8 D6 direct
S7- 11 <= 9 D7 inverted
C3- 17 <=> 17 C3- direct (OC shared)
Gnd 25 === 25 Gnd (ground)
* Note: Control outputs used as inputs must be programmed high:
C0, C1, C3 = 0 and C2 = 1
[A future version of this document may sketch out the code to send and
receive data through these connections]
Dn Out ------+
|+
Sourcing Load (up to 2.6 mA @ 2.4 v)
|-
Ground ------+
If you have an external +5 volt supply, you have two options: use the Data
Out pins to sink up to 24 mA from your +5 volt supply, or use buffer chips
to control (source or sink) more current (or higher voltages). I have
used an exteranl 5 Volt supply (regulated wall wart) plus optocoupled solid
state relays as the "load", to control AC voltages (keep the high AC voltages
away from any of this logic level stuff, obviously).
+------------------------------- (+5 v)
|+
Sinking Load (up to 24 mA @ 4.2v)
|- Power Supply
Dn Out ------+
Ground -------------------------------------- ( Gnd)
Use limiting resistors if you need to limit the current.
If the load were an LED (or optocoupler) through which you wished to put
20 mA, do the calculations. The Dn Output will probably be around 0.7
volts, so you have about 4.3 volts of drop; the LED will drop about 1.9 v
(check specs!), leaving 2.4 V to be dropped by a resister at 20 mA: 120
ohms. Test and measure, adjust to fit.
You can also use the Control Out pins. They can't source much of anything
(about 1 mA through the 4.7K resistors to +5), and can only sink about 7mA.
(The LS TTL gate actually sinks 8 mA, but one is taken up by the 4.7 K
resistor to +5). Again, check on clones with different electical specs.
This can control TTL inputs fine, and might be able to run an optocoupler
or solid state relay in sink mode (depends on the device).
In one application, I used two 74ACT374 latches, which can source 48 mA
or sink 64 mA. I connected the 8 inputs of each to the Data Out, and the
latch clocks to two Cn outputs. In software, I put out 8 bits of data
on the Data Out port, pulsed a Cn bit to latch it into one 74ACT374,
put the next 8 bits out on Data Out, and used the other Cn bit to latch it
into the other 74ACT374 - voila, 16 bits of 64mA output control. Of course,
this took a separate +5 V power supply ($5 surplus regulated wall wart).
If you can still find an old TTL parallel port (especially with sockets),
you can substitute the 74ACT374 chip for the original 74LS374 and get better
drive capability. The back of magazine suppliers were selling *fully
socketed* TTL based parallel ports for about $15 a few years back; by cutting
a trace and soldering a jumper you could make them bidirectional; by plugging
in a $1 chip you could make them source/sink 48/64 mA. You might still find
such TTL parallel port cards in old PCs. Typically, one designed for the
original PC will still work fine on the ISA bus of your 486DX2-66, so don't
worry about that.
Cn Out ------+ (Program output high; read feedback)
|
switch
|
Ground ------+
Another simple method would be to use up to 5 pullup resistors (4.7K) from
the Status inputs to +5 volts, and use switches to pull these down to ground.
One disadvantage of this is that it uses an external +5 supply. TTL inputs
tend somewhat to float high, so you *might* get by without the pullup
resistors, but you are pushing it.
4.7K
Sn In -------+-^^^^^--- (+5 v) (Read status register)
|
switch
|
Ground ------+---------- (gnd)
You could use this same scheme for 8 inputs on the data lines of a
bidirectional printer port - but you have to be sure that the outputs are
tristated beforehand, or your switches may damage the 74LS374 (or equiv).
This latter may be a problem after booting or rebooting. One approach
is to use current limiting resistors in series "just in case". You should
ideally still have pullup resistors too. (The 1K value is chosen for LS TTL,
to keep the 2.4 V output at no more than 2.4 mA sourcing).
1K 4.7K
Dn Out --------^^^^^-----+----^^^^^------ (+5v)
|
Switch
|
Ground ------------------+--------------- (Gnd)
10 K
S4 ------------X X X X--^^^^^--+--- (+5)
S5 ------------X X X X--^^^^^--+
S6 ------------X X X X--^^^^^--+ (these pullups optional?)
S7 ------------X X X X--^^^^^--+
| | | |
C3 ------------+ | | | Scan one Cn low at a time, read Sn each time
C2 --------------+ | |
C1 ----------------+ |
C0 ------------------+
Alternate scheme. Use Dn's for scanning output rows, through diodes which
will isolate them from each other if two keys in the same column are pressed.
(Otherwise we have drivers fighting, and indeterminate voltage levels).
Germanium small signal diodes have less voltage drop. Use the Cn pins
as inputs (with existing pullups) - program Control Out for high TTL levels,
and read the feedback register for input (counting inversions). No extra
power supply is needed. The diode between TTL output low and TTL input low
will push the TTL noise margins, but you can usually get by with it. This
scheme could be expanded up to 8x4 (8 Dn outputs, 4 Cn used as inputs). If
we know that only one key (or one key per column) will be pressed at a time,
the diodes can be omitted.
1N914
D0 ----|<|-----X X X X (Set all Cn high),
D1 ----|<|-----X X X X Scan one Dn low at a time, read all Cn
D2 ----|<|-----X X X X
D3 ----|<|-----X X X X
| | | |
C3 ------------+ | | |
C2 --------------+ | |
C1 ----------------+ |
C0 ------------------+
Note that if we press three switches in the matrix which form 3 corners of
a box, it will appear as if all 4 corners are pressed; this is true of any
such matrix, unless each switch has its own diode.
I hope to have some results to share in a later revision of this doc.
+5 +5
/ \
---H / external resistor
\ \
|_____ ___________/
| out | out
/ /
---L ---L
\ \
Gnd Gnd
Totem Pole Open Collector
Regular TTL outputs basically consist of a two "stacked" transistor in series
between +5 volts and ground, with the output coming from the connection between
them. This is called a "totem pole output". At any given time one of these
transistors is conducting and the other is not. To pull the output "high",
the transistor from +5 to the output conducts (H), which "sources" positive
current from the output to ground (that is, an external device between the
output and ground will get power). To pull the output low, only the lower
transistor (L) conducts, "sinking" current to ground; an external device
between +5 volts and the output can be energized. Current flows into the
chip for low, out of it for high.
+5
/ |
---H on V
\ -->
|________ TTL output on = 1 = high, "sourcing" current
| out \
/ / |
---L off \ V
\_________/
Gnd
+5_________
/ \
---H off / |
\ \ V
|________/ TTL output off = 0 = low, "sinking" current
| <-- out
/
---L on |
\ V
Gnd
The 0 / pull low current capacity (sinking) is larger than the 1 / pull high
capacity (sourcing). If you want to drive something like an LED, or a solid
state relay, you can get more current from the TTL outputs by connecting it
between +5 and the gate output (second picture) - *if* it's electrically
isolated from ground. You still have to check the current and voltage
ratings, tho.
One key here is that the chip is always trying to pull either high
or low, and the currently conducting transistor has voltage and current
limits, beyond which it can be damaged. It is not good design to connect
two such outputs which may have different states - one pulling high and one
low - because this will exceed the current specs. However, if you do, the
one pulling low will "win", since TTL can sink (pull low) more strongly
than it can source (pull high). And there is some slack in the specs, so
this does not always immediately damage the chip; we'll get back to this.
These are the type of outputs on the DATA lines on the original IBM
parallel port. (Well, not exactly, but I'll get back to that too).
Another type of output is the "open collector". In this case, there is a
transistor from the output pin to ground, but none to +5 volts. The two
states are 0, "conducting to ground" (pulling low), and 1, "not conducting"
(floating, not pulled either way). Externally, you can connect a resistor
of proper value between the line and +5 volts to pull the line high when
the chip output is floating. The value is chosen such that when the output
is conducting to ground, it overpowers the external resistor and the line
goes low. The advantage of this scheme is that you can connect multiple
open collector outputs together (or even slip in one totem pole). Every
output that is floating is ignored (and the resistor will pull the line
high if and only if all outputs are floating); multiple outputs pulling
low cause no conflict. This is the type of output used for CONTROL lines
in the original IBM parallel port.
Since each parallel port control output line has a corresponding feedback
bit that can be read (mainly for diagnostics, to see if the line really goes
high or low), it is possible to program these CONTROL outputs "high" (really
floating), and then allow external signals control the high or low state
of the line. An external open collector output, or a totem pole one, is
capable of pulling the line high (reinforcing the pullup resistor) or low
(overpowring it) without exceeding current specs. In this way you can use
the control lines as inputs. If there is no external signal, it will read
high. However, you must program the CONTROL outputs high (taking into
account any logical inversions between the register bits and the electrical
outputs); if the open collector output is low (conducting to ground), the
external signal won't be able to pull it high (or at least not without
exceeding the specs).
The same thing can be done with totem pole outputs - program them high, and
let external logic pull them high (no problem, both pulling up) or low
(overpowering the attempt to pull high), but in this case you are overloading
the H transistor, rather than a pullup resistor, and exceeding spec, with
possible unreliability or damage. However, this has been successfully done
with the data outputs of a conventional parallel port, and some people claim
not to have seen any damage yet. Don't blame me if you do it and something
dies.
A third type of gate is a totem pole in which both high and low transistors
can be non-conducting at once, creating a third, floating state (this is often
called a tri-state output). When it is in this third state, the line is not
being pulled high nor low by this device, and thus can be safely controlled
by some other device. No pullup resistor is used. The 74LS374 chip used
for the standard parallel port DATA outputs actually has tristate ability,
but as described elsewhere the third state is not used, and it is always
trying to pull high or low - thus my initial description of the DATA lines
as totem pole drivers.
The way true bidirectional parallel ports work is to allow the software to
selectively put the DATA outputs into the third, undriven state. Then you
can use the data feedback register to read whatever highs or lows are put
onto the data lines externally.
Non-TTL logic, like CMOS, has the equivalents of these, but with a different
type of transistor, and different voltage and current values. If your
parallel port uses a single chip or otherwise differs from the original
IBM parallel port, the above electrical description cannot be guaranteed,
but it is probably pretty analogous. Let me know if you have specific
knowledge about the electical specs of your single chip parallel port, for
future versions of this document.
Note again that high and low in this description are electrical levels, as
would me measured by a voltmeter on the pins; high is associated with TTL
logic 1, but whether a given CONTROL output line is high when the
corresponding register bit is 1 or 0 varies with the line, as is described
elsewhere in this document. The DATA lines are straight through, with no
inversions, so a 1 bit produces a high output.