The PSION Organiser II Homepage
 
Home
Technical Reference
Introduction
System
Versions
Operating
System
Memory Usage
Filing System
System Timing
System Board
Power Supply Board
Display
Keyboard
Interface Slots
Packs
General
Flashpacks
Low Level
Access
External
Interfacing
Comms Link
Psion Link
Protocol
Utility System
Services
Built-in
Applications
LZ Passwords
Programming
Language
General
Q-Code
Table
Interpreter
System Services
 

Technical Reference Manual

EXTERNAL INTERFACING

GENERAL

SOFTWARE INTERFACING

 

HARDWARE INTERFACES

SYSTEM SERVICES

EXAMPLE

GENERAL

The Organiser II has been designed to be extended in a number of ways

  1. Adding extra software services.
  2. Adding extra hardware interfaces.

In both cases an extension to the operating system is known as a "DEVICE". As far as the operating system is concerned a "DEVICE" can be just an extra software service, or both an extra software service and an hardware interface.

In general if an extra device is added, it will probably be designed to interface to the top slot. However there is no reason why it need not be designed to run in one of the side slots. In fact it is perfectly possible to design an adapter board which will allow an interfaces to run in one of the side slots.

SOFTWARE INTERFACING

Built into the operating system is a service DV$BOOT which will load devices into the operating system. This service will scan each slot in the machine for a normal PACK of any kind which has the NOBOOT bit clear in the first byte on the PACK. Packs with this bit clear are called "BOOTABLE" packs.

Bootable packs have a special header which contains the information the DV$BOOT service requires to load the device into RAM.

Hardware interfaces like the RS232 adapter have an 8K PACK built into them as well as the interface hardware. Together they form the device.

BOOTABLE PACK DESCRIPTION

A pack which is BOOTABLE must have the following header information in the first six bytes of the pack:

ADDRESS

BYTE DESCRIPTION
0 PACK_CONTROL_BYTE
1 PACK_SIZE_BYTE
2 DEVICE_OR_CODE_BYTE
3 DEVICE_NUMBER_BYTE
4 DEVICE_VERSION_BYTE
5 DEVICE_PRIORITY_BYTE
6 DEVICE_CODE_ADDRESS_WORD
PACK_CONTROL_BYTE

This byte is used by the PACK handling services to hold various bits of information about the PACK.

Each bit in the byte has a particular function as follows:

0 This is clear for a valid MKII Organiser pack.
1 This is cleared if the pack is a ram pack.
2 This is set if the pack is paged.
3 This is cleared if the pack is write protected.
4 This is cleared if the pack is bootable.
5 This is set if the pack is copyable.
6 This is cleared if the pack is a flashpack or a debug ram pack.
7 This is set if the pack is a MK1 Organiser datapack.

Hence BIT 4 of the PACK_CONTROL_BYTE must be cleared to indicate that the PACK contains a device to be loaded into the machine. Some examples of valid PACK_CONTROL_BYTEs are as follows:

  • 8K and 16K DATAPACKS: $6A i.e. EPROM device, NOT page counted, writeable, copyable and bootable.
  • 32K, 64K and 128K DATAPACKS: $6E i.e. EPROM device, page counted, writeable, copyable and bootable.
  • 32K RAMPACK: $6C i.e. RAM device, page counted, writeable, copyable and bootable.
PACK_SIZE_BYTE

This byte contains the number of 8K blocks in the PACK.

DEVICE_OR_CODE_BYTE

This byte is used for descriptive purposes only. It should be set to 0 the device is a software application with no additional hardware, otherwise it should be set to 1.

DEVICE_NUMBER_BYTE

This byte contains the device number of the code extension or hardware device.

As more than one device can be "BOOTED" into the operating system, it is necessary to have a mechanism to identify each of the devices currently booted. This is accomplished by having a unique device number for each device.

The device number is a value in the range $01 to $FF. However a number of these are reserved by Psion and should not be used. The reserved numbers are in the range $80 to $C0 and $01 to $40. In 1986 (when the technical manual was published) Psion already supplied a number of devices whose device numbers are as follows:

  • $C0: RS232 INTERFACE
  • $BF: BAR CODE INTERFACE
  • $BE: SWIPE READER INTERFACE
  • $0A: CONCISE OXFORD SPELLING CHECKER

By convention devices which do not have an hardware interface are allocated device numbers in the range $01 to $40 and devices with a hardware interface are allocated device numbers in the range $80 to $C0.

DEVICE_VERSION_BYTE

This byte contains the release version number of the device. This byte is not used by the operating system and is only for documentary purposes.

By convention version numbers are N.M and the byte is formed by the following:

VERSION_BYTE = N*16+M

Thus for a version number of 2.3 the byte will have the value 35 ($23).

DEVICE_PRIORITY_BYTE

This byte determines the order in which devices are booted into memory.

The priority byte may have any value in the range $1 to $FF. The higher the value the higher the priority of the device. Thus a device with priority $FF will be booted before a device with priority $FE.

The DV$BOOT service scans all the slots and builds a table of priorities from all the bootable packs. The priorities are then sorted and each device is loaded in turn. In the event of a tie in priorities the devices will be loaded in the following order:

  1. SIDE SLOT B
  2. SIDE SLOT C
  3. TOP SLOT - SLOT 3

By convention priorities are the same as the device number. By this convention hardware devices will always be booted before software-only applications such as the concise oxford spelling checker etc.

DEVICE_CODE_ADDRESS_WORD

This word contains the address on the PACK of the device code to be booted into the operating system.

If the device code immediately follows the 8 byte header on the PACK then this address will be 8. However it is often desirable to have other information on the PACK before the device code and as such this word allows the device code to be anywhere on the PACK.

RELOCATABLE OBJECT CODE DESCRIPTION

As device code can be loaded anywhere in memory, depending on the machine type (CM, XP or LA etc.), and on how many devices are loaded, it is mandatory that the code to be loaded is in a relocatable form. The operating system provides a service DV$LOAD which will load the relocatable code into the machine and apply the relocation fix-ups.

The code pointed to by the DEVICE_CODE_ADDRESS_WORD must be in Psion's relocatable object code format. The relocatable object code format is as follows:

  1. A word containing the number of bytes of code to be loaded.
  2. The block of code to be loaded.
  3. A word containing the checksum of the preceding block of code.
  4. A word containing the number of fix-up addresses.
  5. One word for each fix-up address.
  6. A word containing the checksum of the preceding fix-up table.

Psion was supplying an assembler which would automatically generate object code in the relocatable format. However to illustrate the relocatable object code format, the following simulates the relocatable object code format using a normal assembler.

                ORG     0
0000 0011               DW      CEND-CBASE      ; SIZE OF CODE
                ORG     0100h
0100            CBASE:
0100 CE 2188            LDX     #RTT_BF         ; RUN TIME BUFFER
0103 86 20              LDAA    #20h            ; SPACE CHARACTER
0105 C6 14              LDAB    #10             ; DO 10 TIMES
0107            LOOP:
0107 A7 00              STAA    0,X             ; STORE SPACE IN BUFFER
0109 08                 INX                     ; GO ON TO NEXT BYTE
010A 5A                 DECB                    ; DECREASE COUNT
010B 26 03              BNE     LEND            ; FINISHED ?
010D 7E 0007    FIX1:   JMP     LOOP            ; NO - SO LOOP
0110            LEND:
0110 39                 RTS                     ; EXIT ROUTINE
0111            CEND:
0111 04E9               DW      04E9h           ; CHECKSUM OF CODE BLOCK
0113 0001               DW      (FIXEN-FIXST)/2 ; NUMBER OF FIXUPS
0115            FIXST:
0115 000E               DW      FIX1-CBASE+1    ; ADDRESS IN CODE BLOCK
0117            FIXEN:
0117 000E               DW      0Eh             ; CHECKSUM OF FIXUPS

The code must be assembled at an address above the zero page (here $100) to avoid zero page adressing.

All checksums are calculated by accumulating each byte in a word. Overflow is ignored. The following code fragment will checksum the code between CBASE and CEND.

        LDX     #CBASE          ; START ADDRESS
        CLRA
        CLRB
        STD     UTW_S0          ; START CHECKSUM AS 0
LOOP:
        CLRA
        LDAB    0,X             ; GET BYTE
        ADDD    UTW_S0          ; ADD CHECKSUM
        STD     UTW_S0          ; SAVE IT
        INX
        CPX     #CEND           ; ALL DONE
        BNE     LOOP            ; NO - SO DO MORE
        ; UTW_S0 NOW HAS THE CHECKSUM

Each entry in the fix-up table is the word-offset of a word in the code which requires relocation. After the code block is loaded, the DV$LOAD service adds the load address to all relative addresses in the code which are mentioned in the fix-up table.

If for example the above code segment was loaded at address $2000 then the fix-up of $E in the fix-up table, would result in $2000 being added to the code block at address $2000+$E in memory. This would change $7E $00 $07 to being $7E $20 $07, the correct absolute address of LOOP.

DEVICE CODE DESCRIPTION

Just loading the code from a device into memory is insufficient as the code itself must interface to the operating system. The following describes the component parts of the interface between the device code and the operating system:

CODE_START:
        DW      0               ; FILLED IN BY DV$BOOT
BOOT_DEVICE:
        DB      0               ; FILLED IN BY DV$BOOT
DEVICE_NUMBER:
        DB      12              ; AS IN THE PACK HEADER
VERSION_NUMBER:
        DB      $10             ; AS IN THE PACK HEADER
MAX_VECTOR_NUMBER:
        DB      3               ; NUMBER OF VECTORS PROVIDED
VECTABLE:
        DW      INSTALL         ; INSTALL VECTOR
        DW      REMOVE          ; REMOVE VECTOR
        DW      LANG            ; LANGUAGE VECTOR
INSTALL:
        ; THE INSTALL CODE
REMOVE:
        ; THE REMOVE CODE
LANG:
        ; THE LANG CODE

When the device is booted into memory DV$BOOT will load the size of the code into the word at CODE_START. This is necessary for DV$VECT to be able to walk the list of device drivers in memory. At the same time the slot that the code was loaded from will be placed in BOOT_DEVICE. This is to allow the device to know which slot it has been booted from. Thus if a device wants to access the PACK from which it has been booted the following code fragment can be used:

        CLRA                    ; REPORT PACK CHANGED ERROR
        LDAB    BOOT_DEVICE     ; SLOT DEVICE WAS BOOTED FROM
        OS      PK$SETP         ; SELECT THE SLOT

The DEVICE_NUMBER byte and the VERSION_NUMBER byte are the same as those on the PACK header. DV$VECT uses the DEVICE_NUMBER byte to select the right device from the list in memory. The VERSION_NUMBER byte is purely for documentary purposes.

The MAX_VECTOR_NUMBER is to allow DV$VECT to check that the device service exists. Thus if DV$VECT were used to call the device in the example above to perform vector number 3, it would fail, as it only provides vectors 0,1 and 2.

There follows a list of vectors which are used to jump to appropriate parts of the code in the device. DV$VECT is called with the device number in the A register and the vector number to be called in the B register. DV$VECT will scan the devices in memory to see if the device is present and if it is, it will then jump to the appropriate vector. All devices must provide vectors 0,1 and 2, and may provide up to 255.

DEVICE VECTORS

Every device which is loaded into the operating system has a vector table which directs the operating system to the appropriate code to handle that "VECTOR SERVICE". The first 3 "VECTOR SERVICES" have a defined meaning as follows:

VECTOR SERVICE 0 - INSTALL VECTOR

Whenever the DV$BOOT service loads a device it will call the INSTALL vector immediately after loading the device. This will give the device the opportunity to initialize itself.

For example the RS232 interface installs the COMMS menu item into the top level menu at this stage by calling the system service TL$ADDI.

On completing the required INSTALL code the device should clear the carry flag and then do an RTS instruction.

If for any reason the INSTALL code decides the device cannot run properly (i.e. not enough memory), then the carry flag should be set and the device will not be installed (and no RAM will be allocated for the device).

A device need not return from this vector, in which case it will have effectively taken control of the machine.

NOTE: The DV$BOOT service uses the first 4 bytes of RTT_FF to build the priorities table and as such the install vector should preserve these 4 bytes if there is any danger of them being corrupted. See the description of DV$BOOT for more details.

VECTOR SERVICE 1 - REMOVE VECTOR

When DV$BOOT is called, it first calls DV$CLER, which calls the REMOVE vector for each device. DV$BOOT then zeroes the permanent cell (and also resets DVA_TOP in LA/OS) effectively discarding all devices. The REMOVE code can then tidy up anything that needs to be done before the device is thrown out of memory. For example the RS232 interface removes the COMMS menu item from the main menu in its REMOVE code. The REMOVE code should terminate with the carry clear and an RTS instruction, even though any errors are ignored.

VECTOR SERVICE 2 - LANGUAGE VECTOR

This vector service is required by the OPL language and provides the mechanism by which the language can be extended.

For any procedure called in an OPL program, the language will first call the DV$LKUP service to see if any devices are prepared to handle the procedure. To do this DV$LKUP calls each device's LANGUAGE vector with the X register pointing to a leading count-byte string containing the name of the procedure. If none of the devices are prepared to handle the procedure then the language will search packs A,B,C and D for an OPL procedure of that name.

If a device is prepared to handle the procedure then it will return its device number in the A register and the vector service number which will handle the procedure in the B register. The language will then immediately call the DV$VECT service which will call the vector service.

For example the RS232 interface provides a language procedure LINPUT$: and as such the LANGUAGE vector code can be coded as follows:

LANGUAGE_VECTOR:
        LDD     0,X             ; GET SIZE AND FIRST LETTER
        SUBD    #7*256+'L'      ; COMPARE
        BNE     NOT_LINPUT      ; NOT A MATCH
        LDD     2,X             ; GET NEXT TWO LETTERS
        SUBD    #'IN'           ; COMPARE
        BNE     NOT_LINPUT
        LDD     4,X             ; GET NEXT TWO LETTERS
        SUBD    #'PU'           ; COMPARE
        BNE     NOT_LINPUT
        LDD     6,X             ; GET NEXT TWO LETTERS
        SUBD    #'T$'           ; COMPARE
        BNE     NOT_LINPUT
        LDAA    #C0h            ; RS232 DEVICE NUMBER
        LDAB    #4              ; VECTOR NUMBER TO HANDLE LINPUT$
        CLC
        RTS
NOT_LINPUT:                     ; NOT LINPUT$ - SO NOT PREPARED TO
        SEC                     ; HANDLE THE PROCEDURE
        RTS

NOTE: As the LANGUAGE vector code is called every time an OPL procedure is executed, it is important that the LANGUAGE vector code be as fast as possible. Clearly a device can handle as many procedures as necessary by just chaining the name matches or by searching a list of procedures. See the chapter on the language as to how OPL passes parameters to device procedure handlers and how devices pass back their results.

BOOTING

The system service DV$BOOT is responsible for loading and removing devices. The area in which devices are loaded in the operating system is one of the preallocated cells, known as the PERMANENT cell. This cell is the first allocated cell and has the unique property that it will never be moved by the allocator (i.e. it always has the same base address). This is obviously crucial as once the code has been relocated in memory it can no longer be moved, as all addresses have been converted from relative addresses to absolute addresses.

Organisers with 32kb or more RAM use the RAM from $0400 to $2000 ('low' RAM) for loading device code, in preference to the permanent cell. This means that while devices occupy less than 7k in total, the full 24k will be available for the user. Note that INFO will only show devices which are occupying high memory - i.e. any devices which have overflowed the 7k. For example with an RS232, a barcode reader, and a concise oxford spelling checker booted, only the spelling checker will be loaded into the permanent cell in high memory, so INFO will report DEVICES xxx%. The addresses DVA_BOT and DVA_TOP mark the lower and upper limits of low memory. DVA_TOP is increased as devices are loaded into low memory. DVA_BOT is initialised to $0400 at cold startup.

The operations performed by DV$BOOT are as follows:

  1. Run the DV$CLER service, which will call the REMOVE service of each device currently in memory. DV$BOOT will then zero the PERMANENT cell. On Organisers with 32kb or more RAM it will also clear the low memory by setting DVA_TOP to DVA_BOT.
  2. Scan the three slots for packs which are bootable.
  3. Build a table of the priorities of each device in RTT_FF.
  4. Scan the table for the highest priority device.
  5. Grow the PERMANENT cell by the size of the device at the end of the PERMANENT cell (see below for LA/OS).
  6. Load the code into the area just allocated.
  7. Store the size of the code into the first word.
  8. Store the slot number that the code was loaded from in the third byte of the device code.
  9. Call DV$VECT to execute the INSTALL vector of the device.
  10. Zero the priority in the table in RTT_FF.
  11. Repeat the above until all priorities in the table are zero.

Organisers with 32kb or more RAM:

The device code is loaded into 'low' memory from $0400 to $2000, and the address of the byte after the code is stored in DVA_TOP. If there is not enough room in low memory, the device code and any further devices will be loaded into the permanent cell.

The DV$BOOT service is called by the operating system when a cold start is required. (On multi-lingual machines like the LZ, devices are booted on cold start before asking for a language and again afterwards when the language has been selected to enable the device to switch languages. This feature can be disabled - see foreign languages.)

Thereafter DV$BOOT is only ever called when the ON/CLEAR key is pressed in the main menu (i.e. at the top level). Thus to load a device into the operating system the device must be plugged into the machine and the ON/CLEAR key pressed until the main menu is reached. Then one further press will execute the DV$BOOT service and load the device driver. There is no problem in booting the device drivers any number of times.

To remove a device from memory, simply remove the device from the machine and repeat the above procedure (i.e. perform a boot). As the device is no longer present and as DV$BOOT always throws out all devices before performing the boot procedure the device will be effectively removed from memory.

NOTE: As DV$BOOT always throws all devices out of memory, no device can call the DV$BOOT service. In order for a device to call the DV$BOOT service it must copy a routine to call DV$BOOT into some safe portion of memory and then jump to that code. The code can then either get back to device, which will have been reloaded, through a known vector service or just simply return from where it came.

OPL programs, because they are running in a different area of memory can easily call the DV$BOOT service as follows:

REBOOT:
REM BOOTS ANY DEVICES INTO MEMORY
LOCAL I%,CODE$(4)
I%=ADDR(CODE$)+1 : REM SKIP THE SIZE BYTE OF THE STRING
POKEB I%,$3F     : REM THE SWI INSTRUCTION
POKEB I%+1,23    : REM THE DV$BOOT VECTOR NUMBER
POKEB I%+2,$39   : REM A RETURN INSTRUCTION
USR(I%,0)        : REM CALL THE MACHINE CODE

This procedure when called will execute the DV$BOOT service.

The following procedure will remove all devices from memory:

        OS      DV$CLER         ; run 'remove' vector of all devices
        LDX     DVA_BOT         ; reset low memory (harmless on non-LA/OS)
        STX     DVA_TOP
        LDX     #2000h          ; zero the permanent cell
        OS      AL$ZERO

From model LA onward, the user can reserve an area of low memory from $400 upwards
as follows:

        LDA     A,$FFE8         ; TEST OS/VERSION

        ANDA    #7
        CMPA    #2              ; must be >= 2
        BLT     NOT_OK
        OS      DV$CLER         ; RUN 'REMOVE' VECTOR OF ALL DEVICES
        LDX     #2000h          ; AND KILL ANY DEVICES IN HIGH MEMORY
        OS      AL$ZERO         ; SO THAT THEY CANNOT BE ACCESSED AFTER THEIR
                                ; REMOVE VECTORS HAVE BEEN CALLED
        LDX     #SPACE_REQUIRED+0400h
        STX     DVA_BOT         ; SET BASE ADDRESS FOR FUTURE DEVICE LOADING
        STX     DVA_TOP         ; SET TOP= NEW BOTTOM
        ; RAM NOW AVAILABLE from $0400 - DVA_BOT - 1

2 AND 4 LINE MODELS

All machine code applications that run on the LZ will automatically be put into "2-line compatibility mode" as soon as anything is printed to the screen. The LZ will however be switched back to 4-line mode after returning. The device itself must put the machine into 4-line mode if required, by calling system service DP$MSET.
Machine code applications which print to the screen should use the following method to implement 2-line and LZ compatible software. Whenever the application is entered the following should be carried out:

  • Before calling any system services, check the value of DPB_MODE. If DPB_MODE = 0, take no further action and run in 2-line mode.
  • If DPB_MODE = 1, call DP$MSET prevent the operating system switching to 2-line mode.

Note that machine code applications can simply check DPB_MODE rather than looking at the ROM id bytes because the mode will not change until anything is printed to the screen. However, OPL applications will have already been put into 2-line mode by the time they are running, so they must check the ROM id.

For example the following procedure will print "HELLO" on the 2nd line of a 2-line machine and on the 4th line of an LZ:

       LDAA   DPB_MODE
       BEQ    1$          ;branch to run in 2-line mode
       OS     DP$MSET     ;set to 4-line mode A=1
       OS     UT$DISP
       DB     12,23        ;clear screen and goto 4th line
       ASCIZ  "HELLO"
       RTS

1$:    OS     UT$DISP
       DB     12,10        ;clear screen and goto 2nd line
       ASCIZ  "HELLO"
       RTS

HARDWARE INTERFACES

The Organiser has three slots available in which hardware interfaces can be fitted. The TOP slot (slot 3) is the preferred slot for interfacing to external hardware as it has been especially designed for this purpose. However there is no reason why one of the two SIDE slots (slots 1 and 2) cannot be used. There are however a number of fundamental differences between the top slot and the side slots.

In general though the 16 way connectors from the Organiser to the outside world constitute a proprietary BUS and as such there are a number of rules from a hardware and software point of view with regard to interfacing on this BUS.

In the following sections the BUS components which are common to all slots are described followed by a section on the differences between the TOP slot and the SIDE slots.

BUS SIGNALS

SIGNAL NAME DESCRIPTION
SD0 - SD7 Data Bus
SOE_B Output Enable (active low)
SMR Master Reset (active high)
SCLK CLocK
SSS_B Slot Select (active low)
SVCC + 5 Volts
SGND 0 Volts

This common set of signals comprise the Psion proprietary BUS. This BUS was designed to allow Psion's removable PACKS to be interfaced to the Organiser. In order to understand the following description of the BUS it is necessary to have read and understood the chapter on low level access to packs. All Psion's hardware interfaces consist of both a PACK and the hardware interface itself. The PACK is used to provide the DEVICE code which is loaded into the operating system, thereby providing the software interfacing to the OPL language and the operating system itself.

While it is possible to build hardware interfaces without a PACK on board, it is strongly recommended that this is not done. The PACK not only provides a mechanism for adding extra code associated with the hardware, it also provides a means whereby the code can tell that the interface is still plugged into the machine by reading the on board PACK.

SSS_B

This signal is the SLOT select signal and is used to select the hardware plugged into that slot. At no time should an external interface try to control any of the signals on the BUS until SSS_B goes low. There is obviously one SSS_B signal for each slot in the machine.

It is also mandatory that none of the control signals on the BUS should be changed while SSS_B is active. The control signals are SOE_B,SMR and SCLK. Thus to change a signal, SSS_B should be raised high, then the signal changed and finally SSS_B can be lowered again.

This signal should always be pulled up through a resistor to SVCC.

SOE_B

The SOE_B signal is used to select between the PACK on the interface and the external hardware. With SOE_B low (i.e. active) the PACK should output its contents onto the DATABUS. With SOE_B high then the hardware interface circuitry should control the DATABUS.

This signal should always be pulled down through a resistor to 0 volts

SMR

The SMR signal is used to reset the counters on the PACK to 0. It is also used in a number of combinations with SOE_B high. These are explained in a table later on.

This signal should always be pulled down through a resistor to 0 volts

SCLK

The SCLK signal is used to clock the counters on the PACK. It can also be used in a number of combinations with SMR high. These are explained in a table later.

This signal should always be pulled down through a resistor to 0 volts

SVCC

This is the +5 Volt rail to external hardware interfaces. It can be used to supply power to the hardware interface. Note that when the Organiser is switched off, this voltage will no longer be supplied. Instead a small amount of current can be drawn from the SSS_B signal as it is supplied from a different power rail. See Chapter 3 for more details.

SGND

This is the 0 Volt signal to the interface.

SD0-SD7

These 8 signals represent an 8 bit DATABUS between the hardware and the Organiser. Since it is possible to both read from and write to hardware interfaces, this bus is BI-DIRECTIONAL. However the rest state when not in use is always INPUT to the Organiser. i.e. The PORT2 direction register should be set to 0 so that all bits of PORT2 are input. If the direction of these bits are ever changed to OUTPUT they must be reset to INPUT before control is passed back to the operating system, as the operating system assumes that PORT2 is always configured as all INPUT.

All these signals are pulled down internally to the Organiser to 0 Volts. Thus if no interface is present in a slot the Organiser will always read a 0. This is used by the operating system to determine that a pack is not present in the slot.

BUS STATES

The following table represents the rules by which the interface should respond to various states of the BUS control signals. In the table, HIGH stands for +5 Volts, LOW stands for 0 Volts and X stands for don't care.

STATE SSS_B SOE_B SMR SCLK DESCRIPTION
0 HIGH X X X All interfaces deselected.
1 LOW HIGH HIGH X 128K PACK device segment select.
2 LOW HIGH LOW X Hardware interface select.
3 LOW LOW HIGH HIGH Ram PACK ID 1 select.
4 LOW LOW HIGH LOW Ram PACK ID 0 select.
5 LOW LOW LOW X PACK read select.

When the operating system selects a slot using the PK$SETP service, it will place the control signals in a number of these states. However the top slot is treated slightly differently, in that the operating system will not support 128K packs or RAM packs. Thus the following states can occur for the various slots:

STATE SLOT 3 SLOTS 1 & 2
0 Yes Yes
1 No Yes
2 No No
3 No Yes
4 No Yes
5 Yes Yes
STATE 0

SSS_B - HIGH
SOE_B - don't care
SMR - don't care
SCLK - don't care

This state is the rest state for all interfaces. When SSS_B is high no interface should be trying to control the databus or any of the control signals.

STATE 1

SSS_B - LOW
SOE_B - HIGH
SMR - HIGH
SCLK - don't care

This state is used by the operating system to select the 16K segment in 128K PACK devices. Note that PK$SETP selects segment 0 every time it is called regardless of the device fitted in the slot. As the operating system does not support 128K PACK in the top slot this state can be used to select devices in a hardware interface to be used in the top slot.

STATE 2

SSS_B - LOW
SOE_B - HIGH
SMR - LOW
SCLK - don't care

This state is used to write data to either packs or RAM packs in the slots. However if the RDWRT bit in the ID byte of the pack is clear then the operating system will never place state 2 on the control lines.

This state is the only state that can be used safely to select other devices than the PACK on interfaces intended for use in the side slots.

STATE 3

SSS_B - LOW
SOE_B - LOW
SMR - HIGH
SCLK - HIGH

This state is used by the operating system to select the RAM pack hardware ID 1. Note that PK$SETP uses this state to determine if a RAM pack is plugged into a slot. If so, it will output an ID byte of 1 in response to this state. Note that packs output byte 1 of the EPROM in response to this state.

As the operating system does not support RAM packs in the top slot this state can be used to select devices in a hardware interface to be used in the top slot.

STATE 4

SSS_B - HIGH
SOE_B - don't care
SMR - don't care
SCLK - don't care

This state is used by the operating system to select the RAM pack hardware ID 0. Note that PK$SETP uses this state to determine if a RAM pack is plugged into a slot. If so, it will output an ID byte of 1 in response to this state. Note that Packs output byte 0 of the EPROM in response to this state.

As the operating system does not support RAM packs in the top slot this state can be used to select devices in a hardware interface to be used in the top slot.

STATE 5

SSS_B - HIGH
SOE_B - LOW
SMR - LOW
SCLK - don't care

This state is used by the operating system to read data from the PACK circuitry on interfaces. The byte, corresponding to the currently selected address on the PACK counters, is output on the databus in response to this state.

EXAMPLE

Take as an example the BARCODE interface for the top slot, as supplied by Psion.

The interface has two discrete interface circuits:

  1. The PACK circuitry.
  2. The BARCODE input signal buffer circuitry.

State 5 is used to enable the EPROM in the PACK circuitry to output its contents on the databus.

States 1 and 2 are used to enable the BARCODE input signal buffer circuitry. I.e.

SSS_B - low,
SOE_B - high,
SMR - don't care,
SCLK - don't care.

Thus to select the BARCODE PACK circuitry the following code fragment can be used:

SELECT_PACK:
         CLRA
         LDAB    #PAKD
         OS      PK$SETP         ; THE PACK IS NOW SELECTED
         ; THE CONTROL LINES ARE IN STATE 5

To select the BARCODE input signal buffer circuitry the following code fragment can be used:

SELECT_BARCODE:
         CLRA
         LDAB    #PAKD
         OS      PK$SETP            ; SELECT PACK AS NORMAL
         OIM     #CS3,POB_PORT6     ; DESELECT THE SLOT
         OIM     #OE,POB_PORT6      ; SET SOE_B HIGH
         AIM     #~CS3,POB_PORT6    ; SELECT THE SLOT AGAIN
         ; BARCODE HARDWARE NOW SELECTED
         ; THE CONTROL LINES ARE IN STATE 1 OR 2

NOTE: Before control can be returned to the operating system, STATE 5 must be reestablished on the control lines. This can be achieved as follows:

DESELECT_BARCODE:
         OIM     #CS3,POB_PORT6      ; DESELECT THE SLOT
         AIM     #~OE,POB_PORT6      ; SET SOE_B LOW
         OIM     #~CS3,POB_PORT6     ; SELECT THE SLOT AGAIN

NOTE: Control lines should only ever change state when the control lines are in STATE 0, i.e. the interface is deselected.

SYSTEM SERVICES

DV$BOOT

Will boot all devices plugged into the Organiser.

Any errors occurring during the boot are reported directly. However the screen is saved before the message is displayed and restored immediately afterwards.

DV$LOAD

This service will load code from a pack which is in the Psion relocatable object format. It loads the code into memory and then applies any fix-ups that are required, thus relocating the code to the address as specified.

The routine assumes that the correct slot has already been selected with the PK$SETP service.

DV$VECT

This service will search the devices in the PERMANENT cell for a device whose device number matches the given number.

Then the service checks that the passed vector number is not greater than the maximum vector number supported by the device. If it is, then an error is returned. Otherwise the appropriate vector is loaded from the device vector table and a JMP is done to the vector.

DV$VECT passes the X register and the scratch register UTW_S0 through to the vectored routine, so that these may be used to pass parameters to the device vector routine. It is up to the device to specify what is passed and what is returned. DV$VECT returns the same things as the vectored routine.

DV$LKUP

This service will call the LANGUAGE vector of all devices in memory. If a device signals that it is prepared to handle the given procedure name then the service will return the device number and the vector number of the code to handle the procedure.

DV$CLER

This service calls the REMOVE vector for all devices currently in memory.

It is usually called by DV$BOOT just before zeroing the permanent cell in preparation to booting.

EXAMPLE

This is an example of a device to allow the operating system services to be called from OPL procedures. The device is a procedure called SWI%: and it takes as its argument an integer specifying which service should be invoked.

Most functions also require values in the A,B(D) or X register as well and so the function requires 2 global variables X% and D% to be declared by the OPL procedure. Any values to be passed in UTW_S0 or UTW_S1 can be set with POKEW before calling SWI%:.

If carry is clear after the call to the operating system SWI%: will return 0 and if it is set, SWI%: will return -1 and D% will have the error number.

If SWI%: signals success D% and X% will be set directly from the machine registers D and X.

NOTE: The D register is actually made up of the A register and the B register so that D = A*256 + B. The global variable D% mimics this. So if a routine requires A = 1 and B = 3 this can be passed as D = 1*256+3. On return the values of A and B can be determined from D% as follows:

A% = (D%/256)
B% = (D% AND 255)

See the full code listing for the routine.

 
first previous   next top