**** **** TTY1050.ASM - 83.07.08: SAROKA **** FOR CP/M PLUS **** (1050 key mappings) **** TELETYPE EMULATOR PROGRAM with FILE SEND/RECEIVE **** COPYRIGHT (C) 1983 VISUAL TECHNOLOGY INC. **** **** Version 1.0 Updated 12/06/83 LEL **** Version 1.1 Updated 01/27/84 LEL **** Version 1.2 Updated 03/02/84 LEL **** Version 1.3 Updated 03/28/84 LEL **** Version 1.4 Updated 07/02/84 KB **** Version 1.5 Updated 03/20/85 DLB MACLIB Z80 ** SYSTEM ADDRESSES SYSFCB EQU 05CH ;system file control block SYSDMA EQU 080H ;system DMA area RSINTR EQU 0FFFEH ;rs-232 port interrupt ** RS-232 PORT ADDRESSES RSDAT EQU 8CH RSCOM EQU 8DH p$misc equ 092H ; Miscellaneous bits int$initial equ 010h ; Value to initialize int port int$port equ 0c0h ; Interrupt port ** BIOS ENTRY POINTS CONINS EQU 06H ;console input ready status CONIN EQU 09H ;console input CONOUT EQU 0CH ** FUNCTION PAD CODES F1KEY EQU 0D4H F2KEY EQU 0D8H F3KEY EQU 0DCH F4KEY EQU 0E0H F5KEY EQU 0E4H F6KEY EQU 0E8H F7KEY EQU 0ECH F8KEY EQU 0F0H F9KEY EQU 0FCH F10KEY EQU 090H HELPKEY EQU 0C0H BRKKEY EQU 088H ** SPECIAL CHARACTERS BEL EQU 07H BS EQU 08H LF EQU 0AH FF EQU 0CH CR EQU 0DH XON EQU 11H XOFF EQU 13H EOF EQU 1AH ESC EQU 1BH DM EQU '$' ;print string delimeter ; page ASEG ORG 0100H JMP START DB ' COPYRIGHT (C) 1983 VISUAL TECHNOLOGY INC. ' ** ** COMMUNICATION PARAM DEFAULTS ** xenb: db '1' ;xon/xoff enabled ;gt XRATE: DB '1' ;=FAST transmission rate BAUD: DB 'F' ;=9600 PARY: DB 'N' ;No parity SBITS: DB '1' ;1 stop DBITS: DB '8' ;8 data ECFLG: DB 'N' ;ECHO Mode=no LOGDRV: DB '@' ;LOG drive=CP/M Logged LEFLG: DB 'N' ;LOCAL ECHO = NO (LEL0284) FLFFLG DB 'Y' ; Filter Line Feeds = YES (LEL0284) RFFLG DB 'N' ; RUBOUT filter = NO (LEL0584) NLFLG: DB 'N' ; New Line flag = no (KB0784) ** ** FUNCTION KEY HANDLERS ** FUNTBL: DB (EFUNTBL-$-1)/3 DB F1KEY DW CMD ;command/online DB F5KEY DW SNDF ;send file DB F3KEY DW STRLGF ;start log DB F4KEY DW STPLGF ;stop log DB HELPKEY DW HELP ;help DB F6KEY DW XSTR1 ;xmit string #1 DB F7KEY DW XSTR2 ;xmit string #2 DB 084H DW SCRLCK ;scroll/no scroll (xon,xoff) DB BRKKEY DW BREAK ;break EFUNTBL EQU $ ** ** BEGIN PROGRAM ** START: ; ; First, relocate interrupt routine to common memory segment ; lxi h,reloc ; FROM location lxi d,reloc$addr ; TO location lxi b,Reloc$length ; Length ldir ; ; Display Sign on message ; LXI D,NAMMSG ;display signon mesg CALL PSTR LXI D,2 MVI C,6DH CALL 5 ;set console mode for no ^s MVI A,26H ;assert RTS,DTR OUT RSCOM STA RSPAR CALL SETPRMS ;set comm params CALL RFLUSH ;flush recv fifo DI ; Disable interrupts while doing this LHLD RSINTR ;rs-232 interrupt SHLD SAVINT LXI H,RS232$INT ;install interrupt handler SHLD RSINTR ;IVECT+16 EI ; reenable them ** ** OPEN POSSIBLE COMMAND FILE ** LDA SYSFCB+1 ;read 1st char of possible file name CPI ' ' ;IF blank JZ MAIN ;THEN no command file LXI H,SYSFCB+9 ;read 1st char of file type MOV A,M CPI ' ' ;IF not blank JNZ CMFIL$1 ;THEN leave alone MVI M,'T' ;ELSE make file type 'TTY' INX H MVI M,'T' INX H MVI M,'Y' CMFIL$1:LXI H,CMFBLK CALL OPENRF ;do open for READ JZ CMFIL$2 LXI D,BADFIL CALL PSTR ;THEN print an informative JMP CEXIT ;and exit program CMFIL$2:CALL CFIL1 ;read 1st char w/o stat check STA CMFCHR MVI A,0 JZ CMFIL$3 MVI A,1 CMFIL$3:STA CMFFLG page ** ** MAIN LOOP ** MAIN: CALL RECINS ;IF recv char avail JZ SENDK CALL RECIN ;THEN get recv'ed char MOV C,A lda xenable ;load xenable status gt ora a ;check if xon/xoff is disabled gt jrz main$5 ;if disabled jump gt call thrttl ;else call throttle gt MOV A,C JZ SENDK main$5: mov a,c ;gt PUSH B CALL PUTCHAR ;THEN send char to display... POP B MOV A,C ;Get the character (KB0784) CPI CR ;Test for CR (KB0784) JRNZ NOTCR ;Br if not (KB0784) LDA NLFLG ;Get the new line flag (KB0784) CPI 'Y' ;Test flag set (KB0784) JRNZ NOTCR ;Br if not (KB0784) PUSH B ;Save the character (KB0784) MVI A,LF ;Send a line feed to the tube (KB0784) CALL PUTCHAR ;. . (KB0784) POP B ;Restore the registers (KB0784) NOTCR: ; (KB0784) LDA ECFLG CPI 'Y' JNZ EC1 PUSH B CALL SNDOT ;ECHO POP B EC1: PUSH B CALL LOGFIL ;...and to LOG file POP B LDA ECFLG CPI 'Y' JNZ SENDK MOV A,C CPI CR JNZ SENDK MVI A,LF MOV C,A PUSH B CALL PUTCHAR POP B PUSH B CALL SNDOT POP B CALL LOGFIL SENDK: CALL EMCONINS ;IF kybd char avail JZ SENDF ; CALL SNDOTS ;AND IF xmitter ready (LEL0184) ; JZ SENDF ; (LEL0184) CALL EMCONIN ;THEN get char MOV C,A ORA A ;IF function key (bit7=1) JM FKEY ;THEN goto key handler ; ; Replace this: ; ; LDA XMTON ;IF xon ; CMP C ; ; JNZ SK$1 ; ; CALL CHKXON ;THEN goto handler ; JMP SENDF ; ; With this: mov a,c ; Get keycode (LEL1283) cpi xon ; Is it XON? (LEL1283) jz ckflow1 ; Jump if yes (LEL1283) cpi XOFF ; Is it XOFF? (LEL1283) jz ckflow2 ; Jump if yes (LEL1283) SK$1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; COMMENTED OUT 11/83 (LEL) ; ; LDA THRFLG ;IF throttle flag = false (LEL1183) ; ORA A ; (LEL1183) ; CZ SNDOT ;THEN transmit (LEL1183) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CALL SNDOT ; Send out (LEL1183) SENDF: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; COMMENTED OUT 11/83 (LEL) ; ; LDA THRFLG ;IF throttle flag = false ; ORA A ; JNZ MAIN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CALL SNDOTS ;AND IF xmitter ready JZ MAIN CALL SNDFIL ;THEN test for SEND file character available CNZ SNDOT ;AND xmit if available JMP MAIN ;continue main loop ** ** FUNCTION KEY HANDLERS ** ** COMMAND MODE CMD: LXI D,CMDMSG CALL PSTR ;print command prompt CALL GETC ;read a command char CPI F1KEY JNZ CMD$1 LXI D,EXCMSG ;"online" mesg CALL PSTR RET CMD$1: CALL NEWLIN ;print cr/lf LXI H,CTBL LXI D,BADCMD ;default is bad command CALL LOOKUP ;see if it's a valid cmd CALL SUBRHL ;exec the handler routine JMP CMD ;continue till no command entered (CR typed) ** ONLINE HELP HELP: LXI D,MHELP CALL PSTR ;print the help message RET ** START, STOP SEND FILE SNDF: LDA SNDFLG ;toggle stop/start bit XRI 2 STA SNDFLG RET ** START LOG FILE STRLGF: LXI H,LOGFLG ;LET LOGging = true MOV A,M MVI M,01H ORA A ;IF LOGging was false JZ XLOG ;THEN go open LOG file RET ** STOP LOG FILE STPLGF: LXI H,LOGFLG ;LET LOGging = false MOV A,M MVI M,00H ORA A ;IF LOGging was true JNZ XLGCL ;THEN go close LOG file RET ** CONTROL Q FROM KEYBOARD CKFLOW1: ; (LEL1283) lxi h,scrflg ; Point to keyboard xon/xoff flag (LEL1283) mov a,m ; get it (LEL1283) ora a ; Check present value (LEL1283) mvi a,0 ; A=0 (LEL1283) mov m,a ; SCRFLG=0 (LEL1283) Cnz SCRL1 ; SEND XON (If not already sent) (LEL1283) JMP SENDF ; (LEL1283) ;* CONTROL S FROM KEYBOARD CKFLOW2: ; (LEL1283) lxi h,scrflg ; Point to keyboard xon/xoff flag (LEL1283) mov a,m ; get it (LEL1283) ora a ; Check present value (LEL1283) MVI A,0FFH ; (LEL1283) mov m,a ; SCRFLG=FF (LEL1283) Cz SCRL$0 ; SEND XOFF (If not already sent) (LEL1283) JMP SENDF ; (LEL1283) ;* SCROLL/NO SCROLL SCRLCK: LDA SCRFLG ;toggle scroll flag XRI 0FFH STA SCRFLG JRZ SCRL$1 ;IF flag = true SCRL$0: lda rqflg ; Get rcv xon/xoff flag (LEL1283) ora a ; Check it (LEL1283) mvi c,XOFF ; Then send xoff (LEL1283) cz sndot ; send it out (LEL1283) RET SCRL$1: LDA XMTON ;ELSE send XON (if allowed) MOV C,A CALL CHKXON RET ** SEND BREAK SIGNAL BREAK: DI LDA RSPAR ORI 08H OUT RSCOM sta rspar ; Restore parameters (LEL0184) ei ; Reenable interrupts (LEL0184) ; ; Space on the line for 250 ms ; LXI H,0A2C2h ;A2c2H*6.0=250ms (LEL0184) BREAK$4: DCX H MOV A,H ORA L JNZ BREAK$4 di ; (LEL0184) LDA RSPAR ANI 0F7H OUT RSCOM sta rspar ; Restore parameters (LEL0184) EI RET ** XMIT STRING 1 XSTR1: LXI H,PM1 JMP XSPM ** XMIT STRING 2 XSTR2: LXI H,PM2 JMP XSPM ** ** COMMANDS ** ** BAD COMMAND BADCMD: STA NGMSG1 ;put bad char in error mesg LXI D,NGMSG CALL PSTR ;type the error mesg RET ** CMD - Command HELP: 'H' CHELP: LXI D,HLPMSG CALL PSTR RET ** CMD - Set params: `S' CSPAR$1:CALL NEWLIN CSPARAM:LXI D,PMMSG ;present 1st form (choose param) CALL PSTR CALL GETC ;get a choice RZ ;if CR then done, exit LXI H,PMTBL CALL LOOKUP ;look up param JC CSPAR$1 ;if invalid SHLD SVP ;save data pointer for this param CSP1: LHLD SVP ;get pointer MOV E,M INX H MOV D,M ;(DE)=next form INX H CALL PSTR ;print form CALL GETC ;read a choice RZ ;if CR then done MOV E,M INX H MOV D,M ;(DE)=choice table INX H PUSH H XCHG PUSH D CALL LOOKUP ;lookup choice POP D POP H JC CSP1 ;if invalid choice MOV B,M INX H MOV H,M MOV L,B ;(HL)=save location for choice MOV M,A CALL SETPRMS ;set new comm params RET ** CMD - display parameters: `D' CDPARAM:CALL NEWLIN LXI D,PRMMSG ;print intro mesg CALL PSTR LXI H,BDTBL LDA BAUD CALL LOOKUP XCHG CALL PSTR ;print baud lxi d,parmsg ;gt call pstr ;gt LXI H,pytbl LDA pary CALL LOOKUP XCHG CALL PSTR ;print parity lxi d,stopmsg ;gt call pstr ;gt lxi h,sbtbl LDA sbits CALL LOOKUP XCHG call pstr ; Print stop bits lxi d,datamsg ;gt call pstr ;gt LDA DBITS CALL PUTC ;print data bits LXI D,TRANSMSG ;gt call pstr ;gt LXI H,rttbl LDA xrate CALL LOOKUP XCHG CALL PSTR ;print transmission rate lxi d,xmsg ;gt call pstr ;gt lxi h,xtbl ;gt lda xenb ;gt call lookup ;gt xchg ;gt call pstr ;print xon/xoff status gt LXI D,RLFMSG CALL PSTR LDA ECFLG CALL PUTC LXI D,LGMSG CALL PSTR LDA LOGDRV CALL PUTC lxi d,lecmsg ; (LEL0284) call pstr ; (LEL0284) lda leflg ; Get current setting of local echo flg (LEL0284) call putc ; Send it out (LEL0284) lxi d,flfmsg ; Filter line feeds (LEL0284) call pstr ; Print header (LEL0284) lda flfflg ; Get current value (LEL0284) call putc ; print it (LEL0284) lxi d,rffmsg ; Rubout filter (LEL0584) call pstr ; Print header (LEL0584) lda rfflg ; Get current value (LEL0584) call putc ; print it (LEL0584) lxi d,crfmsg ; New Line message (KB0784) call pstr ; Print header (KB0784) lda nlflg ; Get current value (KB0784) call putc ; print it (KB0784) call newlin RET ** CMD - Unlock keyboard locked by XOFF CNLCK: XRA A STA THRFLG ;throttle flag:=false call sndot5 ; Send whatever had queued up (LEL0184) RET ** CMD - Exit to OS (hang up): `X' CEXIT: MVI A,24H OUT RSCOM ;turn off DTR ** CMD - Exit to OS (DON'T hang up): `Q' CQUIT: DI LHLD SAVINT SHLD RSINTR EI LXI D,FCBL MVI C,10H CALL 5 LXI D,0 MVI C,6DH CALL 5 ;reset console mode JMP 0 ;exit program (warm boot) ** CMD - Open send file: `O' BADOS: CALL PSTR COSEND: XRA A STA SNDFLG LXI H,FCBS MVI A,36 MVI M,0 INX H DCR A JNZ $-4 LXI H,FCBS+1 MVI A,11 MVI M,' ' INX H DCR A JNZ $-4 LXI D,OSNDMSG CALL PSTR LXI D,CONBUF CALL RDCBUF RZ LXI D,FCBS CALL XLTFN LDA FCBS ADI 40H LXI H,LDTBL CALL LOOKUP LXI D,BADDRV JC BADOS LXI H,SNDBLK CALL OPENRF LXI D,BADFIL JNZ BADOS MVI A,1 STA SNDFLG RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Added to 'S' Set param table instead (LEL0184) ; ;** CMD - Specify LOG file device: 'L' ;BADCSL: CALL NEWLIN ;CSLOG: LXI D,LGDRVMSG ; CALL PSTR ; CALL GETC ; RZ ; LXI H,LDTBL ; CALL LOOKUP ; JC BADCSL ; STA LOGDRV ; RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ** CMD - Program Message strings: 'M' CMSTR: LXI D,PM1MSG CALL PSTR LXI H,PM1 CALL DSPM CALL NEWLIN LXI D,PM2MSG CALL PSTR LXI H,PM2 CALL DSPM CMS$1: LXI D,CHGMSG CALL PSTR CALL GETC RZ LXI H,PSMTBL CALL LOOKUP JC CMS$1 PUSH H LXI D,INPSMSG CALL PSTR LXI D,PSMBUF CALL RDCBUF POP H LXI D,PSMBUF+1 LDAX D MOV B,A INX D CMS$2: MOV A,B ORA A JZ CMS$3 LDAX D MOV M,A INX H INX D DCR B JMP CMS$2 CMS$3: MVI M,0FFH JMP CMS$1 DSPM: MOV A,M INX H CPI 0FFH RZ CALL PUTC JMP DSPM XSPM: MOV A,M INX H CPI 0FFH RZ CPI '^' JNZ XSP$1 MOV A,M INX H CPI 0FFH RZ CALL ADJUP SUI 40H XSP$1: MOV C,A PUSH H CALL SNDOT POP H JMP XSPM ** ** BIOS ENTRY POINTS ** BCONOUT:MVI B,CONOUT JMP XBIOS BCONINS:MVI B,CONINS JMP XBIOS BCONIN: MVI B,CONIN XBIOS: LHLD 1 MOV L,B PCHL ** TRANSLATE FILE DESCRIPTOR INTO FCB NAME,TYPE,DRV XLTFN: LXI H,CONBUF+1 MOV A,M INX H CALL DADDA MVI M,0FFH ;end combuf marker LXI H,CONBUF+3 MOV A,M CPI ':' DCX H JNZ XLT$1 MOV A,M CALL ADJUP SUI 40H STAX D INX H INX H XLT$1: INX D PUSH D MVI B,8 XLT$3: MOV A,M INX H CPI 0FFH JNZ XLT$5 XLT$33: ; (LEL0184) POP D RET XLT$5: CALL ADJUP CPI '.' JZ XLT$2 STAX D INX D DCR B JNZ XLT$3 MOV A,M ; GET CHARACTER (LEL0184) CPI 0FFH ; WAS THAT THE LAST CHAR? (LEL0184) JRZ XLT$33 ; IF YES, DONE (LEL0184) INX H ; ELSE, INC PAST '.' (LEL0184) XLT$2: POP D PUSH H LXI H,8 DAD D XCHG POP H MVI B,3 XLT$4: MOV A,M INX H CPI 0FFH RZ CALL ADJUP STAX D INX D DCR B JNZ XLT$4 RET ; ;Build a command byte for MRSSET based on current ;parameter values SETPRMS: MVI C,01H LDA SBITS CPI '1' MVI B,40H JZ SP2 CPI '.' MVI B,80H JZ SP2 MVI B,0C0H SP2: MOV A,B ORA C ;add stop bits MOV C,A LDA PARY CPI 'E' MVI B,30H JZ SP1 CPI 'O' MVI B,10H JZ SP1 MVI B,00H SP1: MOV A,B ORA C ;add parity MOV C,A LDA DBITS LXI H,DBTBL CALL LOOKUP ; ; Check if parity = IGNORE ; LDA PARY ;Get the parity selection (DLB0385) CPI 'I' ;Is it = IGNORE (DLB0385) JNZ SP7 ;Jump if not set to IGNORE (DLB0385) ; ; mov a,h ; Get data mask (LEL0284) ; sta data$mask ; Store for RINT (LEL0284) ; ; If parity = IGNORE and data bits <> 8, add 1 to # data bits ; lda dbits ; Get # data bits (LEL0284) cpi '8' ; Is it 8? (LEL0284) jrz sp7 ; Jump if yes (LEL0284) adi 1 ; Else add 1 to # data bits (LEL0284) lxi h,dbtbl ; Point to table (LEL0284) call lookup ; Lookup data bits + 1 (LEL0284) sp7: ; (LEL0284) MOV A,L ORA C ;add data bits MOV B,A LDA BAUD SUI 'A' MOV C,A ;add baud CALL RSSET ;set params ; ; Set up wait delay ; lda xrate ;get rate (LEL1083) lxi h,0 ; 1=fast (LEL1083) cpi '1' ; Is is 1? (LEL1083) jrz sp3 ; Jump if yes (LEL1083) lxi h,50 ; (LEL1083) cpi '2' ; Is it 2? (LEL1083) jrz sp3 ; Jump if yes (LEL1083) lxi h,150 ; Else, assume 3 (slow) (LEL1083) sp3: shld wait$time ; (LEL1083) lda xenb ;get xon/xoff gt cpi '1' ;check if on or off gt jrz sp4 ;if xon then jump gt xra a ;else clear acc. gt jr sp5 ;jump to store content of acc. gt sp4: mvi a,0ffh ;set acc. to 1 gt sp5: sta xenable ;store in xenable gt RET ** GET CHAR FROM SEND FILE SNDFIL: LDA SNDFLG CPI 3 JNZ SF$NG LXI H,SNDBLK CALL FILEIN MOV C,A JZ SF$CLSE CPI EOF JZ SF$CLSE lda flfflg ; Filtering line feeds? (LEL0284) cpi 'Y' ; (LEL0284) rnz ; return if not (LEL0284) MOV A,C CPI LF RET SF$NG: XRA A RET SF$CLSE:XRA A STA SNDFLG RET ** LOG FILE HANDLER, CHAR IN C LOGFIL: LDA LOGFLG ANI 1 RZ LOGFIL1:LXI H,LOGBLK CALL FILEOUT JNZ CLSLOG RET ** XLOG: LDA LOGDRV SUI 40H STA FCBL STA FCBBAK LXI H,LGNUM+2 CALL BMPDEC LXI H,BAKNUM+2 CALL BMPDEC LXI H,FCBBAK+12 CALL CLRFCB LXI D,FCBBAK MVI C,13H CALL 5 LXI H,FCBL+16 LXI D,FCBL MVI B,9 CALL MOVCNT XRA A STA FCBL+16 MVI M,'B' INX H MVI M,'A' INX H MVI M,'K' LXI D,FCBL MVI C,17H CALL 5 LXI H,FCBL+12 CALL CLRFCB LXI H,LOGBLK CALL OPENWF RZ LXI D,BLOGMSG CALL PSTR JMP CLSLOG XLGCL: MVI C,EOF CALL LOGFIL1 LXI H,LOGBLK CALL CLOSEWF CLSLOG: XRA A STA LOGFLG STA FCBL RET ** FUNCTION KEY VECTORER FKEY: LXI H,FUNTBL ;enter w/ A=mapped function key code CALL LOOKUP jc AKP$check ; See if AKP key (LEL0284) call SUBRHL ;goto handler routine (IF MATCH FOUND) (LEL1183) JMP MAIN ; ; This code checks to see if the key is from the alternate key pad. ; If it is, the approriate ANSI mode sequence is sent in place of the ; key code. The ANSI sequences are of the form ESC O , where ; is a final character that varies depending on the key hit. ; AKP$check: lxi b,AKP$entries ; Get # entries (LEL0284) lxi h,AKP$table ; And start of table (LEL0284) AKP$loop: ; (LEL0284) cci ; Compare w/keycode in A (LEL0284) jz AKP$match ; Jump if match found (LEL0284) inx h ; Else, point to next entry (LEL0284) jpe AKP$loop ; While BC<>0, loop (LEL0284) jmp main ; Jump out if no match (LEL0284) AKP$match: ; (LEL0284) push h ; Save table pointer (LEL0284) mvi c,01bh ; Send ESC (LEL0284) call sndot ; (LEL0284) mvi c,'O' ; Then 'O' (LEL0284) call sndot ; (LEL0284) pop h ; Restore table pointer (LEL0284) mov c,m ; Move final char to C-reg (LEL0284) call sndot ; send it (LEL0284) jmp main ; That is all (LEL0284) ** SEND XON CHAR IF ALLOWED CHKXON: LDA RQFLG ORA A RNZ ; If flag=FF, don't send XON (LEL1183) MOV A,C DI CALL XMTX ; (LEL1183) EI RET ** FLUSH RECEIVER FIFO RFLUSH: DI LXI H,0 SHLD RFFP LXI H,0 SHLD SFFP XRA A STA RQCNT STA RQFLG EI RET ** READ CONSOLE GETC: PUSH H CALL BRON CALL EMCONIN PUSH PSW CALL EMCONOUT CALL BROF POP PSW CALL ADJUP ;make lower upper CPI CR ;set Z flag for NUL char POP H RET ;** CLR FILE BLOCK CLRFCB: MVI A,24 MVI M,0 INX H DCR A JNZ $-4 RET ** SEND CHAR TO CONSOLE PUTCHAR: PUTC: ora a ; Is character a Null? (LEL1183) rz ; If yes, don't display (LEL1183) MOV E,A ; Put into E-reg lda rfflg ; Filtering RUBOUTS? (LEL0584) cpi 'Y' ; (LEL0584) jrnz PUTC4 ; Jump if not (LEL0584) mov a,e ; Else, get char (LEL0584) cpi 07FH ; Is it a RUBOUT? (LEL0584) rz ; If yes, don't display (LEL0584) putc4: ; (LEL0584) PUSH H MVI C,2 ;and send to console (using BDOS) CALL 5 POP H RET ** PRINT NEW LINE NEWLIN: PUSH PSW MVI A,CR CALL PUTC MVI A,LF CALL PUTC POP PSW RET ** READ CONSOLE BUFFER (BDOS) RDCBUF: PUSH D CALL BRON POP D PUSH D CALL EMRCB CALL BROF POP D INX D LDAX D ORA A RET ** READ CONBUF EMULATOR EMRCB: LDAX D MOV B,A MVI C,0 INX D PUSH D INX D XCHG RCBLP: CALL EMCONIN CPI CR JZ RCBDN CPI BS JZ RCBBS CPI 18H JZ RCBBSA CPI 20H JC RCBLP MOV M,A CALL EMCONOUT INX H INR C MOV A,B CMP C JNZ RCBLP RCBDN: CALL EMCONOUT POP H MOV M,C RET RCBBS: CALL RCBBK JMP RCBLP RCBBSA: CALL RCBBK JNZ RCBBSA JMP RCBLP RCBBK: MOV A,C ORA A RZ DCR C DCX H PUSH PSW MVI A,BS CALL EMCONOUT MVI A,' ' CALL EMCONOUT MVI A,BS CALL EMCONOUT POP PSW RET ** EMCONOUT: PUSH H PUSH D PUSH B MOV C,A CALL BCONOUT POP B POP D POP H RET ** EMCONINS: CALL CFILSTAT RNZ CALL BCONINS RET ** EMCONIN: PUSH H PUSH D PUSH B CALL CFILIN JNZ EMCN$1 CALL BCONIN EMCN$1: POP B POP D POP H RET ** ; ; Check the status of the input file (IE,xxxxxx.tty) before checking ; the keyboard. However, if there is a SEND file activity going on, ; wait till it terminates. This is done to solve the problem that happens ; when doing a SEND operation from an input file. If we do not wait ; for the SEND operation to terminate, operations are not performed ; in the order that was intended. ; CFILSTAT: lda sndflg ; Get send flag (LEL0384) sui 3 ; Sending something? (LEL0384) rz ; If yes, act like file is empty(LEL0384) LDA CMFFLG ORA A RET CFILIN: CALL CFILSTAT RZ LDA CMFCHR MOV B,A PUSH B CALL CFIL1 STA CMFCHR MVI A,0 JZ CFSET MVI A,1 CFSET: STA CMFFLG POP B ORI 0FFH MOV A,B RET CFIL1: CALL GETCFC RZ CPI 20H JC CFIL1 ;IGNORE CTRL CHARS IN FILE CPI '!' JZ CFIL2 CPI '\' JZ CFIL3 RET ;RNZ CFIL2: CALL GETCFC RZ CALL ASC2BIN ADD A ADD A ADD A ADD A MOV B,A PUSH B CALL GETCFC POP B RZ CALL ASC2BIN ORA B MOV B,A ORI 0FFH MOV A,B RET CFIL3: CALL GETCFC RZ CALL ADJUP SUI 40H MOV B,A ORI 0FFH MOV A,B RET GETCFC: LXI H,CMFBLK CALL FILEIN JZ GETCF1 CPI EOF RNZ GETCF1: XRA A STA CMFFLG RET ** BRITE ON,OFF BRON: LXI D,BRONMSG CALL PSTR RET BROF: LXI D,BROFMSG CALL PSTR RET ** PRINT OPERATOR MESSAGE PSTR: PUSH H MVI C,9 ;"print string" CALL 5 POP H RET ** TEST FOR XON, XOFF RECV'ED THRTTL: LDA XMTON XRA C JZ THR$1 LDA XMTOFF CMP C RNZ ; ; Have received XOFF. Turn off XMIT enable. ; DI ; (LEL0184) LXI H,RSPAR ; Point to RS232 param byte (LEL0184) MOV A,M ; Get current byte value (LEL0184) ANI 0FEH ; Turn off Xmit enable (LEL0184) MOV M,A ; Store new value (LEL0184) OUT RSCOM ; Send out (LEL0184) EI ; (LEL0184) XRA A ; Make sure Z flag set (LEL0184) MVI A,0FFH ; jr Thr$4 ; (LEL0184) THR$1: call sndot5 ; send out anything that was queued up (LEL0184) XRA A ; Move 0 to A (LEL0184) thr$4: STA THRFLG RET ;RZ ** MOVE BYTES MOVCNT: LDAX D MOV M,A INX H INX D DCR B JNZ MOVCNT RET ** ** CONVERT ASCII/HEX TO BINARY ** ASC2BIN:CALL ADJUP SUI 30H CPI 10 RC SUI 7 RET ** ** ADD HL+A ** DADDA: ADD L MOV L,A RNC INR H RET ** ** CALL (HL) ** SUBRHL: PCHL ** ** MAKE LOWER UPPER ** ADJUP: CPI 'a' RC CPI 'z'+1 RNC SUI 20H RET ** ** BUMP 3-DIGIT ASCII/DECIMAL COUNT ** IN: (HL)=L/S DIGIT ** BMPDEC: MVI B,3 BDEC$1: INR M MOV A,M CPI '9'+1 RNZ MVI M,'0' DCX H DCR B JNZ BDEC$1 RET ** ** LOOK UP BYTE IN TABLE ** IN: A = lookup byte ** HL = table addr ** DE = default return data ** OUT: A = lookup byte ** CF = 0: byte found, HL = return data ** CF = 1: byte NOT found, HL = default data ** LOOKUP: MOV B,M INX H LK1: CMP M JZ LK2 INX H INX H INX H DCR B JNZ LK1 STC XCHG RET LK2: INX H MOV B,M INX H MOV H,M MOV L,B RET ** ** OPEN FILE FOR READING ** IN: (HL) = CONTROL BLOCK: ** DB ** DW ** DW ** OUT: ZF=1 ---> not found ** =0 ---> file open ** OPENRF: MVI M,127 INX H INX H INX H MOV E,M INX H MOV D,M MVI C,0FH CALL 5 ORA A RM CMP A RET ** ** OPEN FILE FOR WRITING (CREATE) ** IN: (HL) = CONTROL BLOCK: ** DB ** DW ** DW ** OUT: ZF=1 ---> couldn't do create ** =0 ---> file open ** OPENWF: MVI M,0 INX H INX H INX H MOV E,M INX H MOV D,M PUSH D MVI C,13H CALL 5 POP D MVI C,16H CALL 5 ORA A RM CMP A RET ** ** CLOSE A WRITE FILE ** IN: (HL) = CONTROL BLOCK: ** DB ** DW ** DW ** CLOSEWF:PUSH H INX H MOV E,M INX H MOV D,M INX H PUSH H MVI C,1AH CALL 5 POP H MOV E,M INX H MOV D,M POP H MOV A,M ORA A PUSH D MVI C,15H CNZ 5 POP D MVI C,10H CALL 5 RET ** ** READ NEXT BYTE FROM AN OPEN FILE ** IN: (HL) = CONTROL BLOCK: ** DB ** DW ** DW ** OUT: ZF=1 ---> no byte (EOF) ** =0 ---> A=byte ** FILEIN: INR M ;bump count MOV A,M CPI 128 ;IF count EQU 128 JNZ FLIN$1 PUSH H ;save (HL)=count MVI M,0 ;count=0 INX H MOV E,M INX H MOV D,M ;DE=DMA addr INX H PUSH H ;save (HL)=FCB MVI C,1AH CALL 5 ;BDOS SET DMA POP H ;get (HL)=FCB MOV E,M INX H MOV D,M ;DE=FCB MVI C,14H CALL 5 ;BDOS READ SEQ POP H ;get (HL)=count ORA A ;test READ status JZ FLIN$1 ;IF EOF XRA A RET ;exit ENDIF ;ENDIF FLIN$1: MOV E,M MVI D,0 ;DE=count INX H MOV A,M INX H MOV H,M MOV L,A ;HL=DMA DAD D ;HL=addr of this byte ORI 0FFH ;set ZF=0 MOV A,M ;A=input byte RET ** ** WRITE NEXT BYTE TO AN OPEN FILE ** IN: (HL) = CONTROL BLOCK: ** DB ** DW ** DW ** C = byte ** OUT: ZF=1 ---> no write (end of disk space) ** =0 ---> write successful ** FILEOUT:MOV A,M ;A=count PUSH H ;save (HL)=count INX H MOV E,M INX H MOV D,M ;DE=DMA MOV L,A MVI H,0 ;HL=count DAD D ;HL=write addr MOV M,C ;write byte to buffer POP H ;get back (HL)=count INR M ;bump count MOV A,M ;A=count CPI 128 ;IF not end of buffer JNZ FILO$1 ;THEN don't write record to file MVI M,0 ;ELSE reset count INX H MOV E,M INX H MOV D,M ;DE=DMA INX H PUSH H MVI C,1AH CALL 5 ;BDOS SET DMA POP H MOV E,M INX H MOV D,M ;(DE)=FCB PUSH D MVI C,15H ;WRITE SEQ CALL 5 POP D ORA A JP FILO$1 MVI C,10H CALL 5 ;CLOSE ORI 0FFH RET FILO$1: CMP A RET **** **** RS-232 SEND & RECEIVE ROUTINES **** AND **** INTERRUPT HANDLERS **** ** RECEIVER STATUS RECINS: LXI H,RFFP MOV A,M INX H ;(RFEP) SUB M RET ** RECEIVER INPUT RECIN: CALL RECINS JrZ RECIN DI MOV A,M;=LDA RFEP INR A lxi d,rfilen ; Get length of buffer (LEL1083) cmp e ; Past end? (LEL1083) jrnz recin2 ; Jump if not (LEL1083) xra a ; Else, loop back to zero (LEL1083) recin2: ; (LEL1083) mov m,a ; Store new pointer (LEL1083) lxi h,rfi ; Get beginning of buffer (LEL1083) lxi d,0 ; Zero D & E (LEL1083) mov e,a ; Move pointer into low byte (LEL1083) dad d ; Add to start of buffer (LEL1083) MOV A,M PUSH PSW ** RECV QUEUE "GET" LDA RQCNT DCR A STA RQCNT ; CPI RFILEN-24 cpi 01 ;Wait till only 1 left before continuing (LEL1183) JrNZ X$RQG LXI H,RQFLG MOV A,M ORA A JrZ X$RQG INR M ;RQFLG:=0 lda scrflg ; Get keyboard XON/XOFF flag (LEL1283) ora a ; Check it (LEL1283) LDA XMTON Cz XMTX ; Send XON if NOT xoff'd from keyboard (LEL1283) X$RQG: POP PSW EI RET ** TRANSMITTER STATUS SNDOTS: lda thrflg ; Get XON/XOFF Flag (LEL1183) inr a ; Increment (LEL1183) RZ ; If flag was 0FFH,can't send (LEL1183) sndots1: LDA SFFP INR A lxi d,sfilen ; Get length of buffer (LEL1083) cmp e ; Past end? (LEL1083) jrnz sndots2 ; Jump if not (LEL1083) xra a ; Else wrap back to 0 (LEL1083) sndots2: ; (LEL1083) MOV E,A ;E:=(FILL POINTER+1) IN CIRCLE LDA SFEP SUB E RET ** TRANSMITTER OUTPUT SNDOT: CALL SNDOTS1 ; Room in buffer? (LEL0184) JrZ SNDOT9 ; Jump if not (LEL0184) lhld wait$time ; Get time to wait (LEL1083) call waiter ; Wait (LEL1083) DI lxi h,sfi ; Get start of buffer (LEL1083) mvi d,0 ; Clear D (LEL1083) dad d ; Add offset to start of buf (LEL1083) MOV A,C mov m,a ; Store character (LEL1083) MOV A,E STA SFFP ;SAVE NEW FILL POINTER ; ; Check local echo flag. If enabled, Put character on screen as ; well as in the buffer. ; lda leflg ; Get local echo flag (LEL0284) cpi 'Y' ; Enabled? (LEL0284) JRNZ NOTCRL ;Br if not (KB0784) mov a,c ; Get character (LEL0284) ; cz putchar ; If yes, send to display (LEL0284) CALL PUTCHAR ;Send to display (KB0784) LDA NLFLG ;Get the new line flag (KB0784) CPI 'Y' ;Is it set ? (KB0784) JRNZ NOTCRL ;Br if not MOV A,C ;Get character (KB0784) CPI CR ;Test CR code (KB0784) JRNZ NOTCRL ;Br if not CR (KB0784) MVI A,LF ;Add an LF (KB0784) CALL PUTCHAR ;. . (KB0784) NOTCRL: ; (KB0784) ; ; If not XOFFed, enable XMIT ; Sndot$3: lda thrflg ; Get XON/XOFF Flag (LEL0184) inr a ; Increment (LEL0184) RZ ; If flag was 0FFH,can't send (LEL0184) SNDOT5: di LXI H,RSPAR MOV A,M ORI 001H MOV M,A OUT RSCOM ;ENAB SND EI RET ; ; No room in buffer. Beep so that user knows. ; SNDOT9: mvi a,bel ; Send BELL code (LEL0184) call putc ; out to display (LEL0184) ret ; then return (LEL0184) ;SET REC/SND SPEED(C) AND PARAMETERS(B) RSSET: MVI D,0 MOV A,C CPI RTBLSIZ MOV A,D;MVI A,0 RNC ;BAD BAUD RATE ERROR MOV A,B ANI 03FH RZ ;0 STOP BITS ERROR MOV E,C LXI H,RTABLE DAD D RSSET0: IN RSCOM ANI 004H JrZ RSSET0 ;WAIT FOR SEND TO EMPTY RSSET1: DI MVI A,040H OUT RSCOM ;8251 SET MODE COMMAND IN p$misc ;GET OLD F3 BITS XRA M ANI 0F3H XRA M ;MERGE NEW 0C BITS FROM RTABLE OUT p$misc ;SET BASE BAUD RATE MOV A,M ;GET NEW 03 BITS FROM RTABLE XRA B ANI 003H XRA B ;MERGE OLD FC BITS FROM PARAMETER OUT RSCOM ;SET 8251 MODE LDA RSPAR OUT RSCOM ;8251 COMMAND MOV A,B ORI 0FFH ;RATE SET - RET TRUE EI RET ; ; Wait loop. Each iteration of this loop takes approx 1Ms. This ; loop is executed HL times. ; waiter: mov a,l ; Get L (LEL1083) ora h ; H=L=0? (LEL1083) RZ ; If yes, done (LEL1083) xra a ; (LEL1083) wait$1: ; (LEL1083) dcr a ; (LEL1083) JRNZ wait$1 ; Loop 256 times (LEL1083) dcx h ; Decrement count (LEL1083) jr waiter ; (LEL1083) RTABLE: DB 000H OR 003H ;300=1200/4 DB 004H OR 003H ;600=2400/4 DB 000H OR 002H ;1200 DB 004H OR 002H ;2400 DB 008H OR 003H ;4800=19200/4 DB 00CH OR 002H ;9600 DB 008H OR 002H ;19200 RTBLSIZ EQU ($-RTABLE) ** COMMAND HANDLER TABLE CTBL: DB (ECTBL-$-1)/3 DB 'X' DW CEXIT DB 'S' DW CSPARAM DB 'D' DW CDPARAM DB 'Q' DW CQUIT DB 'U' DW CNLCK DB 'O' DW COSEND DB 'M' DW CMSTR DB HELPKEY DW CHELP ECTBL EQU $ PMTBL: DB (EPMTBL-$-1)/3 DB 'B' DW CBAUD db 'X' ;gt dw cxenable ;gt DB 'T' DW CRATE DB 'P' DW CPARY DB 'S' DW CSBITS DB 'D' DW CDBITS DB 'E' DW ECO DB 'L' DW CLDRV DB 'O' ; Local Echo (LEL0284) DW CLECHO ; (LEL0284) DB 'F' ; Filter line feeds (LEL0284) DW FLFEED ; (LEL0284) DB 'R' ; Rubout (07FH) filter (LEL0584) DW RUBFIL ; (LEL0584) DB 'N' ; Rubout (07FH) filter (KB0784) DW CRNLM ; (KB0784) EPMTBL EQU $ BDTBL: DB (EBDTBL-$-1)/3 DB 'A' DW B300 DB 'B' DW B600 DB 'C' DW B1200 DB 'D' DW B2400 DB 'E' DW B4800 DB 'F' DW B9600 DB 'G' DW B19200 EBDTBL EQU $ B300: DB '300 ',DM B600: DB '600 ',DM B1200: DB '1200 ',DM B2400: DB '2400 ',DM B4800: DB '4800 ',DM B9600: DB '9600 ',DM B19200: DB '19200 ',DM PYTBL: DB (EPRTBL-$-1)/3 DB 'O' DW PODD DB 'E' DW PEVEN DB 'N' DW PNONE DB 'I' ; (LEL0284) DW PIGNORE ; (LEL0284) EPRTBL EQU $ PODD: DB 'ODD ',DM PEVEN: DB 'EVEN ',DM PNONE: DB 'NONE ',DM PIGNORE DB 'IGNORE ',DM xtbl: db (xtend-$-1)/3 ;gt db '0' ;gt dw xisoff ;gt db '1' ;gt dw xison ;gt xtend equ $ ;gt xison db 'ENABLED ',dm ;gt xisoff db 'DISABLED ',dm ;gt RTTBL: DB (XPRTBL-$-1)/3 DB '1' DW RFAST DB '2' DW RMED DB '3' DW RSLOW XPRTBL EQU $ RFAST: DB 'FAST ',DM RMED: DB 'MEDIUM ',DM RSLOW: DB 'SLOW ',DM SBTBL: DB (ESBTBL-$-1)/3 DB '1' DW SB1 DB '.' DW SB1P5 DB '2' DW SB2 ESBTBL EQU $ SB1: DB '1 ',DM SB1P5: DB '1.5 ',DM SB2: DB '2 ',DM DBTBL: DB (EDBTBL-$-1)/3 DB '5' DB 00,1fH ;8251 bits, data mask (LEL0284) DB '6' DB 04,3fh ;8251 bits, data mask (LEL0284) DB '7' DB 08,7fh ;8251 bits, data mask (LEL0284) DB '8' DB 0ch,0ffh ;8251 bits, data mask (LEL0284) EDBTBL EQU $ SVP: DS 2 CBAUD: DW BDMSG,BDTBL,BAUD CRATE: DW RTMSG,RTTBL,XRATE CPARY: DW PYMSG,PYTBL,PARY CSBITS: DW SBMSG,SBTBL,SBITS CDBITS: DW DBMSG,DBTBL,DBITS ECO: DW ECMSG,ECHTBL,ECFLG CXENABLE:dw xmssg,XTBL,XENB ;gt CLDRV DW lgdrvmsg,ldtbl,logdrv ; (LEL0184) CLECHO DW LEMSG,LETBL,LEFLG ; (LEL0284) FLFEED DW FLMSG,FLTBL,FLFFLG ; (LEL0284) RUBFIL DW RFMSG,RFTBL,RFFLG ; (LEL0584) CRNLM DW CRMSG,RFTBL,NLFLG ; (KB0784) WAIT$TIME DS 2 ; (LEL1083) THRFLG: DB 0 SAVINT: DS 2 CONBUF: DB 15 DS 15 ** ** LOG FILE ** FCBL: DB 0 ;DRV DB 'TTY' LGNUM: DB '000 ' ;NAM DB 'LOG' ;TYP DB 0 ;EXT DS 2 ;S1,S2 DS 1 ;RC DS 16 ;D0...DN DB 0 ;CR DS 3 ;R0,R1,R2 FCBBAK: DB 0 ;DRV DB 'TTY' BAKNUM: DB '000 ' ;NAM DB 'BAK' ;TYP DS 24 LOGFBF: DS 128 LOGFLG: DB 0 LOGBLK: LOGCNT: DB 0 DW LOGFBF DW FCBL ** ** SEND FILE ** FCBS: DS 1 ;DRV DS 8 ;NAM DS 3 ;TYP DB 0 ;EXT DS 2 ;S1,S2 DS 1 ;RC DS 16 ;D0...DN DB 0 ;CR DS 3 ;R0,R1,R2 ECMSG: DB CR,LF DB '[ ] SYSTEM ECHO Mode ?' DB ' Type Y or N, or to skip.',CR,'[',DM ECHTBL: DB (EECHTBL-$-1)/3 DB 'Y' DW YES DB 'N' DW NO EECHTBL EQU $ LEMSG: DB CR,LF DB '[ ] LOCAL ECHO Mode ?' DB ' Type Y or N, or to skip.',CR,'[',DM LETBL: DB (LECHTBL-$-1)/3 DB 'Y' DW YES DB 'N' DW NO LECHTBL EQU $ FLMSG: DB CR,LF DB '[ ] FILTER line feeds from SEND file?' DB ' Type Y or N, or to skip.',CR,'[',DM FLTBL: DB (FLCHTBL-$-1)/3 DB 'Y' DW YES DB 'N' DW NO FLCHTBL EQU $ RFMSG: DB CR,LF DB '[ ] RUBOUTs (07FH) filtered from input?' DB ' Type Y or N, or to skip.',CR,'[',DM CRMSG: ; (KB0784) DB CR,LF ; (KB0784) DB '[ ] Carriage Return to cause a New Line?' ; (KB0784) DB ' Type Y or N, or to skip.',CR,'[',DM ; (KB0784) RFTBL: DB (RFTBLEND-$-1)/3 DB 'Y' DW YES DB 'N' DW NO RFTBLEND EQU $ SNDFLG: DB 0 SNDFBF: DS 128 YES: DB 'YES',DM NO: DB 'NO',DM SNDBLK: SNDFC: DS 1 DW SNDFBF DW FCBS LDTBL: DB (ELDTBL-$-1)/3 DB 'A' DW 1 DB 'B' DW 2 DB 'C' DW 3 DB 'D' DW 4 DB 'E' DW 5 DB 'G' DW 7 DB '@' DW 0 ELDTBL EQU $ SVXCNS: DS 2 XCNS: DS 2 ** ** PROGRAMMABLE MESSAGE STRINGS ** PM1: DB 0FFH DS 80 PM2: DB 0FFH DS 80 PM1MSG: DB 'MESSAGE NO. 1:',CR,LF,DM PM2MSG: DB 'MESSAGE NO. 2:',CR,LF,DM CHGMSG: DB CR,LF DB '[ ] Type MESSAGE NO. to change, or to skip.',CR,'[',DM INPSMSG: DB CR,LF DB 'Type MESSAGE, then .',CR,LF DB 'Use ^ for control characters: ' DB '^M=carriage return, ^J=line feed, etc.' DB CR,LF,DM PSMTBL: DB (EPSMTBL-$-1)/3 DB '1' DW PM1 DB '2' DW PM2 EPSMTBL EQU $ PSMBUF: DB 80 DS 81 ** ** COMMAND FILE ** CMFFLG: DB 0 CMFCHR: DS 1 CMFBLK: CMFCNT: DS 1 DW SYSDMA DW SYSFCB ** ** DISPLAY MESSAGES ** NGMSG: DB '?' NGMSG1: DB 'X?',BEL,DM EXCMSG: DB CR,09bh,'K','[ ] ONLINE...',CR,LF,DM HLPMSG: DB CR,LF,'COMMAND SET:' DB CR,LF,' D Display parameters' DB CR,LF,' M Program Message strings' DB CR,LF,' O Open a SEND file' DB CR,LF,' Q Exit, warm boot (DON''T disconnect)' DB CR,LF,' S Set communication parameters' DB CR,LF,' U Override last received XOFF' DB CR,LF,' X Exit, warm boot (disconnect)' DB CR,LF,DM CMDMSG: DB CR,LF,'[ ] Type COMMAND, ' DB ' (go ONLINE), or (HELP).',CR,'[',DM BDMSG: DB CR,LF DB ' A (300) C (1200) E (4800) G (19200)',CR,LF DB ' B (600) D (2400) F (9600)',CR,LF DB '[ ] Type BAUD or to skip.',CR,'[',DM xmssg: ;gt db cr,lf ;gt db '[ ] Type XENABLE (0 = Off; 1 = On)',cr,'[',dm ;gt RTMSG: DB CR,LF DB '[ ] Type RATE (1=Fast; 2=Medium; 3=Slow) or to skip.',CR,'[',DM PYMSG: DB CR,LF DB '[ ] Type PARITY (O=Odd; E=Even; N=None, I=Ignore' DB ') or to skip.' DB CR,'[',DM SBMSG: DB CR,LF DB '[ ] Type STOP BITS (1, .=1.5, 2) or to skip.',CR,'[',DM DBMSG: DB CR,LF DB '[ ] Type DATA BITS (5,6,7,8) or to skip.',CR,'[',DM PMMSG: DB ' B (Baud)',CR,LF DB ' P (Parity)',CR,LF DB ' S (Stop bits)',CR,LF DB ' D (Data bits)',CR,LF DB ' T (Transmission rate)',CR,LF db ' X (Xon/Xoff enable)',cr,lf ;gt DB ' E (System Echo mode)',CR,LF db ' L (Logged drive)',CR,LF ; (LEL0184) DB ' O (Local Echo Mode)',CR,LF ; (LEL0284) DB ' F (Filter Line Feeds)',cr,lf ; (LEL0284) DB ' R (Rubout filter)',cr,lf ; (LEL0584) DB ' N (CR New Line Mode)',cr,lf ; (KB0784) DB '[ ] Type PARAMETER or to skip.',CR,'[',DM PRMMSG: DB ff DB cr,lf,'BAUD RATE: ',DM ;gt transmsg: ;gt db cr,lf,'TRANSMIT RATE: ',DM ;gt stopmsg: ;gt db cr,lf,'STOP BITS: ',DM ;gt parmsg: ;gt db cr,lf,'PARITY: ',DM ;gt datamsg: ;gt db cr,lf,'DATA BITS: ',DM ;gt XMSG: ;gt db cr,lf,'XON/XOFF STATUS: ',DM ;GT RLFMSG: DB CR,LF,'SYSTEM ECHO MODE: ',DM LGMSG: DB CR,LF,'LOG DRIVE: ',DM LECMSG: DB cr,lf,'LOCAL ECHO: ',DM ; (LEL0284) FLFMSG: DB CR,LF,'FILTER LINE FEEDS: ',DM ; (LEL0284) RFFMSG: ; (LEL0584) DB CR,LF,'RUBOUTS FILTERED: ',DM ; (LEL0584) CRFMSG: ; (KB0784) DB CR,LF,'CR NEW LINE MODE: ',DM ; (KB0784) NAMMSG: DB FF,ESC,'[1mTTY1050',ESC,'[m' DB ' Version 1.5 ',CR,LF,LF DB 'Teletype Emulator Program.',CR,LF,LF DB 'Type ',ESC,'[1m',ESC,'[m',' to alternate between ONLINE ' DB 'and COMMAND Modes.',CR,LF DB ' ONLINE Mode is for transmitting and receiving data.',CR,LF DB ' COMMAND Mode is for setting program ' DB 'parameters and other functions.' DB CR,LF DB 'Press the ',ESC,'[1m',ESC,'[m',' at any time for HELP.',CR,LF DB 'The program is now in ONLINE Mode.' DB CR,LF,LF,DM MHELP: DB CR,LF DB 'FUNCTION KEYS',CR,LF DB ' (ONLINE Mode only):',CR,LF DB ' Enter COMMAND Mode',CR,LF DB ' Start LOG (open file)',CR,LF DB ' Stop LOG (close file)',CR,LF DB ' Start / Stop SEND file',CR,LF DB ' Transmit programmed Message No. 1',CR,LF DB ' Transmit programmed Message No. 2',CR,LF DB ' (COMMAND and ONLINE Modes):',CR,LF DB ' HELP',CR,LF,LF,DM OSNDMSG: DB '[ ] Type FILENAME then .' DB CR,'[',DM BADFIL: DB CR,LF DB 'FILE ERROR: NOT FOUND',CR,LF,BEL,DM BADDRV: DB CR,LF DB 'FILE ERROR: BAD DRIVE',CR,LF,BEL,DM BLOGMSG: DB CR,LF DB 'FILE ERROR: CAN''T CREATE LOG FILE',CR,LF,BEL,DM BRONMSG: DB ESC,'[1m',DM BROFMSG: DB ESC,'[m',DM LGDRVMSG: DB CR,LF DB '[ ] Type DRIVE (A,B,C,D,E,G,@=CP/M Logged) ' DB 'or to skip.',CR,'[',DM AKP$table: ; (LEL0284) db 0b0h,'p' ; 0 => ESC O p (LEL0284) db 0b1h,'q' ; 1 => ESC O q LEL0284) db 0b2h,'r' ; 2 => ESC O r (LEL0284) db 0b3h,'s' ; 3 => ESC O s (LEL0284) db 0b4h,'t' ; 4 => ESC O t (LEL0284) db 0b5h,'u' ; 5 => ESC O u (LEL0284) db 0b6h,'v' ; 6 => ESC O v (LEL0284) db 0b7h,'w' ; 7 => ESC O w (LEL0284) db 0b8h,'x' ; 8 => ESC O x (LEL0284) db 0b9h,'y' ; 9 => ESC O y (LEL0284) db 0ADh,'m' ; - => ESC O m (LEL0284) db 0Ach,'l' ; , => ESC O l (LEL0284) db 0aeh,'n' ; . => ESC O n (LEL0284) db 083h,'M' ; enter => ESC O M (LEL0284) db 090h,'A' ; F10 (uparrow) => ESC O A (LEL0584) db 0F4h,'B' ; F11 (dnarrow) => ESC O B (LEL0584) db 0F8h,'D' ; F12 (ltarrow) => ESC O D (LEL0584) db 094h,'C' ; F13 (rtarrow) => ESC O C (LEL0584) db 0c4h,'P' ; F14 => ESC O P (LEL0284) db 0c8h,'Q' ; F15 => ESC O Q (LEL0284) db 0cch,'R' ; F16 => ESC O R (LEL0284) db 0d0h,'S' ; F17 => ESC O S (LEL0284) AKP$entries equ ($-AKP$table)/2 PAGE RELOC EQU $ ;REC/SND (RS-2321 INT ;SEE IF RECEIVER OR TRANSMITTER CAUSED INT. ; IF RECEIVER, ACCEPT CHR INTO RECEIVE FIFO. ; IF TRANSMITTER, OUT A CHR FROM TRANSMIT FIFO; ; IF FIFO EMPTY, TURN OFF TRANSMITTER. RSINT: PUSH PSW PUSH D PUSH B push h IN RSCOM ANI 2 JrZ SINT ;REC INT: CHR TO FIFO. RINT: IN RSDAT ; ANI 7FH ; (LEL1183) lxi h,datamask ; point to data mask (LEL0284) ana m ; AND w/mask appropriate for # data bits(LEL0284) MOV D,A ;D:=CHAR(RELIEVES INTERRUPT) IN RSCOM ANI 8 JrZ RINT0 ;IF PARITY ERROR THEN LDA RSPAR ORI 010H OUT RSCOM ANI 0EFH OUT RSCOM ;RESET ERROR MVI D,'?' ;REPLACE CHAR WITH '?' RINT0: ;FI ; XRA A ; (LEL1183) ; CMP D ; (LEL1183) ; JrZ X$999 ;(DONE IF NUL) (LEL1183) LDA RFFP INR A cpi RFILEN ; At end? (LEL1083) jrnz rint1 ; Jump if not (LEL1083) xra a ; Else, point back to 0 (LEL1083) rint1: MOV E,A ;E:=(FILL POINTER+1) IN CIRCLE LDA RFEP SUB E JrNZ RINT8 ;IF FULL THEN MVI D,'?' ;REPLACE CHAR WITH '?' LDA RFFP MOV E,A ;DE-INCREMENT POINTER Jr RINT9 RINT8: MOV A,E ;ELSE STA RFFP ;SAVE NEW POINTER RINT9: ;FI MOV A,D mvi d,0 ; Clear D (LEL1083) lxi h,rfi ; Point to start of buffer (LEL1083) dad d ; Add DE to start of buffer (LEL1083) mov m,a ; Store character (LEL1083) ** RECV QUEUE "PUT" LDA RQCNT CPI RFILEN-1 JrZ RQP$1 INR A STA RQCNT RQP$1: ;IF RQCNT<>RFILEN-1 THEN RQCNT-=1 FI ; CPI RFILEN-16 ; cpi rfilen-64 ; (Send XOFF sooner) (LEL1183) JrNZ X$RQP ;IF RQCNT=RFILEN-16 ... lda xenable ;gt ora a ;check if xon/off is disabled ;gt jrz x$rqp ;if so jump ;gt LDA RQFLG ORA A JrNZ X$RQP ;... AND RQFLG=0 THEN DCR A STA RQFLG ;RQFLAG:=FF lda scrflg ; Get keyboard xon/xoff flag (LEl1283) ora a ; Was xoff already sent? (LEL1283) jrnz x$999 ; (LEL1283) LDA XMTOFF CALL XMTX X$RQP: ;FI X$999: POP h POP B POP D mvi A,int$initial ; Initialize int port out INT$PORT POP PSW EI RET ;SND INT: CHR FROM FIFO SINT: lda send$x ; Send XON or XOFF? (LEL1283) ora a ; (LEL1283) jrnz SINT$55 ; Jump if yes (LEL1283) LDA SFEP MOV E,A LDA SFFP SUB E jrz sint6 SINT0: MOV A,E;=LDA SFEP ;ELSE INR A cpi sfilen ; Past end? (LEL1083) jrnz sint2 ; Jump if not (LEL1083) xra a ; Else, wrap back to 0 (LEL1083) sint2: ; (LEL1083) MOV E,A ;E:=(EMPTY POINTER+1) IN CIRCLE STA SFEP ;ELSE SAVE NEW EMPTY POINTER MVI D,0 ;(DE NOW ADDRESES SLOT) lxi h,sfi ; Point to buffer (LEL1083) dad d ; Add offset to buffer (LEL1083) mov a,m ; Get character (LEL1083) OUT RSDAT ;SEND IT ;FI jr x$999 ; Exit (LEL1083) sint6: LDA RSPAR ANI 0FEH STA RSPAR OUT RSCOM ;SHUT OFF SND Jr x$999 ;(DONE) ; ; Send XON ; sint$55: ; (LEL1283) out rsdat ; Send XON or XOFF (LEL1283) xra a ; a=0 (LEL1283) sta send$X ; Clear flag (LEL1283) jr x$999 ;* XMIT "X" r$XMTX: MOV B,A LDA RSPAR ORI 01H OUT RSCOM STA RSPAR ;r$xmtx$5: ; (LEL1283) ; IN RSCOM ; (LEL1283) ; RRC ; (LEL1283) ; JrnC r$xmtx$5 ; (LEL1283) ; MOV A,B ; (LEL1283) ; OUT RSDAT ; (LEL1283) mov a,b ; Save XON or XOFF char (LEL1283) sta send$X ; Save it (LEL1283) RET r$xenable db 0ffh ;gt r$send$x db 0 r$RSPAR: DS 1 r$RQFLG: DB 0 r$RQCNT: DB 0 r$XMTON: DB XON r$XMTOFF: DB XOFF RFILEN EQU 255 SFILEN EQU 16 r$RFI: DS RFILEN r$SFI: DS SFILEN r$RFFP: DS 1 r$RFEP: DS 1 r$SFFP: DS 1 r$SFEP: DS 1 r$SCRFLG: DB 0 r$data$mask: db 0ffh ; (LEL0284) RELOC$LENGTH EQU $-RELOC ; ; Equates for relocated code ; reloc$addr equ 0c000h ; Start of common segment OFFSET EQU RELOC$ADDR-RELOC RS232$INT EQU RSINT+OFFSET rspar equ r$rspar+offset RQFLG equ r$rqflg+offset RQCNT equ r$rqcnt+offset XMTON equ r$xmton+offset xmtoff equ r$xmtoff+offset RFI equ r$rfi+ offset SFI equ r$sfi+offset RFFP equ r$rffp+offset RFEP equ r$rfep+offset SFFP equ r$sffp+offset SFEP equ r$sfep+offset XMTX equ r$xmtx+offset SCRFLG equ r$scrflg+offset send$x equ r$sendx+offset xenable equ r$xenable+offset ;gt data$mask equ r$data$mask+offset ;(LEL0284) END