A Terminal Operating System For PET To HP3000 +
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.
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
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
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