&lt;img&gt;

Wednesday, November 9th, 2005

Universal Serial Bus

Embedded Internet

Legacy Ports

Device Drivers

Miscellaneous

Interfacing the Standard Parallel Port

Table of Contents

Introduction to Parallel Ports
Hardware Properties
Centronics?
Port Addresses
Software Registers - Standard Parallel Port (SPP)
Bi-directional Ports
Using the Parallel Port to Input 8 Bits
Nibble Mode
Using the Parallel Port's IRQ
Parallel Port Modes in BIOS
Parallel Port Modes and the ECP's Extended Control Register
PDF Version

Introduction to Parallel Ports

The Parallel Port is the most commonly used port for interfacing home made projects.
This port will allow the input of up to 9 bits or the output of 12 bits at any one
given time, thus requiring minimal external circuitry to implement many simpler tasks.
The port is composed of 4 control lines, 5 status lines and 8 data lines. It's found
commonly on the back of your PC as a D-Type 25 Pin female connector. There may also be
a D-Type 25 pin male connector. This will be a serial RS-232 port and thus, is a totally
incompatible port.

For more information on Serial RS-232 Ports See http://www.beyondlogic.org/serial/serial.htm

Newer Parallel Port’s are standardized under the IEEE 1284 standard first released
in 1994. This standard defines 5 modes of operation which are as follows,

1. Compatibility Mode.

2. Nibble Mode. (Protocol not Described in this Document)

3. Byte Mode. (Protocol not Described in this Document)

4. EPP Mode (Enhanced Parallel Port).

5. ECP Mode (Extended Capabilities Mode).

The aim was to design new drivers and devices which were compatible with each other and
also backwards compatible with the Standard Parallel Port (SPP). Compatibility, Nibble
& Byte modes use just the standard hardware available on the original Parallel Port
cards while EPP & ECP modes require additional hardware which can run at faster speeds,
while still being downwards compatible with the Standard Parallel Port.

Compatibility mode or "Centronics Mode" as it is commonly known, can only send data in
the forward direction at a typical speed of 50 kbytes per second but can be as high as
150+ kbytes a second. In order to receive data, you must change the mode to either Nibble
or Byte mode. Nibble mode can input a nibble (4 bits) in the reverse direction. E.g. from
device to computer. Byte mode uses the Parallel's bi-directional feature (found only on
some cards) to input a byte (8 bits) of data in the reverse direction.

Extended and Enhanced Parallel Ports use additional hardware to generate
and manage handshaking. To output a byte to a printer (or anything in that
matter) using compatibility mode, the software must,

1. Write the byte to the Data Port.

2. Check to see is the printer is busy. If the printer is busy, it will
not accept any data, thus any data which is written will be lost.

3. Take the Strobe (Pin 1) low. This tells the printer that there is
the correct data on the data lines. (Pins 2-9)

4. Put the strobe high again after waiting approximately 5 microseconds
after putting the strobe low. (Step 3)

This limits the speed at which the port can run at. The EPP & ECP ports get
around this by letting the hardware check to see if the printer is busy and
generate a strobe and /or appropriate handshaking. This means only one I/O
instruction need to be performed, thus increasing the speed. These ports
can output at around 1-2 megabytes per second. The ECP port also has the
advantage of using DMA channels and FIFO buffers, thus data can be shifted
around without using I/O instructions.

Hardware Properties

Below is a table of the "Pin Outs" of the D-Type 25 Pin
connector and the Centronics 34 Pin connector. The D-Type 25 pin
connector is the most common connector found on the Parallel Port of
the computer, while the Centronics Connector is commonly found on printers.
The IEEE 1284 standard however specifies 3 different connectors for use
with the Parallel Port. The first one, 1284 Type A is the D-Type 25
connector found on the back of most computers. The 2nd is the 1284 Type
B which is the 36 pin Centronics Connector found on most printers.

IEEE 1284 Type C however, is a 36 conductor connector like the Centronics,
but smaller. This connector is claimed to have a better clip latch, better
electrical properties and is easier to assemble. It also contains two more
pins for signals which can be used to see whether the other device
connected, has power. 1284 Type C connectors are recommended for new
designs, so we can look forward on seeing these new connectors in the
near future.

Pin No (D-Type 25)

Pin No (Centronics)

SPP Signal

Direction In/out

Register

Hardware Inverted

1

1

nStrobe

In/Out

Control

Yes

2

2

Data 0

Out

Data

3

3

Data 1

Out

Data

4

4

Data 2

Out

Data

5

5

Data 3

Out

Data

6

6

Data 4

Out

Data

7

7

Data 5

Out

Data

8

8

Data 6

Out

Data

9

9

Data 7

Out

Data

10

10

nAck

In

Status

11

11

Busy

In

Status

Yes

12

12

Paper-Out / Paper-End

In

Status

13

13

Select

In

Status

14

14

nAuto-Linefeed

In/Out

Control

Yes

15

32

nError / nFault

In

Status

16

31

nInitialize

In/Out

Control

17

36

nSelect-Printer / nSelect-In

In/Out

Control

Yes

18 - 25

19-30

Ground

Gnd

Table 1. Pin Assignments of the D-Type 25 pin Parallel Port Connector.

The above table uses "n" in front of the signal name to denote that the
signal is active low. e.g. nError. If the printer has occurred an error
then this line is low. This line normally is high, should the printer be
functioning correctly. The "Hardware Inverted" means the signal is inverted
by the Parallel card's hardware. Such an example is the Busy line. If +5v
(Logic 1) was applied to this pin and the status register read, it would
return back a 0 in Bit 7 of the Status Register.

The output of the Parallel Port is normally TTL logic levels. The voltage
levels are the easy part. The current you can sink and source varies from
port to port. Most Parallel Ports implemented in ASIC, can sink and source
around 12mA. However these are just some of the figures taken from Data
sheets, Sink/Source 6mA, Source 12mA/Sink 20mA, Sink 16mA/Source 4mA,
Sink/Source 12mA. As you can see they vary quite a bit. The best bet is
to use a buffer, so the least current is drawn from the Parallel Port.

Centronics?

Centronics is an early standard for transferring data from a host to the
printer. The majority of printers use this handshake. This handshake is
normally implemented using a Standard Parallel Port under software control.
Below is a simplified diagram of the `Centronics' Protocol.

Data is first applied on the Parallel Port pins 2 to 7. The host then
checks to see if the printer is busy. i.e. the busy line should be low.
The program then asserts the strobe, waits a minimum of 1uS, and then
de-asserts the strobe. Data is normally read by the printer/peripheral
on the rising edge of the strobe. The printer will indicate that it is
busy processing data via the Busy line. Once the printer has accepted
data, it will acknowledge the byte by a negative pulse about 5uS on the
nAck line.

Quite often the host will ignore the nAck line to save time. Latter in
the Extended Capabilities Port, you will see a Fast Centronics Mode,
which lets the hardware do all the handshaking for you. All the programmer
must do is write the byte of data to the I/O port. The hardware will check
to see if the printer is busy, generate the strobe. Note that this mode
commonly doesn't check the nAck either.

Port Addresses

The Parallel Port has three commonly used base addresses. These are
listed in table 2, below. The 3BCh base address was originally introduced
used for Parallel Ports on early Video Cards. This address then disappeared
for a while, when Parallel Ports were later removed from Video Cards. They
has now reappeared as an option for Parallel Ports integrated onto
motherboards, upon which their configuration can be changed using BIOS.

LPT1 is normally assigned base address 378h, while LPT2 is assigned 278h.
However this may not always be the case as explained later. 378h & 278h
have always been commonly used for Parallel Ports. The lower case h
denotes that it is in hexadecimal. These addresses may change from
machine to machine.

Address

Notes:

3BCh - 3BFh

Used for Parallel Ports which were incorporated on to Video Cards - Doesn't support ECP addresses

378h - 37Fh

Usual Address For LPT 1

278h - 27Fh

Usual Address For LPT 2

Table 2 Port Addresses

When the computer is first turned on, BIOS (Basic Input/Output System)
will determine the number of ports you have and assign device labels
LPT1, LPT2 & LPT3 to them. BIOS first looks at address 3BCh. If a
Parallel Port is found here, it is assigned as LPT1, then it searches
at location 378h. If a Parallel card is found there, it is assigned
the next free device label. This would be LPT1 if a card wasn't found
at 3BCh or LPT2 if a card was found at 3BCh. The last port of call, is
278h and follows the same procedure than the other two ports. Therefore
it is possible to have a LPT2 which is at 378h and not at the expected
address 278h.

What can make this even confusing, is that some manufacturers of Parallel
Port Cards, have jumpers which allow you to set your Port to LPT1, LPT2,
LPT3. Now what address is LPT1? - On the majority of cards LPT1 is 378h,
and LPT2, 278h, but some will use 3BCh as LPT1, 378h as LPT1 and 278h as
LPT2. Life wasn't meant to be easy.

The assigned devices LPT1, LPT2 & LPT3 should not be a worry to people
wishing to interface devices to their PC's. Most of the time the base
address is used to interface the port rather than LPT1 etc. However should
you want to find the address of LPT1 or any of the Line PrinTer Devices,
you can use a lookup table provided by BIOS. When BIOS assigns addresses
to your printer devices, it stores the address at specific locations in
memory, so we can find them.

Start Address

Function

0000:0408

LPT1's Base Address

0000:040A

LPT2's Base Address

0000:040C

LPT3's Base Address

0000:040E

LPT4's Base Address (Note 1)

Table 3 - LPT Addresses in the BIOS Data Area;

Note 1 : Address 000
0:040E in the BIOS Data Area may be used as the Extended
Bios Data Area in PS/2 and newer Bioses.

The above table, table 3, shows the address at which we can find the
Printer Port's addresses in the BIOS Data Area. Each address will
take up 2 bytes. The following sample program in C, shows how you
can read these locations to obtain the addresses of your printer ports.

#include <stdio.h>
#include <dos.h>

void main(void)
{
unsigned int far *ptraddr; /* Pointer to location of Port Addresses */
unsigned int address; /* Address of Port */
int a;

ptraddr=(unsigned int far *)0x00000408;

for (a = 0; a < 3; a++)
{
address = *ptraddr;
if (address == 0)
printf("No port found for LPT%d \n",a+1);
else
printf("Address assigned to LPT%d is %Xh\n",a+1,address);
*ptraddr++;
}
}

Software Registers - Standard Parallel Port (SPP)

Offset

Name

Read/Write

Bit No.

Properties

Base + 0

Data Port

Write (Note-1)

Bit 7

Data 7

Bit 6

Data 6

Bit 5

Data 5

Bit 4

Data 4

Bit 3

Data 3

Bit 2

Data 2

Bit 1

Data 1

Bit 0

Data 0

Table 4 Data Port

Note 1 : If the Port is Bi-Directional then Read and Write Operations
can be performed on the Data Register.

The base address, usually called the Data Port or Data Register is simply
used for outputting data on the Parallel Port's data lines (Pins 2-9).
This register is normally a write only port. If you read from the port,
you should get the last byte sent. However if your port is bi-directional,
you can receive data on this address. See Bi-directional Ports for more
detail.

Offset

Name

Read/Write

Bit No.

Properties

Base + 1

Status Port

Read Only

Bit 7

Busy

Bit 6

Ack

Bit 5

Paper Out

Bit 4

Select In

Bit 3

Error

Bit 2

IRQ (Not)

Bit 1

Reserved

Bit 0

Reserved

Table 5 Status Port

The Status Port (base address + 1) is a read only port. Any data written
to this port will be ignored. The Status Port is made up of 5 input lines
(Pins 10,11,12,13 & 15), a IRQ status register and two reserved bits.
Please note that Bit 7 (Busy) is a active low input. E.g. If bit 7
happens to show a logic 0, this means that there is +5v at pin 11.
Likewise with Bit 2. (nIRQ) If this bit shows a '1' then an interrupt
has not occurred.

Offset

Name

Read/Write

Bit No.

Properties

Base + 2

Control Port

Read/Write

Bit 7

Unused

Bit 6

Unused

Bit 5

Enable Bi-Directional Port

Bit 4

Enable IRQ Via Ack Line

Bit 3

Select Printer

Bit 2

Initialize Printer (Reset)

Bit 1

Auto Linefeed

Bit 0

Strobe

Table 6 Control Port

The Control Port (base address + 2) was intended as a write only port.
When a printer is attached to the Parallel Port, four "controls" are used.
These are Strobe, Auto Linefeed, Initialize and Select Printer, all of
which are inverted except Initialize.

The printer would not send a signal to initialize the computer, nor would
it tell the computer to use auto linefeed. However these four outputs can
also be used for inputs. If the computer has placed a pin high (e.g. +5v)
and your device wanted to take it low, you would effectively short out
the port, causing a conflict on that pin. Therefore these lines are "open
collector" outputs (or open drain for CMOS devices). This means that it
has two states. A low state (0v) and a high impedance state (open
circuit).

Normally the Printer Card will have internal pull-up resistors, but as
you would expect, not all will. Some may just have open collector outputs,
while others may even have normal totem pole outputs. In order to make
your device work correctly on as many Printer Ports as possible, you
can use an external resistor as well. Should you already have an internal
resistor, then it will act in Parallel with it, or if you have Totem
pole outputs, the resistor will act as a load.

An external 4.7k resistor can be used to pull the pin high. I wouldn't
use anything lower, just in case you do have an internal pull up resistor,
as the external resistor would act in parallel giving effectively, a
lower value pull up resistor. When in high impedance state the pin on
the Parallel Port is high (+5v). When in this state, your external
device can pull the pin low and have the control port change read a
different value. This way the 4 pins of the Control Port can be used
for bi-directional data transfer. However the Control Port must be
set to xxxx0100 to be able to read data, that is all pins to be +5v
at the port so that you can pull it down to GND (logic 0).

Bits 4 & 5 are internal controls. Bit four will enable the IRQ (See
Using the Parallel Ports IRQ) and Bit 5 will enable the bi-directional
port meaning that you can input 8 bits using (DATA0-7). This mode is
only possible if your card supports it. Bits 6 & 7 are reserved. Any
writes to these two bits will be ignored.

Bi-directional Ports

The schematic diagram below, shows a simplified view of the Parallel
Port's Data Register. The original Parallel Port card's implemented
74LS logic. These days all this is crammed into one ASIC, but the
theory of operation is still the same.

The non bi-directional ports were manufactured with the 74LS374's output
enable tied permanent low, thus the data port is always output only.
When you read the Parallel Port's data register, the data comes from
the 74LS374 which is also connected to the data pins. Now if you can
overdrive the '374 you can effectively have a Bi-directional Port.
(or a input only port, once you blow up the latches output!)

What is very concerning is that people have actually done this. I've
seen one circuit, a scope connected to the Parallel Port distributed
on the Internet. The author uses an ADC of some type, but finds the
ADC requires transistors on each data line, to make it work! No wonder
why. Others have had similar trouble, the 68HC11 cannot sink enough
current (30 to 40mA!)

Bi-directional ports use Control Bit 5 connected to the 374's Output Enable so that
it's output drivers can be turned off. This way you can read data present
on the Parallel Port's Data Pins, without having bus conflicts and
excessive current drains.

Bit 5 of the Control Port enables or disables the bi-directional function
of the Parallel Port. This is only available on true bi-directional ports.
When this bit is set to one, pins 2 to 9 go into high impedance state.
Once in this state you can enter data on
these lines and retrieve it
from the Data Port (base address). Any data which is written to the
data port will be stored but will not be available at the data pins.
To turn off bi-directional mode, set bit 5 of the Control Port to '0'.

However not all ports behave in the same way. Other ports may require
setting bit 6 of the Control Port to enable Bi-directional mode and
setting of Bit 5 to dis-enable Bi-directional mode, Different
manufacturers implement their bi-directional ports in different ways.
If you wish to use your Bi-directional port to input data, test it
with a logic probe or multimeter first to make sure it is in bi-directional
mode.

Using The Parallel Port to Input 8 Bits.

If your Parallel Port doesn't support bi-directional mode, don't despair.
You can input a maximum of 9 bits at any one given time. To do this you
can use the 5 input lines of the Status Port and the 4 inputs (open
collector) lines of the Control Port.

The inputs to the Parallel Port has be chosen as such, to make life easier
for us. Busy just happens to be the MSB (Bit 7) of the Status Port, then
in ascending order comes Ack, Paper Out and Select, making up the most
significant nibble of the Control Port. The Bars are used to represent
which inputs are Hardware inverted, i.e. +5v will read 0 from the
register, while GND will read 1. The Status Port only has one inverted
input.

The Control port is used to read the least significant nibble. As
described before, the control port has open collector outputs, i.e.
two possible states, high impedance and GND. If we connect our inputs
directly to the port (For example an ADC0804 with totem pole outputs),
a conflict will result if the input is high and the port is trying to
pull it down. Therefore we use open collector inverters.

However this is not always entirely necessary. If we were connecting
single pole switches to the port with a pull up resistor, then there is
no need to bother with this protection. Also if your software initializes
the control port with xxxx0100 so that all the pins on the control port
are high, then it may be unnecessary. If however you don't bother and
your device is connected to the Parallel Port before your software has
a chance to initialize then you may encounter problems.

Another problem to be aware of is the pull up resistors on the control
port. The average pull-up resistor is 4.7k. In order to pull the line
low, your device will need to sink 1mA, which some low powered devices
may struggle to do. Now what happens if I suggest that some ports have
1K pull up resistors? Yes, there are such cards. Your device now has to
sink 5mA. More reason to use the open collector inverters.

Open collector inverters were chosen over open collector buffers as they
are more popular, and thus easier to obtain. There is no reason, however
why you can't use them. Another possibility is to use transistors.

The input, D3 is connected via the inverter to Select Printer. Select
Printer just happens to be bit 3 of the control port. D2, D1 & D0 are
connected to Init, Auto linefeed and strobe, respectively to make up
the lower nibble. Now this is done, all we have to do is assemble the
byte using software. The first thing we must do is to write xxxx0100
to the Control Port. This places all the control port lines high, so
they can be pulled down to input data.

outportb(CONTROL, inportb(CONTROL) & 0xF0 | 0x04);

Now that this is done, we can read the most significant nibble. This
just happens to be the most significant nibble of the status port. As
we are only interested in the MSnibble we will AND the results with 0xF0,
so that the LSnibble is clear. Busy is hardware inverted, but we won't
worry about it now. Once the two bytes are constructed, we can kill two
birds with one stone by toggling Busy and Init at the same time.

a = (inportb(STATUS) & 0xF0); /* Read MSnibble */

We can now read the LSnibble. This just happens to be LSnibble of the
control port - How convenient! This time we are not interested with the
MSnibble of the port, thus we AND the result with 0x0F to clear the
MSnibble. Once this is done, it is time to combine the two bytes together.
This is done by OR'ing the two bytes. This now leaves us with one byte,
however we are not finished yet. Bits 2 and 7 are inverted. This is
overcome by XOR'ing the byte with 0x84, which toggles the two bits.

a = a |(inportb(CONTROL) & 0x0F); /* Read LSnibble */
a = a ^ 0x84; /* Toggle Bit 2 & 7 */

Note: Some control ports are not open collector, but have totem pole
outputs. This is also the case with EPP and ECP Ports. Normally when you
place a Parallel Port in ECP or EPP mode, the control port becomes totem
pole outputs only. Now what happens if you connect your device to the
Parallel Port in this mode? Therefore, in the interest of portability
I recommend using the next circuit, reading a nibble at a time.

Nibble Mode.

Nibble mode is the preferred way of reading 8 bits of data without
placing the port in reverse mode and using the data lines. Nibble
mode uses a Quad 2 line to 1 line multiplexer to read a nibble of
data at a time. Then it "switches" to the other nibble and reads its.
Software can then be used to construct the two nibbles into a byte.
The only disadvantage of this technique is that it is slower. It now
requires a few I/O instructions to read the one byte, and it requires
the use of an external IC.

The operation of the 74LS157, Quad 2 line to 1 line multiplexer is quite
simple. It simply acts as four switches. When the A/B input is low, the A
inputs are selected. E.g. 1A passes through to 1Y, 2A passes through to 2Y
etc. When the A/B is high, the B inputs are selected. The Y outputs are
connected up to the Parallel Port's status port, in such a manner that it
represents the MSnibble of the status register. While this is not necessary,
it makes the software easier.

To use this circuit, first we must initialize the multiplexer to switch
either inputs A or B. We will read the LSnibble first, thus we must place
A/B low. The strobe is hardware inverted, thus we must set Bit 0 of the
control port to get a low on Pin 1.

outportb(CONTROL, inportb(CONTROL) | 0x01); /* Select Low Nibble (A)*/

Once the low nibble is selected, we can read the LSnibble from the Status
Port. Take note that the Busy Line is inverted, however we won't tackle it
just yet. We are only interested in the MSnibble of the result, thus we
AND the result with 0xF0, to clear the LSnibble.

a = (inportb(STATUS) & 0xF0); /* Read Low Nibble */

Now it's time to shift the nibble we have just read to the LSnibble of
variable a,

a = a >> 4; /* Shift Right 4 Bits */

We are now half way there. It's time to get the MSnibble, thus we must
switch the multiplexer to select inputs B. Then we can read the MSnibble
and put the two nibbles together to make a byte,

outportb(CONTROL, inportb(CONTROL) & 0xFE); /* Select High Nibble (B)*/
a = a |(inportb(STATUS) & 0xF0); /* Read High Nibble */
byte = byte ^ 0x88;

The last line toggles two inverted bits which were read in on the Busy
line. It may be necessary to add delays in the process, if the incorrect
results are being returned.

Using the Parallel Port's IRQ

The Parallel Port's interrupt request is not used for printing under
DOS or Windows. Early versions of OS-2 used them, but don't anymore.
Interrupts are good when interfacing monitoring devices such as high
temp alarms etc, where you don't know when it is going to be activated.
It's more efficient to have an interrupt request rather than have the
software poll the ports regularly to see if something has changed. This
is even more noticeable if you are using your computer for other tasks,
such as with a multitasking operating system.

The Parallel Port's interrupt request is normally IRQ5 or IRQ7 but may
be something else if these are in use. It may also be possible that the
interrupts are totally disabled on the card, if the card was only used
for printing. The Parallel Port interrupt can be disabled and enabled
using bit 4 of the control register, Enable IRQ Via Ack Line. Once
enabled, an interrupt will occur upon a low to high transition (rising
edge) of the nACK. However like always, some cards may trigger the
interrupt on the high to low transition.

The following code is an Interrupt Polarity Te
ster, which serves as
two things. It will determine which polarity your Parallel Port
interrupt is, while also giving you an example for how to use the
Parallel Port's Interrupt. It checks if your interrupt is generated
on the rising or falling edge of the nACK line. To use the program
simply wire one of the Data lines (Pins 2 to 9) to the Ack Pin (Pin
10). The easiest way to do this is to bridge some solder from DATA7
(Pin 9) to ACK (Pin 10) on a male DB25 connector.

/* Parallel Port Interrupt Polarity Tester */
/* 2nd February 1998 */
/* Copyright 1997 Craig Peacock */
/* WWW - http://www.beyondlogic.org */
/* Email - [email-masked] */

#include <dos.h>

#define PORTADDRESS 0x378 /* Enter Your Port Address Here */
#define IRQ 7 /* IRQ Here */

#define DATA PORTADDRESS+0
#define STATUS PORTADDRESS+1
#define CONTROL PORTADDRESS+2

#define PIC1 0x20
#define PIC2 0xA0

int interflag; /* Interrupt Flag */
int picaddr; /* Programmable Interrupt Controller (PIC) Base Address */

void interrupt (*oldhandler)();

void interrupt parisr() /* Interrupt Service Routine (ISR) */
{
interflag = 1;
outportb(picaddr,0x20); /* End of Interrupt (EOI) */
}

void main(void)
{
int c;
int intno; /* Interrupt Vector Number */
int picmask; /* PIC's Mask */

/* Calculate Interrupt Vector, PIC Addr & Mask. */

if (IRQ >= 2 && IRQ <= 7) {
intno = IRQ + 0x08;
picaddr = PIC1;
picmask = 1;
picmask = picmask << IRQ;
}
if (IRQ >= 8 && IRQ <= 15) {
intno = IRQ + 0x68;
picaddr = PIC2;
picmask = 1;
picmask = picmask << (IRQ-8);
}
if (IRQ < 2 || IRQ > 15)
{
printf("IRQ Out of Range\n");
exit();
}

outportb(CONTROL, inportb(CONTROL) & 0xDF); /* Make sure port is in Forward Direction */
outportb(DATA,0xFF);
oldhandler = getvect(intno); /* Save Old Interrupt Vector */
setvect(intno, parisr); /* Set New Interrupt Vector Entry */
outportb(picaddr+1,inportb(picaddr+1) & (0xFF - picmask)); /* Un-Mask Pic */
outportb(CONTROL, inportb(CONTROL) | 0x10); /* Enable Parallel Port IRQ's */

clrscr();
printf("Parallel Port Interrupt Polarity Tester\n");
printf("IRQ %d : INTNO %02X : PIC Addr 0x%X : Mask 0x%02X\n",IRQ,intno,picaddr,picmask);
interflag = 0; /* Reset Interrupt Flag */
delay(10);
outportb(DATA,0x00); /* High to Low Transition */
delay(10); /* Wait */
if (interflag == 1) printf("Interrupts Occur on High to Low Transition of ACK.\n");
else
{
outportb(DATA,0xFF); /* Low to High Transition */
delay(10); /* wait */
if (interflag == 1) printf("Interrupts Occur on Low to High Transition of ACK.\n");
else printf("No Interrupt Activity Occurred. \nCheck IRQ Number, Port Address and Wiring.");
}

outportb(CONTROL, inportb(CONTROL) & 0xEF); /* Disable Parallel Port IRQ's */
outportb(picaddr+1,inportb(picaddr+1) | picmask); /* Mask Pic */
setvect(intno, oldhandler); /* Restore old Interrupt Vector Before Exit */
}

At compile time, the above source may generate a few warnings, condition
always true, condition always false, unreachable code etc. These are
perfectly O.K. They are generated as some of the condition structures
test which IRQ you are using, and as the IRQ is defined as a constant
some outcomes will never change. While they would of been better
implemented as a preprocessor directive, I've done this so you can
cut and paste the source code in your own programs which may use
command line arguments, user input etc instead of a defined IRQ.

To understand how this example works, the reader must have an assumed
knowledge and understanding of Interrupts and Interrupt Service Routines
(ISR). If not, See Interfacing the PC : Using Interrupts
for a quick introduction.

The first part of the mainline routine calculates the
Interrupt Vector, PIC Addr & Mask in order to use the Parallel Port's
Interrupt Facility. After the Interrupt Service Routine (ISR) has been
set up and the Programmable Interrupt Controller (PIC) set, we must
enable the interrupt on the Parallel Port. This is done by setting bit
4 of the Parallel Port's Control Register using

outportb(CONTROL,inportb(CONTROL) | 0x10);

Before enabling the interrupts, we wrote 0xFF to the Parallel Port to
enable the 8 data lines into a known state. At this point of the program,
all the data lines should be high. The interrupt service routine simply
sets a flag (interflag), thus we can determine when an IRQ occurs. We are
now in a position to write 0x00 to the data port, which causes a high to
low transition on the Parallel Port's Acknowledge line as it's connected
to one of the data lines.

If the interrupt occurs on the high to low transition, the interrupt
flag (interflag) should be set. We now test this, and if this is so the
program informs the user. However if it is not set, then an interrupt
has not yet occurred. We now write 0xFF to the data port, which will
cause a low to high transition on the nAck line and check the interrupt
flag again. If set, then the interrupt occurs on the low to high
transition.

However if the interrupt flag is still reset, then this would suggest
that the interrupts are not working. Make sure your IRQ and Base Address
is correct and also check the wiring of the plug.

Parallel Port Modes in BIOS

Today, most Parallel Ports are mulimode ports. They are normally software
configurable to one of many modes from BIOS. The typical modes are,

Printer Mode (Sometimes called Default or Normal Modes)

Standard & Bi-directional (SPP) Mode

EPP1.7 and SPP Mode

EPP1.9 and SPP Mode

ECP Mode

ECP and EPP1.7 Mode

ECP and EPP1.9 Mode

Printer Mode is the most basic mode. It is a Standard Parallel
Port in forward mode only. It has no bi-directional feature, thus Bit 5
of the Control Port will not respond. Standard & Bi-directional (SPP)
Mode is the bi-directional mode. Using this mode, bit 5 of the Control
Port will reverse the direction of the port, so you can read back a
value on the data lines.

EPP1.7 and SPP Mode is a combination of EPP 1.7 (Enhanced Parallel
Port) and SPP Modes. In this mode of operation you will have access to
the SPP registers (Data, Status and Control) and access to the EPP
Registers. In this mode you should be able to reverse the direction
of the port using bit 5 of the control register. EPP 1.7 is the earlier
version of EPP. This version, version 1.7, may not have the time-out bit.
See
Interfacing the Enhanced Parallel Port for more information.

EPP1.9 and SPP Mode is just like the previous mode, only it uses
EPP Version 1.9 this time. As in the other mode, you will have access to
the SPP registers, including Bit 5 of the control port. However this
differs from EPP1.7 and SPP Mode as you should have access to the EPP
Timeout bit.

ECP Mode will give you an Extended Capabilities Port. The mode of
this port can then be set using the ECP's Extended Control Register (ECR).
However in this mode from BIOS the EPP Mode (100) will not be available.
We will further discuss the ECP's Extended Control Register in this
document, but if you want further information on the ECP port, consult
Interfacing the Extended Capabilities Port.

ECP and EPP1.7 Mode and ECP and EPP1.9 Mode will give you
an Extended Capabilities Port, just like the previous mode. However the
EPP Mode in the ECP's ECR will now be available. Should you be in ECP and
EPP1.7 Mode you will get an EPP1.7 Port, or if you are in ECP and EPP1.9
Mode, an EPP1.9 Port will be at your disposal.

The above modes are configurable via BIOS. You can reconfigure them by
using your own software, but this is not recommended. These software
registers, typically found at 0x2FA, 0x3F0, 0x3F1 etc are only intended
to be accessed by BIOS. There is no set standard for these configuration
registers, thus if you were to use these registers, your software would
not be very portable. With today's multitasking operating systems, its
also not a good idea to change them when it suits you.

A better option is to select ECP and EPP1.7 Mode or ECP and EPP1.9 Mode
from BIOS and then use the ECP's Extended Control Register to select your
Parallel Port's Mode. The EPP1.7 mode had a few problems in regards to the
Data and Address Strobes being asserted to start a cycle regardless of
the wait state, thus this mode if not typically used now. Best set your
Parallel Port to ECP and EPP1.9 Mode.

Parallel Port Modes and the ECP's Extended Control Register

As we have just discussed, it is better to set the Parallel Port to ECP
and EPP1.9 Mode and use the ECP's Exten
ded Control Register to select
different modes of operation. The ECP Registers are standardized under
Microsoft's Extended Capabilities Port Protocol and ISA Interface
Standard, thus we don't have that problem of every vendor having their
own register set.

When set to ECP Mode, a new set of registers become available at Base +
0x400h. A discussion of these registers are available in
Interfacing the Extended Capabilities Port.
Here we are only interested in the Extended
Control Register (ECR) which is mapped at Base + 0x402h. It should be
stated that the ECP's registers are not available for port's with a base
address of 0x3BCh.

Bit

Function

7:5

Selects Current Mode of Operation

000

Standard Mode

001

Byte Mode

010

Parallel Port FIFO Mode

011

ECP FIFO Mode

100

EPP Mode

101

Reserved

110

FIFO Test Mode

111

Configuration Mode

4

ECP Interrupt Bit

3

DMA Enable Bit

2

ECP Service Bit

1

FIFO Full

0

FIFO Empty

Table 7 - Extended Control Register (ECR)

The table above is of the Extended Control Register. We are only
interested in the three MSB of the Extended Control Register which
selects the mode of operation. There are 7 possible modes of operation,
but not all ports will support all modes. The EPP mode is one such example,
not being available on some ports.

Modes of Operation

Standard Mode

Selecting this mode will cause the ECP port to behave as a Standard Parallel Port, without bi-directional functionality.

Byte Mode / PS/2 Mode

Behaves as a SPP in bi-directional mode. Bit 5 will place the port in reverse mode.

Parallel Port FIFO Mode

In this mode, any
data written to the Data FIFO will be sent to the peripheral using the
SPP Handshake. The hardware will generate the handshaking required.
Useful with non-ECP devices such as Printers. You can have some of the
features of ECP like FIFO buffers and hardware generation of
handshaking but with the existing SPP handshake instead of the
ECP Handshake.

ECP FIFO Mode

Standard mode for ECP use. This mode uses the ECP Handshake described in Interfacing the Extended Capabilities Port. - When in ECP Mode though BIOS, and the ECR register is set to ECP FIFO Mode (011), the SPP registers may disappear.

EPP Mode/Reserved

This will enable
EPP Mode, if available. Under BIOS, if ECP mode is set then it's more
than likely, this mode is not an option. However if BIOS is set to ECP
and EPP1.x Mode, then EPP 1.x will be enabled. - Under Microsoft's Extended Capabilities Port Protocol and ISA Interface Standard this mode is Vendor Specified.

Reserved

Currently Reserved. - Under Microsoft's Extended Capabilities Port Protocol and ISA Interface Standard this mode is Vendor Specified.

FIFO Test Mode

While in this mode, any
data written to the Test FIFO Register will be placed into the FIFO and
any data read from the Test FIFO register will be read from the
FIFO buffer. The FIFO Full/Empty Status Bits will reflect their true
value, thus FIFO depth, among other things can be determined in this
mode.

Configuration Mode

In this mode, the two configuration registers, cnfgA & cnfgB become available at their designated register addresses.

If you are in ECP Mode under BIOS, or if your card is jumpered to use
ECP then it is a good idea to initialize the mode of your ECP port to
a pre-defined state before use. If you are using SPP, then set the port
to Standard Mode as the first thing you do. Don't assume that the port
will already be in Standard (SPP) mode.

Under some of the modes, the SPP registers may disappear or not work
correctly. If you are using SPP, then set the ECR to Standard Mode. This
is one of the most common mistakes that people make.

PDF Version

This page, Interfacing the Standard Parallel Port is also avaliable in PDF (Portable Document Format),

Interfacing the Standard Parallel Port (76KB)

Copyright 1999-2005 Craig Peacock 15th June 2005.

USB in a Nutshell - Introduction

USB in a Nutshell - Hardware

USB in a Nutshell - USB Protocols

USB in a Nutshell - Endpoint Types

USB in a Nutshell - USB Descriptors

USB in a Nutshell - USB Requests

USB in a Nutshell - Enumeration

PIC16F87x and PDIUSBD11 USB Example

USB 1.1 Integrated Circuits

USB 2.0 Integrated Circuits

USB Protocol Analysers

USB Device Driver Development

USB with the simplicity of RS-232

On-The-Go Supplement - Point-to-Point Connectivity for USB.

ISP1161 Host Controller for Embedded Systems

PDIUSBD11 USB Interface

Win 2000/XP Driver for DeVaSys USBLPT-PD11 USB Boards

USB Driver for the Cypress USB Starter Kit

Links

Ethernet & TCP/IP Interfaces

Embedded Linux, Setting up the Development Environment

Embedded Linux, Understanding the Build Tools

Embedded Linux, Building gcc-2.95.3 m68k-elf for uClinux

Embedded Linux, BFLT Binary Flat Format

Exploring the Netcomm NB5

Links

Standard Parallel Port (SPP)

Enhanced Parallel Port (EPP)

Extended Capabilities Parallel Port (ECP)

Parallel Port Debug Tool

Parallel Port LCD Interface Example

RS-232 Hardware & Software Registers

RS-232 Low Level Programming & External Hardware

Using Interrupts (PC)

Interfacing Example - Analog Sampling Via the RS-232 Port

Interfacing Example - Connecting a LCD Module to the RS-232 Port

Quick and Simple RS-232 Terminal

RS-232 Protocol Analyser

Links

PortTalk - A Windows NT I/O Port Device Driver

Universal Serial Bus Device Driver Development

Interrupts and Deferred Procedure Calls on Windows NT4/2000/XP

USB Driver for the Cypress USB Starter Kit

Device Driver Fiddler (tools)

Windows NT Device Driver Installer (tools)

Device Driver Remover Win9x (tools)

Links

CMOS Digital Image Sensors and Lenses

Generate Ring Tones on your PIC16F87x Microcontroller

Interfacing the AT Keyboard

How does the Microchip ICD Work?

Trust-No-Exe

Command Line Process Viewer/Killer/Suspender for Windows NT/2000/XP

BeyondExec - Spawn Processes on Remote Windows NT/2000/XP WorkStations

Beyond Logic Shutdown Utility for NT/2000/XP

Bmail - Command Line SMTP Mailer for Batch Jobs

Delete/Copy by Owner utility for Windows NT/2000/XP

Win32 Pipe Security Editor Windows NT/2000/XP

Console Computer Information Utility for 2000/XP

SMART & Simple for NT/2000/XP

Kodak DC215 Support and FAQ

South Australian Electricity Generation

Links