A TWO-CHIP I/O EXPANDER FOR IBM PC PARALLEL PRINTER PORT Francis J. Deck fdeck@grumpy.helios.nd.edu INTRODUCTION A two-chip circuit which connects to the parallel printer port of an IBM PC or compatible computer provides 16 TTL-compatible i/o lines which are programmable in 4 groups of 4 bits. A short program in Turbo Pascal is given as an example of how to program the interface. The circuit can be expanded at the cost of one additional chip per 16 i/o bits. Total cost for the circuit is well under $10, using mail-order components. CIRCUIT DESCRIPTION Refer to the schematic diagram. Four Data lines from the parallel printer port are fed through a 74LS126 tri-state buffer. The outputs of the '126 are fed back into four Status inputs on the printer port. The Output Enable (OE) lines of the '126 are controlled by the PC, and the result is a 4-bit bidirectional "bus" which is shown as a double vertical bar. The 8243 is a specialized circuit which is part of the 8048 microcontroller family, and is intended for expanding the i/o ports of the 8048/49. It connects to the 4-bit bus, and has 4 4-bit i/o ports. It is controlled by a Chip Select (CS') line and a Program (PROG) line. To execute an 8243 operation, the PC places a 4-bit "instruction" on the bus, with the PROG line HIGH, and then pulls the PROG line LOW. If a "write" instruction is requested, the data to be written is placed on the bus, and the PROG line returned to a HIGH state. If a "read" instruction is requested, the 8243 places the input data on the bus. The driver software anticipates this, and disables the outputs of the '126, so that data can flow from the 8243 back into the PC via the Status inputs. None of this happens if the CS' line is HIGH, so multiple 8243s can share the same 4-bit bus, as long as the PC can control the CS' line of each 8243 separately. Although not shown in the schematic or implemented in the software listing, an additional 16 i/o bits can be implemented by adding a second 8243, whose CS' line is controlled by D7 (pin 9) from the PC. Note that the four ports are identified as P4 through P7, so that, e.g. P41 corresponds to bit 1 of port P4. SCHEMATIC DIAGRAM IBM PC Parallel Printer Port: 8 6 --------- 2 D6 >------------------------------|CS' P40|-------o P40 7 7| |3 D5 >------------------------------|PROG P41|-------o P41 2 2 -------- 3 11| |4 D0 >--------|1A 1Q|-----||-----|P20 P42|-------o P42 3 5| |6 || 10| |5 D1 >--------|2A 2Q|-----||-----|P21 P43|-------o P43 4 9| |8 || 9| |1 D2 >--------|3A 3Q|-----||-----|P22 P50|-------o P50 5 12| |11 || 8| |23 D3 >--------|4A 4Q|-----||-----|P23 P51|-------o P51 6 1| | || | |22 D4 >--------|1OE | || | P52|-------o P52 | 4| IC1 | || | IC2 |21 |----|2OE | || | P53|-------o P53 | 10| | || | |20 |----|3OE | || | P60|-------o P60 | 13| | || | |19 ----|4OE | || | P61|-------o P61 13 -------- || | |18 S4 <-----------------------|| | P62|-------o P62 12 || | |17 S5 <-----------------------|| | P63|-------o P63 10 || | |13 S6 <-----------------------|| | P70|-------o P70 11 || | |14 S7 <-----------------------|| | P71|-------o P71 18 | |15 GND >------Gnd | P72|-------o P72 | |16 | P73|-------o P73 --------- INTEGRATED CIRCUITS AND POWER CONNECTIONS # Type +5 Gnd -- ---- --- --- IC1 74LS126 14 7 IC2 8243 24 12 PARTS LIST The prices shown here are taken from Catalog #20 (1992) of: JDR Microdevices 2233 Samaritan Drive San Jose, CA 95124 800-538-5000 Description Cat. # Price ----------- ------ ----- 8243 IC 8243 2.95 74LS126 IC 74LS126 .39 24-pin IC socket 24 PIN ST .20 14-pin IC socket 14 PIN St .11 DB25 male plug DB25P .69 ----- TOTAL: 4.34 SOFTWARE LISTING {-------- 8243 i/o expander controller --------} program e8243; const cs = 64; {8243 chip select} prog = 32; {8243 program line} oe = 16; {74LS126 output enable} p4 = 0; {identifier corresponding to hardware port P4} p5 = 1; {and so on} p6 = 2; p7 = 3; var ina, outa: word; {input, output port addresses} {-------- Write an output port ---------} procedure write_8243 (p: integer; b: byte); var instr: byte; {8243 instruction} begin instr := p + 4; {signifies "write to port ch"} port [outa] := instr + prog + oe; port [outa] := instr + oe; port [outa] := (b and 15) + oe; port [outa] := (b and 15) + prog + oe; port [outa] := prog + cs + oe; end; {-------- Read an input port -------} function read_8243 (p: integer): byte; var instr: byte; {8243 instruction} begin instr := p; {signifies "read from port ch"} port [outa] := instr + prog + oe; port [outa] := instr + oe; port [outa] := 0; read_8243 := (port[ina] div 16) xor 8; port [outa] := prog + cs; end; {-------- Mainline --------} const nlpt = 1; base: word = $40; offs: array[1..3] of word = ($08,$0A,$0C); begin outa := memw[base:offs[nlpt]]; ina := outa + 1; port [outa] := cs + prog; write_8243 (p4,15); {set port P4 to all 1's} writeln (read_8243(p5)); {read port P5} end.