:TITLE[CDCTask];	*Microcode for Color Display
			*Last edited: 16 January 1981 by Fiala

SetTask[cdcTask];

*Output Registers
Set[cdcCReg,0];				*Control register
Set[cdcBuf,Add[LShift[cdcTask,4],1]];	*Data buffer - use with IOFetch

Set[cdcID,0];				*Input register

*R Regsters
Set[cdcRB,LShift[And[cdcTask,3],4]];	*Enforce reg alloc convention

RV[cdcTemp,Add[cdcRB,0]];
RV[cdcTemp1,Add[cdcRB,1]];
*Long pointer to bitmap & to color map data (60d words)
RV4[cdcDataPointer,cdcDataPointer1,cdcCMPointer,cdcCMPointer1,Add[cdcRB,4]];
RV[cdcScanLineCount,Add[cdcRB,10]];
RV[cdcWordCount,Add[cdcRB,11]];
RV2[cdcMDS400,cdcMDS400hi,Add[cdcRB,12]];

*Must turn off CDC before overwriting its microcode.
cdcOff:	cdcTemp ← 0C, Skip, At[cdcOffLoc];

*Get to cdcIni during device initialization, or when the display has finished 
*sending all words for a field.  Disable the data wakeup request, and wait
*for the sync wakeup.

cdcIni:	cdcTemp ← 6C, At[cdcInitLoc];
*Clear Sync wakeup, enable Sync wakeup, no data wakeup
	Output[cdcTemp,cdcCReg];
	cdcTemp ← cdcTemp;		*interlock the output
	cdcMDS400 ← 400C;		*wait for the wakeup pipe to empty
	Call[cdcRTN];

*Wake up here due to sync wakeup (we hope).
	Input[cdcTemp,cdcID];		*gets FieldA into bit 15
	cdcTemp1 ← 17C, Skip[IOAtten];	*Skips if SyncWakeup
	  Goto[cdcIni];			*should have seen SyncWakeup.
*Fetch the Data and ColorMap (long) pointers from 414b - 417b.
	PFetch4[cdcMDS400,cdcDataPointer,14];
	T ← cdcDataPointer1;		*check for display on (pointer >64k)
	cdcDataPointer1 ← T ← (Lsh[cdcDataPointer1,10]) + T + 1, Skip[ALU#0];
	  Goto[cdcIni];			*display is off
*clear sync wakeup, SWE, DWE, ForceBActive
	Output[cdcTemp1,cdcCReg];
	cdcTemp1 ← 23C;
*long data pointer to base register
	cdcDataPointer1 ← T ← (FixVA[cdcDataPointer1]) or T;
*interlock and set up for next output: ForceAActive, SWE, DWE
	LU ← cdcTemp, IOStrobe, DblGoto[cdcFieldA,cdcFieldB,R Odd]; *load the wakeup counter with 0

*Sync wakeups occur at the end of the field, so FieldB is about to start.
*We will load the color map, and add 160d (one scan line) to the Data address.
*We cleared the wakeup request counter here, and will not increment it.  We are writing bufferA,
*and when we switch to sending data to buffer B, the wakeup counter will be zero.
cdcFieldA:
	T ← cdcCMPointer1;
*convert long pointer to base register
	cdcCMPointer1 ← T ← (Lsh[cdcCMPointer1,10]) + T + 1;
	cdcCMPointer1 ← (FixVA[cdcCMPointer1]) or T;
*data must be placed so that this doesn't carry
	cdcDataPointer ← (cdcDataPointer) +  (240C);
	IOFetch16[cdcCMPointer,cdcBuf,0], Call[cdcIncCMPtr];
	IOFetch16[cdcCMPointer,cdcBuf,0], Call[cdcIncCMPtr];
	IOFetch16[cdcCMPointer,cdcBuf,0], Call[cdcIncCMPtr];
	IOFetch4[cdcCMPointer,cdcBuf,0], Call[cdcRTN];
	IOFetch4[cdcCMPointer,cdcBuf,4], Call[cdcRTN];
	IOFetch4[cdcCMPointer,cdcBuf,10];
	cdcWordCount ← 10C, Goto[cdcFieldCommon];

*FieldA is about to start.
*We will write 16 words into buffer A, then switch to buffer B and fill it.
cdcFieldB:
	IOFetch16[cdcDataPointer,cdcBuf,0];
	cdcDataPointer ← (cdcDataPointer) + (20C), Call[cdcRTN];
	cdcWordCount ← 7C;

cdcFieldCommon:
	Output[cdcTemp1,cdcCReg];	*cdcTemp1 ← ForceAActive, SWE, DWE earlier.
	cdcTemp ← 3C;			*SWE, DWE
	Output[cdcTemp,cdcCReg]; 
*We are now set up to write into buffer A.  Buffer B has been loaded with the
*color map data or with the first 16 words of the first scan line, depending
*on the field.  Pump out the rest of the field.
	cdcScanLineCount ← 357C, Call[cdcRTN];	*240d - 1
cdcDataLoop:
	IOFetch16[cdcDataPointer,cdcBuf,0];
	cdcDataPointer ← (cdcDataPointer) + (20C), Skip[IOAtten'];
	  Goto[cdcIni];			*Field ended prematurely
	IOStrobe, Skip[Carry'];
	  cdcDataPointer1 ← (cdcDataPointer1) + (400C) + 1;	*64k boundary crossed
	cdcWordCount ← (cdcWordCount) - 1, Skip[R<0];
cdcRTN:	  cdcTemp ← cdcTemp, Return;	*interlock Output at cdcFieldCommon+2
	cdcScanLineCount ← (cdcScanLineCount) - 1, Skip[R>=0];
	  Goto[cdcIni];		*end of field
	cdcDataPointer ← (cdcDataPointer) + (240C);	*Increment base by 160d for interlace
	cdcWordCount ← 10C, Skip[Carry'];
	  cdcDataPointer1 ← (cdcDataPointer1) + (400C) + 1; *64K boundary
	Return;


cdcIncCMPtr:
	cdcCMPointer ← (cdcCMPointer) + (20C), Return;

:END[CDCTask];