.TITLE DUPLEX DO COMMUNICATIONS BETWEEN TERMINALS (MACHINES?) .IDENT /1.20A/ .MCALL QIO$S,QIOW$S,CLEF$S,WTSE$S,ASTX$S,EXIT$S,SETF$S .MCALL FCSMC$,CSI$,CSI$1,CSI$2,DIR$,QIO$,QIOW$ .MCALL MRKT$S FCSMC$ .PAGE ;--------------------------------------------------------------------------- ; ; AUTHOR: MARTIN HELLER DATE:24-OCT-79 ; DUPLEX: ; The idea here is to provide the wiring (in software) ; so that a single terminal (unit 1, by convention) can ; be hard wired to the PDP-11 and yet function as a terminal ; to any computer that can be called on the telephone or ; wired to another terminal port. ; For dial-up use, a full-duplex modem needs to be ; connected to another port on the PDP-11. This is useful ; anyway, so that you can dial into the PDP-11; this program ; lets you reverse the process and dial out. When you ; task-build, ASG=TI:1, and explicitly assign the proper ; port to unit 2. ; There is no reason that the second port couldn't be ; hardwired as well. Therefore, if you have two computers within ; a few hundred yards of each other, you can connect them together ; through EIA ports and have just one terminal at your desk ; to talk to both of them. ; CONTROL-B CAUSES EXIT FROM THE PROGRAM ; ;** 26-OCT-79: VERSION 1.01 -- CTRL-T IS TRANSMIT A FILE ; ; TO USE: TYPE CONTROL AND T SIMULTANEOUSLY. THIS WILL NOT BE TRANSMITTED. ; THE PROGRAM WILL PROMPT FOR AN INPUT FILE SPECIFICATION, I.E. ; DUPLEX>=SY0:[25,34]FILENAME.TYP;4 ; THE USUAL RULES FOR DEFAULTS APPLY; NO WILDCARDS OR LISTS ARE ALLOWED. ; NOTICE THAT THE EQUALS SIGN IS NOT OPTIONAL--PARSING IS FOR AN INPUT FILE. ; ; ** 31-OCT-79: VERSION 1.02 ; CTRL-P TOGGLES BETWEEN FILE TRANSMISSION AND LINE TRANSMISSION ; CTRL-N CAUSES TRANSMISSION OF NEXT LINE OF FILE IN LINE MODE ; ; VERSION 1.03 ; CTRL-A ABORTS A FILE TRANSMISSION ; CTRL-F OPENS/CLOSES FILE OF RECEIVED DATA ; ; ** 26-NOV-79: VERSION 1.04 ; MESSAGES FOR CTRL-F ; USE DIR$ FORM FOR QIO'S ISSUED FROM AST HANDLERS ; ; ** 7-DEC-79: VERSION 1.05 ; HANDLING OF CONTROL CHARACTERS FROM TERMINAL 2 CHANGED: ; ALL BOTHERSOME NULLS AND CONTROL CHARACTERS IGNORED FROM TERM 2 ; ; ** 23-MAR-83 VERSION 1.20 ; G. EVERHART ; ADD DELAY LOGIC. CTRL-\ SETS DELAY UP... SETS UP A PREDEFINED ; NUMBER OF TICKS DELAY AFTER EACH LINE (IF IN LINE MODE) AND ; AUTOMATICALLY SENDS LINES OUT AFTER THAT DELAY. ANOTHER CTRL-\ ; TOGGLES THE MODE OFF AGAIN. (36 OCTAL) ; CTRL-^ SETS CHARACTER DELAY OF (NOMINALLY) 1 TICK PER CHAR SENT ; OR TURNS THIS DELAY OFF AGAIN. (34 OCTAL) ; CTRL-] (OCTAL 35) ALLOWS DELAY FOR LINES TO BE SET. 1 CHARACTER ; IS READ AND 60 OCTAL SUBTRACTED FROM IT TO GIVE DELAY. ; IF RESULT IS NEGATIVE, DELAY IS SET TO 4. ;--------------------------------------------------------------------------- .PAGE .SBTTL DIRECTIVES .PSECT DIRECT,D,REL,RW ; AQ1: QIO$ IO.WVB,2,2,,,,<,1> AQ2: QIO$ IO.WVB,1,1,,,,<,1> OPERR: QIOW$ IO.WVB,1,1,,,,<OPNERR,OPNERL,'0> ROMSG: QIOW$ IO.WVB,1,1,,,,<ROMT,ROML,'0> RCMSG: QIOW$ IO.WVB,1,1,,,,<RCMT,RCML,'0> .PAGE .SBTTL INITIALIZATION FSRSZ$ 2 ;INITIALIZE FCS RECORD BUFFER CSI$ ;DEFINE CSI CONTROL BLOCK .PSECT DUPLEX,I,REL,RO DUPLEX:: QIOW$S #IO.ATA,#1,#1,,,,<#AST1> ;ATTACH DEVICE 1 QIOW$S #IO.ATA,#2,#2,,,,<#AST2> ;ATTACH DEVICE 2 FINIT$ ;INITIALIZE FCS MOV #BUF1,B1PTR ;INITIALIZE BUFFERS FOR EACH TERMINAL MOV #BUF2,B2PTR 1$: CLEF$S #3 ;WAIT FOREVER: ALL WE WANT IS THE AST HANDLING WTSE$S #3 MOVB SENTIN,R1 ;SOMETHING SPECIAL CALLED FOR? BGT 20$ ;YES QIOW$S #IO.KIL,#1,#1 ;NO -- EXIT QIOW$S #IO.KIL,#2,#2 QIOW$S #IO.DET,#1,#1 QIOW$S #IO.DET,#2,#2 TSTB RCVFIL ;FILE OPEN? BEQ 10$ ;NO CLOSE$ #RCVFDB ;YES - CLOSE IT 10$: EXIT$S ; ;SPECIAL FUNCTION DESIRED: R1 HOLDS INDEX ; 20$: CMP #ENTRIES,R1 ;CHECK FOR NON-EXISTENT CALL BLT 25$ ;NO GOOD -- IGNORE DEC R1 ASL R1 ;CHANGE INDEX TO OFFSET CALL @TABLE(R1) ; GO DO THE GOOD WORK 25$: CLRB SENTIN ;SET UP FOR ANOTHER REQUEST BR 1$ ;GO WAIT (PROCESS AST'S) .PAGE .SBTTL BUFFERS AND POINTERS .PSECT DATA,D,REL,RW CIRSIZ = 256. BUFSIZ = 136. B1PTR: .WORD 0 B2PTR: .WORD 0 SAVE: .WORD 0 RPTR: .WORD 0 IOSB: .BLKW 2 ; XMTFDB: FDBDF$ FDRC$A ,XMTBUF,BUFSIZ FDOP$A 3,CSIBLK+C.DSDS ;FILENAME WILL BE PARSED BY CSI XMTBUF: .BLKB BUFSIZ FILENAME: .BLKB 30. .EVEN CSIBLK: .BLKB C.SIZE .EVEN RCVFDB: FDBDF$ FDRC$A ,RCVBUF,BUFSIZ FDOP$A 4,,RCVNAM RCVBUF: .BLKB BUFSIZ .EVEN RCVNAM: NMBLK$ RECEIVED,DAT ; BUF1: .BLKB CIRSIZ ;THESE CIRCULAR BUFFERS JUST HAVE TO BE BUF2: .BLKB CIRSIZ ;BIG ENOUGH TO PROVIDE A REASONABLE TYPE-AHEAD SENTIN: .BYTE 0 ;CAPABILITY WHEN THE TERMINALS GO AT DIFFERENT SPEEDS XFMODE: .BYTE 0 XABORT: .BYTE 0 RCVFIL: .BYTE 0 XACTIV: .BYTE 0 .EVEN LDLYV: .WORD 6 ;NUMBER OF TICKS TO WAIT BETWEEN LINES CHDLV: .WORD 1 ;NUMBER OF TICKS BETWEEN CHARACTERS (IF WAITING) LWF: .WORD 0 ;FLAG 1 IF LINEWAIT ACTIVE CWF: .WORD 0 ;FLAG 1 IF CHAR WAIT ACTIVE ; FASK: .ASCII /DUPLEX>/ FASKL = .-FASK OPNERR: .ASCII /ERROR OPENING FILE/ OPNERL = .-OPNERR LMSG: .ASCII /TYPE CTRL-N TO TRANSMIT A LINE/ LMSGL = .-LMSG ROMT: .ASCII /RECEIVED DATA FILE HAS BEEN OPENED/ ROML = .-ROMT RCMT: .ASCII /RECEIVED DATA FILE HAS BEEN CLOSED/ RCML = .-RCMT LDMT: .ASCII /LINE DELAY SET TO / DSMB: LDMC: .ASCII /4 TICKS/ LDML=.-LDMT CDMT: .ASCII /CHARACTER DELAY SET TO 1 TICK/ CDML=.-CDMT LUMT: .ASCII /LINE DELAY CLEARED/ LUML=.-LUMT CUMT: .ASCII /CHAR DELAY CLEARED/ CUML=.-CUMT XCMT: .ASCII /Transmission Complete/ XCML=.-XCMT DSMT: .ASCII /Enter value (1 char) for delay:/ DSML=.-DSMT .EVEN .SBTTL TABLES .PSECT TABLE,D,REL,RO ; ; SUBROUTINES FOR SPECIAL FUNCTIONS ; TABLE: XMIT ;#1 -- CTRL-T RECV ;#2 -- CTRL-F LDM ;#3 -- CTRL-\ (LINE DELAY ACTIVE MSG) CDM ;#4 -- CTRL-^ (CHARACTER DELAY ACTIVE MSG) LDS ;#5 -- OCTAL 35 (SET UP DELAYS) CTRL-] ENTRIES = .-TABLE/2 .PAGE .SBTTL ASYNCHRONOUS TRAP HANDLERS .PSECT AST,I,REL,RO ; ; AST SERVICE ROUTINE FOR TERMINAL 1 ; AST1: MOV R0,SAVE ;ON GENERAL PRINCIPLES MOV (SP)+,R0 ;CHARACTER RECIEVED AND PARAMETER2 BIC #177400,R0 ;LOW BYTE FOR KEY PRESSED ;NOTE THE TEST FOR EXIT IS NOW CONTROL B. THIS ALLOWS CONTROL C TO BE ;USED TO CONTROL THE REMOTE COMPUTER. CMP #2,R0 ;CTRL-B WANTS IMMEDIATE EXIT FROM PROGRAM BEQ XIT ;EXIT TASK CMP #24,R0 ;CTRL-T BEQ 10$ ;TRANSMIT FILE CMP #20,R0 ;CTRL-P BEQ 20$ ;TOGGLE XMIT MODE CMP #16,R0 ;CTRL-N BEQ 30$ ;XMIT NEXT LINE CMP #1,R0 ;CTRL-A BEQ 15$ ;ABORT TRANSMISSION CMP #6,R0 ;CTRL-F BEQ 25$ ;RECEIVE FILE OPEN/CLOSE CMPB #36,R0 ;CTRL-\ BEQ 507$ ;TOGGLE LINE DELAY MODE CMPB #34,R0 ;CTRL-^ BEQ 508$ ;TOGGLE CHARACTER DELAY MODE CMPB #35,R0 ;CTRL-] BEQ 509$ ;SET UP DELAY MAGNITUDE FOR LINES MOVB R0,@B1PTR ;TRANSMIT BYTE MOV B1PTR,AQ1+Q.IOPL DIR$ #AQ1 INC B1PTR ;MAINTAIN CIRCULAR BUFFER CMP B1PTR,#BUF1+CIRSIZ BLE 5$ MOV #BUF1,B1PTR 5$: MOV SAVE,R0 ;GENERAL PRINCIPLES AGAIN ASTX$S ;RETURN FROM AST SERVICE ; 10$: MOVB #1,SENTIN 11$: SETF$S #3 BR 5$ ; CTRL-A: ABORT TRANSMISSION 15$: INCB XABORT BR 5$ ; CTRL-P: TOGGLE TRANSMISSION MODE 20$: COMB XFMODE CLEF$S #4 BR 5$ ; CTRL-F: OPEN/CLOSE FILE FOR DATA RECEIVED 25$: MOVB #2,SENTIN BR 11$ ; CTRL-N: TRANSMIT NEXT LINE 30$: SETF$S #4 BR 5$ ; CTRL-\: TOGGLE LINE DELAY 507$: COM LWF ;SET FLAG OR CLEAR IT MOVB #3,SENTIN BR 11$ ; OCTAL 35 : SET UP DELAY MAGNITUDE 509$: MOVB #5,SENTIN BR 11$ ;35 - SET UP DELAY ; ; CTRL-^: TOGGLE CHARACTER DELAY 508$: COM CWF MOVB #4,SENTIN BR 11$ ; ; CONTROL-B PRESSED: IMMEDIATE EXIT ; XIT: CLRB SENTIN SETF$S #3 MOV SAVE,R0 ASTX$S ; ; AST HANDLER FOR 2ND TERMINAL ; AST2: MOV R0,SAVE MOV (SP)+,R0 BIC #177400,R0 ;1 BYTE FOR KEY PRESSED CMP #3,R0 ;CTRL-C BEQ 5$ ;IGNORE CTRL-C ( THIS IS A CHANGE ) CMP #24,R0 ;CTRL-T (DC4) BEQ 5$ ;IGNORE DC4 (GENERATED BY 6800 EDITOR) CMP #25,R0 ;CTRL-U (NAK) BEQ 5$ ;IGNORE NAK (GENERATED BY 6800 BASIC) CMP #177,R0 ;DEL BEQ 5$ ;IGNORE DEL (GENERATED BY 6800 BASIC) MOVB R0,@B2PTR ;TRANSMIT BYTE MOV B2PTR,AQ2+Q.IOPL DIR$ #AQ2 TSTB RCVFIL ;FILE OPEN TO RECEIVE DATA? BEQ 2$ ;NO CALL RCVCHR ;YES: PUT CHARACTER INTO FILE 2$: INC B2PTR CMP B2PTR,#BUF2+CIRSIZ BLE 5$ MOV #BUF2,B2PTR 5$: MOV SAVE,R0 ASTX$S ;RETURN FROM AST SERVICE .PAGE .SBTTL XMIT - TRANSMIT A FILE .PSECT XMIT,I,REL,RO ; ; GET FILE DESCRIPTER, PARSE IT, OPEN INPUT FILE ; XMIT: QIOW$S #IO.RPR,#1,#1,,#IOSB,,<#FILENAME,#30.,#6,#FASK,#FASKL,#'$> BR 522$ 521$: JMP 10$ 520$: JMP 20$ 522$: CSI$1 #CSIBLK,#FILENAME,IOSB+2 ;COMPRESS LINE BCS 520$ ;ERROR HANDLING CSI$2 #CSIBLK,INPUT ;PARSE FILE DESCRIPTOR BCS 520$ ;ERROR HANDLING OPEN$R #XMTFDB ;OPEN FILE FOR READING BCS 520$ ;ERROR HANDLING CLRB XABORT ;INITIALIZE INCB XACTIV ;FLAG FILE ACTIVE TSTB XFMODE BEQ 5$ QIOW$S #IO.WVB,#1,#1,,,,<#LMSG,#LMSGL,#'0> ;SAY LINE MODE ACTIVE ; ; READ A RECORD FROM FILE AND WRITE IT TO TERMINAL 2 ; 5$: TSTB XABORT ;STOP NOW? BNE 521$ ;YES TSTB XFMODE ;TRANSMIT WHOLE FILE INTACT? BEQ 8$ ;YES ;DELAY ROUTINE HERE IF ACTIVE... TST LWF ;ARE WE DELAYING PER LINE? BEQ 501$ ;IF EQ, NO, JUST AWAIT CTRL-N MRKT$S #15,LDLYV,#1 ;SET FLAG 15 AFTER 'LDLYV' TICKS WTSE$S #15 ;AWAIT TIMEOUT BR 8$ ;AND SKIP THE WAITS FOR CONTROL-N... 501$: WTSE$S #4 ;NO- WAIT FOR PERMISSION FOR THIS LINE CLEF$S #4 ;INHIBIT NEXT LINE 8$: GET$ #XMTFDB BCS 10$ ; END AND ERROR HANDLING TST CWF ;ARE WE INSERTING DELAYS BETWEEN CHARACTERS? BEQ 502$ ;IF EQ NO...(THANK HEAVEN...DELAY IS COSTLY) ;CHARACTER DELAY. THIS MUST BE HANDLED BY SINGLE-CHARACTER QIO$'S ;SO LET'S GET AT IT. TST XMTFDB+F.NRBD ;ZERO BYTES? NORMAL IF SO BLE 502$ MOV R0,-(SP) MOV R1,-(SP) ;NEED SOME REGISTERS MOV #XMTFDB+F.NRBD+2,R0 ;ADDRESS TO SHOOT OUT MOV XMTFDB+F.NRBD,R1 ;BYTE COUNT QIOW$S #IO.WVB,#2,#2,,,,<R0,#1,#'+> ;EMIT 1ST CHAR WITH CR FIRST INC R0 ;PASS CHARACTER EMITTED DEC R1 BLE 503$ 504$: MRKT$S #15,CHDLV,#1 WTSE$S #15 ;WAIT FOR 'CHDLV' TICKS QIOW$S #IO.WVB,#2,#2,,,,<R0,#1,#0> INC R0 DEC R1 BGT 504$ 503$: MOV (SP)+,R1 ;RESTORE REGS USED... MOV (SP)+,R0 JMP 5$ 502$: QIOW$S #IO.WVB,#2,#2,,,,<XMTFDB+F.NRBD+2,XMTFDB+F.NRBD,#'+> JMP 5$ ; ; DONE WITH FILE (EITHER END OR ERROR) -- CLOSE IT ; 10$: CLOSE$ #XMTFDB CLRB XACTIV ;FLAG FILE CLOSED QIOW$S #IO.WVB,#1,#1,,,,<#XCMT,#XCML,#'0> ;SAY TRANSMISSION DONE RETURN ; ; ERROR OPENING FILE -- SAY SO AND WAIT ; 20$: DIR$ #OPERR RETURN .PAGE .SBTTL RECV - HANDLE DATA RECEIVED .PSECT RECV,I,REL,RO RECV: TSTB RCVFIL ;IS A FILE OPEN BNE 10$ ;YES -- CLOSE IT ;OPEN FILE FDAT$R #RCVFDB,#R.VAR,#FD.CR,,#-5,#-5 OPEN$W #RCVFDB BCS 20$ ; ERROR HANDLING MOVB #1,RCVFIL ;MARK FILE OPEN MOV #RCVBUF,RPTR DIR$ #ROMSG ;SAY FILE OPENED RETURN ;CLOSE FILE 10$: CLOSE$ #RCVFDB CLRB RCVFIL ;MARK FILE CLOSED DIR$ #RCMSG ;SAY FILE CLOSED RETURN ; ; ERROR OPENING FILE -- SAY SO AND WAIT ; 20$: DIR$ #OPERR RETURN ; ; LDM - LINE DISPLAY MESSAGE DISPLAY ; LDM: TST LWF ;NOW IN LINEWAITING MODE? BNE 510$ ;IF NE NO, WAITING CLEARED QIOW$S #IO.WVB,#14,#14,,,,<#LDMT,#LDML,#'+> RETURN 510$: QIOW$S #IO.WVB,#14,#14,,,,<#LUMT,#LUML,#'+> RETURN ; ; CDM - CHAR DISPLAY MESSAGE DISPLAY ; CDM: TST CWF ;NOW IN CHAR WAITING MODE? BNE 511$ ;IF NE NO, WAITING CLEARED QIOW$S #IO.WVB,#14,#14,,,,<#CDMT,#CDML,#'+> RETURN 511$: QIOW$S #IO.WVB,#14,#14,,,,<#CUMT,#CUML,#'+> RETURN ; ; ; LDS - LINE DELAY MAGNITUDE SETUP LDS: QIOW$S #IO.WVB,#14,#14,,,,<#DSMT,#DSML,#'+> QIOW$S #IO.RVB,#14,#14,,,,<#DSMB,#1> ;READ 1 CHARACTER INTO BUFFER. THEN SET DELAY FROM IT. ; (SUBTRACT ASCII 0) MOVB DSMB,-(SP) BIC #177400,(SP) ;ZERO HIGH BYTE SUB #60,(SP) ;ADJUST THE ASCII MOV (SP)+,LDLYV ;STORE AS NEW DELAY VALUE BGT 512$ ;AS LONG AS >0 ALL'S WELL MOV #4,LDLYV ;IF NEGATIVE JUST PUT IN 4 512$: RETURN ; ; ; RECIEVE A CHAR: BYTE IN R0 IS TO BE STUFFED INTO BUFFER ; WHEN BUFFER IS FULL OR CR DETECTED, FLAG BUFFER FOR WRITING RCVCHR: CMPB #15,R0 ;CR? BEQ 20$ ;YES - PUT BUFFER CMPB #12,R0 ;LF? BEQ 10$ ;IGNORE LF TSTB R0 ;NUL? BEQ 10$ ;IGNORE NUL MOVB R0,@RPTR ;STUFF CHAR INTO BUFFER INC RPTR ;MAINTAIN POINTER CMP RPTR,#RCVBUF+BUFSIZ ;CHECK FOR BUFFER FULL BGT 20$ ;NEED TO PUT BUFFER 10$: RETURN ;ALL DONE 20$: MOV RPTR,R0 ;COMPUTE RECORD LENGTH SUB #RCVBUF,R0 BLT 25$ ;NEGATIVE CHARS WOULD BE AN ERROR MOV R0,RCVFDB+F.NRBD ;SET LENGTH PUT$ #RCVFDB ;SHIP IT OUT 25$: MOV #RCVBUF,RPTR ;SET UP FOR NEW BUFFER RETURN .END DUPLEX