:IF[WithCDC]; **********************************
TITLE[CDCTask];*Color Display microcode
*Ed Fiala 1 June 1982
%The color display controller has a 256d-word buffer and consumes 160d
words per 63 (?) microsecond scanline. It does not turn off its wakeup when
cdcTask is running, so only higher priority tasks will intervene on tasking.
It uses up about 27 percent of the machine at 100 ns/cycle and can run at
a very low priority because the 256d-word buffer allows about 100 us of
delay before the buffer goes empty.
The controller microcode loops reading the high part of the data long pointer
once each field until that word becomes non-zero. Then it builds a base
register from the data long pointer, and a partial base register from the
color map long pointer. Both the data and color map long pointers must be
16d-word aligned, and the 60d-word color map must not cross a 64k-word
boundary. Page faults are also verboten.
To stop the controller, first store 0 in the data long pointer and wait
one field time; this ensures that the microcode will be in its idle loop
rather than somewhere else. Then output a 0 to device 0 of cdcTask using
the Output opcode; this will stop wakeups for cdcTask. To restart, output
a 6 to device 0 of cdcTask. This will restart the idle loop running. Then
to show data, first setup the color map long pointer and finally the data
long pointer, being certain to store into the high part of the data long
pointer last.
%
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
*RM Registers
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[cdcDPtr,cdcDPtrHi,cdcCMPtr,cdcCMPtrHi,Add[cdcRB,4]];
RV[cdcScanLineCount,Add[cdcRB,10]];
RV[cdcWordCount,Add[cdcRB,11]];
RV2[cdcMDSLoc,cdcMDSLochi,Add[cdcRB,12]];
:IF[AltoMode]; *********************************
Set[cdcBaseLoc,414];
:ELSE; *****************************************
*By convention the blocks of 20b locations on IOPage (177400b to 177777b)
*are reserved as core locations for tasks 0 to 16b.
Set[cdcBaseLoc,Add[177400,LShift[CDCTask,4]]];*177520b
:ENDIF; ****************************************
*Must turn off CDC before overwriting its microcode.
*Simply use the Mesa Output opcode with TOS = 0,,0,,cdcTask,,0 and 2OS =
*0 to turn off the CDC.
**Used to have here:
*cdcOff:cdcTemp1 ← 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:cdcTemp1 ← 6C, At[cdcInitLoc];
*Clear Sync wakeup, enable Sync wakeup, no data wakeup
:UNLESS[AltoMode]; *****************************
cdcMDSLocHi ← 0C;
:ENDIF; ****************************************
Output[cdcTemp1,cdcCReg];
cdcTemp1 ← 17C;*Interlock the output and
cdcMDSLoc ← HiA[cdcBaseLoc];*wait for wakeup pipe to empty
cdcMDSLoc ← (cdcMDSLoc) or (LoA[cdcBaseLoc]), Call[cdcRTN];
*Wake up here due to sync wakeup (we hope).
Input[cdcTemp,cdcID];*gets FieldA into bit 15
*Fetch the Data and ColorMap (long) pointers from the cdcBaseLoc quadword
*and skip if SyncWakeup.
PFetch4[cdcMDSLoc,cdcDPtr,0], Skip[IOAtten];
GoTo[cdcIni];*should have seen SyncWakeup.
T ← cdcDPtrHi;*check for display on (pointer >64k)
*Convert long pointer to base register format
cdcDPtrHi ← T ← (LSh[cdcDPtrHi,10]) + T + 1, Skip[ALU#0];
GoTo[cdcIni];*display is off
*clear sync wakeup, SWE, DWE, ForceBActive
Output[cdcTemp1,cdcCReg];
*interlock and set up for next output: ForceAActive, SWE, DWE
cdcTemp1 ← 23C;
*cdcDPtrHi ← T ← (FixVA[cdcDPtrHi]) or T;
LU ← cdcTemp, IOStrobe, DblGoTo[cdcFieldA,cdcFieldB,R Odd]; *load the wakeup counter with 0
*Sync wakeups occur at end of field, so FieldB is about to start.
*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.
***Color map must not cross 64k boundary.
cdcFieldA:
cdcCMPtrHi ← LSh[cdcCMPtrHi,10];
cdcScanLineCount ← 356C;*240d scanlines - 2
IOFetch16[cdcCMPtr,cdcBuf,0], Call[cdcIncCMPtr];
IOFetch16[cdcCMPtr,cdcBuf,0], Call[cdcIncCMPtr];
IOFetch16[cdcCMPtr,cdcBuf,0], Call[cdcIncCMPtr];
IOFetch4[cdcCMPtr,cdcBuf,0];
*Offset the data pointer by one scanline (160d words).
cdcDPtr ← (cdcDPtr) + (240C), Call[cdcDPCarry];
IOFetch4[cdcCMPtr,cdcBuf,4], Call[cdcRTN];
IOFetch4[cdcCMPtr,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[cdcDPtr,cdcBuf,0];
cdcDPtr ← (cdcDPtr) + (20C), Call[cdcDPCarry];
cdcScanLineCount ← 357C;*241d scanlines - 2
cdcWordCount ← 7C, GoTo[cdcFieldCommon];
cdcFieldCommon:
Output[cdcTemp1,cdcCReg];*cdcTemp1 ← ForceAActive, SWE, DWE earlier.
cdcTemp ← 3C;*SWE, DWE
Output[cdcTemp,cdcCReg], Call[cdcRTN];
*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. Note that the hardware
*will display about 480.6 lines of data per frame, so the extra scanline
*output here will be only partly shown in one field and not shown at all in
*the other field, but storage has to be underneath it
IOFetch16[cdcDPtr,cdcBuf,0];
cdcWordCount ← (cdcWordCount) - 1, IOStrobe, GoTo[cdcThisSL,R>=0];
cdcScanLineCount ← (cdcScanLineCount) - 1, Skip[R>=0];
GoTo[cdcIni];
cdcWordCount ← 10C;
*Increment base by 160d for interlace + 16d for this IOFetch16.
cdcDPtr ← (cdcDPtr) + (260C), DblGoTo[cdcDPCarry,.+2,IOAtten’];
cdcThisSL:
cdcDPtr ← (cdcDPtr) + (20C), Skip[IOAtten’];
GoTo[cdcIni];*Premature end of field
cdcDPCarry:
Skip[Carry’];
cdcDPtrHi ← (cdcDPtrHi) + (400C) + 1;*64k boundary
cdcRTN:cdcTemp ← cdcTemp, Return;*Interlock Output at cdcFieldCommon+2
cdcIncCMPtr:
cdcCMPtr ← (cdcCMPtr) + (20C), Return;
END[CDCTask];
:ELSE; *****************************************
TITLE[No.color.display.microcode];
:ENDIF; ****************************************