-- UserTerminalHeadD0.mesa -- Last Edited by: Taft, February 27, 1983 3:27 pm DIRECTORY BitBlt USING [BBTable], D0InputOutput USING [ ControllerNumber, ControllerType, GetNextController, Input, null, nullControllerNumber, uibScb, utvfc], DeviceCleanup USING [Await, Item, Reason], DisplayFace USING [Background, Cursor, CursorPtr, GlobalStatePtr, Point], DisplayFaceExtras USING [FieldRate, MonitorType], Environment USING [bitsPerWord, first64K, PageCount, PageNumber, wordsPerPage], HeadStartChain USING [Start], Inline USING [BITOR, LongMult, LowHalf], KeyboardFace USING [], KeyStations USING [KeyBits], MouseFace USING [Buttons, Point], ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses], RuntimeInternal USING [WorryCallDebugger], SoundGenerator USING []; UserTerminalHeadD0: PROGRAM IMPORTS D0InputOutput, DeviceCleanup, RemainingHeads: HeadStartChain, Inline, ProcessorFace, RuntimeInternal EXPORTS DisplayFace, DisplayFaceExtras, HeadStartChain, KeyboardFace, MouseFace, ProcessorFace, SoundGenerator = BEGIN ErrorHalt: PROCEDURE = {RuntimeInternal.WorryCallDebugger["Error in UserTerminalHeadD0"L]}; -- -- DisplayFace CSBPtr: TYPE = LONG POINTER TO CSBState; CSBState: TYPE = MACHINE DEPENDENT RECORD [ dcbChainHead: PDCB, wakeupMask: WORD]; csbPtr: CSBPtr = LOOPHOLE[LONG[420B]]; -- SHOULD MOVE TO IO PAGE PDCB: TYPE = POINTER TO DCB; DCB: TYPE = MACHINE DEPENDENT RECORD [ -- address must be even next: PDCB, resolution: {high, low}, background: DisplayFace.Background, indenting: [0..77B], -- in units of 16 bits width: [0..377B], -- in units of 16 bits; must be even shortBitmap: POINTER, -- must be even tag: {short, long}, height: [0..77777B], -- in double scan lines longBitmap: LONG POINTER]; -- must be even UTVFCControlRegister: TYPE = MACHINE DEPENDENT RECORD [ -- not currently used controlNibbles: [0..377B] ← 0, IncNC: [0..1] ← 0, PPBckGnd: [0..3] ← 0, PPBlank, PPVS, PreOField, AllowWU, ClrNC: [0..1] ← 0]; UTVFCInputRegister: TYPE = MACHINE DEPENDENT RECORD [ controllerIDa: [0..377B] ← 2, bitClockRate: [0..37B], controllerIDb: [0..3] ← 2, test: [0..1]]; cslBitClockRate: [0..37B] = 5B; lfBitClockRate: [0..37B] = 3B; displayState: {disconnected, off, on} ← disconnected; bitmapBase: LONG POINTER; -- undefined if displayState=disconnected controllerType: D0InputOutput.ControllerType; controller: D0InputOutput.ControllerNumber; pDCBReal: LONG POINTER TO DCB; pDCBBlank: LONG POINTER TO DCB; pDCBNull: PDCB = LOOPHOLE[0]; hasBuffer: PUBLIC BOOLEAN ← FALSE; pagesForBitmap: PUBLIC Environment.PageCount; -- see initialization below Connect: PUBLIC PROCEDURE [bitmap: Environment.PageNumber] = BEGIN displayState ← off; bitmapBase ← LOOPHOLE[Inline.LongMult[bitmap, Environment.wordsPerPage]]; -- LongPointerFromPage csbPtr.dcbChainHead ← Inline.LowHalf[pDCBBlank]; -- DCB's are in first64K END; Disconnect: PUBLIC PROCEDURE = {displayState ← disconnected; csbPtr.dcbChainHead ← pDCBNull}; TurnOn: PUBLIC PROCEDURE = BEGIN IF displayState = disconnected THEN ErrorHalt[]; displayState ← on; pDCBReal.longBitmap ← bitmapBase; csbPtr.dcbChainHead ← Inline.LowHalf[pDCBReal] -- DCB's are in first64K END; TurnOff: PUBLIC PROCEDURE = BEGIN IF displayState = disconnected THEN ErrorHalt[]; displayState ← off; csbPtr.dcbChainHead ← Inline.LowHalf[pDCBBlank]; -- DCB's are in first64K END; GetBitBltTable: PUBLIC PROCEDURE RETURNS [BitBlt.BBTable] = BEGIN IF displayState = disconnected THEN ErrorHalt[]; RETURN[[ dst: [word: bitmapBase, bit: 0], dstBpl: bitmapWidth, src: [word: bitmapBase, bit: 0], srcDesc: [srcBpl[bitmapWidth]], width: width, height: height, flags: []]]; END; SetBackground: PUBLIC PROCEDURE [background: DisplayFace.Background] = {pDCBReal.background ← pDCBBlank.background ← background}; -- See Start for initialization: width: PUBLIC CARDINAL [0..32767] ← lfWordsPerLine*Environment.bitsPerWord; cslWordsPerLine: CARDINAL = 38; lfWordsPerLine: CARDINAL = 64; torWordsPerLine: CARDINAL = 40; -- Size of bitmap, possibly large than screen image (initialized in Start): bitmapWidth: CARDINAL ← lfWordsPerLine*Environment.bitsPerWord; -- See Start for initialization: height: PUBLIC CARDINAL [0..32767] ← 808; -- LF and CSL torHeight: CARDINAL = 800; pixelsPerInch: PUBLIC CARDINAL ← 72; -- See Start for initialization: refreshRate: PUBLIC CARDINAL ← lfRefreshRate; -- frames (two fields) per second cslRefreshRate: CARDINAL = 30; lfRefreshRate: CARDINAL = 38; -- actually ?? interlaced: PUBLIC BOOLEAN ← TRUE; -- Scan line wakeups -- SetScanLineWakeup not implemented. -- GetScanLine not implemented. -- Border pattern hasBorder: PUBLIC BOOLEAN ← FALSE; SetBorderPattern: PUBLIC PROCEDURE [oddPairs, evenPairs: [0..377B]] = {}; -- Cursor pHardwareCursor: DisplayFace.CursorPtr = LOOPHOLE[LONG[431B]]; -- SHOULD BE IN IO PAGE SetCursorPattern: PUBLIC PROCEDURE [cursorPtr: DisplayFace.CursorPtr] = BEGIN pHardwareCursor↑ ← cursorPtr↑ END; cursorPosition: PUBLIC LONG POINTER TO DisplayFace.Point ← LOOPHOLE[LONG[426B]]; -- Initialization globalStateSize: PUBLIC CARDINAL ← SIZE[DCB]*2; InitializeCleanup: PUBLIC PROCEDURE = BEGIN OPEN DeviceCleanup; item: Item; reason: Reason; state: CSBState; mouseCoord: MouseFace.Point; cursorCoord: DisplayFace.Point; cursor: DisplayFace.Cursor; timeDone: LONG CARDINAL; maxPulsesPerRefresh: LONG CARDINAL = 2* --for safety-- (LONG[100]* --pulsesPerHundredPulses--1000000 --microsecondsPerSecond-- )/(LONG[refreshRate] --framesPerSecond-- *ProcessorFace.microsecondsPerHundredPulses); DO reason ← Await[@item]; SELECT reason FROM turnOff => BEGIN state ← csbPtr↑; mouseCoord ← mouse↑; cursorCoord ← cursorPosition↑; cursor ← pHardwareCursor↑; csbPtr.dcbChainHead ← pDCBNull; timeDone ← ProcessorFace.GetClockPulses[]; WHILE ProcessorFace.GetClockPulses[] - timeDone < maxPulsesPerRefresh DO ENDLOOP; END; turnOn => BEGIN mouse↑ ← mouseCoord; cursorPosition↑ ← cursorCoord; pHardwareCursor↑ ← cursor; csbPtr↑ ← state; END; ENDCASE; ENDLOOP; END; Initialize: PUBLIC PROCEDURE [ globalState: DisplayFace.GlobalStatePtr, wakeVF: WORD] = BEGIN dcb: DCB = [next: pDCBNull, resolution: high, background: white, indenting: 0, width: 0, shortBitmap: NIL, tag: long, height: 0, longBitmap: NIL]; csbPtr.wakeupMask ← Inline.BITOR[wakeVF, csbPtr.wakeupMask]; pDCBBlank ← LOOPHOLE[@Environment.first64K[globalState]]; pDCBReal ← LOOPHOLE[@Environment.first64K[globalState] + SIZE[DCB]]; pDCBBlank↑ ← pDCBReal↑ ← dcb; pDCBReal.width ← width/Environment.bitsPerWord; pDCBReal.height ← height/2; END; -- DisplayFaceExtras. monitorType: PUBLIC DisplayFaceExtras.MonitorType ← lf; -- changed in Start SetFieldRate: PUBLIC PROCEDURE [rate: DisplayFaceExtras.FieldRate] RETURNS [ok: BOOLEAN] = BEGIN RETURN [ SELECT monitorType FROM alto => rate=normalAlto, lf => rate=normalLF, ENDCASE => FALSE]; END; SetVerticalWaveforms: PUBLIC PROCEDURE [sync, visible, topBorder: CARDINAL] RETURNS [ok: BOOLEAN] = {RETURN [FALSE]}; -- -- HeadStartChain Start: PUBLIC PROCEDURE = BEGIN OPEN D0InputOutput; IF (controller ← GetNextController[utvfc, nullControllerNumber]) ~= nullControllerNumber THEN BEGIN inputReg: UTVFCInputRegister = Input[[controller: controller, register: 0]]; controllerType ← utvfc; IF inputReg.bitClockRate = cslBitClockRate THEN BEGIN monitorType ← alto; bitmapWidth ← width ← cslWordsPerLine*Environment.bitsPerWord; refreshRate ← cslRefreshRate; millisecondsPerTick ← cslMillisecondsPerTick; END; END ELSE IF (controller ← GetNextController[uibScb, nullControllerNumber]) ~= nullControllerNumber THEN BEGIN monitorType ← lf; controllerType ← uibScb; width ← torWordsPerLine*Environment.bitsPerWord; bitmapWidth ← torWordsPerLine*Environment.bitsPerWord; height ← torHeight; millisecondsPerTick ← torMillisecondsPerTick; END ELSE controllerType ← null; pagesForBitmap ← ((bitmapWidth/Environment.bitsPerWord)*height + Environment.wordsPerPage - 1)/Environment.wordsPerPage; csbPtr.dcbChainHead ← pDCBNull; -- DCB's are in first64K RemainingHeads.Start[]; END; -- -- KeyboardFace keyboard: PUBLIC LONG POINTER TO READONLY KeyStations.KeyBits ← LOOPHOLE[LONG[177033B]]; -- -- MouseFace position: PUBLIC LONG POINTER TO READONLY MouseFace.Point ← mouse; SetPosition: PUBLIC PROCEDURE [newMousePosition: MouseFace.Point] = BEGIN mouse↑ ← newMousePosition END; buttons: PUBLIC LONG POINTER TO READONLY MouseFace.Buttons ← LOOPHOLE[keyboard]; mouse: LONG POINTER TO MouseFace.Point = LOOPHOLE[LONG[424B]]; -- -- ProcessorFace -- See main body for initialization: millisecondsPerTick: PUBLIC CARDINAL ← lfMillisecondsPerTick; cslMillisecondsPerTick: CARDINAL = 50; lfMillisecondsPerTick: CARDINAL = 40; -- actually 39.7 torMillisecondsPerTick: CARDINAL = 40; -- what should this be? -- -- SoundGenerator (dummy implementation) Beep: PUBLIC PROCEDURE [frequency: CARDINAL, duration: CARDINAL] = {}; END. February 6, 1980 3:55 PM Gobbel Create file from UserTerminalImpl February 8, 1980 12:29 PM McJones Start chaining February 25, 1980 1:46 PM McJones Automatic determination of LF/CSL/Tor display March 7, 1980 5:56 PM McJones Wait for two frames in turnOff arm of cleanup procedure June 26, 1980 11:04 AM McJones OISProcessorFace=>ProcessorFace; allow Disconnect in disconnected state; add cursorPosition, mousePosition July 29, 1980 9:54 AM McJones Add keyboard, hasBorder; split off MouseFace July 30, 1980 6:21 PM McJones Add pagesForBitmap, GetBitBltTables; buffered=>hasBuffer January 28, 1981 9:27 AM McJones Dummy SoundGenerator March 24, 1981 3:06 PM Jose Correct width for Tor. February 27, 1983 2:12 pm Taft DisplayFaceExtras