Functional Specification of ParaPort
Global
Operating Model
To use ParaPort, its driver must first be installed
by the Windows "Add/Remove Hardware Wizard".
Client applications ( executables ) do not access directly the driver,
but use the Application Programming Interface ( "API" )
of the "ParaPort.dll" dynamic library. They generally follows
these steps:
- load the "ParaPort.dll"
- use functionality "open a port" to get a HANDLE ( in
the sense of Microsoft's Windows API ) to a port
- if needed, get information about the port
- write data to or read data from the port by "executing a
cycle" or
- write data to or read data from the port by using the "direct
register access"
- close the port, when no more needed
The ParaPortUtility application uses the underlying dll and driver
to set or clear pins of the parallel port.
System
Architecture

Data
Model
The central information item of ParaPort is a "cycle".
This is a structure ( in the sense of C or C++ ) containing seven
bytes:
A special direction bit ( 0x20 ) of the control register determines
whether the data register is used as output ( bit cleared ) or input
( bit set ).
As example:
- To set the pin 7 of the parallel port to logical high ( 5 Volt
TTL ), the structure member PARAPORT_CYCLE::Data must be set to
0x20 ( in comparison with the data
table ). PARAPORT_CYCLE::MaskData must also set to 0x20.
- To clear the pin 7 ( logical low = 0 Volt TTL ), PARAPORT_CYCLE::Data
must be set to 0x00. PARAPORT_CYCLE::MaskData must set to 0x20.
Timing
Model
Each cycle is seen as one moment in time. But since there are CPU
instructions to execute on the PC and electronic reaction on parallel
port hardware, the following timing diagrams can be measured on the
parallel port:
- if the direction bit 0x20 of the control register is cleared (
data register is output ):
- configure data register as output
- write data register ( * )
- write control register ( * )
- apply the "repeat factor" to waste time ( to enable
connected hardware to react )
- read status register ( * )
- if the direction bit 0x20 of the control register is set ( data
register is input ):
- configure data register as input
- write control register ( * )
- apply the "repeat factor" to waste time ( to enable
connected hardware to react )
- read data register ( * )
- read status register ( * )
All register are written or read ( the lines marked with "*"
) only, if the correspondent mask byte is not equal to 0x00.
Repeat Factor
The following figure has been measured with a logical analyser during
the execution of the sample application "sampleRepeatFactor".
As you can see in the source
code, different pulses has been generated using each two cycles.
Each cycle lasts approximate 5 micro seconds. By setting the byte
"PARAPORT_CYCLE::RepeatFactor" in the structure, a cycle
can be extended ( e.g.: cycles 3, 5, 7 ).
To extend the time between pulses, the cycles 2, 4, 6 should get
a value > 0 for the byte "PARAPORT_CYCLE::RepeatFactor".

Pulsed or Clocked Input / Output
During one cycle, the state of the pins can be set, cleared or read.
To realize "Pulsed or Clocked I/0", two cycles are needed
for each pulse, if the hardware is "edge driven". In other
cases, three cycles are needed.
As example 1:
To write 0xAE on the data register with a clock (e.g.: _Strobe),
two cycles are needed:
| |
Cycle 1 |
Cycle 2 |
| PARAPORT_CYCLE::Control |
0x01 |
0x00 |
| PARAPORT_CYCLE::MaskControl |
0x21 |
0x01 |
| PARAPORT_CYCLE::Data |
0xAE |
0x00 |
| PARAPORT_CYCLE::MaskData |
0xFF |
0xFF |
- Cycle 1 configures the data register as output and puts 0xAF on
the parallel port. Then the _Strobe signal line is triggered and
the repeat factor is applied.
- Cycle 2 resets the _Strobe signal line and puts into the data
register 0x00 as the default value on idle time. If an other value
( e.g.: 0xFF ) is wanted, "Data" must be changed; if the
last set value ( here 0xAE ) is wanted, the "MaskData"
must set to 0x00. If the default state of the data register is input,
the bit 0x20 must be set in the "Control" structure member.
As example 2:
To read a byte from the data register with a clock (e.g.: _Strobe),
two cycles are needed:
| |
Cycle 1 |
Cycle 2 |
| PARAPORT_CYCLE::Control |
0x21 |
0x00 |
| PARAPORT_CYCLE::MaskControl |
0x21 |
0x01 |
| PARAPORT_CYCLE::Data |
read value |
0x00 |
| PARAPORT_CYCLE::MaskData |
0xFF |
0xFF |
- Cycle 1 configures the data register as input, the _Strobe signal
line is triggered and the repeat factor is applied. Then the data
register will be read and the value will be stored in the "Data"
structure member.
- Cycle 2 resets the _Strobe signal line and puts into the data
register ( here, its default state is "output" ) 0x00
as the default value on idle time. If an other value ( e.g.: 0xFF
) is wanted, "Data" must be changed; if the last set value
( here 0xAE ) is wanted, the "MaskData" must set to 0x00.
If the default state of the data register is input, the bit 0x20
must be set in the "Control" structure member.
Direct
Register Access
From release v2.0 on, the data, control and status register can be
accessed directly using "input"
and "output" methods. By calling the function "getPortAddress(
)" the client application can use these functions like "inp(
)" and "outp( )" known from DOS and Windows 9x operating
systems.
Copyright (c) 2002, 2003, 2004 by Paul R. ADAM,
v2.0, read the Terms of Use