TECH: 6808 Theory
Author: Clive Jones
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 Description Function ----- ----------- -------- 0 0 Peripheral Register A Port data bits themselves 0 0 Data Direction Reg. A Sets I/O 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 port...
RS0/1 Description Function ----- ----------- -------- 0 1 Control Register A
|bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0| | | | | | | |_____| | | | | | | | | | | | | | '-- 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...
RS0/1 Description Function ----- ----------- -------- 1 0 Peripheral Register B Port data bits themselves 1 0 Data Direction Reg. B Sets I/O pin. 0=input, 1=output 1 1 Control Register B Sets CBx config. Port Register access etc.
...so 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 Init_pia: 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 ;...data 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.
Added 10 January 2001
there is some supplementary info for this post...
Interrupt Handling, Control Register
Cx2 is the only interrupt generating pin that can also be configured as I/O. Cx1 is only capable of generating interrupts.
* 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)