par. Interface
Slot Control
Slot Pinouts
Signals & Ports
pk$setp Info

How to build a Parallel Interface

Dr. Andrew Smith


This document describes how the three slots of the Psion II can be controlled by assembly language routines, and how a parallel I/O facility providing up to eight 8-bit parallel I/O devices can be connected to a slot. Example assembly-language device-driver routines are included. The system can be used with OPL routines running on the Psion if this approach is required.

General Slot Control

Parallel interfacing to the Psion II can be effected via any of the three interface slots - the Topslot, or the memory pack slots B or C. These slots carry signals derived from two on-chip parallel I/O ports on the 6303 CPU. Interfacing is achieved by manipulating these ports with machine code routines running in the Psion's RAM. It is not realistic to attempt to manipulate the ports directly using OPL programs, although short machine code routines can be written which are then called using the OPL USR function. This technique can make the ports accessible to OPL programmers: examples of suitable assembler routines are given later.

The 6303 ports of interest are port 6 and port 2. Both are 8-bit parallel I/O ports, and each has a data register and an associated data direction register (ddr). Writing $FF to a ddr makes the related data port an output, while writing 0 to a ddr makes the port an input. Addresses are given below:


Register Address
Port 2 DDR 1
Port 2 Data (P2D) 3
Port 6 DDR $16
Port 6 Data (P6D) $17


P2D is available directly on the Psion's slots and is the port through which external data exchanges are made.

Since the port is common to all three slots it forms a kind of peripheral data bus, and data on it is therefore presented to all devices in any slot. This means that the data is transitory, and is must be addressed to a specific device in a specific slot at a specific time. Slot devices must latch output data, or enable input data under the control of ancillary control signals. P6D controls these signals.

Names of signals and allocation to ports

Slot data signals (the peripheral data bus) are designated SD0 to SD7 and correspond to Port 2 signals P2-0 to P2-7 respectively.

Slot ancillary control signals have the following names - SS1, SS2, SS3, SOE, SMR, SCK, SVCC, SPGM, and are derived from P6D as follows:


Port 5 Bit 7 6 5 4 3 2 1 0


The functions of these signals will be described later, but at this stage it is worth noting that the most critical signals from the point of view of the programmer are SS1 to SS3. These are used as low-active Slot Select signals. Only one of these is available at each slot, a different one in each case. SS3 is present on the Topslot, SS1 on Slot B and SS2 on Slot C.

It is most important that the programmer only writes one of these low at any time, since the signals are used to enable slot devices, and if two or more devices are simultaneously enabled data contentions will occur. These signals are held high even when the Psion is switched off.

Slot Pinouts

Top Slot

Fig 1. Top Slot (Slot 3)


Pin 15 13 11 9 7 5 3 1
Pin 16 14 12 10 8 6 4 2


Side Slots

Fig 2. Slots B (1) and C (2)


Pin 16 14 12 10 8 6 4 2
Pin 15 13 11 9 7 5 3 1


Signal Descriptions

Name Description
AC Topslot External On/Clear.
Ground this to turn the Psion on.
GND 0v
Parallel I/O Peripheral Bus (P2D)
SCK Peripheral Control lines - see below
SPGM Program enable for EPROM packs
SS1-3 Slot select (active low) - see above
SVB Topslot External Power Input. Can be connected
to an external 9v power supply via a diode.
SVCC 5v Power supply output to slot devices,
derived internally from SVB or battery
SVPP 21v programming voltage for EPROM packs



These signals can be used as general purpose signals for controlling I/O devices connected to the slots. Typical functions include Read/Write control, I/O Device Select, etc.

Some information is given here relating to conventions used by existing Psion devices. Note that Psion memory packs generate a local address signal by means of binary counters which are incremented or cleared (reset) by these signals.


0 0 1/0 Clock (increment) address counter
0 1 0 Reset address counter
0 1 1 No information
1 0 0 Output enable
1 1 1/0 Printer latch
see: Technical Reference > Low Level Pack Access

A Simple System for up to Eight parallel Ports

This system (Fig 3) uses a 74LS244 octal buffer as an input device and a 74LS374 octal D-type flip-flop as an output device.

A 74LS138 decoder is used to select the devices: up to 8 I/O devices can be addressed, and they may be any mix of the two types illustrated.

74HC devices can be used, but it is then probably wise to add pull-up resistors to the SD bus and control lines in order to define their state when all attached devices are either high-Z outputs or inputs.

Since it is necessary to apply power to the '374 device on order to retain stored data, it is best to power the system from an independent 5v supply rather than SVCC.


Please note:

The prototype system was attached to Slot C since I have a serial Comms Link on the topslot and a datapack in slot B.

The system described here is fully compatible with these devices on the other slots, but the software must be edited if the I/O system is to reside on any other slot than C.

It is recommended that the I/O software should not be run when any device other than the I/O system is present on Slot C.


Fig 3. Parallel I/O System Expandable to 8 Ports



As has been previously mentioned, it is necessary to control the slots using machine code routines. Although at first sight it might seem that Ports 2 and 6, and their ddrs might be written to using POKEB statements, in fact any effect this might have is strictly transitory: the registers revert to their default states as soon as OPL is re-entered. Three suitable assembler routines (read, write, and setp) are listed below, and will now be discussed in relation to general slot control conventions.

Software conventions

Some important conventions must be observed while writing to the slot-control registers. These are

  1. For full system compatibility a system call to pk$setp (SWI $62) must be made before accessing a slot. This is discussed further below.
  2. Only one SS output should be written low at any time. In the present case SS2 is used since it is assumed that the I/O ports will be connected to Slot C (2). Topslot (3) is controlled by SS3, while Slot B (1) is controlled by SS1.
  3. Port 2 can be assumed to be in the input condition at entry to the user routines, and must be left as an input on exit. Port 6 can be assumed to be an output at all times, and its ddr need not be changed.

The general protocol for controlling the slots for is as follows:

  • Set Port 6 to output a byte which deselects all slots except the required one, and sets the other control lines as required. In the present case SOE, SCK and SMR will represent a 3-bit device-select code, while SS1-3 will be 101 (SS2 low-active for slot C).
  • If an output is required, set Port 2 to output the required byte. The default state of Port 2 is input, so if an input is required this step can be omitted.
  • If an input is required, read from P2D.
  • Change the state of P6D to deselect the port (SS1-3 all high). In the present case this will latch output data if an output device has been selected. ('374 G goes high).
  • Return P2 to the input condition if its ddr has been changed.

The write Subroutine

This has been designed to be compatible with a call from OPL via a USR statement.

The routine should be called with the byte to be output in B while a device-select code should be in A.

In Fig 3 the output device will be selected if A is 1.

The call to pk$setp is discussed in the section on System Compatibility.

The read Subroutine

Entry conditions are the same as in 'write' except that the content of B is not used.

The input device is selected by a byte in A (for Fig 3, A should be clear). The byte which has been read from the input device is passed out in X.

Device-select Codes for I/O devices enabled by the 74LS138

Enable Code
Y0 0
Y1 1
Y2 2
Y3 3
Enable Code
Y4 8
Y5 9
Y6 10
Y7 11


System Compatibility

For full compatibility with devices which might be present on other slots a call must be made to the system routine pk$setp each time the I/O slot is selected. A description of pk$setp, is given below.

If the read or write routines are called from OPL, pk$setp must be called each time read or write is used; hence the bsr setp statement is included in these routines.

However, pk$setp is very slow in execution, and flashes an unwanted 'Sizing Pack C' message on the screen, both of which are less than desirable features. It is better to use read and write as a components of a purely machine-code program, in which case setp need only be run once each time the active slot is changed to slot C. The calls to setp at the beginning of read and write can then be deleted.

It is evident that the Psion's normal operating system interrogates the slots from time to time in order to determine which hardware elements are present. It does this by sending an appropriate byte on Port 6 and reading a response on Port 2.

The circuit of Fig 3 makes no provision for returning this kind of information in a controlled way. Its response will depend on the signals on Port 6 and (perhaps) on any inputs connected to the input port. Inappropriate messages relating to the supposed nature of Slot C therefore appear from time to time on the Psion's screen, but apparently without harmful effect. This defect is currently being researched.

Example routines

1) Assembly language Routines

    ;code for psion parallel io.
    ddr2    equ     1
    port2   equ     3
    ddr6    equ     $16
    port6   equ     $17
    noslot  equ     $70         ;P6 data - deselect all slots
    pk$setp equ     $62
    setss   equ     $50         ;P6 - select slot C (2). 
                                ;Change to $30 for topslot or $60 for slot B (1)
    slot    equ     2           ;used in setp to enable slot 2.
                                ;Change to 1 or 3 as required

    write       ;writes a byte in b to an output port
                ;call with a device-select code in a
            bsr     setp        ;see notes on compatibility
            oraa    #setss      ;enable slot and select output device.
            staa    port6
            stab    port2       ;write data to port 2
            ldaa    #$ff        ;set port2 to output and output the data
            staa    ddr2
            ldab    #noslot     ;deselect all slots.  G (latch) goes high
            stab    port6
            clr     ddr2        ;set port 2 back to input

    read        ;reads an input port and returns data in x
                ;call with a device-select code in a
            bsr     setp        ;see notes on compatibility
            oraa    #setss      ;select an input device and enable slot...
            staa    port6       ;...input device enabled
            ldab    port2       ;read port2
            clrb                ;reserve two bytes on the stack for x
            pulx                ;get data into x
            ldab    #noslot     ;deselect all slots.  Input device disabled
            stab    port6

    setp        ;this is just a system call to pk$setp.
                ;see notes on compatibility
            psha                ;preserve registers
            ldab    #slot       ;enable the designated slot
            byte    pk$setp
            pulb                ;restore registers


2) OPL Routines

In these examples it is assumed that write has been assembled to $400, and read to $415. If the code has been stored at different addresses the mc% variables must be altered to suit. See MC-tutorial for techniques of loading machine code.

dev% is used to contain a device-select code.

Warning: Using these routines without having loaded the machine code to the proper address will almost certainly crash the system!


This routine prompts for a number, which is forced to be in the range 0 - 255, and outputs it to the device enabled by Y1, (i.e. the 74LS374 output device, Fig 3)

        local mc%,dev%,byt%,num%
        mc%=$400 :rem code addresse
        dev%=1 :rem output device
        do print "Number ?"
          input num%
          byt%=num%-256*(num%/256) :rem equivalent to byt%=num% mod 256
          usr(mc%,dev%*256+byt%) :rem dev% in A, byte% in B
        until num%>255


This routine reads the input device selected by Y0 - i.e. the 74LS244 input device (Fig 3) and prints the returned byte.

        local mc%,dev%,byt%
        mc%=$415 :rem code addresse
        dev%=0 :rem input device
        print "Press Z to end"
          byt%=usr(mc%,dev%*256): rem dev% is put into A
          print hex$(byt%)
        until byt%=%Z or byt%=%z

Description of system call pk$setp


Sets up the operating system to access the current pack.

It powers up the slots (if they are powered down) and selects the required slot. It then detects if a pack is plugged into that slot and if so "logs on" that pack.

INPUT: A = Non-zero if pack change is to be an error, zero otherwise.
  B = Pack to select (0-3)
OUTPUT: A = Pack type
  X = Size of pack in 8K units (not for pack A:)

This routine must be run before using any other pack routines if the packs have been turned off.

In preparing the system to use a pack

  • the packs are powered up if necessary: PKB_CPAK ($8C) is $FF when packs are off
  • the variables PKB_CPAK and PKB_CURP ($8B) are set to the contents of the B register
  • the first 10 bytes of the pack are read into PKT_ID ($20D7 - an array of 4 elements each 10 bytes long for each of the packs)
  • PKA_PKID ($94) is set to point to the pack ID string in PKT_ID
  • the pack header checksum is checked, if this fails, the the pack is seized
  • the pack address is set to 0:
    • PKW_CMAD ($8F) for pack A,
    • PKW_CPAD ($92) in connection with PKB_HPAD ($91 - high order byte) for a datapack.
  • if a datapack is chosen then a battery check is also performed.

The following errors can be generated:

194 battery too low
240 unknown pack
241 pack not blank
242 pack changed
243 bad device name
244 read only pack
245 write pack error
246 no pack in slot


The information contained in this document is presented in good faith. The systems described here have been tried on my own equipment, and operate successfully. However, this information is released on the condition that any one who uses it, does so entirely at their own risk and on the understanding that they alone must be responsible for any loss or damage which may result.


This document is based on information drawn from many sources including my own experience and other material published on this website.

The author wishes to thank all those who have made information about the Psion publicly available.


Dr. Andrew Smith 1/2003