INSERT[DisplayDefs];	*Defs file common to DisplayInit and Display

:TITLE[DisplayInit];	*Last edited by Fiala 28 April 1981

%When started by Initial, various overlays are in core, the next of which
is for CSL keyboard microcode.  If the hardware has a CSL keyboard, the code
below loads the overlay; otherwise, it advances LoadRAM pointers past the
overlay and continues with LF keyboard microcode.  When running with Midas,
no overlays are in core, and the microcode is used as loaded.

The CSLOverlay integer controls assembly of this source to produce the
microcode configuration required.  This same initialization is used for
both LF and CSL keyboard drivers and monitors.
%
*DisplayInitLoc must be odd; DisplayInitLoc to DisplayInitloc+4 are used
**NOTE: These are known to MakeLoaderFile command files.
Set[DpNotifyLoc,Add[DisplayInitLoc,1]];		*7610b must be even
Set[DpContInitLoc,Add[DisplayInitLoc,4]];	*7613
Set[DpOvlSkipLoc,Add[DisplayInitLoc,5]];	*7614

SetTask[DpTask];

*Get here from DeviceInit running at the Display's task level.
DisplayInit:
	vCR ← ClrNC&Blank, At[DisplayInitLoc];	*Clear Nibble counter
*Suspicious that the nibble counter is only cleared when AllowWU is false,
*so do this output twice.
	vSLC ← 104400C, Call[vCRout];	*Start←nibble 44b, ForceAARLoad'←0
	vMDS420 ← 177000C, Call[vCRout];
	Output[vSLC,vBufStart];		**5 mi after Output before PStore4
	T ← vDBuf0 ← IncNC&Blank, Call[vQIni];
	vMDS420 ← (vMDS420) or (30C);
	PStore4[vMDS420,vDBuf0,0];
	vMDS ← 0C;			*vMDS = vZero, so both are initialized
	Input[vTemp,0];			*Controller ID code in bits 10:14b

:IF[CSLOverlay]; *******************************

	T ← 3C;
	LU ← (LdF[vTemp,10,5]) xor T;	*Check for LF keyboard
	vCnt ← LoA[DpOvlSkipLoc], GoTo[.+3,ALU=0];
*Notify LoadRAM at its continue-loading address to read CSL keyboard overlay.
*LoadRAM reenters at DpNotifyLoc.
***RTemp1 (RM 53) has to be EVEN or be made even here, even though it lies
***within the device table manipulated by Initialize.  xBuf to xBuf3 are also
***smashed by LoadRAM ????.
	  vCnt ← LoA[LRJContinue];
	  vCnt ← (vCnt) or (HiA[LRJContinue]), Skip;
	vCnt ← (vCnt) or (HiA[DpOvlSkipLoc]);
	APCTask&APC ← vCnt;
vMPRet:
	IncMPanel, Return;

SetTask[0];
	T ← xfTemp, At[DpOvlSkipLoc];	*Skip CSL keyboard overlay
vSkpOv:	PFetch1[LP,RTemp], Task;
	T ← 170000C;
	LU ← (LdF[RTemp,0,14]) xnor T;	*Check address .eq. 7777b
	T ← xfTemp ← (xfTemp) + (3C), GoTo[vSkpOv,ALU#0];

*CSL ucode has been skipped or loaded.  Notify display task to continue init.
	RTemp ← LoA[DpContInitLoc], At[DpNotifyLoc];
	RTemp ← (RTemp) or (HiA[DpContInitLoc,DpTask]);
	APCTask&APC ← RTemp, Call[vMPRet];
*Next time emulator runs, it begins here--pass control back to DeviceInit.
	LoadPage[InitPage];
	T ← xCNT, GoToP[DI6];

SetTask[DpTask];
:ENDIF; ****************************************

	vDBuf0 ← 40000C, At[DpContInitLoc];	*to load AAR
	vCR ← IncNC&Blank, Call[vNClk];	*Increment NClk bit; generate NClk
***Don't know why next mi is useful
	Output[vZero,vHCRam], Call[vNClk];
	Output[vDBuf0,vBufStart];	*ForceAARLoad'←1, ForceIARLoad'←0
	Output[vDBuf0,vLdIAR];
***Pilot code does vDBuf0 ← 140000C; Output[vSLC,vBufStart] here***
	LU ← (vTemp) and (40C);		*vTemp[10:14b] = 3 LF, 5 CSL, or 11 LF
	vDBA ← 44C, GoTo[vLFInit,ALU=0];	*Load HRam, starting at nibble 44

*CSL display HRAM init
	T ← 277C, Call[vOutNClk0];	* 44 - 277 ← 0 (150 up data)
*ML at 150 + (1/2 * (230+46)) - 7 = 300
	vSLC ← 1C, Call[vOutNClk];	*300	   ← 1 (ML)
	T ← 376C, Call[vOutNClk0];	*301 - 376 ← 0 (data)
	vSLC ← 10C, Call[vOutNClk];	*377	   ← 10 (SetC--start blanking)
*46b nibbles of blanking must have 32b words of horizontal sync; the other
*14b nibbles may be blanked either before or after horizontal sync; this
*positions the active image left or right on the screen.
	T ← 4C, Call[vOutNClk0];		*  0 -   4 ← 0 (blank, no sync)
	vSLC ← 4C;
	T ← 36C, Call[vOutNClk];		*  5 -  36 ← 4 (blank, hor. sync)
	T ← 44C, Call[vOutNClk0];	* 37 -  44 ← 0 (blank)
	vMDS177400 ← 177400C, GoTo[vSwiI];

%Since HRam is only 256 bits long, it is necessary to take advantage of the
fact that the Switch bit is ignored unless blanking is in force. On each
scanline, AAR is initialized to vBufSt (150b) and then cycles until SetC
is turned on to start blanking and then until the Switch bit occurs.
Hence, initialization must setup a total line time such that data bits+
blanking bits = 1088+352, where at least 608 of the bits must be data bits
and 352 of bits must be blanked with horizontal sync true; the other 480
bits may be displayed as a constant value or blanked, as chosen, and the
blanked bits may be divided arbitrarily between the left and right parts
of the display.  The code below shows 256 nibbles data, 16 nibbles blanking,
and 88 nibbles horizontal sync.
%
vLFInit:
	vMDS177400 ← 177400C;		*Only for LF keyboard
*This code has the computed parameters for a 50 mhz crystal (i.e.,
*1088-bit forward scan, 352-bit horizontal sync):
	T ← 336C, Call[vOutNClk0];	* 44 - 336 ← 0 (partly redundant)
*ML at 150 + (.5*(416+130)) - 74 = 337
	vSLC ← 1C, Call[vOutNClk];	*337       ← 1 (ML)
	T ← 376C, Call[vOutNClk0];	*340 - 376 ← 0
	vSLC ← 10C, Call[vOutNClk];	*377       ← 10 (SetC)
	T ← 72C, Call[vOutNClk0];	*  0 -  72 ← 0 (blanking--74b)
	vSLC ← 4C;
	T ← 222C, Call[vOutNClk];	* 73 - 222 ← 4 (Hor. sync--130b)
	T ← 316C, Call[vOutNClk0];	*223 - 316 ← 0 (blanking--74b)

%These parameters for a 1024-bit forward scan, 332-bit horizontal sync
(possibly used with 44.5 mhz crystal):
	T ← 335C, Call[vOutNClk0];	* 44 - 335 ← 0 (partly redundant)
*ML = 150 + (400+123)/2 - 64 = 336
	vSLC ← 1C, Call[vOutNClk];	*336       ← 1 (ML)
	T ← 376C, Call[vOutNClk0];	*337 - 376 ← 0
	vSLC ← 10C, Call[vOutNClk];	*377       ← 10 (SetC--start blanking)
	T ← 62C, Call[vOutNClk0];	*  0 -  62 ← 0 (blanking--63b)
	vSLC ← 4C;
	T ← 205C, Call[vOutNClk];	* 63 - 205 ← 4 (Hor. sync--123b)
	T ← 271C, Call[vOutNClk0];	*206 - 271 ← 0 (blanking--64b)
%
vSwiI:	vSLC ← 2C, Call[vOutNClk];	*272       ← 2 (Switch--end blanking)
*Set keyboard words 177030-177043 to -1	(177040-177043 unused by CSL keyboard)
	T ← vDBuf0 ← (Zero) - 1, Call[vQIni];
	vCR ← AllowWU&Blank;
	PStore4[vMDS420,vDBuf0,0];
	PStore4[vMDS420,vDBuf0,4];
	PStore4[vMDS420,vDBuf0,10];
	T ← vMsgStatus ← 0C, Call[vCRout];	*Task sets up loop

%Substitute this code for previous mi to zero pingpong buffers.
*Clear the two ping-pong buffers and block (not needed unless a white area
*is to be shown to the right of the active display)
	vSLC ← 140000C;
	Output[vSLC,vBufStart];		*ForceIARLoad'←ForceAARLoad'←Start←0
	T ← vMsgStatus ← 0C;
	Output[vZero,vLdIAR], Call[vClrBf];	*IAR ← Start
	vButtons ← T, Call[vClrBf];	*This call sets up loop
%
*Clear cursor memory (32 bits/scanline x 32 scan lines) because in Alto
*compatible mode, only 16x16 of the hardware's 32x32 cursor is used.
**NOTE: Blanking must be on here.  The final overlay must not overwrite this
**code until it has finished.
	vSLC ← 6C;			*8 nibbles/scan line
	Output[vMsgStatus,vCursor0];
	vMsgStatus ← (vMsgStatus) + (4C);
	Output[vZero,vCursorMem0];
**Used to have IOStrobe in this mi.
	vSLC ← (vSLC) - 1, GoTo[.-3,R>=0];	*IOStrobe = block
	vMsgStatus ← (vMsgStatus) + (4000C);
	vMsgStatus ← (vMsgStatus) and (174000C), Skip[Carry];
	  vMDS420 ← (vMDS420) or (20C), Return;
*Wind up here with vMsgStatus .eq. 0
	vMDS420 ← 400C, Call[.-1];
	vCR ← AllowWU;
	vKeyBuffer ← T, LoadPage[DisplayPage];
	vButtons ← T, GoToP[vFDone];	*End init

**NOTE: An NClk is produced with an IOFetch4 rather than four Output's so
**that display initialization doesn't defer memory refresh too long; as
**coded, initialization runs about 0.4 msec before tasking.

*SUBROUTINE vNClk generates one NClk.
vNClk:	UseCTask;
	IOFetch4[vMDS420,vfCReg,0], Return;	*vMDS420 holds 177030b here

vCRout:	UseCTask;
	Output[vCR,vCReg], Return;

*SUBROUTINE vOutNClk sends the pattern in vSLC to the HCRam until the
*address = T; does T←T+1 prior to Return for caller.
vOutNClk0:	vSLC ← 0C;
vOutNClk:
	vDBA ← (vDBA) + 1;
	LU ← (RHMask[vDBA]) xor T;
	Output[vSLC,vHCRam], Skip[ALU#0];
	  T ← (Zero) + T + 1, GoTo[vNClk];
	IOFetch4[vMDS420,vfCReg,0], GoTo[vOutNClk];

vQIni:	vDBuf1 ← T;
	vTemp1 ← T, UseCTask;
	vTemp ← T, Return;

%vClrBf:	IOFetch16[vMDS177400,vfBuf0,0];
	IOStrobe;
	IOFetch16[vMDS177400,vfBuf0,0];
	IOFetch16[vMDS177400,vfBuf0,0];
	IOFetch16[vMDS177400,vfBuf0,0], Return;
%

:END[DisplayInit];