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 readbackThe 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,16Note: 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 CollectorRegular 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 GndThe 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.