
;TYMNET INTERFACE.

TYMORG = 7600	;Where to assemble fixed part of TYMNet code.

;A-MEM USAGE.
; 0: STANDARD.
; 1: STATE OF OUTPUT FFS (SEE CFTNET)
; 2: OUTPUT COROUTINE ADR (LO 6 BITS)
; 3: INPUT COROUTINE ADR (LO 6 BITS)
; 4: CURRENT -10 WORD BEING OUTPUT (FOR STATE 1 ONLY)
; 5: CURRENT -10 WORD BEING ASSEMBLED ON INPUT (STATE 1)
; 6: IOWD FOR PACKET CURRENTLY BEING READ
; 7: B0-2, STATE OF MAP BEFORE INT; B3-35, INP REG AT INT START

;MAIN MEMORY LOCATIONS:
; 2000/	KEY:	0		;FLAGS
; 2200/	IRING: BLOCK 200	;INPUT (TO HOST) RING
; 2400/ ORING: BLOCK 400	;OUTPUT (FROM HOST) RING
; 2005/ HIRP:  0	;HOST IRING PTR (TAKER)
; 2006/ BIRP:  0	;BASE IRING PTR (PUTTER)
; 2011/ HORP:  0	;HOST ORING PTR (PUTTER)
; 2012/ BORP:  0	;BASE ORING PTR (TAKER)

;DR11C FLAG NAMES.  (FIELD VALUES).
TNODIBN = 2	;OUTPUT DONE ROTATE AMOUNT (INPUT) = REQ B.
TNIRIBN = 3	;INPUT READY ROTATE AMOUNT (INPUT) = REQ A.
TNODOBN = 6	;OUTPUT DONE ROTATE AMOUNT (OUTPUT) = CSR1.
TNODOBNPO = 7
TNIROBN = 7	;INPUT READY ROTATE AMOUNT (OUTPUT) = CSR0.
TNIROBNPO = 10


.DEFINE TNOCEC[] [ ;SEND 0 BYTE IF ESCAPE WORD (-1) JUST SENT.
	D[14] ROT[34] MASK[20] DEST[Q] NORM $
	D[MASK 20] ALU[D#Q] COND[-OBUS=0] JUMP[. + 3] C550 $
	ALU[0] DEST[Q] PUSHJ[TNSEND] NORM $
	D[CONST[. & 77 + 1]] DEST[2] DEST-A-MEM JUMP[TNI0] NORM $
]
.DEFINE GBORP[] [
	D[CONST 12] DEST[Q] PUSHJ[TNRCW] NORM $
]
.DEFINE GHORP[] [
	D[CONST 11] DEST[Q] PUSHJ[TNRCW] NORM $
]
.DEFINE GBIRP[] [
	D[CONST 6] DEST[Q] PUSHJ[TNRCW] NORM $
]
.DEFINE GHIRP[] [
	D[CONST 5] DEST[Q] PUSHJ[TNRCW] NORM $
]


;HERE TO SERVICE INPUT READY OR OUTPUT DONE INTERRUPT BY
; TYMNET INTERFACE.
	;SAVE MAP STATE IN A-MEM[7].0-2 & TURN MAP OFF.
TNI:	DEST[CLR-DEV-FROM-INTR] SPEC[IOB-IN] NORM PUSHJ[MAPOFF] $
	D[IR] MASK[3] DEST[AR] MAPF[10] CYLEN[IOB-OUT] $	;MAPOFF NEEDS MAPF, CYLEN.
	D[AR] ROT[41] DEST[Q] NORM $
	D[CONST 6] DEST[DEV-ADR] SPEC[IOB-IN] NORM $ ;BACK TO 6 FOR TN

	;SAVE INPUT REG IN A-MEM[7].
	MAPF[TYM.RD] D[IOD] MASK[41] DEST[AR] CYLEN[IOB-IN] $
	D[AR] ALU[DORQ] DEST[Q 7] DEST-A-MEM NORM $
	D[CONST 1] ROT[TNODIBN] ALU[D&Q] COND[OBUS=0] JUMP[TNI1] C550 $
	D[CONST (TYMORG / 100)] ROT[6] DEST[Q] SPEC[IOB-OUT] CYLEN[IOB-OUT] $
	D[12] ALU[DORQ] COND[OBUS<0] JUMP[. + 2] MAPF[TNODIFS] C550 $	;OUTPUT DONE.
	D[12] ALU[DORQ] SDISP C550 $	;OUTPUT DONE.
TNI0:	D[17] DEST[Q] NORM $	;RESTORE INP REG
TNI1:	D[CONST 1] ROT[TNIRIBN] ALU[D&Q] COND[OBUS=0] JUMP[TNI2] C550 $
	D[17] ROT[34] MASK[20] DEST[Q] PUSHJ[BITREV] NORM $
	D[CONST (TYMORG / 100)] ROT[6] DEST[Q] SPEC[IOB-OUT] CYLEN[IOB-OUT] $
	D[13] ALU[DORQ] COND[OBUS<0] JUMP[. + 2] MAPF[TNIRIFS] CYLEN[C500] $	;INPUT READY.
	D[13] ALU[DORQ] SDISP CYLEN[C500] $	;INPUT READY.
TNI2:	D[17] ROT[3] MASK[3] DEST[IOD] NORM $
	ALU[0] DEST[DEV-ADR] SPEC[IOB-OUT] JUMP[MPOFF1] NORM $	;ENDS UP AT MAIN.

;VARIOUS SUBROUTINES.
;Q LOADED WITH 16. BIT WORD TO SEND, SHIFTED LEFT BY 8.
TNSEND:	ALU[Q] DEST[AR] NORM $
	D[AR] ROT[34] DEST[Q] PUSHJ[BITREV] NORM $
	D[AR] ROT[8] DEST[Q] SHORT $
	D[MASK 16.] ROT[8] ALU[D&Q] DEST[AR] NORM $
	D[MASK 8] DEST[Q] PUSHJ[DEV6ST1] NORM $
	;CLEAR THEN SET INPUT READY FLAG TO DR11C.
	D[MASK 43] ROT[TNIROBNPO] DEST[Q] PUSHJ[DEV6CL] NORM $
	D[CONST 1] ROT[TNIROBN] DEST[AR] NORM JUMP[DEV6ST2] $
;NO OUTPUT TO DO.  DO NOT CHANGE TNIROBN, SET A-MEM FLAG FOR
; CLOCK ROUTINE.
TNORE:	ALU[-1] DEST[2] DEST-A-MEM JUMP[TNI0] NORM $
;READ WORD FROM BASE-HOST COMMUNICATION AREA, LOCATION 20XX;
; Q HAS XX.
TNRCW:	D[CONST 20] ROT[6] ALU[DORQ] DEST[MA] NORM $
	FIXM0 POPJ $

;HERE WHEN INPUT RING FULL.  SET CLOCK FLAG AND RETURN WITHOUT
; SETTING TNODOBN.
TNIRF:	ALU[-1] DEST[3] JUMP[TNI2] DEST-A-MEM NORM $
;CLEAR THEN SET TNODOBN.
TNCASODOF:
	D[MASK 43] ROT[TNODOBNPO] DEST[Q] PUSHJ[DEV6CL] NORM $
	D[CONST 1] ROT[TNODOBN] DEST[AR] NORM JUMP[DEV6ST2] $

.REPEAT SLOWTAPE [

;REVERSE RIGHTMOST 16. BITS IN Q.  LEAVES RESULT IN Q&AR.
; CLOBBERS IR, MEM.
BITREV:	ALU[Q] DEST[AR] SHORT $
	D[CONST 17] LLOAD NORM $
	D[AR] ROT[23] DEST[AR] SHORT $
	ALU[0] DEST[Q HOLD] NORM $
	D[CONST 1] DEST[IR-ALL] NORM $
BRLP:	D[AR] ROT[1] DEST[AR] COND[-OBUS<0] JUMP[BRLP1] C550 $
	D[IR] ALU[QORD] DEST[Q] SHORT $
BRLP1:	D[IR] ROT[1] DEST[IR-ALL] LOOP[BRLP] NORM $
	ALU[Q] DEST[AR] POPJ NORM $

 ] ;SLOWTAPE

.REPEAT 1 - SLOWTAPE [

BITREV:	D[MASK 20] ALU[D&Q] DEST[Q AR] NORM POPJ $

 ]

	.ORG[TYMORG]	;$*$*$* Dispatch mechanism is a real loser here.  We
			;	won't be able to flush this one until
			;	references are made relative.  Essentially,
			;	[xx & 77] gets replaced by [. - TNOC0] and
			;	TNOC0 is kept in a A-MEM for speed.  Then,
			;	instead of D[CONST 71] ROT[6] ALU[DORQ], one
			;	uses D[10 + x] ALU[D+Q] to do the dispatch.
;********** OUTPUT DONE CO-ROUTINE.
;A-MEM[4] = ROTATED -10 WORD WITH -11 WORD JUST SENT IN 12-27.
;STATE 0: FETCH NEXT -10 WORD OR QUIT IF RING EMPTY.
TNOC0:	GBORP
	D[MEM] DEST[AR] NORM $
TNOC0A:	GHORP
	D[AR] DEST[Q] NORM $
	D[MEM] ALU[D-Q] COND[OBUS=0] JUMP[TNORE] C600 $
	D[CONST 24] ROT[6] ALU[D+Q] DEST[MA] NORM $
	FIXM0 $
	D[MEM] ROT[30] DEST[4 Q] DEST-A-MEM PUSHJ[TNSEND] NORM $
	D[CONST[. & 77 + 1]] DEST[2] DEST-A-MEM JUMP[TNI0] NORM $
;CLOCK RESTARTS COROUTINE HERE.
TNOC2:	TNOCEC
;STATE 1: SEND LOW ORDER HALF OF -10 WORD.
	D[14] ROT[20] DEST[Q] NORM $
	ALU[Q] DEST[4] PUSHJ[TNSEND] DEST-A-MEM NORM $
	D[CONST[. & 77 + 1]] DEST[2] DEST-A-MEM JUMP[TNI0] NORM $
	TNOCEC
	GBORP
	D[MEM] ALU[D+1] DEST[Q] NORM $
	D[MASK 8] ALU[D&Q] DEST[AR MEMSTO] JUMP[TNOC0A] CYLEN[MEMSTO] $

;********** INPUT READY CO-ROUTINE.
; A-MEM[5] HAS CURRENT INPUT WORD BEING ASSEMBLED.
;STATE 0: AWAITING START OF NEXT MESSAGE.

TNIC0:	D[CONST 2] ROT[9] DEST[MA] NORM $ ;ADDRESS OF KEY IN MAIN MEM.
	ALU[0] DEST[MEMSTO] NORM $ ;CLEAR KEY AT START OF EVERY MESSAGE
	D[AR] DEST[Q 5] DEST-A-MEM NORM $
	D[CONST 1] ROT[17] ALU[D&Q] COND[OBUS=0] JUMP[TNIC0A] C550 $
;DATA PACKET MESSAGE.
	D[AR] ROT[34] MASK[7] DEST[Q] SHORT $
	D[CONST 5] ALU[D+Q] DEST[AR] SHORT $
	D[AR] ROT[42] MASK[18.] DEST[6] DEST-A-MEM NORM $
	D[15] DEST[AR] SHORT $
;READ MSG.  A-MEM[6]:=# -10 WORDS IN MESSAGE.
; AR:=FIRST -11 WORD IN MESSAGE.
TNICRM:
	GBIRP
	D[16] ROT[18.] ALU[0-D] DEST[Q] NORM $
	D[MEM] MASK[18.] ALU[QORD] DEST[6] DEST-A-MEM NORM $
;STATE 1: HO 16 BITS OF WORD ARRIVES.
TNIC1:	D[AR] ROT[24] DEST[5] DEST-A-MEM NORM $
	GHIRP
	D[16] ALU[D+1] DEST[Q] NORM $
	D[MASK 7] ALU[D&Q] DEST[Q] SHORT $
	D[MEM] ALU[D-Q] COND[OBUS=0] JUMP[TNIRF] C600 $
	PUSHJ[TNCASODOF] NORM $
	D[CONST[. & 77 + 1]] DEST[3] DEST-A-MEM JUMP[TNI2] NORM $
;STATE 2: LO 16 BITS OF WORD ARRIVES.
; ALSO STARTED HERE BY CLOCK ROUTINE.
TNIC2:	D[16] MASK[7] DEST[Q] NORM $
	D[CONST 22] ROT[6] ALU[D+Q] DEST[MA] NORM $
	D[15] DEST[Q] NORM $
	D[AR] ROT[4] ALU[DORQ] DEST[MEMSTO] NORM $
	PUSHJ[TNCASODOF] NORM $
	D[16] ALU[D+1] DEST[Q] CYLEN[MEMSTO] $
	D[CONST 1] ROT[18.] ALU[D+Q] DEST[6] DEST-A-MEM COND[-OBUS<0] JUMP[TNICDN] C600 $
	D[CONST[77 & TNIC1]] DEST[3] JUMP[TNI2] DEST-A-MEM NORM $

 .RELOC

TNICDN:	D[CONST 6] DEST[Q] SHORT $
	D[CONST 20] ROT[6] ALU[DORQ] DEST[MA] SHORT $
	D[16] MASK[7] DEST[MEMSTO] NORM $
	D[CONST[TNIC0 & 77]] DEST[3] DEST-A-MEM JUMP[TNI2] CYLEN[MEMSTO] $
;1 WD OR 2 WD OR ESCAPE MESSAGE.
TNIC0A:	D[CONST 1] ROT[16] ALU[D&Q] COND[-OBUS=0] JUMP[TNIC0B] C550 $
;ONE WORD PACKET.
	D[CONST 1] DEST[6] JUMP[TNICRM] DEST-A-MEM NORM $
TNIC0B:	D[CONST 1] ROT[16] ALU[D#Q] DEST[Q AR] SHORT $
	D[MASK 6] ROT[8] ALU[D&Q] DEST[Q] SHORT $
	D[MASK 6] ROT[8] ALU[D#Q] COND[OBUS=0] JUMP[TNIC0C] C550 $
;2 WORD PACKET.
	D[CONST 2] DEST[6] JUMP[TNICRM] DEST-A-MEM NORM $
;ESCAPE SEQUENCE.  BETTER NOT HAPPEN.
TNIC0C:	JUMP[.] $

;CLOCK ROUTINE, CALLED EVERY TICK OF 60HZ CLOCK.

TYMCLK:	D[CONST 1] DEST[DEV-ADR] PUSHJ[MAPOFF] SPEC[IOB-IN] NORM $
	MAPF[10] CYLEN[IOB-OUT] D[CONST 6] DEST[DEV-ADR] $
	D[IR] DEST[7] DEST-A-MEM NORM $
	D[13] COND[OBUS<0] PUSHJ[TNSI] C550 $
	D[12] COND[OBUS<0] PUSHJ[TNSO] C550 $
	D[17] MASK[3] DEST[IOD] NORM $
	ALU[0] DEST[DEV-ADR] SPEC[IOB-OUT] NORM $
	MAPF[10] CYLEN[IOB-OUT] $
	D[CONST 6] DEST[DEV-ADR] POPJ NORM $

TNSI:	GHIRP
	D[16] ALU[D+1] DEST[Q] NORM $
	D[MASK 7] ALU[D&Q] DEST[Q] SHORT $
	D[MEM] ALU[D-Q] COND[OBUS=0] POPJ C600 $
	D[CONST[TNIC2 & 77]] DEST[3] DEST-A-MEM JUMP[TNCASODOF] NORM $
TNSO:	GBORP
	D[MEM] DEST[AR] NORM $
	GHORP
	D[AR] DEST[Q] NORM $
	D[MEM] ALU[D-Q] COND[OBUS=0] POPJ C600 $
	D[CONST 24] ROT[6] ALU[D+Q] DEST[MA] NORM $
	FIXM0 $
	D[MEM] ROT[30] DEST[4 Q] DEST-A-MEM PUSHJ[TNSEND] NORM $
	D[CONST[TNOC2 & 77]] DEST[2] POPJ DEST-A-MEM NORM $

;RESET TYMNET INTERFACE.  OUTPUT COROUTINE GOES INTO NULL STATE.
; INPUT COROUTINE GOES INTO STATE 0, INTRPTS GET ENABLED.
TYMRS1:	D[CONST 3] ROT[2] DEST[AR] CYLEN[IOB-OUT] SPEC[IOB-OUT] $
	 ;GET CONST TO ENB. INTRPTS; IOB-OUT CLEARS FLAGS.
TYMRS2:	MAPF[TNODIFS] START-OUT C600 $
	MAPF[TNIRIFS] D[MASK 2] ALU[NOTD] ROT[2] DEST[Q] PUSHJ[DEV6ST1] C600 $
	ALU[-1] DEST[2] DEST-A-MEM NORM $
	D[CONST[TNIC0 & 77]] DEST[3] POPJ DEST-A-MEM NORM $

TYMAREA:	;SAVE LOCATION

	.OPCODE[744]	  ;RESET TYMNET

	NOP $
	D[CONST 6] DEST[DEV-ADR] NORM JUMP[TYMNRESET] $

	NOP $
	D[CONST 6] DEST[DEV-ADR] NORM JUMP[TYMNOUT] $

	NOP $
	D[CONST 6] DEST[DEV-ADR] NORM JUMP[TYMNIN] $

	NOP $	;AS NEAR AS I CAN TELL, THIS ONE (747) ISN'T USED. - PG
	D[CONST 6] DEST[DEV-ADR] NORM JUMP[F5DIAG] $

	.USE[TYMAREA]	;RETURN TO MAIN CODE

TYMNRESET:  SPEC[IOB-OUT] D[MA] ROT[2] DEST[AR] NORM PUSHJ[TYMRS2] $
		;RESET CO-ROUTINES, ENB. INTRPTS FROM EFF. ADDR. 34,35
	JUMP[MAIN] $

TYMNOUT: SPEC[IOB-OUT] NORM $  ;CLEAR "RDY FOR DATA" FROM PDP11
	MAPF[TNODIFS] D[MA] ROT[8.] DEST[Q] NORM PUSHJ[TNSEND] $
	  ;SEND EFF. ADDR. 20-35 TO PDP11.
	JUMP[MAIN] $

TYMNIN:	D[CONST 25.] LLOAD NORM $
	NORM LOOP[.] $  ;GIVE DMA DEVICES SOME MEMORY TIME.
	SPEC[IOB-IN] NORM $
	MAPF[TYM.RD] D[IOD] ROT[27. + 1] DEST[AR] C800 $
	   ;Align input word with 16 data bits at RIGHT end.
	D[AR] ROT[4] C550 COND[-OBUS<0] JUMP[. + 2] $
	   ;Don't clear "INPUT RDY" flag unless it's on.
	SPEC[IOB-OUT] SHORT $  ;IT'S ON.
	MAPF[TNIRIFS] D[AR] DEST[MEMSTO] MEMST $

F5DIAG: FIXM1 $
	D[IR] ALU[NOTD] DEST[AR] NORM $
		;AR=-IR
	D[AR] ROT[13.] MASK[2] DEST[AR] NORM $
		;AR=-AC MASK 2
	D[AR] ROT[6] DEST[Q] NORM $
		;Q=INVERTED 2 LSB'S OF AC SHIFTED INTO STROBES
	D[MEM] ROT[8.] ALU[DORQ] DEST[HOLD] NORM $
		;DATA SHIFTED WITH STROBES INSERTED
	D[MEM] DEST[AR] NORM $
		;DATA=(E) (LSH 8) (STB ACTIVE LOW)
	D[MASK 18.] ROT[18. + 6] DEST[Q] PUSHJ[DEV6ST1] NORM $
		;LEAVE BITS 0-11. AND 30.-35. UNCHANGED
	D[MASK 2] ROT[6] DEST[Q] NORM $
		;MASK TO FORCE STB'S HIGH
	D[MEM] ALU[DORQ] DEST[AR] NORM $
		;DATA=(E) (LSH 8) (STB'S FORCED INACTIVE HIGH)
	D[MASK 18.] ROT[18. + 6] DEST[Q] PUSHJ[DEV6ST1] NORM $
		;LEAVE BITS 0-11. AND 30.-35. UNCHANGED
	ALU[0] DEST[DEV-ADR] JUMP[MAIN] $
