-- 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