SQ Notes: Terminal Program

Publication

Pub Details

Date

Pages

BASIC Terms

See all articles from SMUG Bytes v6 n4

Ever been frustrated with the type of terminal programs available for your computers? Well some years ago, the only terminal programs available for the 2068 were MTERM & MTERM II, the slow key response of either program got to me, so I sat down and wrote my own. Perhaps some of you still remember the printout which I brought to one of the meetings.

At that time I was looking for a solution to the slow screen action on the 2068 while running the 2050 modem at 1200 baud. I was loosing one or two characters at the beginning of each line after the initial screen had filled, and the scroll routine in ROM was activated. I solved the problem a few days later by telling the TNC (Terminal Node Controller) to send a few nulls after each linefeed, this took care of the problem.

The program I wrote, which you can see in the next columns, was originally written for use with PACKET RADIO, a form of digital communication developed by Amateur Radio Operators, where instead digital signals are send via Radio rather than via the telephone lines. This should tell you that this program will work with an RS 232 board which I installed into the 2050 modem, but I have never checked this program with the phone modem in the 2050.

In the next column is a listing of the 275 bytes of code for the main module, nothing fancy, but fast. There are some features incorporated in the code, an audible tone when a control “G” is received, and the chance to open a capture buffer, 32K in length, from basic, which you may reset and clear while in terminal mode. All this could be enhanced with the support of a basic program. You will find a few lines of basic I wrote to give you some idea. Make any additions or changes to your liking or needs.

Assembly Listing

ORG     $EE00

BAUD: NOP ; BAUDRATE, 4E=1200
BOPN: NOP ; FF=BUFFER OPEN, 00 CLOSED
BFER: NOP ; START OF BUFFER CONSTANT
NOP ; AT 6DF6H = 28150 DEC
PBFR: NOP ; BUFFER POINTER (WRITE)
NOP
LBFR: NOP ; REMAINING SPACE IN BUFFER
NOP
INIT: LD HL,6DF6 ; LOAD HL - START BUFFER
LD (BFER),HL ; LOAD EE02 HL
LD (PBFR),HL ; LOAD EE04 HL
LD HL,8000 ; LOAD HL, LENGTH BUFFER
LD (LBFR),HL ; LOAD EE06 HL
UART: XOR A ; CLEAR A
OUT (77),A ; OUTPUT 0 THREE TIMES TO
OUT (77),A ; ENSURE THAT USART IS
OUT (77),A ; IN A KNOWN STATE.
LD A,40 ; RESET USART=40H - 64DEC
OUT (77),A ; OUTPUT TO COMMAND CHANNEL
LD A,(BAUD) ; SET BAUDRATE
OUT (77),A ; OUTPUT TO COMMAND CHANNEL
LD A,37 ; ENABLE INPUT & OUTPUT
OUT (77),A ; OUTPUT TO COMMAND CHANNEL
CLBF: LD BC,8000 ; SET BC TO CLEAR BUFFER
LD HL,6DF4 ; SET HL TWO AHEAD OF BUFFER
LD DE,(BFER) ; SET DE TO START OF BUFFER
LDIR ; CLEAR BUFFER
RET ; RETURN
XOR A ; CLEAR REGISTER A
RLOP: LD A,(LASK) ; LOAD A, LAST KEY PRESSED
CP 00 ; COMPARE WITH 00
JP NZ,STTX ; JUMP TO STTX IF > 00
IN A,(77) ; GET USART STATUS
BIT 1,A ; CHECK IF USART HAS CHR$
JR Z,RLOP ; IF NO CHR$, START OVER
IN A,(73) ; GET CHR$ FROM USART
CP 08 ; IS IT A DELETE CHR$?
JP Z,DELE ; IF YES, JUMP TO DELETE ROUT.
CP 0D ; IS IT A (CR)?
JR Z,BFST ; IF YES, JUMP FORWARD
CP 07 ; IS IT A CTRL "G"?
CALL Z,BELL ; IF YES, GOTO BELL ROUTINE
CP 80 ; IS THE CHR$ > THAN 80H
JR NC,RLOP ; IF NOT PRINTABLE GOTO START
CP 20 ; IS THE CHR$ < THAN 20H
JR C,RLOP ; IF YES GOTO START
BFST: PUSH AF ; SAVE THE CHR$
LD A,(BOPN) ; LOAD A EE01
CP 00 ; CHECK IF BUFFER IS OPEN
JR Z,OUCH ; IF NOT, GOTO PRINT ROUTINE
PRBF: POP AF ; GET CHR$
CALL PNT1 ; GO SET HL & BC FOR BUFFER
LD (HL),A ; LOAD CHR$ INTO BUFFER
CPI ; UPDATE HL & BC
CALL PNT2 ; GO SAVE HL & BC
PUSH AF ; SAVE CHR$ AGAIN
JP PE,OUCH ; IF BUFFER NOT FILLED GOTO OUCH
XOR A ; CLEAR A REGISTER
LD (BOPN),A ; CLOSE BUFFER
CALL BELL ; RING BELL TO INDICATE
JR OUCH ; NOW GO AND PRINT CHR$
PNT1: LD HL,(PBFR) ; LOAD HL CONTENTS EE04
LD BC,(LBFR) ; LOAD BC CONTENTS EE06
RET ; RETURN
PNT2: LD (LBFR),BC ; LOAD EE06 BC
LD (PBFR),HL ; LOAD EE04 HL
RET ; RETURN
OUCH: POP AF ; GET CHR$ AGAIN
RST 10H ; PRINT CHR$ TO SCREEN
LD A,FFH ; LOAD REG. A WITH 255
LD (SCCT),A ; SET SCROLL COUNT CONTINUDUS
XOR A ; CLEAR REGISTER A
RET': JR RLOP ; DONE, GOTO START
DELE: LD HL,(DFCC) ; LOAD HL ADDRESS DISPLAY FILE
DEC HL ; GO BACK ONE SPACE
LD (DFCC),HL ; SET DISPLAY BACK ONE SPACE
PUSH HL ; SAVE POINTER
LD A,20H ; LOAD REG A WITH SPACE CHR$
RST 10H ; PRINT SPACE, ERASE OLD CHR$
POP HL ; GET POINTER BACK IN HL
LD (DFCC),HL ; SET DISPLAY FILE POINTER
LD A,(BOPN) ; LOAD REG A, EE01
CP 00 ; CHECK IF BUFFER OPEN
JR Z,RLOP ; FINISHED IF NOT
CALL PNT1 ; IF OPEN, SET HL & BC
DEC HL ; SET BUFFER POINTER BACK ONE
INC BC ; INCREMENT BUFFER LENGTH
CALL PNT2 ; RESAVE EE04 & EE06
XOR A ; CLEAR REGISTER A
JR RET' ; RETURN RLOP, TWO HOPS
BELL: PUSH AF ; SAVE CHR$
LD DE,00FF ; SET LENGTH OF TONE
LD HL,00FF ; SET PITCH OF TONE
CALL 03B5 ; CALL ROM BEEP (SINCLAIR)
POP AF ; GET CHR$ BACK
RET ; DONE, RETURN
; THIS ROUTINE CHECKS FOR CHR$ NORMALY NOT PASSED
; SINCE THEY ARE GREATER THAN 80H OR SMALER THAN 20H.
STTX: CP 80 ; UNPRINTABLE CHR$ ? (TOKEN)
JR NC,RET: ; RETURN BUT CLEAR KEY FIRST
CP 0E ; CS/SS PRESSED ? (CTRL KEY)
JR Z,CONV ; GOTO CONVERT ROUTINE
CP 0D ; IS IT THE ENTER KEY ?
JR Z,OUTX ; GOTO TRANSMITT ROUTINE
CP 0C ; DELETE KEY PRESSED ?
JR Z,OUTX ; GOTO TRANSMITT ROUTINE
CP 20 ; IS IT A SPACE ?
JR Z,OUTX ; AGAIN SEND CHR$
JR TXCH ; GOTO TX ROUT. BUT
CONV: LD A,(lask) ; GET 2ND KEY PRESS AFTER CS/SS
CP 0E ; BUT WAIT FOR 2ND KEY PRESS
JR Z,CONV ; LOOP TO WAIT
SUB 40H ; SUBTRACT 40H FROM CHR$
CP 20 ; WAS IT A CAPITAL CHR$ ?
CALL NC,AGAN ; IF NOT, GO DEDUCT ANOTHER 20H
CP 01 ; IS IT THE CHR$ "A" ?
RET Z ; IF YES, RETURN TO BASIC
CP 02 ; IS IT CHR$ "B" ?
CALL Z,CLBF ; IF YES, RESET & CLEAR BUFFER
CP 05 ; IS IT CHR$ "E" ?
CALL Z,OPEN ; IF YES, GOTO TOGLE THE BFFR.
CP 02 ; CHECK FOR CHR$ <03H
JR NC,OUTX ; IF NOT, SEND THEM
JR RET: ; IF YES, RETURN
TXCH: CP 20 ; REJECT CHR$ < THAN 20H
JR C,RET: ; RETURN, BUT CLEAR LAST KEY
OUTX: PUSH AF ; SAVE CHR$ TO BE SEND
XLOP: IN A,(77) ; GET USART STATUS
BIT 0,A ; IS USART BUSY ?
JR Z,XLOP ; IF YES, LOOP AND WAIT
POP AF ; GET CHR$ TO BE SEND TO REMOTE
OUT (73),A ; SEND CHR$ TO REMOTE
RET: XOR A ; CLEAR REGISTER A
LD (lask),A ; LOAD KEY PRESSED WITH 00
LD B,FF ; LOAD REGISTER B=FF
DLP1: DJNZ,DLP1 ; DELAY LOOP 255 CYCLES
JP RLOP ; NOW RETURN TO START
AGAN: SUB 20 ; SUBTRACT 20H AGAIN FROM CHR$
RET ; RETURN
OPEN: LD A,(BOPN) ; LOAD REG. "A" BUFFER STATUS
CP 00 ; BUFFER CLOSED ??
JR Z,OPN1 ; IF NOT, GO OPEN BUFFER
LD A,00H ; LOAD REG "A" 00 TO CLOSE
LD (BOPN),A ; CLOSE BUFFER
RET ; RETURN TO CONV
OPN1: LD A,FF ; LOAD REG "A" 255=FFH
LD (BOPN),A ; OPEN BUFFER
XOR A ; CLEAR REG "A"
RET ; DONE, RETURN TO CONV

A bit crude in places, but it works, and if it works, don’t fix it. I probably could have done a few things different, but when I wrote this program, I wasn’t as proficient writing code. Guess we all have to learn, and one way to learn, is, to do it! Start with something simple, and have a book handy which explains the mnemonics. An assembler is a must, most full screen editors & assemblers will do fine, but are a bit complex at times, a real good assembler / disassembler is HOT Z, which one could use to enter the above code. I bought HOT Z second hand from someone who had bought a better computer, poor guy! And I love it. To bad HOT Z is not available for other computers.

Reading through the code, you may have noticed, that when pressing Caps Shift & Symbol Shift together, and then pressing the “A” key, this will get you back to basic, while pressing the “B” key after CS/SS, will reset and clear the buffer, pressing the “E” key after CS/SS will togle the buffer either on or off, depending on in which state the buffer is. This will permit you to open the buffer from within the terminal program. If the buffer is togled, no reset or erase is performed, this will let you save some incoming, close the buffer, wait for some other stuffs, and reopen the buffer again to save some more without loosing text you had already saved.

I just typed this feature in right now without the aid of an assembler, all I can say is, I hope it works!! Use the clear buffer function to clear the buffer if you wish to do so.

Now that I took all the challenge out of adding this, I will give you another! There is no indicator that the buffer is open or closed! You could figure out to put an asterisk somewhere on the screen when the buffer is open, but you would slow the program down if you put it into the present read routine. One way to get out of the slow screen routine in ROM is to write your own routine, which, since you wont need all the checks the ROM routine normally makes, especially after the srceen has filled, will run quite a bit faster. This is a bit of a challenge for a novice to code, maybe you find such a routine somewhere, and are able to incorporate it into the above code.

Here now a few lines of basic, which should go along with the code.

BASIC Listing

10 CLEAR 60927: PAPER 0: BORDER 0: INK 7: CLS
20 LOAD "TERMINAL"CODE
30 INPUT "BAUD RATE * 300/1200 >";B: IF B=300 THEN POKE 60929,79
40 IF B=1200 THEN POKE 60928,78
50 INPUT "BUFFER OPEN (Y/N) ";A$: IF A$="Y" OR A$="y" THEN POKE 60929,255: GO TO 70
60 POKE 60929,0
70 RANDOMIZE USR 60984: RANDOMIZE USR 60984
80 PRINT "DO YOU WISH TO VIEW BUFFER (Y/N)": PAUSE 0: IF INKEY$="N" OR INKEY$="n" THEN STOP
90 PRINT ''"HARDCOPY (Y/N)": PAUSE 0: IF INKEY$="N" OR INKEY$="n" THEN LET A=2: GO TO 110
100 LET A=3
110 FOR X=28150 TO 60918
120 IF PEEK X=0 THEN STOP
130 PRINT #A;CHR$ PEEK X;
140 NEXT X

The code has one ROM call, you would have to change the call at location EEC0 if you are planing to use this program with the 2068 in the TIMEX mode, to 03F3. The above program should work with OS64, to give you 64 columns, but you may have to decrease the buffer size !? This can be accomplished, changing the code at EE11 & EE2B from 8000 to whatever number will work.

Have fun! Next month I will be in Europe, I hope to have a column ready for the May issue of SMUG BYTES before I leave (something about the QL & TURBO). If not, you will find it in the June issue.

About this transcription

This listing was transcribed from the original scan and checked line by line. The published address column, object-byte column and mnemonics each independently determine the program, so all three were cross-referenced against one another: 147 lines carried both bytes and mnemonics and were fully verified.

The following could not be resolved from the available scan and are reproduced as printed: EE3Eh (JP NZ,STTX computes to EEC0h, not EEC5h where STTX is defined) and EE50h (JR Z,BFST computes to EE52h, not EE5Fh where BFST is defined). Both labels are referenced only once in the excerpt, so nothing else in the article confirms which column is at fault. If you have a cleaner copy of this issue, corrections are welcome.

Products

 

Media

 

Image Gallery

Source Code

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top