Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-02 - 43,50273/commps.mac
There are 2 other files named commps.mac in the archive. Click here to see a list.
TITLE   COMMPS
SUBTTL  COMMUNICATION WITH PDP-11/45 MUMPS SYSTEM

;P. HURLEY/R. SCHMIDT MAYNARD OCT-72

;*** COPYRIGHT 1972 DIGITAL EQUIPMENT CORP. MAYNARD MASS. ***

	CUSTVER==	0	;CUSTOMER VERSION NUMBER
	DECVER==	1	;DEC VERSION NUMBER
	DECMVR==	0	;DEC MINOR VERSION
	DECEVR==	101	;DEC EDIT VERSION

	LOC	137		;SET UP VERSION NUMBER
	BYTE	(3)CUSTVER(9)DECVER(6)DECMVR(18)DECEVR
	RELOC

;ASSEMBLY CONDITIONS:

;ASSEMBLE WITH C.MAC
;IF CC (3RD HEADER WORD IN A MESSAGE) IS TO BE SETUP AND
;CHECKED FOR ODD PARITY, ASSEMBLE WITH FTODCC==1
IFNDEF	FTODCC,	<FTODCC==0	;NO PARITY CHECK ON CC>

;DEFINE ACCUMULATORS AND CONSTANTS

	TIME=	10		;KEEPS DAYTIME
	CHR=	1		;KEEPS CURRENT CHARACTER
	CRC=	2		;KEEPS CYCLIC REDUNDANCY CHECK
	T1=	CRC+1		;TEMP
	T2=	T1+1		;TEMP
	CNT=	5		;CHARACTER COUNT AC
	Q=	16		;FOR PC FOR FORTRAN CALL
	P=	17		;PUSH DOWN POINTER

	SOH=	001		;START OF HEADER
	STX=	002		;START OF TEXT (DATA)
	ETX=	203		;END OF TEXT
	ACK=	240		;ACKNOWLEDGE
	NAK=	120		;NOT ACKNOWLEDGE

	SLPTIM=	^D3000		;MSEC TO HIBERNATE BEFORE NEXT TRY
	HNGACK=	^D5000		;M-SEC BEFORE SENDING RETRANSMISSION
	HNGMES=	^D30000		;MSEC TO TRY BEFORE GIVING UP
	TRYMAX=	10		;MAXIMUM NO. OF RETRIES (EITHER TO
				;SEND A MESS. OR TO ACK AN OLD ONE)
	MSLMAX=	^D80		;MAXIMUM LENGTH OF MESSAGE
	TXLMAX=	^D72		;MAXIMUM LENGTH OF TEXT
	HB.RTC=1B14		;WAKE ON CHARACTER READY
;DEFINE MACROS

DEFINE	SAVE(N)			;AC SAVE MACRO
<	MOVEM	N,ACSAV+N	;SAVE AC N
	HRRZI	N,ACSAV		;SET UP BLT WORD
	BLT	N,N-1		;SAVE OTHER ACS
>				; 

DEFINE	RESTOR(N)		;RETORE AC MACRO
<	HRLZI	N,ACSAV		;SET UP BLT WORD
	BLT	N,N		;RESTORE ACS
>				; 

	ENTRY RECVC,SENDC	;COBOL ENTRY POINTS
	ENTRY RECVF,SENDF	;FORTRAN ENTRY POINTS
	INTERNAL TABGEN,MSN	;###


	IFNDEF FTDEBUG,<FTDEBUG==0>

IFE FTDEBUG,<			;DEFINE NULL MACRO IF SWITCH IS 0
DEFINE DEBUG(A)
<>>

IFN FTDEBUG,<			;DEFINE MACRO FOR WHEN SWITCH IS ON
DEFINE DEBUG(A)
<	PUSH P,0		;SAVE AC 0
	MOVSI 111111		;SET UP LEFT HALF WORD
	HRRI A			;SET UP DEBUG NUMBER
	PUSHJ P,DEBPNT##	;WRITE OUT DEBUG ENTRY POINT
	POP P,0			;RESTORE 0
>>				;END OF DEFINE

SUBTTL  GENERAL ROUTINES TO HANDLE CHARACTERS AND MESSAGES

;G E T C H R
;CALLED BY	PUSHJ	P,GETCHR
;		ERROR RETURN		;NO CHAR FOUND
;		NORMAL RETURN		;RETURNS CHAR IN CHR

EXTERNAL GETCHR			;ROUTINE TO GETR A CHARACTER IN C


;N O C H R
;CALLED BY	PUSHJ	P,NOCHR
;PUTS JOB INTO SLEEP UNTIL CHAR AVAILABLE. TRIES UNTIL TIMEOUT
;OCCURS.

NOCHR:	DEBUG(1)		;NO CHARACTER READY, WAIT FOR ONE
	MSTIME	T1,			;GET CURRENT TIME
	MOVEM	T1,CURTIM#		;STORE FOR LATER USE
	MOVSI	T1,(HB.RTC)		;SETUP WAKE CONDITIONS
	HRRI	T1,SLPTIM		;AND SLEEP TIME
	HIBER	T1,			;WAIT
	JRST	NOHIB			;UUO NOT IMPLEMENTED
CHKTIM:	MSTIME	T1,			;GET DAYTIME
	SUB	T1,CURTIM		;DID WE TRY
	CAIL	T1,SLPTIM		;LONG ENOUGH?
	POPJ	P,			;YES, GIVE ERROR RETURN
GET:	PUSHJ	P,GETCHR		;NOT YET.
	JRST	NOCHR			;STILL NO CHAR THERE.
	JRST	CPOPJ1##		;RETURN WITH CHAR

NOHIB:	MOVEI	T1,SLPTIM/^D1000	;SLEEP TIME IN SECONDS
	SLEEP	T1,		;SLEEP
	JRST	CHKTIM			;CHECK ELAPSED TIME



;P U T C H R
;CALLED BY	MOVE	CHR,CHAR	;CHARACTER IN CHR
;		PUSHJ	P,PUTCHR	;SEND IT

EXTERNAL PUTCHR			;ROUTINE TO SEND ONE CHARACTER OUT
;R C V B C C
;CALLED BY	PUSHJ	P,RCVBCC
;RETURNS NEXT BYTE IN CHR WITHOUT AFFECTING CHECKSUM.
;EXITS IN CASE OF TIMEOUT.

RCVBCC:	DEBUG(2)
	PUSHJ	P,GET		;GET CRC BYTE
	POPJ	P,			;NONE THERE
	MSTIME	TIME,			;RESET TIMER
	JRST	CPOPJ1		;SKIP RETURN


;R C V C H R
;CALLED BY	PUSHJ	P,RCVCHAR
;UPDATES ACCUMULATED CHECKSUM.
;RETURNS NEXT CHAR IN CHR OR EXITS IN CASE OF TIMEOUT.

RCVCHR:	DEBUG(3)
	PUSHJ	P,GET		;GET A BYTE
	POPJ	P,			;NONE THERE
	MSTIME	TIME,			;RESET TIMER
	MOVE	T1,CHR			;COMPUTE CRC:
	XOR	T1,CRC			;  MAKE 8 BIT INDEX
	ANDI	T1,377		;  CLEAR UNWANTED BITS
	LSH	CRC,-10			;  SHIFT CRC 8 BITS
	XOR	CRC,CRCTAB(T1)		;  UPDATE IT
	JRST	CPOPJ1			;RETURN WITH CHAR


;S A C K
;CALLED BY	MOVE	T1,MSN		;MESSAGE NUMBER IN T1
;		PUSHJ	P,SACK		;SEND ACKNOWLEDGE

SACK:	IORI	T1,ACK			;BUILD MESS. IDENT.
SACK1:	MOVEM	T1,MSI			;STORE IT
	DEBUG(4)
	SETZ	CRC,			;CLEAR CRC
	MOVEI	CHR,SOH		;GET START OF HEADER CHARACTER
	PUSHJ	P,SNDCHR		;1ST BYTE OUT
	MOVE	CHR,MSI
	PUSHJ	P,SNDCHR		;2ND BYTE OUT
	ROT	CRC,-10			;GET BCC0
	MOVE	CHR,CRC
	PUSHJ	P,PUTCHR		;SEND IT. DO NO CRC
	ROT	CRC,10			;RESTORE CRC
	MOVE	CHR,CRC
	PUSHJ	P,PUTCHR		;SEND BCC1
	PUSHJ	P,CLRINP##		;CLEAR ANY CHARACTERS IN INPUT BUFFER
	PUSHJ	P,PUTOUT##	;OUTPUT THE MESSAGE
	JRST	CPOPJ		;RETURN


;S N A K
;ENTERED BY	JRST	SNACK
;NOT ACKNOWLEDGES CURRENT MESSAGE, RETURNS TO RCVNXT.


SNAK:	DEBUG(5)
	MOVE	T1,MSN		;GET MESSAGE NUMBER TO NAK
	IORI	T1,NAK			;MESS. IDENTIFICATION
	PUSHJ	P,SACK1			;SEND NAK MESSAGE
	MOVEI	CNT,MSLMAX		;RESET COUNTER
	JRST	RCVNXT			;GET NEXT MESSAGE


;SANED CYHMRVE	CHR,CHAR		;CHARACTER IN CHR
;		PUSHJ	P,SNDCHR
;SENDS A BYTE AND UPDATES CYCLIC REDUNDANCY CHECK.

SNDCHR:	DEBUG(6)
	MOVE	T1,CHR			;SAVE CHR FOR CRC
	PUSHJ	P,PUTCHR		;SEND BYTE
	XOR	T1,CRC			;COMPUTE CRC
	ANDI	T1,377
	LSH	CRC,-10
	XOR	CRC,CRCTAB(T1)
	JRST	CPOPJ		;RETURN


;T A B G E N
;CALLED BY	PUSHJ	P,TABGEN
;GENERATES CRCTAB (256 WORDS) WITH 16 BIT BYTE DEPENDENT
;CRC RIGHT JUSTIFIED. BIT 35 IS 1 IFF BYTE HAS ODD PARITY.

TABGEN:	MOVEI	CHR,377			;START WITH LAST BYTE
CRCNXT:	MOVEI	T2,7			;HERE ONCE FOR EACH BYTE
	MOVE	CRC,CHR			;GET CURRENT CHAR
CRCSHF:	LSHC	CRC,-1			;SHIFT IT AND
	SKIPGE	CRC+1			;CHECK RIGHT END BIT
	XORI	CRC,120001		;HERE IF BIT WAS ON
	SOJGE	T2,CRCSHF		;NEXT BIT
	MOVEM	CRC,CRCTAB(CHR)		;STORE CRC
	SOJGE	CHR,CRCNXT		;NEXT BYTE
CPOPJ:	POPJ	P,		;NON-SKIP RETURN

SUBTTL  RECV - TO RECEIVE MESSAGES FROM PDP-11

;R E C V 

COMMENT                                                        %
CALL FROM COBOL:

	77 NUMBER
	77 FLAG

	01 DUMMY
	   02 ARRAY OCCURS 211 TIMES
	...
	ENTER MACRO RECVC USING ARRAY, NUMBER, FLAG.
	...

COBOL SHOULD GENERATE THE FOLLOWING MACRO CODE:

	PUSHJ	17,RECVC
	ARG	[ARRAY]
	ARG	0,NUMBER
	ARG	0,FLAG
	ARG	0,TYPE

RECVC		RECEIVES MESSAGES FROM PDP-11/45 MUMPS (A INIT11
		CALL  MUST  HAVE   ESTABLISHED   CONNECTION  AND
		INITIALIZED THE APPROPRIATE PDP-11 ROUTINE).

		EXTRACTS THE DATA AND STORES THEM AS 8 BIT BYTES
		RIGHT JUSTIFIED IN ARRAY. CONTINUES UNTIL EITHER
		THE  NUMBER'TH  BYTE HAS BEEN STORED,  OR A TIME-
		OUT OCCURS.

		RETURNS IN FLAG -1, IF THE REQUEST HAS COMPLETELY
				   BEEN SATIESFIED.
			       N, IF  THERE  OCCURED  A TIMEOUT
				   AFTER THE N'TH BYTE WAS PROPER-
				   LY RECEIVED.

A TIMEOUT OCCURS, WHEN WITHIN 30 SECONDS
		NO SOH COULD BE RECOGNIZED BY RECV11, OR
		NO CHARACTER AT ALL COULD BE RECEIVED.         %

;COME IN HERE FOR FORTRAN CALL.

RECVF:	Z			;TO SAVE Q
	PUSH	P,Q		;Q ONTO STACK (ARG POINTER)
	SETOM	F4FLG		;MARK THAT THIS CALL CAME FROM FORTRAN
	JRST	RECV		;GO RECEIVE
;COME IN HERE IN CASE OF COBOL CALL:

RECVC:	SETZM	F4FLG		;MARK THAT THIS WAS A COBOL CALL
RECV:	SAVE	5		;SAVE 5 ACS
	HRRZ	T1,(P)			;GET ADR OF 1ST ARG
	HRRZ	T1,(T1)		;GET ARRAY ADDRESS
	SKIPN	F4FLG		;COBOL CALL?
	HRRZ	T1,(T1)		;YES, GET REAL ARRAY ADDRESS
	HRLI	T1,TXTBUF
	MOVEM	T1,BLTPTR		;INITIALIZE BLT POINTER
	AOS	(P)		;INCREMENT ARG POINTER
	HRRZ	T1,(P)
	MOVE	T1,@(T1)		;GET 2ND ARG
	MOVEM	T1,NUMBER		;SAVE IT
	AOS	(P)		;INCREMENT ARG POINTER
	AOS	T1,MSN			;UPDATE MESS NO.
	ANDI	T1,17			;TRUNCATE TO 4 BITS
	MOVEM	T1,MSN		;SAVE 4 BIT MESSAGE NUMBER
	SETZM	FLAG		;INITIALIZE FLAG
	SETZM	RESEND		;AND RESEND COUNTER
RCVNXT:	DEBUG(7)
	MSTIME	TIME,			;INITIALIZE TIMER
RCVNX1:	MOVEI	CNT,MSLMAX		;INITIALIZE COUNTER
	PUSHJ	P,RCVMES		;GO RECEIVE A MESSAGE
	JRST	NOMESS			;THERE WASN'T A COMPLETE ONE
	SKIPE	ACKCHR			;DID WE GET AN ACK INSTEAD?
	JRST	NOMESS			;YES, GO HANDLE IT
	MOVE	T1,MSNRCV		;NOW CHECK MESSAGE NUM
	CAME	T1,MSN			;IS THIS THE CORRECT MESSAGE
	AOJA	T1,BADMSN		;NO SEE IF IT IS MESS-1
	DEBUG(21)
	PUSHJ	P,SACK			;ACKNOWLEDGE
RCVOK:	DEBUG(22)
	SETZM	RESEND

	MOVE	CNT,CCRCV#		;GET TEXT COUNT
	CAMLE	CNT,NUMBER		;ALL DATA BYTES WANTED?
	MOVE	CNT,NUMBER		;NO.
	ADDM	CNT,FLAG		;NO. OF PROPERLY RECEIVED BYTES
	MOVE	T1,BLTPTR		;GET BLT POINTER
	HRRZ	T2,T1			;SET UP LAST BLT ADDRESS
	ADD	T2,CNT
	BLT	T1,-1(T2)		;TRANSFER TO USER'S ARRAY
	MOVN	T1,CNT
	ADDM	T1,NUMBER
	SKIPG	NUMBER			;MORE BYTES WANTED?
	JRST	RCVXIT			;NO.
	ADDM	CNT,BLTPTR		;YES. UPDATE BLT POINTER
	AOS	T1,MSN			;NO. OF NEXT MESS.
	ANDI	T1,17			;CLEAR CARRY
	MOVEM	T1,MSN
	JRST	RCVNXT			;GET IT

RCVXT1:	TDZA	T2,T2		;ERROR EXIT, SET IERR TO 0
RCVXIT:	SETO	T2,		; SUCCESFUL EXIT, SET IERR TO -1
	HRRZ	T1,(P)		;GET ADDR OF ERROR FLAG
	MOVEM	T2,@(T1)	;STORE ERROR FLAG
	AOS	(P)		;INCREMENT ARG POINTER
	HRRZ	T1,(P)		;GET ADDR OF TYPE
	DEBUG(23)
	MOVE	T2,FLAG		;GET TYPE 
	MOVEM	T2,@(T1)		;SET UP FLAGWORD
	AOS	(P)			;SET UP RETURN ADR
	RESTOR	5		;RESTORE ACS
	SKIPE	F4FLG			;WAS IT FORTRAN CALL?
	JRST	EXITF4			;YES.
	JRST	CPOPJ		;RETURN
NOMESS:	DEBUG(24)
	CAIGE	CNT,MSLMAX	;HAVE WE RECEIVED ANY LEGAL CHARACTERS
	JRST	SNAK		;YES, SEND A NAK OUT
	DEBUG(25)
	MSTIME	T1,		;GET CURRENT TIME
	SUB	T1,TIME		;CALCULATE TIME SINCE START
	CAIGE	T1,HNGMES	;HAVE WE WAITED LONG ENOUGH
	JRST	RCVNX1		;YES, GIVE TIMED OUT ERROR RETURN
	DEBUG(26)
	JRST	RCVXT1		;GO GIV ERROR RETURN

BADMSN:	DEBUG(27)
	ANDI	T1,17		;GET MESSAGE NUMBER RECEIVED
	CAMN	T1,MSN		;IS IT SAME AS LAST ONE
	JRST	MESM1		;YES, GO SEND AN ACK
	MOVE	T1,MSNRCV	;NO, ASSUME A RESTART IN OTHER SYSTEM
	MOVEM	T1,MSN		;AND INITIALIZE MESSAGE NUMBER TO THE ONE RECEIVED
	PUSHJ	P,SACK		;SEND AN ACK OF THIS MESSAGE NUMBER
	JRST	RCVOK		;GO BACK TO MAIN STREAM

MESM1:	MOVE	T1,MSNRCV	;MESSAGE MINUS ONE WAS RECEIVED
	PUSHJ	P,SACK		;SO SEND OUT AN ACK FOR IT
	JRST	RCVNXT		;THEN GO WAIT FOR THE RIGHT MESSAGE

;ROUTINE TO RECEIVE MESSAGES OR ACK/NAK'S
;CALLED BY:	PUSHJ P,RCVMES
;		ERROR RETURN		;NO CORRECT MESSAGE RECIEVED
;		NORMAL RETURN

RCVMES:


;CHECK FOR START OF HEADER.

RCVSOH:	DEBUG(10)
	SETZ	CRC,			;INITIALIZE CRC
	PUSHJ	P,RCVCHR		;GET A BYTE
	POPJ	P,			;TIMED OUT
	CAIN	CHR,SOH			;IS IT SOH?
	SOJG	CNT,RCVMSN		;YES. CHECK MESS. NO.
BADCHR:	DEBUG(11)
	JRST	RCVSOH		;GO WAIT FOR A SOH

;CHECK MESSAGE IDENTIFICATION. EXPECTED
;NUMBER IS MSN. IF ONE LESS: SEND ACK FOR PREVIOUS MESSAGE.

RCVMSN:	DEBUG(12)
	PUSHJ	P,RCVCHR		;GET A BYTE
	POPJ	P,			;TIMED OUT
	SETZM	ACKCHR#			;INITIALIZE FLAG
	TRNE	CHR,360			;IS THIS AN ACK OR A NAK?
	JRST	CHKMSI			;POSSIBLY
	MOVEM	CHR,MSNRCV#		;STORE MESSAGE NUMBER
	SOJG	CNT,RCVCC		;YES. CHECK CC
	JRST	BADCHR		;RECEIVED TOO MANY CHARACTERS

;CHECK CHARACTER COUNT (ODD PARITY, COUNT.LE.TXLMAX).

RCVCC:	DEBUG(13)
	PUSHJ	P,RCVCHR		;GET A BYTE
	POPJ	P,			;TIMED OUT
IFN	FTODCC,
<	MOVE	T1,CRCTAB(CHR)		;LOOK INTO TABLE
	TRNN	T1,1			;WHETHER BYTE HAS
					;ODD PARITY.
	JRST	BADCHR			;IT HASN'T.
	ANDI	CHR,177			;GET CHAR COUNT
>
	CAILE	CHR,TXLMAX		;TOO MANY?
	JRST	BADCHR			;YES.
	MOVEM	CHR,CCRCV		;SAVE COUNT
	MOVN	T2,CHR			;FOR DATA POINTER
	HRLI	T2,TXTBUF	;SET UP TO SEND OUT TEXT
	SOJG	CNT,RCVSTX	;STILL GOT ROOM
	JRST	BADCHR		;NO, TOO MANY CHARACTERS RECEIVED

;CHECK START OF TEXT.

RCVSTX:	DEBUG(14)
	PUSHJ	P,RCVCHR		;GET A BYTE
	POPJ	P,			;TIMED OUT
	SOSLE	CNT			;RECEIVED TOO MANY CHARS YET?
	CAIE	CHR,STX			;IS IT STX?
	JRST	BADCHR			;NO.

;READ IN TEXT AND STORE IN TXTBUF.

	MOVSS	T2			;DATA POINTER IN CNT
RCVTXT:	DEBUG(15)
	PUSHJ	P,RCVCHR		;GET A DATA ITEM
	POPJ	P,			;TIMED OUT
	MOVEM	CHR,(T2)		;STORE IT
	SOSG	CNT
	JRST	BADCHR			;RECEIVED TOO MANY CHARACTERS!
	AOBJN	T2,RCVTXT		;NEXT DATA ITEM

;CHECK FOR ETX

RCVETX:	DEBUG(16)
	PUSHJ	P,RCVCHR		;GET A BYTE
	POPJ	P,			;TIMED OUT
	SOSLE	CNT			;MESSAGE TOO LONG?
	CAIE	CHR,ETX			;IS IT ETX?
	JRST	BADCHR			;NO.

;CHECK CRC. USE RCVBCC INSTEAD RCVCHR TO NOT INCLUDE
;BCC0 AND BCC1 IN CHECKSUM.

RCVBC0:	DEBUG(17)
	PUSHJ	P,RCVBCC		;GET A BYTE
	POPJ	P,			;TIMED OUT
	LSHC	CRC,-10			;GET HIGH ORDER PART OF CRC
	SOSLE	CNT
	CAME	CRC,CHR			;OK?
	JRST	BADCHR			;NO.
	LSHC	CRC,10			;RESTORE CRC
	ANDI	CRC,377			;GET LOW ORDER PART
	DEBUG(20)
	PUSHJ	P,RCVBCC		;GET A BYTE
	POPJ	P,			;TIMED OUT
	CAME	CRC,CHR			;CRC OK?
	JRST	BADCHR			;NO
	JRST	CPOPJ1			;MESSAGE OK

CHKMSI:	LDB	T1,ANPTR	;GET ACK FIELD
	MOVEM	T1,ACKCHR	;STORE FOR LATER
	DEBUG(35)
	ANDI	CHR,17		;CLEAR ACK FIELD
	MOVEM	CHR,ACKMSN#	;STORE MSN NUMBER
	SOJG	CNT,CHKBCC	;GO GET CRC
	JRST	BADCHR		;TOO MANY CHARACTERS RECEIVED

CHKBCC:	DEBUG(36)
	PUSHJ	P,RCVBCC	;GET CRC 1
	POPJ	P,		;NONE THERE GIVE ERROR RETURN
	LSHC	CRC,-10		;SHIFT IT
	SOSLE	CNT		;CHECK COUNT
	CAME	CRC,CHR		;IS THIS CHARACTER CORRECT
	JRST	BADCHR		;NO

	LSHC	CRC,10		;RESTORE ORIGINAL CRC
	ANDI	CRC,377		;CLEAR LEFTMOST BITS
	PUSHJ	P,RCVBCC	;GET LOWORDER CRC BITS
	POPJ	P,		;NONE THERE
	CAME	CRC,CHR		;IS THIS CHARACTER OK
	JRST	BADCHR		;NO
	JRST	CPOPJ1		;YES, GIVE SKIP RETURN

SUBTTL  SEND - TO SEND MESSAGES TO PDP-11
;S E N D 

COMMENT								%
CALL FROM COBOL:

	...
	ENTER MACRO SENDC USING ARRAY, NUMBER.
	...
								%
;COME IN HERRE FOR FORTRAN CALL.

SENDF:	0			;CALL SENDF(ARRAY,NUMBER,IERR,ITYPE)
	PUSH	P,Q		;STORE RETURN AC
	SETOM	F4FLG		;MARK THAT A FORTRAN CALL WAS DONE
	JRST	SEND		;GO SEND

;COME IN HERE IN CASE OF COBOL CALL.

SENDC:	SETZM	F4FLG		;MARK THAT A COBOL CALL WAS DONE
SEND:	SAVE	5		;SAVE 5 ACS
	HRRZ	T2,(P)			;GET ADR OF 1ST ARGUMENT
	HRRZ	T2,(T2)		;GET ARRAY ADDRESS
	SKIPN	F4FLG		;COBOL CALL?
	HRRZ	T2,(T2)		;YES, GET CORRECT ARRAY ADDRESS
	MOVEM	T2,ARYPTR		;STORE AS ARRAY POINTER
	AOS	(P)			;ADVANCE  ARG POINTER
	HRRZ	T1,(P)			;GET 2ND ARGUMENT
	MOVE	T1,@(T1)	;GET NUMBER OF CHARACTERS TO SEND
	MOVEM	T1,NUMBER	;STORE IT
	AOS	(P)			;ADVANCE ARG POINTER
	AOS	T1,MSN			;UPDATE MESS NO.
	ANDI	T1,17		;TRUNCATE MSN TO 4 BITS
	MOVEM	T1,MSN		;SAVE TRUNCATED MSN
	SETZM	FLAG		;CLEAR FLAG
	SETZM	RESEND		;ZERO RESEND COUNT

SNDNXT:	DEBUG(30)
	MOVEI	T1,TXLMAX		;TO SET UP CC
	CAMLE	T1,NUMBER		;MORE THAN TXLMAX CHAR'S LEFT?
	MOVE	T1,NUMBER		;NO. THIS IS LAST MESS.
	MOVEM	T1,CCSEND#		;SAVE CHAR COUNT

;SEND THE MESSAGE.
;SEND SOH:

	SETZ	CRC,			;INITIALIZE CRC
	MOVEI	CHR,SOH		;GET START OF HEADER CHARACTER
	PUSHJ	P,SNDCHR	;SEND IT OUT

;SEND MSN:

	MOVE	CHR,MSN		;GET MSN
	PUSHJ	P,SNDCHR	;SEND IT OUT

;SEND CC, ODD PARITY:

	MOVE	CHR,CCSEND	;GET CHARACTER COUNT
IFN	FTODCC,
<	MOVE	T1,CRCTAB(CHR)
	TRNN	T1,1			;HAS BYTE ODD PAR?
	TRO	CHR,200			;NO. MAKE IT ODD
>
	PUSHJ	P,SNDCHR	;SEND OUT CHARACTER COUNT

;SEND STX:

	MOVEI	CHR,STX		;GET START OF TEXT
	PUSHJ	P,SNDCHR	;SEND STX OUT

;SEND THE TEXT (CC BYTES):

	MOVN	T1,CCSEND		;POINTER
	HRL	T2,T1			;ARRAY ADDR IN T2
SNDTXT:	MOVE	CHR,(T2)	;GET NEXT CHARACTER TO SEND
	PUSHJ	P,SNDCHR	;SEND IT
	AOBJN	T2,SNDTXT	;LOOP BACK FOR MORE

;SEND ETX:

	MOVEI	CHR,ETX		;GET END OF TEXT CHARACTER
	PUSHJ	P,SNDCHR	;SEND OUT ETX

;SEND BCC0:

	ROT	CRC,-10		;GET HIGH ORDER CRC BITS
	MOVE	CHR,CRC		;...
	PUSHJ	P,PUTCHR	;SEND OUT BCC1

;SEND BCC1:

	ROT	CRC,10		;GET LOW ORDER CRC BITS
	MOVE	CHR,CRC		;...
	PUSHJ	P,PUTCHR	;SEND OUT BCC2
	PUSHJ	P,CLRINP	;CLEAR THE TTY INPUT BUFFER
	PUSHJ	P,PUTOUT	;SEND OUT THE MESSAGE

;RECEIVE AN ACK OR NAK MESSAGE:

	DEBUG(31)
	MSTIME	TIME,		;READ CURRENT TIME FOR TIMEOUT PURPOSES
RCVACK:	MOVEI	CNT,MSLMAX	;INITIALIZE COUNT TO MAX MESSAGE SIZE
	SETZM	NAKFLG		;INITIALIZE NAK FLAG
	PUSHJ	P,RCVMES		;GET ACK OR NAK
	JRST	NOACK			;NONE THERE
	SKIPN	T1,ACKCHR		;WAS THIS AN ACK/NAK
	JRST	GOTMES			;NO, IT WAS ANOTHER MESSAGE
	CAIN	T1,ACK_-4		;IS THIS AN ACK?
	JRST	CHKMSN			;YES
	CAIE	T1,NAK_-4		;IS THIS A NAK?
	JRST	NOACK			;NO, THIS IS A BAD MESSAGE
	SETOM	NAKFLG			;MARK THAT A NAK WAS SEEN
CHKMSN:	MOVE	T1,ACKMSN	;GET MSN RECEIVED
	CAMN	T1,MSN		;IS THIS THE ONE WE EXPECT
	SKIPE	NAKFLG		;AND WAS THIS AN ACK
	JRST	BADACK		;NO, GO RESEND

;ACKNOWLEDGE RECEIVED. CHECK FOR MORE CHAR'S TO BE SENT.

SNDMOR:	DEBUG(37)
	MOVN	T1,CCSEND	;GET CHARACTERS SENT COUNT
	ADDM	T1,NUMBER	;SUBTRACT FROM NUMBER LEFT
	SKIPG	NUMBER		;ANY MORE TO GO OUT
	JRST	SNDXIT		;NO, WE ARE THROUGH
	SETZM	RESEND		;YES, GO SEND OUT NEXT GROUP
	MOVE	T2,CCSEND	;GET CHARACTERS SENT COUNT
	ADDB	T2,ARYPTR	;UPDATE ARRAY POINTER
	AOS	T1,MSN		;UPDATE MSN
	ANDI	T1,17		;TRUNCATE TO 4 BITS
	MOVEM	T1,MSN		;STORE TRUNCATED MSN
	JRST	SNDNXT		;GO SEND OUT NEXT MESSAGE

NOACK:	DEBUG(40)
	CAIGE	CNT,MSLMAX	;ANY LEGAL CHARACTERS SEEN
	JRST	BADACK		;YES, GO RESEND
NOACK1:	DEBUG(41)
	MSTIME	T1,		;GET TIME
	SUB	T1,TIME		;CALCULATE TIME WAITED
	CAIG	T1,HNGACK	;HAVE WE TIMED OUT
	JRST	RCVACK		;NO, GO WAIT SOME MORE
BADACK:	DEBUG(42)
	AOS	T1,RESEND		;UPDATE COUNTER
	CAIL	T1,TRYMAX		;DID WE TRY ENOUGH?
	JRST	SNDXT1			;YES. QUIT.

;NOT ACKNOWLEDGE RECEIVED. RETRANSMIT MESSAGE.

SNDAGN:	DEBUG(43)
	MOVE	T2,ARYPTR		;NO
	JRST	SNDNXT		;GO RETRANSMIT THE MESSAGE


;WAITING FOR ACK OR NAK BUT GOT A MESSAGE

GOTMES:	MOVE	T1,MSNRCV	;GET MSN RECEIVED
	CAMN	T1,MSN		;IS IT WHAT WE ARE TRYING TO SEND
	JRST	SNDXT0		;YES, GIVE ERROR RETURN. BOTH PROGRAMS ARE SENDING
	AOS	T1		;INCREMENT MSN
	ANDI	T1,17		;TRUNCATE
	CAME	T1,MSN		;IS THIS MSN-1
	JRST	NOACK1		;NO, THEN IGNORE THIS MESSAGE
	MOVE	T1,MSNRCV	;YES, THEN SEND OUT AN ACK FOR THIS MSN
	PUSHJ	P,SACK		;THE OTHER PROGRAM PROBABLY LOST OUR ACK
	JRST	NOACK1		;NOW GO WAIT SOME MORE

SNDXT0:	SETOM RESEND		;SET ERROR FLAG
SNDXT1:	TDZA	T2,T2		;IERR = 0
SNDXIT:	SETO	T2,		;IERR = -1  OK RETURN
	HRRZ	T1,(P)		;GET ADDRESS OF IERR
	MOVEM	T2,@(T1)	;STORE ERROR FLAG
	AOS	(P)		;INCREMENT ARG POINTER
	MOVE	T2,RESEND	;GET TYPE
	HRRZ	T1,(P)		;GET ITYPE ADDRESS
	MOVEM	T2,@(T1)	;STORE ITYPE
	AOS	(P)		;INCREMENT ARG POINTER
	RESTOR	5		;RESTORE THE ACS
	SKIPE	F4FLG		;WAS THIS CALL FROM A FORTRAN PROGRAM
	JRST	EXITF4		;YES, GO RETURN
	POPJ	P,		;NO JUST POPJ RETURN

EXITF4:	POP	P,Q		;RESTORE RETURN ADDRESS
	JRA	Q,(Q)		;RETURN

ANPTR:	POINT	4,CHR,31		;TO DECODE MSI
ARYPTR:	Z				;POINTS TO 1ST BYTE IN
					;USER ARRAY TO BE SENT
BLTPTR:	XWD	TXTBUF,0		;TO FILL USER'S ARRAY
F4FLG:	Z				;IF -1: CALL FROM F4
					;ELSE FROM COBOL
FLAG:	Z				;TO COUNT NO. OF ACTUALLY
					;XMITTED BYTES AND TO INDICATE
					;TIMEOUT
MSI:	Z				;MESS. IDENTIFICATION
MSN:	Z				;NO. OF CURRENT MESSAGE
NAKFLG:	Z				;IF -1: LAST MESSAGE
					;RECEIVED WAS NAK
NUMBER:	Z				;FOR 2ND ARGUMENT
RESEND:	Z				;NO. OF TRIES OF RETRANSMITS
ACSAV:	BLOCK	7			;ACC. SAVE AREA
CRCTAB:	BLOCK	400			;TABLE FOR CRC
TXTBUF:	BLOCK	^D72			;TO STORE TEXT

	END			;END OF COMMPS