Inside the Motorola 6820/1 PIA
(Peripheral Interface Adaptor)

Originally published on September 18th, 1999 in the Usenet newsgroup: Rec.Games.Pinball

Functional Overview

The 6820/1 PIA can be classed as two seperate 8-bit ports with interrupt generating pins in one device. A two "channel" device if you like. 

Each channel has an 8-bit (byte wide) port and any of those 8 port pins can be configured as an input or output in any configuration. The ports are refered to as "port A" and "port B". The interrupt generating pins are CA1 and CA2 for port A and CB1, CB2 for port B. These are inputs on the the other side of the PIA (to the "outside world" - not the processor bus side). Cx1 is *always* an interrupt input pin, Cx2 can be either an interrupt generating pin or a basic output pin as per the ports.

Any state change received on the Cxx pins appear on the IRQ (Interrupt ReQuest) pins on the bus side of the PIA (providing Cx2 is set to generate interrupts). These pins - IRQa/b are tied together and also
tied to all other PIA IRQ pins in the system. This IRQ line is tied to the 680x processor with a pull-up resistor (wire OR operation). When the PIA acknowledges an interrupt on it's own Cxx pins, it sets the IRQa/b output pins low and the processor starts the IRQ service routine.

The PIA also has three Chip Select pins (CSx) which bring the PIA out of standby or "tri-state" operation via address decoding. In it's tri-state, the data bus lines are high impedance - virtually open circuit so
that they do not present any weight or draw current from the processor data bus whilst it's carrying out other system hardware operations. The IRQa/b output pins and the port sides/Cxx pins remain active even during tri-state operation so that they can still assert IRQs or acknowledge incomming data on the port side.

There are also two Register Select pins (RS0/1) and these two bits determine which of the internal six registers are being read from or written too. However, you don't need to be a rocket scientist to work
out that you can't address six registers with two bits (00,01,10,11 = 4 address combinations). So to understand how the PIA works - you need to look inside:

RS0/1  Register Select Bits

1 0 (Register select bits 1-0)

0 0 Peripheral Register A: Actual port data bits/pins
0 0 Data Direction Reg. A: Sets I/O for each pin. 0=input, 1=output.

The first thing you see here as that both registers share the same address. You determine which register you want to access by setting bit 2 of the "control" register. A "control" register exists for each

0 1 Control Register A:

 |      |    |    |    |    |    |_____|
 |      |    |    |    |    |       |
 |      |    |    |    |    |       '-- CA1 control (set-up)
 |      |    |    |    |    '-- =0 Direction. =1 Port itself/Periph. A
 |      |    '----'----'--- CA2 control (set-up)
 |      '--- (read only) Interrupt via CA2 (if set to gen. interrupts)
 '--- (read only) Interrupt via CA1

Bits 0-5 can be written too and read by the processor but the IRQ bits (6 and 7) are set by the PIA internally and the processor reads these two bits to determine which CAx pin asserted the interrupt and the appropriate action is then taken. The processor cannot write to bits 6 and 7. When the PIA sets bit 6 or 7 to "1" - it will lower the appropriate IRQa/b output pin, but since they're both tied together -
they both go low. The PIA will clear bit 6 and 7 itself after the processor has read the control port, ready for the next interrupt.

Port B has exactly the same configuration but substisute "B" for "A" and "2" for "1" on the CA/B inputs...

1 0 Peripheral Register B: Actual port data bits/pins
1 0 Data Direction Reg. B: Sets I/O for each pin. 0=input, 1=output.
1 1 Control Register B: Sets CBx config. Port Register access etc. that's your register addressing taken care of.

Out of reset. The PIA will always configure itself to both ports being inputs and all interrupts disabled. The processor has to reconfigure this for proper in-game operation.

So if you were to set up port A using 6800/2/8 assembly, it would look like this (for example):

A_direct   equ $2000
A_data     equ $2000
A_cntrl    equ $2001

         clr A_cntrl     ;access port A direction register (bit2=0)
         ldaa #$0f       ;upper 4 bits=input, lower 4 bits=output
         staa A_direct   ;set them.
         tab             ;accumulator B=accumulator A
         ldaa #$04       ;now access the...
         staa A_cntrl    ; port iself
         stab A_data     ;set outputs (lower 4 lines PA0/3 high out)

         ...             ;set port B...

The set-up and programming of the PIA depends on it's function. For instance, port "A" may set set to all outputs and each bit individually set high in sequence to sweep the switch matrix. Port "B"" may be
configured as all inputs to read the returns from the matrix and the code will determine the valid switch closures and their scoring etc.

Interupt Handling

Cx2 is the only pin that can be configured as I/O. Cx1 is interrupt generating only.

Cx1 configuration

bit1 bit0 Cx1 state  IRQa/b status    bit7 state
---- ---- ---------  -------------    ----------

 0    0   High>Low   Disabled (High)  =1 on low transition Cx1 pin
 0    1   High>Low   low when bit7=1  =1 on low transition Cx1 pin
 1    0   Low>High   Disabled (High)  =1 on High transition Cx1 pin
 1    1   Low>High   low when bit7=1  =1 on High transition Cx1 pin

Cx2 as Interrupt Generating
(Bit 5 cleared)

bit5 bit4 bit3  Cx2 state  IRQa/b status    bit6 state
---- ---- ----  ---------  -------------    ----------

 0    0    0    High>Low   Disabled (High)  =1 on low transition Cx2
 0    0    1    High>Low   low when bit6=1  =1 on low transition Cx2
 0    1    0    Low>High   Disabled (High)  =1 on high transition Cx2
 0    1    1    Low>High   low when bit6=1  =1 on high transition Cx2

Cx2 as I/O
(Bit 5 set)

bit5 bit4 bit3 bit2  Function
---- ---- ---- ----  --------

 1    0    0    0    Cx2 low after CPU reads port A data next low clock
 1    0    0    1    Cx2 high when bit 7 is set (interrupt pending Cx1)
 1    1    0    x    Cx2 = contents of bit 3 (Cx2=output 0 this case)
 1    1    1    x    Cx2 = contents of bit 3 (Cx2=output 1 this case)

-- End