:TITLE[CdcTask];*Microcode for Color Display

SETTASK[cdcTask];

*Output Registers
SET[cdcCReg,0]; *Control register
SET[cdcBuf,ADD[LSHIFT[cdcTask,4],1]]; *Data buffer - use with IOFetch
*Input Register
SET[cdcID,0];

*R Regsters
SET[cdcRB,LSHIFT[AND[cdcTask,3],4]]; *enforces register allocation conventions

RV[cdcTemp,ADD[cdcRB,0]];
RV[cdcTemp1,ADD[cdcRB,1]];

RV[cdcDataPointer,ADD[cdcRB,4]]; *Long pointer to bitmap
RV[cdcDataPointer1,ADD[cdcRB,5]];
RV[cdcCMPointer,ADD[cdcRB,6]]; *Long pointer to color map data (60d words)
RV[cdcCMPointer1,ADD[cdcRB,7]];

RV[cdcScanLineCount,ADD[cdcRB,10]];
RV[cdcWordCount,ADD[cdcRB,11]];
RV[cdcMDS,76]; *contains 400 (initialized elsewhere)
RV[cdcMDShi,77]; *contains MDShi (initialized elsewhere)


ONPAGE[ColorDisplayPage];


*Get here 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.

cdcInit:
cdcTemp ← 6c, AT[cdcInitLoc]; *Clear Sync wakeup, enable Sync wakeup, no data wakeup
Output[cdcTemp, cdcCReg];
cdcTemp ← cdcTemp; *interlock the output
nop; *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
T ← 14c, skip[IOAtten]; *skips if SyncWakeup
goto[cdcInit]; *should have seen SyncWakeup.
PFetch4[cdcMDS,cdcDataPointer]; *Fetch the Data and ColorMap (long) pointers from 414b - 417b.
T ← cdcDataPointer1; *check for display on (pointer >64k)
cdcTemp1 ← 17c, skip[alu#0]; *clear sync wakeup, SWE, DWE, ForceBActive
goto[cdcInit]; *display is off
Output[cdcTemp1,cdcCReg];
cdcDataPointer1 ← T ← (lsh[cdcDataPointer1,10]) + (T) + 1; *long data pointer to base register
cdcDataPointer1 ← T ← (fixVA[cdcDataPointer1]) or (T);
cdcTemp1 ← 23c; *interlock and set up for next output: ForceAActive, SWE, DWE
lu ← cdcTemp, dblgoto[cdcFieldA,cdcFieldB, ROdd], IOStrobe; *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;
cdcCMPointer1 ← T ← (lsh[cdcCMPointer1,10]) + (T) + 1; *convert long pointer to base register
cdcCMPointer1 ← (fixVA[cdcCMPointer1]) or (T);
cdcDataPointer ← (cdcDataPointer) + (240c); *data must be placed so that this doesn’t carry
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
call[.+1];
cdcDataLoop:
IOFetch16[cdcDataPointer,cdcBuf,0];
cdcDataPointer ← (cdcDataPointer) + (20c), skip[NoAtten];
goto[cdcInit]; *Field ended prematurely
IOStrobe, skip[NoCarry];
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[cdcInit]; *end of field
cdcDataPointer ← (cdcDataPointer) + (240c); *Increment base by 160d for interlace
cdcWordCount ← 10c, skip[NoCarry];
cdcDataPointer1 ← (cdcDataPointer1) + (400c) + 1; *64K boundary
return;


cdcIncCMPtr:
cdcCMPointer ← (cdcCMPointer) + (20c), return;

:END[CdcTask];