The Parallel Port What is the difference between a parallel port and a serial port? What makes the parallel port useful to me? The parallel port is a port which was originally designed by the Centronics Corporation as a way of transferring data to dot matrix printers. As the name implies data is transferred in parallel… opposed to serially. What does it mean to be transferred in parallel? It means that an entire byte is sent at a time. Where data transferred serially is transferred one bit at a time (recall there are 8 bits in 1 byte). So a parallel port can transfer data could in theory 8 times faster then a serial port. This however isn’t true since serial ports can have a higher baud rate depending on the design of the parallel port and the resources it has access to. For a parallel port transfers an entire byte at a time this means it must have 8 output pins. The point is since the parallel port transfers in parallel -> more input/output pins -> much easier to design circuits to interface (avoid using multiplexers, encoders/decoders, shift registers etc etc). Why the parallel port has 25 pins… How is it organized? The parallel port is made up of 3 registers (a register is a latch that digital logic can read/write values to depending on whether it’s an input or output). The three registers are called the DATA register, the STATUS register, and the CONTROL register. So each register is 8 bits or 1 byte -> 3 x 8 = 24 and the 25th pin is connected to GND. How each register is used DATA Register – was used to transfer data from the computer to the printer. So it is an output register. STATUS Register – is a register used for the states of the printer… Is a printer on, does it have paper, is there a paper jam… etc Therefore this register is an input register. CONTROL Register – is the register used to perform what is called handshaking. Handshaking is how a peripheral and the computer talk to one another while they’re transferring data. There are lines for when the peripheral is busy and ready so the computer knows when it can send the next byte to the printer. Since handshaking is bi-directional – the computer talks to the peripheral and the peripheral talks to the computer the register is bi-directional. Programming Statements Inportb(ADDRESS_OF_PORT) Outportb(ADDRESS_OF_PORT, BYTE_OF_DATA) ADDRESS_OF_PORT – is the port which you want to read (inportb) or write (outportb) to. BYTE_OF_DATA – since we are transferring data in parallel you have to write an entire byte at a time. A lot of the time when we’re using the parallel port for data acquisition or control we would like to be able to just modify one pin of the parallel port to send a pulse or enable an IC. But you can’t. you have to write an entire byte at a time which is no problem as you will see in the next section. How to output information using the DATA Port Example 1 – We have a LED attached to D0 and we want to blink it. Data Bit Binary Hex 76543210 00000001 01 // Convert Binary to hex by looking at bits 7-4, and 3-0 // Convert the 4 bits to DEC then to HEX (recall A=10, B=11…F=15) Therefore the code we’d use to blink a lead for 1 second is while(1) { outportb(DATA, 0x01) delay(1000) outportb(DATA, 0x00) } Example 2 – We have a LED attached to every other bit (pin) on the DATA port and we want to blink it. Data Bit Binary HEX 76543210 01010101 55 //note 0101 = 5 in DEC and 5 in HEX Code: while(1) { outportb(DATA, 0x55); delay(1000); outportb(DATA, 0x00); } // Makes every other LED light up // Keeps LED’s on for 1000ms or 1 sec before next statement turns them off How to input with the STATUS Port? First we need to talk about inverted bits. Recall in the beginning we talked about the status port which is used to tell the status of a printer. Well for the bit that is used for telling us whether or not there is a printer connected it is inverted in hardware. Reason is think about what would happen if there was no printer attached to the computer. Then you would have the infinite impedance state on all of the input bits on most bits this doesn’t cause a problem. But for a bit which is used to say whether a printer is connected or not since the infinite impedance state is a logic 1 the computer would think that a printer is connected when it really isn’t. Therefore to fix this problem the engineers who developed the parallel port inverted these bits in hardware. The status port only has 5 useable bits the other 3 are reserved. Bits 3-7 are the input bits and pin 7 is the inverted bit. From now on inverted bits will have an * next to them. Example 1 – we have a circuit which looks like: BINARY S7* | +5V 1 S6 | 0V 0 RawIn = inportb(STATUS) S5 | +5V 1 S4 | +5V 1 S3 | 0V 0 x x x // x’s are don’t cares for s2,s1,s0 -> RawIn = 00110xxx The inverted bit inverted bit 7. So we need to somehow invert the bit back in software. We will have to do this with bitwise operators (operators that are applied to each bit in the byte). There are several ways to invert a bit. One way to do it is to use the XOR operator. Recall that x XOR 1 = ~x XorIn = inportb(STATUS) ^ 0x80 Inportb(STATUS) ^ 0x08 // ^ is the bitwise XOR operator 0011 0xxx XOR 1000 0000 ---------------------1011 0xxx Now S7 has been inverted again which nulls out the prev. inverse Still need to get rid of the 3 x’s (the don’t cares from the reserved bits) Todo this we will just use the bitwise shift operator to shift each bit to the right 3 bits 10110xxx >> 3 = 00010110 or 10110 which is the desired result SUMMARY: Function is how you should read in from the status port to take into account the inversion. unsigned char get_correct_status_port() { return inportb(STATUS) ^ 0x80 >> 3 ; }