The Dragon and Tandy microcomputers have two Motorola 6821 peripheral interface adapters (PIA) mapped into the address space between $FF00 and $FF3F. The first of these, PIA-0, is located $FF00-$FF03, and the second, PIA-1, is located $FF20-$FF23. The Dragon 64 also has a third PIA at $FF04-$FF07 but this is not discussed here. Each PIA contains two 8-bit I/O ports, port A and port B, where each port and each of the 16 I/O pins are independently programmable as either input or output pins. Two control/interrupt lines are also associated with each port, allowing one extra input/output pin and one input-only pin per port. These pins can trigger an interrupt upon 0->1 or 1->0 transitions, or 'follow' outputs, and are therefore slightly more sophisticated than simple buffers, but can nevertheless be used simply as additional I/O. Each port is accessed and controlled through 3 registers. These are the peripheral data register (PDR), the data direction register (DDR) and the control register (CR). For PIA-0 port A the control register is mapped into the CPU address space at $FF01. However, only two memory addresses are used for each port and therefore both the PDR and DDR cannot be made available simultaneously. Instead bit 2 of the control register must be set or cleared to select whether it is the PDR or DDR which is visible at $FF00. This applies similarly to port B on PIA-0, and both ports of PIA-1. The memory map for the four ports of the Dragon/Tandy is as follows: ++---------+-------------------+----------------------------------------++ || Address | PIA & Register Id | Description of Dragon/Tandy Usage || ++---------+-------------------+----------------------------------------++ || $FF00 | PIA0-A PDR/DDR | Keyboard and joystick input. || || $FF01 | PIA0-A CR | MUX selector. || || | | || || $FF02 | PIA0-B PDR/DDR | Keyboard input and printer output. || || $FF03 | PIA0-B CR | MUX selector and timer interrupt. || ++---------+-------------------+----------------------------------------++ || $FF20 | PIA1-A PDR/DDR | 6-bit DAC, strobe, cassette input. || || $FF21 | PIA1-A CR | Cassette relay. || || | | || || $FF22 | PIA1-B PDR/DDR | VDG register and ROM/sound/busy bits. || || $FF23 | PIA1-B CR | Sound enable, cartridge interrupt. || ++---------+-------------------+----------------------------------------++ In normal operation the PDR is left visible for each port, with the DDR only made visible when necessary during configuration or reconfiguration. The format of the port registers is as follows: PDR - 8 bits of data as currently being input/output on the device pins. DDR - 8 bits, each indicating whether the corresponding PDR bits are for input (0) or output (1). CR - bit 7: control line 1 interrupt status (0 = idle, 1 = request) RO bit 6: control line 2 interrupt status (0 = idle, 1 = request) RO bit 5: control line 2 direction (0 = input, 1 = output) RW bit 4: control line 2 mode (0 = 1->0, 1 = 0->1 or 'follow') RW bit 3: control line 2 enable (0 = disable, 1 = enable) RW bit 2: PDR/DDR select (0 = DDR, 1 = PDR) RW bit 1: control line 1 mode (0 = 1->0, 1 = 0->1) RW bit 0: control line 1 enable (0 = disable, 1 = enable) RW RO = Read only RW = Read/write All registers are initialised to 0 upon hardware reset, although a pull-up resistor selects the 32K compatible ROM in Dragon 64 (see $FF22 below). Here is the complete bit-by-bit description of the Dragon/Tandy PIA connections: +---------+------+---------------------------------------------------------+ | Address | Bit | PDR / CR Description | +---------+------+---------------------------------------------------------+ | $FF00 | b7 | Joystick comparator - result of DAC value compared with | | | | the wiper selected by MUX. | | | b6 | \ | | | b5 | \ | | | b4 | \ Keyboard | | | b3 | > row 0 = pressed | | | b2 | / input. 1 = released | | | b1 | Left fire button. / | | | b0 | Right fire button. / | +---------+------+---------------------------------------------------------+ | $FF01 | b7 | Interrupt request (unused). | | | b6 | Interrupt request (unused). | | | b5 | \ | | | b4 | > MUX output bit 0 (see below). | | | b3 | / | | | b2 | DDR/PDR | | | b1 | \ | | | b0 | > Unused in D32, selects timer rate in D64. | +---------+------+---------------------------------------------------------+ | $FF02 | b7 | \ | | | b6 | \ | | | b5 | \ | | | b4 | \ Keyboard column output (0 = enable, 1 = disable). | | | b3 | / Printer parallel data output (strobe using $FF20 | | | b2 | / bit 1). Dragon only, as Tandy has serial port. | | | b1 | / | | | b0 | / | +---------+------+---------------------------------------------------------+ | $FF03 | b7 | IRQ interrupt request (read from PDR to clear). | | | b6 | Interrupt request (unused). | | | b5 | \ | | | b4 | > MUX output bit 1 (see below). | | | b3 | / | | | b2 | DDR/PDR | | | b1 | \ | | | b0 | > 50Hz timer IRQ enable/disable (60Hz in Tandy). | +---------+------+---------------------------------------------------------+ | $FF20 | b7 | \ | | | b6 | \ | | | b5 | \ 6-bit DAC (used for sound and joystick reading). | | | b4 | / | | | b3 | / | | | b2 | / | | | b1 | Printer strobe output in Dragon (on 0->1 transition). | | | | Printer serial data output in Tandy. | | | b0 | Cassette data input. | +---------+------+---------------------------------------------------------+ | $FF21 | b7 | Interrupt request (unused in D32, NMI in D64). | | | b6 | Interrupt request (unused). | | | b5 | \ | | | b4 | > Cassette motor relay output (0 = off, 1 = on). | | | b3 | / | | | b2 | DDR/PDR | | | b1 | \ | | | b0 | > Printer ACK (NMI in D64, usually disabled). | +---------+------+---------------------------------------------------------+ | $FF22 | b7 | \ | | | b6 | \ | | | b5 | > VDG video mode selector output. | | | b4 | / | | | b3 | / | | | b2 | RAM size input in D32 and Tandy (0 = 16K, 1 = 32K). | | | | ROM select output in D64 (0 = 64K, 1 = 32K compatible). | | | b1 | Single bit sound output. | | | b0 | Printer busy input (0 = available, 1 = busy). | +---------+------+---------------------------------------------------------+ | $FF23 | b7 | FIRQ interrupt request (read from PDR to clear). | | | b6 | Interrupt request (unused). | | | b5 | \ | | | b4 | > Sound output enable/disable. | | | b3 | / | | | b2 | DDR/PDR | | | b1 | \ | | | b0 | > Cartridge FIRQ enable/disable. | +---------+------+---------------------------------------------------------+ The MUX outputs are connected to a 2-bit multiplexer that is used to select which of the analogue joystick wipers are compared against the DAC output value by the comparator. The wipers can be selected as follows: 00 = right joystick, x wiper 01 = right joystick, y wiper 10 = left joystick, x wiper 11 = left joystick, y wiper The MUX also selects the current sound source as follows: 00 = 6-bit DAC 01 = cassette 10 = cartridge? 11 = cartridge?