Tutorial navigation bar (Parallel port and Joystick port)

Introduction.

The serial port enables to the electronic designer to communicate a PC with devices that supports the RS-232 standard. On the other hand, the parallel port outputs eight data bits and five input signals. It outputs only one interrupt signal (IRQ7).

On the contrary the ISA BUS outputs a 20 bit address bus and a 8 bit data BUS. Allows to manage most of the PC interrupt signals and even, drive DMA (direct memory access) transfers.

Description of the BUS.

In the figure you can see the pinouts of the ISA BUS. The BUS is divided into two sides. The first side pins are named A1 to A31 and it is the components side. It consist of the address and data buses. The second side pins are named B1 to B31 and it is the solder side. This side contents the power pins and the signals related to interrupts and DMA transfers.

We list the most used pins and its description below. For the "A" side:

A0-A19 (pins A31 to A12): This twenty lines are the address BUS. They can address 1MB (2^20 bytes).
D0-D7 (pins A9 to A2): The data BUS consist of this eight data lines.
AEN (pin B11): It is used for the DMA controller to take over the data and address buses in a DMA transfer.

For the "B" side:

GND (pins B1, B10, B31): Connected to the ground of the computer
+5V (pins B3, B29): 5V DC output of the power source.
-5V (pin B5): -5V DC output.
-12V (pin B7): -12V DC output.
+12V (pin B9): +12V DC output.
MEMW (pin B11): The uP asserts this signal when doing a write to the memory.
MEMR (pin B12): The uP asserts this signal when doing a read from the memory.
IOW (pin B13): The uP asserts this signal when doing a write to a port.
IOR (pin B14): The uP asserts this signal when doing a read from a port.
DACK0-DACK3 (pins B15, B17, B19 and B26): The DMA controller sets this signals to let a device know that the DMA has the control of the buses.

DRQ1-DRQ3 (pins B6, B16 and B18): Allow the peripheral boards to request the use of the buses.
+T/C (pin B27): The DMA controller sets this signal to let the peripheral know that the programmed number of bytes has been sent.
IRQ2-IRQ7 (pins B4, B21, B22, B23, B24 and B25): Interrupt signals. The peripheral devices sets this signals to request for the attention of the uP.
ALE (pin 28): This signal is used for the uP to lock the 16 lower address BUS in a latch during a memory (or port) input/output operation.
CLOCK (pin 20): Is the system clock.
OSC (pin 30): Is a high frequency clock which can be used for the I/O boards.

Let's start describing the operation of the ISA bus with a simple read cycle from an Input/Output port. The first thing the microprocessor does is to send out a high on the ALE signal, then sends out the A0-A19 lines. After, the ALE signal goes low. From now on the address of the target port to be read will be latched. Then the BUS takes the -IOR signal to a low level. So that the addressed device will take a data byte to the D0-D7 data bus. The microprocessor will read then the data bus and take the -IOR signal to a high again.

A write cycle to a port works this way: The microprocessor asserts the ALE high, then outputs A0-A19. ALE goes low again. The microprocessor send out the data byte to be write. It then asserts the -IOW signal. After the device have time to read the data byte, the uP raises the -IOW signal high again.

The only difference between a memory read/write cycle and a port read/write cycle is that in a memory cycle the -MEMR and -MEMW signals will be asserted, working the same way as -IOR and -IOW do.

Driving Interrupts.

In the PC memory map we can find two kinds of interrupts, the software interrupts and the hardware interrupts. In this tutorial only the hardware interrupts will be explained. In a PC, the external interrupts are driven by the 8259A priority interrupt controller. When an 8259A receives an interrupt signal through the IRQ2 to IRQ7 signals, it sends an interrupt request signal to the INTR input of the uP. Then the 8086 outputs an INTA (interrupt-acknowledge) signal to the 8259. So that the uP can get interrupt type of the external device. The 8086 then uses the type read from the external device to get the address for the interrupt-service procedure from the interrupt pointer table in memory. Note that INTR and INTA are not present in the ISA bus, this signals are only used for the uP and the 8259A.

Programming Interrupts.

The basic target of an interrupt is to execute a function that response to the request of a hardware device. An interrupt vector contents the address of this function. In an 8086 system the first Kbyte of memory (from 00000H to 003FFH) is used for the interrupt vectors. To point to any address of the whole memory map four bytes are needed. 16 bits for the base address and 16 bits to identify the segment. So, a 1Kbyte of memory allows to store 256 interrupt vectors. Some of the 256 interrupt vectors are used for the system, others are free to be used for the user programs. To install a user interrupt service procedure you can use a program like the one of the example.

The program install an interrupt routine in the IRQ1 interrupt channel, which is the system timer. This timer generates an interrupt 18.2 times per second. In the interrupt service routine, we increment a global variable. When this variable equals to 18 is printed on the screen. So that, we will get on the screen a second counter.

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

#define IMR 0x21

int _key=1;
int global=0;
void interrupt (*_old_int_function)();
char _old_mask;

char _interrupt_mask(int IRQn)
{
char p=1;
p=p< return ~p;
}

void _install_int_function(int IRQn, void interrupt (*_new_int_function)())
{
int inter = IRQn + 8;
_disable(); //disable interrupts
_old_int_function=_dos_getvect(inter); //save the old interrupt vector
_dos_setvect(inter,_new_int_function); //install the new interrupt vector

_old_mask=inportb(IMR); //save the state of the 8259A IMR register
outportb(IMR,_old_mask&_interrupt_mask(IRQn)); //Set new value for IMR register
_enable(); //enable interrupts
}

void _end_interrupt(void)
{
outportb(0x20,0x20);
}

void _Unistall_new_int_function(int IRQn)
{
int inter = IRQn + 8;

_disable(); //disable interrupts
_dos_setvect(inter,_old_int_function); //restore the old interrupt service function

outportb(IMR,_old_mask); //restore the IMR
_enable(); //enable interrupts again
}

void interrupt _new_int_function()
{

_disable(); //disable interrupts
global++; //global count the number of interrupts
//that the system has requested
_end_interrupt(); //to tell the system the interrupt service function has finished
_enable(); //enable interrupts again
}

/*********************************************************/
/*Read the keyboard. If "ESC" is pressed the program ends*/
/*********************************************************/

void _keyboard(void)
{
union u_type{int a;char b[3];}keystroke;char inkey=0;

if(bioskey(1)==0) return;
keystroke.a=bioskey(0);
inkey=keystroke.b[1];
switch (inkey)
{
case 1: _key=0;
return;
case 11: _key=39;
return; /*_key 0*/
default: _key=15;
return;
}
}

void main(void)
{
int second=0;
clrscr();
cprintf("Press 'ESC' to exit \n \n");

_install_int_function(0,_new_int_function);
do
{
_keyboard(); //read the keyboard
if (global >=18)
{
second++; //incremented each second
gotoxy(2,2);
cprintf("Time: %d",second);
global=0;
}
}
while(_key !=0);
_Unistall_new_int_function(0);
}

DMA transfers.

Some input/output devices send data faster than the microprocessor can get it. The DMA (Direct Memory Access) is a dedicated IC that sends and receives data faster than the microprocessor. So magnetic and optical disks use this IC to access the memory of the system.

The DMA (Direct Memory Access) controller borrows the address bus, the data bus and the control bus from the system and transfers a programmed series of bytes from a fast I/O device to the memory. The 8237 DMA controller is the device used for the PC to do this job.

When a device has a data block ready to be send to the memory, sends a DMA request asserting a DRQn signal to the DMA controller. If the requested channel is unmasked, the DMA will send a HRQ (hold request) signal to the microprocessor. The microprocessor will respond floating its buses and sending a HLDA (hold acknowledge) signal to the DMA. Then the DMA gets the control of the buses asserting the AEN signal high and sending out the address of memory to be written. Next the DMA outputs the DACKn (DMA acknowledge) to the device. Finally the DMA controller asserts the MEMW and IOR signals on the control bus. When the data transfer is completed unasserts the HRQ signal and the processor gets the control of the buses again.

If a device needs some data from the memory, the process is similar. The only difference is that the DMA controller outputs the MEMR and IOW on the control bus.


[ Home page ] [ Tutorial ] [ Kits ] [ Links ] [ Versión en español ]


Questions, comments, suggestions ?

Please e-mail us at: pckits@apdo.com