{ File name: Raven.mc Description: Raven LSEP (Low Speed Electronic Printer) microcode Author: Pitts Jarvis, Created: March 14, 1980, Last Edited: Jarvis, November 25, 1980 2:14 PM Olmstead, March 23, 1981 5:25 PM: Remove some unneeded CANCELBR's Garner, July 30, 1981 11:51 PM: added ClrDPRq & PCtl← after endBand so that hardware fix to allow slower LSEP's works. (Note that the click at endBand can be eliminated if the click before uses nibCarry.) BJackson, 16-Nov-85 19:10:07: Cleanup tabs, etc. Fiala, 24-Jul-86 10:50:46 Initialize displayBase0 and displayBase2 from the constant cedarIOPageHigh instead of from the rh of uIOPage. Also add 1 to the values for WakeupMaskOffset here and PrinterOverrunOffsetM1 and PrinterRunOffset in NewDandelion.dfn because the value in uIOPage is 1 less. } { Printer Control register on X-Bus ~ClearLineActive 8 Inhibits data wakeups and forces video to all white until next line sync ForceRequest 4 forces printer wakeups every round VideoWhite 2 forces video to white EnablePrinter 1 enables printer and memory refresh task wakeups } Set[EndActiveScanCtl, 1]; Set[EndBandScanCtl, 5]; Set[StartScanCtl, 9]; Set[StartActiveCtl, 0B]; { Raven CSB (read once per page, immediately after code detects run#0) run non-zero=> index of 1st band record (displayBase0 relative), read then zeroed overrun non-zero=> over ran band buffer interruptMask Mesa process stuff bandSize number of lines in a band active scan number of words in line buffer actually sent to printer line size number of words in line buffer tab number of words skipped from line sync before sending image to printer scans number of blank lines sent to printer at start of page } { Raven band record pointer real address of band (displayBase1 relative) next index of next band record (displayBase0 relative) status 0=> empty, #0=> full, <0=> last band } SetTask[1]; StartAddress[PrinterInit]; PrinterInit: displayBase1 ← 0 {band buffer in first 64K}, CancelDisp[$] ,c1; PrinterInitC2: displayBase0 ← cedarIOPageHigh, c2; rD0 ← uIOPage, c3; pageGap: MAR← [displayBase0, rD0 + PrinterRunOffset] ,c1; {wait for non-zero run} MDR← 0, CancelPgCross[$, 0], LOOPHOLE[wok] ,c2; {. . . clear it immediately} rD1← MD ,c3; uThis← rD1, ZeroBr ,c1; rD1← 0A, BRANCH[startPage, $] ,c2; {rD1← AltUaddr index} PCtl← EndActiveScanCtl, GOTO[pageGap] ,c3; startPage: Noop ,c3; rD0 ← MAR ← [displayBase0, rD0 + PrinterOverrunOffsetM1 + 1] ,c1; {clear overrun} MDR ← 0, CancelPgCross[$, 0], LOOPHOLE[wok] ,c2; Noop ,c3; loadParam: MAR← [displayBase0, rD0+1], rD0← rD0+1 ,c1; {load parameters} uScans← rD0, CancelPgCross[$] ,c2; rD0← MD ,c3; Ybus← rD1, rD1← rD1+1, NibCarryBr, AltUaddr ,c1; uyParamBase← rD0, BRANCH[$, skipLines] ,c2; rD0← uScans, GOTO[loadParam] ,c3; skipLines: rD0← rD0-1, ZeroBr ,c3; {loaded uScans last} BRANCH[$, firstBand] ,c1; PCtl← EndActiveScanCtl, GOTO[skipLines] ,c2; firstBand: rD0← uThis ,c2; rD1← 1 ,c3; {not last band} advanceBand: MAR← [displayBase0, rD0], rD0← rD0+1, ClrDPRq ,c1; []← rD1, NegBr, CancelPgCross[$] ,c2; {test for last band} rD1← MD, BRANCH[$, lastBandDone] ,c3; {pointer to band} MAR← [displayBase0, rD0], rD0← rD0+1, ClrDPRq ,c1; uLineAddress← rD1, CancelPgCross[$] ,c2; rD1← MD ,c3; {next band} MAR← [displayBase0, rD0], uBandStatus← rD0, ClrDPRq ,c1; {save address for later} uThis← rD1, CancelPgCross[$] ,c2; rD1← MD ,c3; {status of this band} []← rD1, ZeroBr ,c1; rD1← uLineAddress, BRANCH[$, RavenOverrun], ClrDPRq ,c2; rD0← uBandSize ,c3; uLineCount← rD0, ClrDPRq ,c1; rD0← uTabCnt ,c2; rD0← rD0-4, GOTO[startLine1] ,c3; {4 click band overhead} startLine: PCtl← EndActiveScanCtl ,c1; rD0← uLineSize, ClrDPRq ,c2; rD1← uLineAddress ,c3; rD1← rD1+rD0, ClrDPRq ,c1; {line sync wakeup} PCtl← StartScanCtl ,c2; rD0← uTabCnt ,c3; {Enter from advanceBand or startLine. At this point rD0 has uTabCnt, rD1 has uLineAddress} startLine1: uLineAddress← rD1, ClrDPRq ,c1; Noop ,c2; Noop ,c3; idle: rD0← rD0-1, ZeroBr ,c1; {tab over to active area} BRANCH[$, startActive], ClrDPRq ,c2; GOTO[idle] ,c3; startActive: PCtl← StartActiveCtl ,c3; scan: MAR← [displayBase1, rD1+0], ClrDPRq ,c1; MDR← rD0{= zero}, rD1← rD1+1, PgCarryBr ,c2; POData← MD, BRANCH[scan, endLine] ,c3; endLine: rD1← uLineCount, ClrDPRq ,c1; {play out last word} rD1← rD1-1, ZeroBr ,c2; uLineCount← rD1, BRANCH[startLine, endBand] ,c3; endBand: ClrDPRq ,c1; PCtl← EndBandScanCtl ,c2; rD0← uBandStatus ,c3; MAR← [displayBase0, rD0+0] ,c1; {mark band empty} MDR← rD1 ,c2; {. . . and get next band} rD1← MD ,c3; {negative=> last band} {initiate band complete interrupt} rD0← uWP ,c1; rD0← uInterruptMask or rD0, MesaIntRq ,c2; uWP← rD0 ,c3; rD0← uThis ,c1; endBand1: Noop ,c2; PCtl← EndActiveScanCtl, GOTO[advanceBand] ,c3; {save old status for test} lastBandDone: PCtl← EndActiveScanCtl, GOTO[PrinterInitC2] ,c1; RavenOverrun: rD0 ← uIOPage ,c3; MAR← [displayBase0, rD0 + PrinterOverrunOffsetM1 + 1] ,c1; {set overrun} rD1 ← MDR ← 1, CancelPgCross[$, 0], LOOPHOLE[wok] ,c2; {. . . and not last band} rD0← uBandStatus ,c3; rD0← rD0-2, GOTO[endBand1] ,c1; {retry this band again} {Memory Refresh Task} SetTask[3]; StartAddress[RefreshGo]; Set[WakeupMaskOffset, 0EB]; {added to uIOPage=(0)4000} Set[HalfFieldSize, 0E0]; RefreshGo: uClockBits ← 0, CancelDisp[$] ,c1; displayBase2 ← cedarIOPageHigh, c2; RefreshField: rD2 ← uIOPage, c3; MAR ← [displayBase2, rD2 + WakeupMaskOffset] ,c1; Noop, CancelPgCross[$, 0] ,c2; rD2 ← MD ,c3; uPWakeup ← rD2 ,c1; {***Maybe bum 1 click here with: rD2 ← uWP or rD2, MesaIntRq, c2; uWP ← rD2, c3; } Noop ,c2; Noop ,c3; {This code looks this way because uWP must be updated within one click.} rD2 ← uWP ,c1; rD2 ← uPWakeup or rD2, MesaIntRq ,c2; uWP ← rD2 ,c3; rD2 ← LShift1 HalfFieldSize ,c1; uRefreshLine ← rD2 ,c2; ClrRefRq ,c3; Refresh: rD2 ← uClockLow, Refresh ,c1; rD2 ← rD2 + 1, CarryBr ,c2; uRefreshTemp ← rD2, BRANCH[$, RefreshCarry] ,c3; Refresh ,c1; Noop ,c2; Refresh1: uClockLow ← rD2 ,c3; rD2 ← uRefreshLine, ZeroBr ,c1; rD2 ← rD2 - 1, BRANCH[$, RefreshField] ,c2; uRefreshLine ← rD2, ClrRefRq, GOTO[Refresh] ,c3; RefreshCarry: rD2 ← uClockHigh, Refresh ,c1; rD2 ← rD2 + 1 ,c2; Noop ,c3; uClockHigh ← rD2 ,c1; rD2 ← uRefreshTemp, GOTO[Refresh1] ,c2;