How to control peripheral ports: Accessing and writing on Parallel Port with C on Linux. Part I
One of the most striking and emerging use cases to control peripheral ports on a PC is home automation, this technology offers an infinite field of possibilities in our homes. Home Automation is a technical discipline with a social side. Our approach is, using some key phrases, to improve the quality of life, expand the communication and automate processes. All this seems to be quite simple, but the complexity inherent in this new world of home automation is exciting, let´s see why.
Home Automation is a complex activity for several reasons. First, the operation on home devices (sensors, smart appliances, actuators ...) gives you an idea of the complicated physical phenomenons, such as mechanical quantum or the photoelectric effect. Furthermore, one of these devices can perform various tasks and not necessarily just a simple one. In the second place, talking about Home Automation is talking about systems made up of many different components that do not always interact easily (imagine a home security system that includes video cameras, presence detectors, communication equipment, alarms with a remote warning system, etc. ...). Finally, and most importantly, it is complex because it faces automation of technical systems with social systems.
Definition of Terms
Parallel Port:
A parallel port is an interface between a computer and a peripheral device, whose main characteristic is that the data bits are traveling together, sending a packet byte at a time. A cable or physical pathway for each bit of data is implemented by forming a bus of 8 lines. Through the parallel port, we can also control peripherals such as lights, motors, and other devices.
Web Interfaces:
A Web Interface allows users to control and interact with their devices through a web browser. This can be used for a remote control, library management, visual feedback, and many other things.
Home Automation:
It's the automation of all systems capable of automating a home, providing energy management services, security, welfare and communication, and can be integrated in wired or wireless indoor and outdoor communication networks.
How to work with Parallel Ports in C
For our primary purpose, the basic home automation, we will use the parallel port to demonstrate how we can write (or read) some bytes for controlling simple devices. The parallel port of a PC ECP Type has a female DB25 type output connector whose diagram and signals can be seen in the following figure:
Parallel port output
The parallel port of a PC, according to the Centronics standard, is composed of a bidirectional 8 data bit communication bus, plus a set of lines for the protocol. Communication lines have a retainer that holds the last value that was written to them until new data is written, the electrical characteristics are:
- High-level voltage: 3.3 to 5V.
- Low level voltage: 0 V.
- Maximum output current: 2.6 mA.
- Maximum input current: 24 mA.
The voltage and current can feed a set of control devices like LED's, Relays, and Solid State switches. These buffers are required to turn off or on elements with a higher power consumption.
Addressing
The addressing of a standard parallel port is important due to the variety of resources it uses from the computer and for identification purposes. The standard parallel port uses three contiguous addresses, usually in one of these ranges:
3BCh | 3BDh | 3BEh |
378h | 379h | 37Ah |
278h | 279h | 27Ah |
The first address in the range is the port's base address, also called the Data register or just the port address. The second address is the port's Status register, and the third is the Control register.
EPPs and ECPs reserve additional addresses for each port. An EPP adds five registers at base the address + 3 through base address + 7, and an ECP adds three registers at base address + 400h through base address + 402h. For a base address of 378h, the EPP registers are at 37Bh through 37Fh, and the ECP registers are at 778h through 77Fh.
DMA Channels
ECPs can use direct memory access (DMA) for data transfers to the parallel port. During the DMA transfers, the CPU is free to do other things, so DMA transfers can result in faster performance overall. In order to use DMA, the port must have an assigned DMA channel, in the range 0 to 3.
Accessing Physical Ports on Linux
Because the port hardware on a PC is controlled directly by the Linux kernel, we must access certain headers related to the parallel port bus. The GCC compiler can access these headers, always bearing in mind that the user must have root privileges to avoid access errors. These headers are:
- stdio.h: The "standard input-output header" (standard header I / O) is the header file that contains the macro definitions, constants, function declarations in the standard library of the C programming language to perform operations, standard input and output, as well as the definition of types necessary for such operations. For compatibility reasons, the programming language C ++ (C derivative) also has its own implementation of these functions, which are declared with cstdio file header. The function I have to use is fprintf which allows to print on a terminal window if there is any error.
- stdlib.h: Is the header file for the standard library of the general-purpose programming language C. It contains the C function prototypes for dynamic memory management, process control and other. It supports C ++ where it is known as cstdlib. The function I will use is exit when we get an error
- unistd.h: Header file that provides access to the POSIX operating system API. On Unix-like systems, the interface defined by unistd.h is typically made up largely of system call wrapper functions such as fork, pipe and I/O primitives (read, write, close, etc.).
- sys/io.h: This family of functions is used to do low-level port input and output. The out* functions do port output, the in* functions do port input; the b-suffix functions are byte-width and the w-suffix functions word-width; the _p-suffix functions pause until the I/O completes. Of this family function I will use outb.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
In Linux, it is easy to access and control the parallel port, however, root access must be highly considered. The above are all required libraries for our tutorial today.
Defining the Memory Address for the Parallel Port
Once included the libraries, we must define the memory address assigned to the parallel port, as mentioned above, the default address for the first parallel port is 0x378.
#define base 0x378 /* parallel port base address */
If you have any issue trying this address you should try 0x278.
Using the Data Bus as an Output Port
For this first part tutorial I´m going to use the Data Bus as an output Port. In the next chapter we'll see how to use it as a port for data input or even as mixed port. In the image below we can see the control of a set 8 LEDs connected, through current limiting resistors, to parallel port, which respond to the value assigned to the address 0x378. The value for the resistors may vary from 100 Ohms to 300 Ohms, it´s important this part because we can damage the port if we don't limit the current.
Schematic
Note: The color of the LEDs is not important.
Real Circuit
Caution: Please be careful in the handling of the parallel port connector, be sure you don't disconnect the circuit before turning off the PC. This may cause damage to the port or even to the Motherboard. We cannot assume any damage you can cause to your hardware devices.
Software Implementation
For my purposes, I'll show you how to put some values in the port, and how the timing of those values has to be done, this is a very simple routineto show you how it works.
Now I will explain all the commands and words used in the control software:
- Step 1: Condition if the user has root permission to access the port. The argument for this conditional command is ioperm which sets the port access permission bits for the port address base.
if (ioperm(base,1,1))
- Step 2: If the user does not have sufficient privileges to access the parallel port, an access error will be displayed and the program execution will end.
fprintf(stderr, "Access denied to %x\n", base), exit(1);
- Step 3: If the access is granted, then a for loop will give a sequence of on and off to the LEDs by predefined values to display in the port. The timing function I used is sleep() which makes the calling thread sleep until seconds in argument have elapsed.
w=0;
for (x=0; x=7; x++)
{
y=pow(2,w);
outb(y, base);
sleep(1);
w=w+1;
}
When the code processing passed the access allowed line, 'fprintf (stderr, "Access denied to% x \ n", base), exit (1);', the data pins of the parallel port are available at your disposal and imagination. In my case I only take a simple sequence from the first led to the last with an interval of one second, using powers of base 2. (see the video link). However, the possibilities are infinite, in fact, without using multiplexing can control up to 8 independent outputs, with multiplexing outputs can grow up to 255 possibilities. Depending on the application, whether it is in terms of home automation, we can handle the port without multiplexing, placing the appropriate buffers to handle higher current loads, which will be treated later in another tutorial.
References:
Martin H, Saez F. Domotica, Un Enfoque Sociotécnico. June 2006. Fundación Rogelio Segovia para el Desarrollo de las Telecomunicaciones, Ciudad Universitaria, s/n 28040-Madrid, ISBN: 84-7402-335-1.
Axelson J. Parallel Port Complete. Programming, Interfacing, & Using the PC's Parallel Printer Port. Amazon INC.. ISBN: 0-9650819-1-5
Kerrisk M. The Linux Programming Interface. Linux man-pages Project. ISBN 978-1-59327-220-3