Classic Computer Magazine Archive COMPUTE! ISSUE 30 / NOVEMBER 1982 / PAGE 145

A Terminal Operating System For PET To HP3000 +

Penny Peterson
Department of Chemistry
Bryn Mawr College
Bryn Mawr, PA

This article describes how a communications system can be set up between a PET (Upgrade ROMs) and a Hewlett-Packard HP3000. The problems solved during the creation of this system suggest solutions to other similar peripheral communications tasks.

We have developed a Terminal Operating System (TOS) to link a PET (Upgrade ROMs) to a Hewlett-Packard HP3000 Series III computer. The guiding principle was to implement a link that would permit using the PET as a dumb terminal and that would also permit the transfer of programs and data.

In addition to a standard Model 32N PET, our link made use of a SADI from Connecticut Micro-computers Corporation for the needed conversion from PET IEEE-488 Parallel to RS-232-C Serial. A Bell modem and phone lines provided the remote connection to the main computer. A Toolkit ROM supplement provided some useful software features, but led to some modifications.

The TOS described here was part of a larger project to construct a PET-controlled tunable dye laser spectroscopy system with data acquisition and graphics capability. The TOS provided a link to a larger computer for program editing, major file storage, large scale data processing, and routine terminal access. In particular, the TOS has been used to upload programs from the PET to the HP3000 using the Toolkit APPEND function.

General Idea Of TOS

We want the PET to simply transmit data from the keyboard to the HP3000 via the SADI, and display to the screen data received from the HP3000 via the SADI. There are also some compatibility problems between the PET and the HP3000 which the program must compensate for.

The program first opens a file to the SADI using the options: 300 baud, auto suppression of line feeds from the HP3000, reversal of upper/lowercase from the PET, and a lot of nulls to be sent by the SADI to the HP3000 after a Carriage Return. The program also POKEs the appropriate values in memory to select the alternate character set (which includes lowercase) and to enable the cursor (needed for use in the HP3000's line-oriented editor).

The main body of the program consists of two loops – one to get a character from the keyboard and send it to the SADI, and one to get a character from the SADI and send it to the screen. In each loop, any conversions of characters necessary to achieve compatibility are made. (Most of these compatibility problems were not evident until the program was in operation.)

In the loop which gets characters from the keyboard, provisions are made to convert PET keys to control keys for the HP3000. PET DELETE is converted to HP3000 BACKSPACE; PET CURSOR RIGHT is converted to HP3000 CONTROL Y (Software Break for use in the Editor). PET CLEARSCREEN (Shift Home) is used to leave the TOS.

In the loop which gets characters from the HP3000, provisions are made to suppress unwanted characters sent by the HP3000. The HP3000 sends XOFF (Control Q) to indicate the end of a message. This control character is an ASCII 17, which happens to correspond to a PET linefeed. The program does not transmit this character, thus avoiding unwanted extra linefeeds. Another compatibility problem was that the HP3000 sends Carriage Return and Linefeed separately, but the PET automatically does a Linefeed upon receipt of a Carriage Return. This was solved by simply ignoring Linefeeds sent by the HP3000. Finally, the PET's blinking cursor caused problems. If the cursor happened to be blinking "on" just before a Carriage Return, a stray cursor would be left behind while the new cursor moved on to the next line. This was prevented by turning off the cursor before executing a Carriage Return from the HP3000, and turning it back on again afterwards.

Speeding Up The Old TOS

The original version of the TOS worked, albeit with some losses of characters in both directions due to speed problems. The BASIC program in the PET that is the TOS must run very quickly in order to catch all incoming characters from the HP3000. A sure-fire way to make the program run fast enough would be to rewrite it in machine language, but this would require a considerable amount of work.

Therefore, I tried all the tricks at my disposal to make the program run fast enough in BASIC. This involved removing all REMark statements and putting the loops where speed was crucial at the beginning of the program. These loops made liberal use of GOTOs, and, since the execution of a GOTO requires searching sequentially through the program line numbers until the desired one is found, considerable time can be saved by having line numbers frequently jumped to at the beginning of the program. These modifications speeded up the program noticeably.

At this point I discovered that when the "BASIC Programmer's Toolkit" ROM was invoked (SYS 45056), the revised, speed-conscious TOS was not fast enough. Unfortunately, the only documented way to turn the Toolkit off was to turn off the PET, of course resulting in the loss of any programs in the PET. The Toolkit's APPEND function was needed to append programs to be uploaded onto the end of the TOS. (More about the Uploading capabilities of the TOS later).

So until we figured out a software way to turn the Toolkit off, a complicated and time-consuming series of reads and writes to tape was necessary to upload a program to the HP3000 printing (e.g., Load TOS, Append program to be uploaded, Save the TOS + program combination, Turn off the PET to turn off the Toolkit, Reload the TOS + program combination, Run TOS). Disassembling sections of PET BASIC and the Toolkit ROM uncovered the patch which the Toolkit makes to the BASIC Input/Output routines.

In addition to the normal checks for BASIC keywords, the Toolkit adds checks for the Toolkit keywords. These additional checks also slow down BASIC Input/Output. A machine language routine was written which replaced the Toolkit patch with the original BASIC routine. (See Program 2 machine language routine, written by Gary Kaufman, which turns off the Toolkit.) After this routine was incorporated into the TOS, the PET no longer missed characters coming from the HP3000.

The other half of the speed problem – the HP3000 Editor's loss of characters from the PET – occurred because there is a delay between the time that the Editor accepts a line of input (terminated by a carriage return) and the time it starts accepting the next line. This means that any characters sent from the PET to the HP3000 during the delay will be lost. The use of the SADI's ability to send multiple nulls to the HP3000 after a carriage return is an attempt to send only meaningless information during the Editor delay.

This helps alleviate the problem, but does not totally cure it. This loss of characters by the HP3000 Editor is noticeable only when information is being transmitted very quickly, thus ordinary typing into the Editor is not affected. However, the original Uploading routine, which LISTs information to the HP3000 at about 30 characters per second, was hampered. (See below for instructions for use of original uploading routine.)

Uploading Into The HP3000 Editor

The purpose of the Uploading routine was to transfer a BASIC program from the PET's memory to the HP3000. The original routine works on the premise that the HP3000 Editor neither knows nor cares whether the input it receives from the SADI is being typed in by hand. By using the BASIC commands LIST and CMD, the program to be uploaded can be listed directly to the SADI. First, a file to the SADI must be opened, specifying a non-PET controller and conversion of PET graphics characters to printable mnemonics. Then the command CMD is given, which transfers the PET-User screen dialogue to the HP3000. The subsequent LIST command is performed on the new designated device – the HP3000 Editor.

As mentioned before, the accuracy of the uploading is limited by the time lag in the HP3000 Editor that occurs between the receipt of one line of text and the acceptance of the next. This is a major limitation which cannot be overcome. We thought about developing a handshaking protocol in which the HP3000 Editor would signal when it was ready to accept a new line; but this plan was discarded because it would require each line to be listed individually, and the LIST command is not capable of this. (It is essential to use the LIST command because PET BASIC programs are stored in memory in tokenized form, and LIST is one of the few commands which untokenizes.)

Uploading Into A FORTRAN/3000 File

Even if occasional loss of characters for uploading programs could be lived with, it was certainly unacceptable for the uploading of data. Thus, a completely new uploading routine was designed which did not rely on the HP3000 Editor (Program 3). The new routine lists the program to be uploaded directly into a HP3000 data file via a FORTRAN program.

The data file is created using the :BUILD. The file created must be large enough to hold the programs or data to be loaded into it from the PET. A FORTRAN program (INFILE) reads lines in from the keyboard. Again, lines LISTed from the PET are indistinguishable from lines typed in at the keyboard. These lines are stored into the data file (UPLOAD). A separate FORTRAN program (OUTFILE) allows reading of the data file. Since a FORTRAN program will wait for input as long as necessary, there is no problem with lost characters. This Uploading routine even runs faster because it does not require the multitude of nulls to be sent after a carriage return.

Program 1.

50000 REM TERMINAL OPERATING SYSTEM
50010 REM PENNY PETERSON
50020 REM PET TO HP3000 VIA SADI
50030 REM MENU
50040 POKE59468, 12 : REM NORMAL CHARSET
50050 PRINT"(H(C> TOS: T) ERMINAL U)PLOAD Q)UIT": PRINT
50060 GETA$
50070 IF (A$ = "T")GOTO50120
50080 IF (A$ = "U")GOTO50310
50090 IF (A$ = "Q")GOTO50380
50100 GOTO50060
50110 REM ACT AS A DUMB TERMINAL
50120 CLOSE 5
50130 PRINT" (H(CPET TO HP3000 TERMINAL OPERATING SYSTEM"
50140 POKE 59468, 14 : REM ALTERNATE CHARSET
50150 POKE167,0 REM CURSOR ENABLE
50160 D$ = "EAR"   :REM SADI DESCRIPTORS E-300 B AUD; A-AUTO SUPPRESS
50161 : REM R - REVERSES UPPER/LOWER CASE FROM PET
50170 OPEN 5,4,15,D$                   : REM SADI DEVICE #4; SECONDARY ADDRESS = 15
50179 REM
50180 GET A$ : IF A$ = "" THEN 50240 REM GET CHAR FROM PET
50181 : REM IF NOT FOUND, GO CHECK FOR CHAR FROM HP
50190 IF ASC (A$) = 13 THEN PRINT#5 : GOTO50180 : REM IF <CR> SEND IT TO HP
50200 IF ASC (A$) = 20THENA$ = CHR$(8)                : REM PET DELETE --> HP BACKSPACE
50210 IFASC (A$) = 29THENA$ = CHR$(25) : REM PET CURSOR RT --> CNTLEY
50220 IFASC (A$) = 147THEN50030                : REM IF PET CLR SCREEN, JUMP TO MENU
50230 PRINT #5, A$; : REM SEND CHAR FROM PET KEYBOARD TO HP3000
50239 REM
50240 GET #5, A$ : IF A$ = " " THEN 50180 : REM GET CHAR FROM HP
50241 : REM IF NOT FOUND, GO CHECK FOR CHAR FROM PET
50250 IFA$ = CHR$(17) THEN50180                        : REM SUPPRESS UNWANTED LINEFEED
50260 IFA$ = CHR$(13) THENPOKE167,1 : PRINT" " : A$ = " " : POKE167,0 : GOTO50180
50261 : REM WIPE CURSORS FROM END OF LINES SO DON'T LITTER SCREEN
50270 IFA$ = CHR$ (10) THENA$ = " " : REM SUPPRESS LINEFEED FROM HP
50280 PRINT A$;                                        : REM SEND HP CHAR TO PET SCREEN
50290 GOTO 50180
50300 REM UPLOAD
50310 CLOSE 5
50320 PRINT " (H(CUPLOADING…"
50330 POKE 167,1                                               : REM DISENABLE CURSOR
50340 OPEN 5,4,15, "EPC997"                        : REM SADI DESCRIPTORS
50341 : REM 300 BAUD/NONPET CONTROLLER/PRINT CONTROL CHARS/
50342 : REM 9 + 9 + 7 = 25 EXTRA NULLS SENT AFTER <CR>
50350 CND 5                         : REM TRANSFER SCREEN DIALOGUE FROM PET TO HP
50360 LIST		:REM SENDS PROGRAM TO BE UP LOADED FROM PET TO HP
50370 REM LIST KICKS US BACK TO BASIC
50380 CLOSE 5
50390 END

Program 2.

140 PRINT"(H(C"
150 PRINT"TOOLKIT DISCONNECT ROUTINE"
160 N = 832:FORI = 57647 TO 57656
170 X = PEEK(I) : POKEN, X : N = N+ 1 : MEXTI
180 FORI = 826TO831 : HEADX : POKEI, X : NEXTI
190 FORI = 842TO848 : READX : POKEI, X : NEXTI
200 DATA165, 119, 72, 165, 120, 72
210 DATA104, 133, 120, 104, 133, 119, 96
220 POKE833, 24 : SYS826
230 PRINT"TOOLKIT DISCONNECTED"
240 END

Program 3.

0 GOTO100
1 GOSUB 29
2 GOTO15
3 GETA$ : IFA$ = "" THEN9
4 IFASC (A$) = 13THENPRINT#5 : GOTO3
5 IFASC (A$) = 20THENA$ = CHR$(8)
6 IFASC (A$) = 29THENA$ = CHR$(25)
7 IFASC (A$) = 147THEN15
8 PRINT#5, A$;
9 GET#5, A$ : IFA$ = "" THEN 3
10 IFA$ = CHR$(17) THEN3
11 IFA$ = CHR$(13) THENPOKE167, 1 : PRINT" " : A$ = "" : POKE167,0 : GOTO3
12 IFA$ = CHR$(8) THENA$ = CHR$(20)
13 PRINTA$; : GOTO3
14 RETURN
15 POKE59468, 12 : PRINT "(H(C> TOS : T) ERMINAL U) PLOAD Q) UIT"
16 GETA$ : IF (A$ = "T") GOTO21
17 IF (A$ = "T") GOTO21
18 IF (A$ = "U") GOTO24
19 IF (A$ = "Q") GOTO27
20 GOTO16
21 CLOSE5 : PRINT" (H(CPET TO HP3000 TERMINAL OPERATING SYSTEM"
22 POKE59468, 14 : POKE167, 0 : D$ = "EAR" : OPEN 5, 4, 15, D$
23 GOSUB3
24 CLOSE5 : PRINT" (H(CUPLOADING…"
25 POKE167, 1 : OPEN5, 4, 15, "EPC999997" : CMD5
26 LIST
27 CLOSE 5
28 RETURN
29 REM
30 REM MACHINE CODE TO DISCONNECT
31 REM THE BASIC PROGRAMMER'S TOOLKIT
32 REM
33 PRINT "(H(C"
34 PRINT"TOOLKIT DISCONNECT ROUTINE"
35 N = 832 : FORI = 57647TO57656
36 X = PEEK (I) : POKEN, X : N = N + 1 : NEXTI
37 FORI = 826TO831 : READX : POKEI, X : NEXTI
38 FORI = 842TO848 : READX : POKEI, X : NEXTI
39 DATA165, 119, 72, 165, 120, 72
40 DATA104, 133, 120, 104, 133, 119, 96
41 POKE833, 24 : SYS826
42 PRINT "TOOLKIT DISCONNECTED" : FORI = 1TO 1000 : NEXTI
43 RETURN