Technical Reference Manual
COMMS LINK driver code is interrupt driven and handles XON/XOFF and hardware handshaking at the lowest level. It also parity checks all incoming data if parity is enabled.
As all serial I/O is interrupt driven, interrupts CANNOT be disabled (as with the keyboard). All calls to the operating system via the SWI instruction are intercepted by the driver code once the port has been opened, to make data pack access transparent (and possible!) while the port is open. It also ensures that the port is active and not affected by various power saving techniques in the operating system while it is open.
The function of the following operating system services are altered when the port is opened; PK$SETP, PK$PKOF, BZ$TONE, BZ$ALRM and BZ$BELL. As all SWI's and interrupts are intercepted directly, and the old handlers are not chained to, any other application that re-vectors the same services will not function correctly while the port is open. The old handlers are saved only when the comms pack is booted during the install code but are restored every time the port is closed. Any application booted in after the comms pack, which re-vectors any service used by the comms pack, will not function correctly even when the port has been closed as the original handler will be restored.
The interface to the COMMS LINK driver code is via a block of fixed address memory of 40 bytes long starting at dvt_spar ($214F). This memory is divided into two areas: a table of variables which set various I/O parameters and an entry point for calls to the driver code. All these variables and a macro for calling the driver code via this entry point are defined below.
The following variables can be set set to control the function of the COMMS LINK driver code. However, these variables are also set by the SETUP option in the COMMS menu and by the LSET OPL function, so generally their values must be preserved.
After any of these variables have been altered a call to rs$setvars must be made to set up various derived variables.
None of these variables should be altered while the port is open.
SINGLE BYTE VARIABLES
3 BYTE VARIABLES:
All contain a length byte (0-2) and two bytes of data
It is strongly suggested to leave these unchanged.
The general purpose timer rsb_sec_timer is used by the higher level functions such as LPRINT to implement time outs so be warned!
All calls to the COMMS LINK driver code are made via the macro "RS" which is defined below:
; ; RS - Macro for assembler interface to COMMS LINK drivers ; .macro RS function jsr rst_entry_point .byte function .endm
Before using this macro a check must be made that the COMMS LINK code has been booted as follows:
ldx #opl_name ; choose an OPL function unique to COMMS-LINK os dv$lkup ; ask O/S if it's booted bcs not_booted ;ok to call RS$ routines now opl_name: .ascic"XFEOF"
The following functions are available:
Example to open the RS232 port for reading and writing:
clrb ; Open for reading and writing RS RS$open bcs error ; Deal with error ... ; Rest of code
In general all functions indicate an error condition by returning with the carry flag set and the appropriate error code in the B register.
The COMMSLINK hardware provides the following RS232 control signals on the port POB_PORT2 (address $03).
All bits are readable, writing to input bits is to be avoided.
Note that DTR (normally an output) is merely linked to DSR and can not be driven by a program.
In between a call to RS$OPEN and a call to RS$CLOSE, programmers should look out for the following operating system routines:
Routines which access packs:
These turn off the RS232 port, until the next call to COMMS LINK. This is normally no problem, unless a program tries to access POB_PORT2 after a call to one of the above routines but before another COMMS LINK call. The RS232 port should then be turned on by calling RS$OPEN again, as follows:
Example: no problem here
os FL$OPEN ... ; RS232 now off jsr rst_entry_point Byte RS$getchar ; or similar COMMS LINK function ... tim #cts,POB_PORT2 ; test the CTS line
Example: this is a BUG
Os PK$SETP ... ; RS232 now off Tim #CTS,POB_PORT2 ; test the CTS line
Example: corrected version of above
Os PK$SETP ; Re-open the RS232 port, to switch it on ldab #opened_with ; use value originally supplied to RS$OPEN andb #^XFE ; but with bit 0 clear to indicate that jsr rst_entry_point ; the handshaking state is not to be reset Byte RS$open ... Tim #CTS,POB_PORT2 ; now OK to access port
Other routines whose behavior is altered while the RS232 port open:
Do not call BT$SWOF without first closing the RS232 port with RS$CLOSE
The keyboard interrupt service routine is altered so that interrupts remain enabled while the keyboard is being scanned. This gives RS232 interrupts a higher priority than keyboard interrupts.
Checking that COMMS LINK is installed
First check that the COMMS LINK software has been loaded - i.e. COMMS is in the top-level menu. If COMMS LINK is not installed, any program which calls the machine code interface routines provided by COMMS LINK will crash.
This check can be performed in OPL as follows:
commsin%: rem return true if COMMS LINK installed onerr iserr:: xfeof: :rem try a harmless COMMS LINK function iserr:: return err<>203 : rem not installed if "missing proc" error
or in machine code:
bsr check_present bcs not_present bra is_present check_present: bsr 1$ ; PC relative LDX #XFEOF .ascic "XFEOF" ; leading count byte string 1$: pulx ; PC = address of "XFEOF" Os dv$lkup ; if XFEOF not there, no COMMS LINK rts
Opening and closing the RS232 port
Before accessing the RS232 port, the program must first call the COMMS LINK machine code interface routine RS$OPEN. This indicates that the RS232 port is now in use.
clrb ; Open for reading and writing jsr rst_entry_point Byte RS$open bcs error ; Deal with error ... ; Now free to access the port
RS$CLOSE should be called when the RS232 port is no longer needed.
; bit masks for RS$close turn_off_immed= 1 ; switch off immediately after close ; else leave port on fail_busy= 2 ; fail with carry set if paused by XOFF ; else ignore XOFF state, and close immediately ; Example where port not closed while XOFF handshake close_type = fail_busy ; dont close if busy handshaking, ; leave port switched on wait_busy: ldab #close_type jsr rst_entry_point Byte RS$close bcs wait_busy ; wait until XON ; Straight close close_type = 0 ; ignore XOFF state, ; leave port switched on ldab #close_type jsr rst_entry_point Byte RS$close
Using handshaking lines
; Bit masks CTS= 1 dsr= 2 rts= 4 ;Set CTS to indicate ORGANISER II busy oim #CTS,POB_PORT2 ;Clear CTS to indicate ORGANISER II ready for input aim #CTS,POB_PORT2 ; not (1) = $FE ;Wait on both RTS and DSR wait: Tim #rts!dsr,POB_PORT2 bne wait
Example: OPL/Machine code for controlling the RTS line directly:
global rtshigh%(2),rtslow%(2),a% rtshigh%(1)=$71fe rtshigh%(2)=$0339 rtslow%(1)=$7201 rtslow%(2)=$0339 rem to assert (raise) the rts line a%=usr%(addr(rtshigh%()),0) rem to de-assert (lower) the rts line a%=usr%(addr(rtslow%()),0)
All all function calls are made via the macro "RS", see above.
Opens the RS232 channel and initialises the hardware, also sets various modes of operation for the port depending on the value passed in B.
If a pack access is made while RS232 is open this access will be delayed until any stray characters have been delt with. Any subsequent calls to RS_putchar or RS_getchar will switch the port on again. If a call to RS$open is made while the port is already open the call is ignored.
Closes the RS232 port. Carry is set if failed to close due to host busy
Transmits the passed character. Returns with the carry set if an error or the port was busy, else the carry is clear. B is clear if no error.
Gets the next character from the receive buffer. Returns with carry set if error or no characters in the buffer, else the next character from the buffer in the A register B is clear.
Flushes the receive buffer.
Sets the derived COMMS LINK variables after a change to the setable COMMS LINK variables.
Opens the RS232 port for output only, then writes the passed string to the port applying all the translates, timeouts etc. specified.
Opens the RS232 port for output and input and then reads the passed number of bytes into the passed buffer applying all the translates, timeouts etc. specified.
Attempts to establish a logical link with the correspondent link entity. Wait for a suitable acknowledgment.
Disconnect the logical link with the correspondent link layer. Harmless if the link is already disconnected.
Send data in buffer to the correspondent. The data length must be >=0 and <=MAXILEN. Waits for a suitable acknowledgment. (MAXILEN currently 260)
Wait for a frame to arrive from the physical layer. Returns number of bytes placed in buffer if all OK