;------------------------------------------------------------------------------
;
;	UCODE FOR BARE 800 BPI, 125 IPS TAPE DRIVE
;
;------------------------------------------------------------------------------

;TAPE DELAY CONSTANTS

 .REPEAT 0 [	;45 IPS VALUES
TP-RD-STRT-DLY = 59.
TP-BOT-DLY = 34.
TP-GAP-DETECT-DLY = 61.
TP-EOR-DLY = 18.
TP-WR-STRT-DLY = 36.
TP-MBOOT-GAP-DLY = 14.

 ]

 .REPEAT 1 [	;125 IPS VALUES
TP-RD-STRT-DLY = 20.
TP-BOT-DLY = 12.
TP-GAP-DETECT-DLY = 22.
TP-EOR-DLY = 7.
TP-WR-STRT-DLY = 13.
TP-MBOOT-GAP-DLY = 9.

 ]

;TAPE READING AND WRITING CODE
; A-MEM USAGE:
;		0	DISPATCH ADDR.
TPMODE =	1       ;MODE BITS (SEE BELOWS)
;		4	COPY OF HDWR CTRL REGISTER (WRITE)
;		5	READ ERROR FLAGS
;		6	TEMP WITHIN TRP2 (HOLDS TP PAR ERR FLG)
;			WHEN WRITING, HOLDS ODD-EVEN WC FLAG.
;
;Mode bits:
;	Bit 35		Industry compatable mode (4 bytes/word)
;			(Otherwise, PDP-10 dump mode)
;
;PDP-10 Dump mode
;  ------------------------------------------------------------------------
; |               |               |               |               |        |
; |    Byte 1     |    Byte 2     |    Byte 3     |    Byte 4     |        |
; |               |               |               |               |        |
;  ------------------------------------------------------------------------
;								  |        |
;								  V        V
;							  -----------------
;							 |        |  Bits  |
;							 |    0   |  32:35 |
;							 |     Byte 5      |
;							  -----------------
;
;Industry Compatable Mode
;  ------------------------------------------------------------------------
; |               |               |               |               |        |
; |    Byte 1     |    Byte 2     |    Byte 3     |    Byte 4     |   0    |
; |               |               |               |               |        |
;  ------------------------------------------------------------------------
;


   ;727 - OBSOLETE VERSION OF READ
	.PAIR
	UIOTRP[MUUO] $
TAPERD:	D[CONST 22] ROT[6] DEST[IOD] SPEC[IOB-OUT] 
		NORM PUSHJ[TPRDGO] $
	D[MASK 17.] DEST[IR-ADR] PUSHJ[TRP2] NORM $
		;MOVE STATUS INTO AC.
	ALU[Q] DEST[AC] ACSEL[AC] MAPF[2] JUMP[MAIN] CYLEN[IOB-OUT] $

; TPRDGO -- CALLED AS TAPE MOTION IS STARTED.  WAITS FOR
;	FIRST GAP TO PASS.

TPRDGO:	MAPF[2] D[CONST 2] ROT[35. - 5] DEST[Q] C800 $
	   ;FIRST SET "CTL WD SEL" TO 1 (SELECT TP RD DAT)
	SPEC[IOB-OUT] D[CONST 1] ROT[35. - 28.] ALU[DORQ]  DEST[IOD] NORM $
	   ;..ALSO SET THE "IN" BIT.

	 ;NOW WAIT 8.3MSEC FOR 45IPS TAPE (38MSEC IF AT BOT).
	 ; (GET 2*DELAY-COUNT)
	MAPF[4] D[CONST TP-RD-STRT-DLY] ROT[9.] DEST[AR] CYLEN[IOB-OUT]
	  SPEC[IOB-IN] PUSHJ[TPBOTD] $  ;HANDLE BOT CASE.
	D[AR] ROT[35.] MASK[20.] DEST[AR] NORM $ ;GET DELAY-COUNT
	 ;IF FOLLOWING CYLEN IS MADE 1000, DMA XFERS LOSE.
	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[.] C550 $

	SPEC[IOB-IN] D[CONST 40] ROT[14.] DEST[Q] NORM $ 
	  ;CLEAR DATA RDY FLAGI, GET TIMOUT COUNT IN Q
	MAPF[1] NORM ALU[0] DEST[5] DEST-A-MEM $ ;CLR ERROR REG
P1:	SPEC[IOB-IN]  C550 $ ;NOW WAIT FOR FIRST BYTE
	D[IOD] DEST[HOLD] MAPF[2] C550 $
	D[MEM] ROT[33] MASK[1] COND[-OBUS=0] C550 POPJ $
	ALU[Q-1] DEST[Q] COND[-OBUS=0] JUMP[P1] C550 $
	ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $ ;TIMEOUT... STOP TAPE.
	MAPF[2] D[CONST 41] ROT[36] DEST[Q] JPOP[TNRP3] NORM $ ;ABORT 

	;IF WE ARE AT BOT, SET DELAY TIME FOR LARGE GAP.
TPBOTD:	D[IOD] MAPF[4] ROT[15.] DEST[Q] CYLEN[IOB-IN] $
	ALU[Q] OBUS<0 POPJ C550 $ ;RET IF NOT BOT
TP3IDL:	D[CONST TP-BOT-DLY] ROT[12.] DEST[AR] NORM POPJ $ ;ABOUT 77MSEC

;READ A RECORD.  STORE UP TO C(IR-ADR) WORDS.

TRP2:	ALU[0] DEST[6] DEST-A-MEM NORM PUSHJ[TRBA] $
	JUMP[TRP2B] NORM $	;Already have first byte, Jump into loop
;This loop is repeated for each word.  At end-of-record, TRBYTE terminates
;the loop by popping off return address and returning to the routine that
;requested that a record be read.
TRP2A:	ALU[0] DEST[6] DEST-A-MEM PUSHJ[TRBYTE] NORM $
TRP2B:	D[MEM] ROT[34] DEST[Q] PUSHJ[TRBYTE] NORM $
	D[MEM] ROT[24] ALU[DORQ] DEST[Q] PUSHJ[TRBYTE] NORM $
	D[10 + TPMODE] MASK[1] NORM COND[-OBUS=0] JUMP[TRP2D] $
		;While we have the time to decide, handle last
		;byte of industry-compatable mode differently
	D[MEM] ROT[14] ALU[DORQ] DEST[Q] PUSHJ[TRBYTE] NORM $
	D[MEM] ROT[4] ALU[DORQ] DEST[Q] PUSHJ[TRBYTE] NORM $
	D[IR] MASK[18.] ALU[D-1] DEST[IR-ADR] COND[OBUS18] JUMP[TRP2A] C600 $
		;Decrement count.  If word count exhausted, finish reading
		;record but don't write anything.
	D[MEM] MASK[4]  ALU[DORQ] DEST[MEMSTO] NORM $
		;Note that it is presumed here that the operating system has
		;already dealt with page faults before we get here.
TRP2C:	D[16] DEST[Q] NORM$
	D[15] ALU[DORQ] DEST[Q] NORM $ ;GET ERROR FLG FOR WORD.
	ALU[Q] DEST[5] DEST-A-MEM NORM $
	D[MA] ALU[D+1] DEST[MA] JUMP[TRP2A] NORM $
;Special for industry compatable mode.
TRP2D:	D[MEM] ROT[14] ALU[DORQ] DEST[Q] PUSHJ[TRBYTE] NORM $
		;Deposit byte 3, get byte 4
	D[IR] MASK[18.] ALU[D-1] DEST[IR-ADR] COND[OBUS18] JUMP[TRP2A] C600 $
		;Decrement count.  If word count exhausted, finish reading
		;record but don't write anything.
	D[MEM] ROT[4] ALU[DORQ] DEST[MEMSTO] NORM JUMP[TRP2C] $
		;Deposit byte 4 (last) and store away.  Rejoin regular program.
		
;READ 1 BYTE.  IF ERROR, EOR, EOF, SET Q_2,HIGHEST LOC WRITTEN+1,1 & POP
; ONE OFF THE STACK AND RETURN.  IF BYTE SUCCESSFULLY
; READ, JUST RETURN WITH BYTE IN HOLD.
TRBYTE:	D[CONST TP-GAP-DETECT-DLY] LLOAD NORM $
TRB2:	SPEC[IOB-IN] LOOP[TRB1] C550 $
	D[CONST TP-EOR-DLY] ROT[6] LLOAD C550 $
	LOOP[.] C550 $
	SPEC[IOB-IN] C550 $
	MAPF[1] D[AR] ROT[42] MASK[21]	; IS RECORD <4 CHRS (MEAN-
		COND[-OBUS=0] JUMP[TREOR] C550 $ ; ING END-OF-FILE) ?
	D[CONST 60] ROT[36] DEST[5] DEST-A-MEM NORM $ ;YES
	ALU[Q] DEST[AR] NORM $
	D[AR] ROT[28.] DEST[Q] JPOP[TRDONE] NORM $
TREOR:	ALU[Q] DEST[7] DEST-A-MEM NORM $ ;SAVE CHECK CHRS.
	D[MA] MASK[24] DEST[Q] NORM JPOP[TRDONE] $ ;ENDX OF REC.

TRB1:	D[IOD] ALU[NOTD] DEST[HOLD] MAPF[2] LONG $
	C550 $ ;GIVE DMA DEVICES A CHANCE AT THE BUS !!
	D[MEM] ROT[33] MASK[1] COND[-OBUS=0] JUMP[TRB2] C550 $
TRBA:	SPEC[IOB-IN] D[AR] ALU[D+1] DEST[AR] NORM $
	MAPF[2] SPEC[IOB-IN] D[IOD] ALU[NOTD] DEST[HOLD] C800 $
	MAPF[1] D[MEM] ROT[31] C550
	   OBUS<0 JUMP[TRERR] $  ;TEST THE ERROR BIT.
TRB4:	D[MEM] MASK[10] DEST[HOLD] POPJ NORM $

TRDONE:	D[CONST 0] DEST[IOD] SPEC[IOB-OUT] NORM $  ;STOP TAPE.
	 ;COMBINE ERROR CODE WITH MA AND RETURN (UPLEVEL).
	MAPF[2] CYLEN[IOB-OUT]  D[15] ALU[DORQ] DEST[Q] POPJ $

		;BYTE PARITY ERROR - CODE TO AMEM(6), CONT.
TRERR:	D[CONST 50] ROT[36] DEST[6] DEST-A-MEM 
	 NORM JUMP[TRB4] $  ;SET BIT 2 OF ERROR FLAGS.


	.PAIR
	UIOTRP[MUUO] $
TAPEMT:	;MTAPE FUNCTIONS.
	D[MA] DEST[Q] COND[OBUS=0] JUMP[TAPERW] C550 $
		;Start rewinding
	D[CONST 5] ALU[D-Q] COND[OBUS=0] JUMP[TAPEFR] C550 $
		;Forward space one record
	D[CONST 6] ALU[D-Q] COND[OBUS=0] JUMP[TAPEBR] C550 $
		;Backspace space one record
	D[CONST 1] ALU[D-Q] COND[OBUS=0] JUMP[TWREOF] C550 $
		;Write EOF
	D[CONST 50] ALU[D-Q] COND[OBUS=0] JUMP[TPSETIND] C550 $
		;Code ?, set industry compatable mode.
	D[CONST 51] ALU[D-Q] COND[OBUS=0] JUMP[TPSETDMP] C550 $
		;Code ?, set PDP-10 dump mode.
	JUMP[MAIN] $ ;UNKNOWN CODE -- TREAT AS NOP.
TWREOF:	ALU[0] DEST[MA] NORM PUSHJ[TP3IDL] $ ;SET FLG AND GET 
	D[CONST 0] DEST[6] DEST-A-MEM NORM JUMP[TWEOF] $ ; 3" GAP DLY CNT, THEN GO TO WRITE CODE.

TAPERW:	;REWIND
	D[CONST 6] ROT[6] DEST[IOD] SPEC[IOB-OUT] NORM $
	MAPF[2] CYLEN[IOB-OUT] ALU[0] DEST[IOD] SPEC[IOB-OUT] $
	MAPF[2] JUMP[MAIN] CYLEN[IOB-OUT] $

TAPEFR:	;SKIP FORWARD ONE RECORD.
	D[CONST 22] ROT[6] DEST[IOD] SPEC[IOB-OUT] 
		NORM PUSHJ[TPRDGO] $
	D[CONST 0] DEST[IR-ADR] PUSHJ[TRP2] NORM $
		;MOVE STATUS INTO AC.
	ALU[Q] DEST[AC] ACSEL[AC] MAPF[2] JUMP[MAIN] CYLEN[LONG] $

TAPEBR:	;SKIP BACKWARD ONE RECORD.
	D[CONST 2] ROT[6] DEST[IOD] SPEC[IOB-OUT] CYLEN[LONG] $
	MAPF[2] SPEC[IOB-IN] CYLEN[IOB-OUT] $
	D[IOD] ROT[18.] MASK[6] DEST[Q] MAPF[4] CYLEN[IOB-IN] $
	D[CONST 4] ALU[D&Q] COND[OBUS=0] JUMP[TBRLP] C550 $	;JUMP IF AT LP
	D[CONST 12] ROT[6] DEST[IOD] SPEC[IOB-OUT] 
		NORM PUSHJ[TPRDGO] $
	D[CONST 0] DEST[IR-ADR] PUSHJ[TRP2] NORM $
	ALU[Q] DEST[AC] ACSEL[AC] MAPF[2] JUMP[MAIN] NORM $

TPSETIND:	;Set industry compatable mode
	D[10 + TPMODE] DEST[Q] NORM $	;Stupid A-MEM
	D[CONST 1] ALU[DORQ] DEST[TPMODE] DEST-A-MEM JUMP[MAIN] NORM $
		;Set appropriate bit and done

TPSETDMP:	;Set PDP-10 Dump Mode
	D[10 + TPMODE] DEST[Q] NORM $	;Stupid A-MEM
	D[CONST 1] ALU[-D&Q] DEST[TPMODE] DEST-A-MEM JUMP[MAIN] NORM $
		;Clear industry compatable mode and done.

TAPERS:	;READ STATUS BITS FROM TAPE DRIVE.
	D[CONST 2] ROT[6] DEST[IOD] SPEC[IOB-OUT] 
		NORM $  ;; SELECT THE DRIVE.
	MAPF[2] CYLEN[IOB-OUT] SPEC[IOB-IN] $
	MAPF[4] D[IOD] ROT[18.] MASK[6] DEST[Q] CYLEN[IOB-IN] $
	D[MASK 6] ALU[D#Q] DEST[MEMSTO] NORM
		COND[-MA-AC] LBJUMP[SMAIN] $

TBRLP:	ALU[0] DEST[IOD] SPEC[IOB-OUT] NORM $
	MAPF[6] JUMP[MAIN] CYLEN[IOB-OUT] $


	.PAIR
	UIOTRP[MUUO] $
TAPENR:	;730, AC/COUNT.  READ WHOLE RECORD,
	;STORING UP TO COUNT WORDS STARTING AT EFF ADR.
	;IF AC<>0 RETURN STATUS AS FOR 727.
	;SWAP AC AND MA, THEN DO TAPERX.
	D[MA] DEST[O_AC MA] ACSEL[AC]  NORM JUMP[TAPERX] $ 

	.PAIR
	UIOTRP[MUUO] $
TAPERX:	;732 - (AC) IS START ADDR., E IS # OF WORDS TO READ.
	D[CONST 22] ROT[6] DEST[IOD] SPEC[IOB-OUT] 
		NORM PUSHJ[TPRDGO] $ ;GET TAPE STARTED.
	ALU[AC] ACSEL[AC] DEST[MA] PUSHJ[TRP2] NORM $ ;READ REC.
		;MOVE STATUS INTO AC.
	D[IR] COND[-OBUS18] JUMP[TNRP3] C550 $ ; WAS RECORD TOO LONG ?
	D[CONST 44] ROT[30.] ALU[DORQ] DEST[Q] NORM $ ;YES, SET BIT 3.
TNRP3:	ALU[Q] DEST[AC] ACSEL[AC] JPOP[MAIN] NORM $  ;NO, NOT TOO LONG.


UTAPWR:	UIOTRP[MUUO] $
	D[CONST 2] ROT[6] DEST[IOD] SPEC[IOB-OUT] NORM JUMP[TAPEWR] $
		;Copy of thing in dispatch
TAPEWR:	;731, AC/ADR, E/+COUNT.  WRITE RECORD OF +COUNT
	; WORDS, DATA FROM ADR.
	;SET AC:=0 IF OPERATION COMPLETED SUCCESSFULLY.
	; SET AC:=<SETZ> + HIGHEST -10 ADR READ IF REACHED
	; EOT DURING OPERATION (CURRENTLY THIS IS THE ONLY
	; ERROR CONDITION.)

	ALU[0] DEST[AR] SPEC[IOB-IN] MAPF[2] CYLEN[IOB-OUT] 
	  PUSHJ[TPBOTD] $ ;GET 3.5 IN. DLY CNT IN AR IFF AT BOT
	D[MA] MASK[1] ALU[NOTD] DEST[6] DEST-A-MEM NORM $ ;SAVE LSB OF WC

 ;### AR HOLDING GOOD STUFF BETWEEN HERE AND TPWR2. #############

TWEOF:	;CLEAR FLAG WHICH WHEN DONE WILL SAY IF PASSED PHYSICAL EOT.
	ALU[0] DEST[5] DEST-A-MEM NORM $

	;TP WR CLK:=-97.
	D[CONST 76] ROT[24] DEST[Q] SHORT $
	D[CONST 37] ROT[16] ALU[DORQ] DEST[Q] NORM $
	D[CONST 1] ROT[41] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] NORM $

	;-CTL WD SEL:=1,1; DISABLE TP I WARS
	D[CONST 3] ROT[35. - 5] DEST[Q] MAPF[1] CYLEN[IOB-OUT] $
	D[CONST 1] ROT[35. - 26.] ALU[DORQ] DEST[4] DEST-A-MEM NORM $
	D[14] DEST[IOD] SPEC[IOB-OUT] NORM $
			MAPF[4] CYLEN[IOB-OUT] $
	;SEND TP MR, TP CLEAR LPCC
	D[CONST 1] ROT[40] DEST[Q] NORM $
	D[CONST 1] ROT[32] ALU[DORQ] DEST[IOD] SPEC[IOB-OUT] NORM $
			MAPF[1] CYLEN[IOB-OUT] $
	;SET SWS, SLT.
	D[CONST 3] ROT[6] DEST[IOD] SPEC[IOB-OUT] NORM $
	;SET SFC, SWS, SLT.
	MAPF[2] D[CONST 23] ROT[6] DEST[IOD] SPEC[IOB-OUT] CYLEN[IOB-OUT] $
	MAPF[2] CYLEN[IOB-OUT] D[CONST TP-WR-STRT-DLY] ROT[9.] DEST[Q] $ ;GET 10.1MSEC DLY

;#######  SEE ABOVE NOTE ABOUT AR ###############################

TPWR2:	D[AR] ALU[D+Q] DEST[AR] SHORT $ ;GET TOTAL DELAY
	;SPACE OVER GAP (10.1 MSEC, + ABOUT .077 SEC IFF AT BOT)
	 ;IF FOLLOWING CYLEN IS MADE 1000, DMA XFERS LOSE.
 	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[.] C550 $
	;START WRITE CLOCK.
	D[14] DEST[Q] SHORT $
	D[CONST 3] ROT[35. - 10.]  ALU[DORQ] DEST[4] DEST-A-MEM NORM $
	D[14] DEST[IOD] SPEC[IOB-OUT] NORM $
	D[MA] MASK[18.] DEST[AR]  MAPF[4] CYLEN[IOB-OUT]
		COND[OBUS=0] JUMP[TWEOF1] $ ;WRT FILE MARK ESCAPE
	;NEXT WORD.  AR:=+COUNT, AC:=ADR.
TWNW:	ALU[AC] ACSEL[AC] DEST[MA] NORM $
	NORM $ ;WAIT FOR FIRST MEMORY FETCH.
TWNWL:	D[MEM] ROT[8] DEST[Q] PUSHJ[TWBYTE] NORM $
	D[MEM] ROT[20] DEST[Q] PUSHJ[TWBYTE] NORM $
	D[MEM] ROT[30] DEST[Q] PUSHJ[TWBYTE] NORM $
	D[10 + TPMODE] MASK[1] C550 COND[-OBUS=0] JUMP[TWNWI] $
		;Check for industry compatable mode while we have time.
	D[MEM] ROT[40] DEST[Q] PUSHJ[TWBYTE] NORM $
  ;Write last byte of PDP-10 dump mode and decide what's left to do.
	D[MEM] MASK[4] DEST[Q] PUSHJ[TWBYTE] NORM $
	ALU[AC+1] ACSEL[AC] DEST[AC MA] SHORT $
	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[TWNWL] C600 $
   ;DONE. WRITE A BLANK FRAME.
	D[CONST 1] DEST[AR] NORM PUSHJ[TWDLY] $
    ;PREPARE TO WRITE CRCC BYTE.
	D[CONST 50] DEST[Q] SPEC[IOB-IN] NORM JUMP[TWNW1X] $ ;GET CRCC BYTE
;Write last byte of industry compatable mode and decide what's left to do.
TWNWI:	D[MEM] ROT[40] DEST[Q] PUSHJ[TWBYTE] NORM $
		;Write byte 4, the last byte in this mode
	ALU[AC+1] ACSEL[AC] DEST[AC MA] SHORT $
	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[TWNWL] C600 $
   ;DONE. WRITE A BLANK FRAME.
	D[CONST 1] DEST[AR] NORM PUSHJ[TWDLY] $
	D[CONST 50] DEST[Q] SPEC[IOB-IN] NORM $ ;GET CRCC BYTE
;Previous three lines are same as normal mode and are included separately for
;speed considerations.
TWNW1X:	MAPF[2] D[IOD] ROT[8] MASK[8] ; ...AND COMP. CERTAIN BITS.
	  ALU[D/#Q] DEST[HOLD] CYLEN[IOB-IN] $ 
	D[CONST 2] DEST[AR] NORM PUSHJ[TWDLY] $
	  ;WRITE 2 MORE BLANK FRAMES.
	D[MEM] DEST[Q] NORM $
	D[16] MASK[1] DEST[AR] NORM $
	D[AR] ROT[43] ALU[-D&Q] DEST[IOD] ;IF WC WAS ODD, WRITE THE
	  SPEC[IOB-IN] NORM PUSHJ[TWBYT1] $ ; CRCC WITH EVEN PAR.
	;WAIT 3 BYTE TIMES, SEND WARS TO WRITE LPCC.
	D[CONST 3] DEST[AR] PUSHJ[TWDLY] $
TWEOFX:	D[14] DEST[Q] SHORT $ ;PREPARE TO SEND WARS.
	D[CONST 1] ROT[11] ALU[-D&Q] DEST[IOD] SPEC[IOB-OUT] NORM $
	;CLEAR TP WR CLK RUN, WARS.
TWEXIT:	D[14] DEST[Q] MAPF[4] CYLEN[IOB-OUT] $	;WARS ON.
	D[CONST 1] ROT[10] ALU[DORQ] DEST[Q] SHORT $
	D[CONST 1] ROT[32] ALU[-D&Q] DEST[4] DEST-A-MEM NORM $
	D[14] DEST[IOD] SPEC[IOB-OUT] SHORT $
	MAPF[4] SPEC[IOB-IN] CYLEN[IOB-OUT] $	;WARS OFF, WIDTH SHORT + NORM + SHORT +IOB-OUT = 2.0US.
	;CHECK TO SEE IF REACHED EOT.
	D[IOD] DEST[Q] MAPF[4] CYLEN[IOB-IN] $
	D[CONST 1] ROT[18.] ALU[D&Q] COND[-OBUS=0] JUMP[TWEX1] $
	ALU[-1] DEST[5] NORM DEST-A-MEM $	;YES, SET FLAG.
TWEX1:	D[MA] MASK[18.] 	COND[OBUS=0] C550 JUMP[TWEOF2] $ ;WRT FILE MARK ESCAPE
	D[15] DEST[AC] ACSEL[AC] NORM $
TWEOF2:	 ;NOW DELAY FOR 7071 CYCLES (*C550 = 3.89MS = .175" OF TAPE).
	D[CONST 67] ROT[7] DEST[AR] NORM $
	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[.] C550 $

	;CLEAR SWS, DESELECT TAPE, STOP MOTION.
	JUMP[TBRLP] $


    ;TAPEWR&TWBYTE.  WRITE BYTE IN Q.
TWBYTE:	D[MASK 8] ALU[D&Q] DEST[IOD] SPEC[IOB-IN] NORM $
TWBYT1:	D[IOD] DEST[Q] MAPF[4] CYLEN[IOB-IN] SPEC[IOB-OUT] $
	D[CONST 1] ROT[18.] ALU[D&Q] COND[OBUS=0] MAPF[14] JUMP[TWEOT] SPEC[IOB-IN] CYLEN[IOB-OUT] $
TWBLP:	D[IOD] ROT[21.] DEST[Q] MAPF[2] CYLEN[IOB-IN] $
	ALU[Q] -OBUS<0 C600 POPJ $
	C550 $
TWBLP1:	SPEC[IOB-IN] NORM JUMP[TWBLP] $

	;EOT DETECTED, SET FLAG AND CONTINUE.
TWEOT:	ALU[-1] DEST[5] DEST-A-MEM JUMP[TWBLP1] NORM $

TWEOF1:	D[CONST 23] DEST[Q] NORM $ ;23 IS FILE MARK CHAR.
	D[CONST 1] ROT[43] ALU[DORQ] DEST[IOD]  ;SET BIT 0 IN ORDER TO
	 SPEC[IOB-IN] NORM PUSHJ[TWBYT1] $ ;WRITE IT WITH EVEN PARITY.
	D[CONST 7] DEST[AR] PUSHJ[TWDLY] NORM $ ;SKIP 7 FRAMES.
	NORM JUMP[TWEOFX] $ ;COMPLETE THE RECORD AS USUAL.

    ;TAPEWR&TWDLY.  WRITE EVEN PARITY 0S UNTIL TP BYTE DAT COMES ON C(AR) TIMES
TWDLY:	D[CONST 1] ROT[43] DEST[IOD] SPEC[IOB-OUT] NORM $
	PUSHJ[TWBLP] MAPF[14] SPEC[IOB-IN] CYLEN[IOB-OUT] $
	D[AR] ALU[D-1] DEST[AR] COND[-OBUS=0] JUMP[TWDLY] C600 $
	POPJ NORM $

;BOOTSTRAP LOADER FOR MACROCODE.

	.ORG[5000]
MBOOT:	JUMP[5001] CYLEN[LONG] $
	ALU[0] DEST[HI-ABS-MA] PUSHJ[CCLR] NORM $
	D[CONST 1] ROT[18.] DEST[HI-ABS-MA] PUSHJ[CCLR] NORM $
	D[CONST 7] DEST[DEV-ADR] CYLEN[LONG] $
		;SELECT DEVICE 7.
	D[CONST 22] ROT[6] DEST[IOD] SPEC[IOB-OUT]
	   NORM PUSHJ[TPRDGO] $  ;SET "SELECT" AND "FORWARD MOTION"
	ALU[0] DEST[MA HI-ABS-MA] NORM PUSHJ[B3] $
	 ;MAKE MA RIGHT AND GET FIRST BYTE.
	NORM JUMP[P2A] $
P2:	PUSHJ[BYTE] NORM $
P2A:	D[MEM] ROT[34] DEST[Q] PUSHJ[BYTE] NORM $
	D[MEM] ROT[24] ALU[DORQ] DEST[Q] PUSHJ[BYTE] NORM $
	D[MEM] ROT[14] ALU[DORQ] DEST[Q] PUSHJ[BYTE] NORM $
	D[MEM] ROT[4] ALU[DORQ] DEST[Q] PUSHJ[BYTE] NORM $
	D[MEM] MASK[4]  ALU[DORQ] DEST[MEMSTO] NORM $
	D[MA] ALU[D+1] DEST[MA] JUMP[P2] NORM $
CCLR:	ALU[0] DEST[MA] NORM $
	ALU[0] DEST[MEMSTO] NORM $
	D[MA] ALU[D+1] DEST[MA] NORM $
	D[MA] MASK[18.] COND[-OBUS=0] JUMP[. - 2] C600 $
	POPJ NORM $

BYTE:	D[CONST TP-MBOOT-GAP-DLY] LLOAD NORM $
B2:	SPEC[IOB-IN] LOOP[B1] C550 $
	D[CONST 10] ROT[6] LLOAD CYLEN[LONG] $
	LOOP[.] CYLEN[LONG] $
	SPEC[IOB-IN] CYLEN[LONG] $
	MAPF[1] D[AR] ROT[43] MASK[21]
		COND[OBUS=0] JUMP[DONE] CYLEN[LONG] $
B5:	SPEC[IOB-IN] D[CONST 0] DEST[AR] NORM $
	MAPF[2] D[IOD] ALU[NOTD] DEST[HOLD] CYLEN[C800] $
	D[MEM] ROT[33] MASK[1] COND[-OBUS=0] JUMP[B5] C550 $
	JUMP[B3] NORM $
B1:	D[IOD] ALU[NOTD] DEST[HOLD] MAPF[2] CYLEN[LONG] $
	D[MEM] ROT[33] MASK[1] COND[-OBUS=0] JUMP[B2] C550 $
B3:	SPEC[IOB-IN] D[AR] ALU[D+1] DEST[AR] NORM $
	MAPF[2] SPEC[IOB-IN] D[IOD] ALU[NOTD] DEST[HOLD] C800 $
	MAPF[1] D[MEM] ROT[31] C550
	   OBUS<0 JUMP[MBERR] $ ;TEST FOR GOOD PARITY IN BYTE.
	D[MEM] MASK[10] DEST[HOLD] POPJ NORM $

MBERR:	JUMP[DONE] $ ;;D[CONST 0] DEST[MA] NORM JUMP[DONE] $

DONE:	D[CONST 0] DEST[IOD] SPEC[IOB-OUT] CYLEN[LONG] $
.REPEAT 1 - STANSW [
D1:	MAPF[2] D[CONST 0] DEST[DEV-ADR] SPEC[IOB-IN] CYLEN[LONG] $
	   ;CHECK START AND CONT SWITCHES.  RD NEXT FILE ON CONT
	MAPF[4] D[IOD] ROT[5] MASK[2] DEST[AR]
		COND[OBUS=0] JUMP[D1] CYLEN[LONG] $
	   ;  ... START MAIN MICROCODE ON START SWITCH.
	D[AR] MASK[1] COND[-OBUS=0] JUMP[MSTART] C550 $
	SPEC[IOB-OUT] NORM $
	MAPF[4] JUMP[MBOOT] CYLEN[LONG] $
];.REPEAT 1 - STANSW
.REPEAT STANSW [
	MAPF[2] D[CONST 0] DEST[DEV-ADR] SPEC[IOB-IN] CYLEN[LONG] $
	   ;CHECK START AND CONT SWITCHES.  RD NEXT FILE ON CONT
	MAPF[4] D[IOD] DEST[AR]	SPEC[IOB-OUT] LONG $
		;Fetch switches.  Clear old ones
	MAPF[4]	SWTEST[3 JUMP NOAUTO] $
		;STOP - Don't auto-load
	D[CONST (120 / 2)] ROT[1] DEST[MA] $
		;Fetch starting address
	D[MEM] MASK[22] DEST[PC] jump[mstart] LONG $
		;Set starting address
		;We can't auto-start yet because Reset code isn't a subroutine.
NOAUTO:	MAPF[4]	SWTEST[5 JUMP MSTART] $	;START - Start ucode
	SWTEST[4 JUMP MBOOT] $		;CONT - Read next file on tape
;Nothing happening.  Wait some more.
	D[CONST 0] DEST[DEV-ADR] SPEC[IOB-IN] CYLEN[LONG] $
	   	;Check START and CONT switches.
	MAPF[4] D[IOD] DEST[AR]	SPEC[IOB-OUT] JUMP[NOAUTO] LONG $
		;Fetch switches.  Clear old ones

];.REPEAT STANSW

	.RELOC
] ;END OF SLOW 125 IPS TAPE CODE


.DEFINE FOOLIST[] [ XLIST ]
LIST

