-- ColorDisplayHeadD0.mesa -- Last edit by Doug Wyatt on 21-Dec-81 9:40:49 -- Last edit by Levin on 26-Feb-82 13:12:24 DIRECTORY ColorDisplayFace USING [Color, Mode], DeviceCleanup USING [Await, Item, Reason], D0InputOutput USING [ControllerNumber, ControllerType, GetNextController, IOPage, nullControllerNumber, Output], Environment USING [Base, PageCount, PageNumber, wordsPerPage], HeadStartChain USING [Start], Inline USING [LongDivMod, LongMult], ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses], RuntimeInternal USING [WorryCallDebugger]; ColorDisplayHeadD0: PROGRAM IMPORTS DeviceCleanup, D0InputOutput, RemainingHeads: HeadStartChain, Inline, ProcessorFace, RuntimeInternal EXPORTS ColorDisplayFace, HeadStartChain = { ErrorHalt: PROC = {RuntimeInternal.WorryCallDebugger["Error in ColorDisplayHeadD0"L]}; RPtr: TYPE = Environment.Base RELATIVE POINTER; -- relative to absolute address 0 rpNIL: RPtr = LOOPHOLE[0]; Mode: TYPE = ColorDisplayFace.Mode; Color: TYPE = ColorDisplayFace.Color; screenwidth: CARDINAL = 640; -- pixels per line screenheight: CARDINAL = 481; -- scan lines (part of last line is not visible) wordsPerLine: CARDINAL = screenwidth/4; screenSize: LONG CARDINAL = Inline.LongMult[wordsPerLine,screenheight]; ColorData: TYPE = MACHINE DEPENDENT RECORD [ addr: [0..17B], r,g,b,unused: BOOLEAN ← FALSE, data: [0..377B]]; ColorEntry: TYPE = MACHINE DEPENDENT RECORD [r,g,b: ColorData]; ColorTable: TYPE = MACHINE DEPENDENT RECORD [ front: ARRAY [0..2) OF CARDINAL ← ALL[0], array: ARRAY [0..16) OF ColorEntry, back: ARRAY [0..10) OF CARDINAL ← ALL[0] ]; tableSize: CARDINAL = ((SIZE[ColorTable]+15)/16)*16; -- round up to multiple of 16 CSBState: TYPE = MACHINE DEPENDENT RECORD [ bitmap: LONG POINTER, -- must be a multiple of 16 table: LONG POINTER TO ColorTable -- must be a multiple of 16 ]; colorControllerType: D0InputOutput.ControllerType = 257B; colorControllerNumber: D0InputOutput.ControllerNumber ← D0InputOutput.nullControllerNumber; csb: LONG POINTER TO CSBState ← NIL; -- Interface variables -- The following are valid as soon as the module start code has run (see Start) globalStateSize: PUBLIC CARDINAL ← 0; -- for Initialize displayType: PUBLIC CARDINAL ← 0; -- display type; 0 means display not available Ramtek525: CARDINAL = 1; -- displayType for Ramtek 525 line monitor pixelsPerInch: PUBLIC CARDINAL ← 0; -- Size of a pixel mixedRG: PUBLIC BOOLEAN ← FALSE; -- in fullmode, red and green alternate in A bitmap width,height: PUBLIC CARDINAL ← 0; -- Dimensions of current raster in pixels baseA,baseB,baseC: PUBLIC LONG POINTER ← NIL; -- bitmap addresses bplA,bplB,bplC: PUBLIC CARDINAL ← 0; -- bitmap bits per line -- Internal globals initialized: BOOLEAN ← FALSE; -- control blocks are allocated connected: BOOLEAN ← FALSE; -- bitmaps and tables are allocated, globals are set turnedon: BOOLEAN ← FALSE; -- display is on, bitmaps and tables are resident fullmode: BOOLEAN ← FALSE; -- connected in 24 bit per pixel mode mapmode: BOOLEAN ← FALSE; -- connected in a mapped mode -- The following globals are valid when initialized=TRUE (see Initialize) -- (none for D0) -- -- The following globals are valid when connected=TRUE (see Connect) showA: BOOLEAN ← FALSE; -- to be shown table: LONG POINTER TO ColorTable ← NIL; Initialize: PUBLIC PROC [globalState: RPtr] = { initialized ← TRUE; }; Lg: TYPE = [0..4); -- logarithm base 2 lg1: Lg = 0; lg2: Lg = 1; lg4: Lg = 2; lg8: Lg = 3; PagesForWords: PROC[words: LONG CARDINAL] RETURNS[CARDINAL] = INLINE { q,r: CARDINAL; [q,r] ← Inline.LongDivMod[words,Environment.wordsPerPage]; RETURN[IF r>0 THEN q+1 ELSE q] }; WordsForPages: PROC[pages: CARDINAL] RETURNS[LONG CARDINAL] = INLINE { RETURN[Inline.LongMult[pages,Environment.wordsPerPage]] }; LPFromPage: PROC[page: Environment.PageNumber] RETURNS[LONG POINTER] = INLINE { RETURN[LOOPHOLE[Inline.LongMult[page, Environment.wordsPerPage]]] }; HasMode: PUBLIC PROC[mode: Mode] RETURNS[BOOLEAN] = { IF displayType=0 THEN RETURN[FALSE]; IF mode.full OR mode.useB THEN RETURN[FALSE]; RETURN[mode.useA AND mode.lgBitsPerPixelA=lg4]; }; PagesForMode: PUBLIC PROC[mode: Mode] RETURNS[Environment.PageCount] = { RETURN[PagesForWords[tableSize + screenSize]]; }; Connect: PUBLIC PROC [mode: Mode, firstPage: Environment.PageNumber, nPages: Environment.PageCount] = { alloc: LONG POINTER ← LPFromPage[firstPage]; -- next available word Alloc: PROC[words: LONG CARDINAL] RETURNS[LONG POINTER] = INLINE { p: LONG POINTER ← alloc; alloc ← alloc + words; RETURN[p] }; wpl: CARDINAL = screenwidth/4; -- words per scan line IF NOT initialized OR NOT HasMode[mode] OR connected THEN ErrorHalt[]; IF nPages<PagesForMode[mode] THEN ErrorHalt[]; width ← screenwidth; height ← screenheight; bplA ← 4*screenwidth; -- Note: both the following pointers must be multiples of 16. -- table is a multiple of 16, since it starts at a page boundary -- baseA is a multiple of 16, since tableSize is a multiple of 16 -- Also, the color table must not cross a 64K boundary; should be OK -- here since table starts at a page boundary and tableSize<wordsPerPage. table ← Alloc[tableSize]; baseA ← Alloc[screenSize]; table↑ ← [front: ALL[0], array: , back: ALL[0]]; FOR i: CARDINAL IN [0..16) DO table.array[i].r ← [addr: i, r: TRUE, data: 255]; table.array[i].g ← [addr: i, g: TRUE, data: 255]; table.array[i].b ← [addr: i, b: TRUE, data: 255]; ENDLOOP; csb.table ← table; showA ← TRUE; connected ← TRUE; }; Disconnect: PUBLIC PROC = { IF turnedon THEN TurnOff[]; csb.table ← NIL; width ← height ← 0; baseA ← NIL; bplA ← 0; table ← NIL; connected ← FALSE; }; TurnOn: PUBLIC PROC = { IF (NOT connected) OR turnedon THEN RETURN; IF showA THEN { csb.bitmap ← baseA; HardwareOn[] }; turnedon ← TRUE; }; TurnOff: PUBLIC PROC = { IF NOT turnedon THEN RETURN; IF showA THEN { csb.bitmap ← NIL; Wait[]; HardwareOff[] }; turnedon ← FALSE; }; Show: PUBLIC PROC[a,b,c: BOOLEAN] = { IF showA=a THEN RETURN; showA ← a; IF NOT turnedon THEN RETURN; IF showA THEN { csb.bitmap ← baseA; HardwareOn[] } ELSE { csb.bitmap ← NIL; Wait[]; HardwareOff[] }; }; -- For D0 color map, 0 = white, 255 = black! GetColor: PUBLIC PROC[pixelA,pixelB: CARDINAL] RETURNS[r,g,b: Color] = { IF connected THEN { index: [0..16) ← pixelA MOD 16; entry: ColorEntry ← table.array[index]; RETURN[r: 255 - entry.r.data, g: 255 - entry.g.data, b: 255 - entry.b.data] } ELSE RETURN[0,0,0]; }; SetColor: PUBLIC PROC[pixelA,pixelB: CARDINAL, r,g,b: Color] = { IF connected THEN { index: [0..16) ← pixelA MOD 16; table.array[index].r.data ← 255 - r; table.array[index].g.data ← 255 - g; table.array[index].b.data ← 255 - b; }; }; GetRedMap: PUBLIC PROC[in: Color] RETURNS[out: Color] = { RETURN[0] }; GetGreenMap: PUBLIC PROC[in: Color] RETURNS[out: Color] = { RETURN[0] }; GetBlueMap: PUBLIC PROC[in: Color] RETURNS[out: Color] = { RETURN[0] }; SetRedMap: PUBLIC PROC[in,out: Color] = { }; SetGreenMap: PUBLIC PROC[in,out: Color] = { }; SetBlueMap: PUBLIC PROC[in,out: Color] = { }; -- Initialization minFPS: CARDINAL = 30; -- minimum number of frames per second maxPulsesPerRefresh: LONG CARDINAL = 2* --for safety-- (LONG[100]* --pulsesPerHundredPulses-- 1000000 --microsecondsPerSecond--)/ (LONG[minFPS]*ProcessorFace.microsecondsPerHundredPulses); Wait: PROC = INLINE { timeDone: LONG CARDINAL ← ProcessorFace.GetClockPulses[]; WHILE ProcessorFace.GetClockPulses[] - timeDone < maxPulsesPerRefresh DO ENDLOOP }; HardwareOn: PROC = INLINE { D0InputOutput.Output[datum: 6, register: [controller: colorControllerNumber, register: 0]] }; HardwareOff: PROC = INLINE { D0InputOutput.Output[datum: 0, register: [controller: colorControllerNumber, register: 0]] }; InitializeCleanup: PUBLIC PROC = { OPEN DeviceCleanup; item: Item; reason: Reason; state: CSBState; DO reason ← Await[@item]; IF csb = NIL THEN LOOP; -- Driver doesn't know that there isn't a color display! (RL) SELECT reason FROM turnOff => { state ← csb↑; IF state.bitmap#NIL THEN { csb.bitmap ← NIL; Wait[]; HardwareOff[] }; }; turnOn => { csb↑ ← state; IF state.bitmap#NIL THEN HardwareOn[]; }; ENDCASE; ENDLOOP; }; -- HeadStartChain Start: PUBLIC PROC = { OPEN D0InputOutput; colorControllerNumber ← GetNextController[colorControllerType,nullControllerNumber]; IF colorControllerNumber#nullControllerNumber THEN { displayType ← Ramtek525; pixelsPerInch ← 72; -- *** Is this right? *** csb ← LOOPHOLE[@IOPage[colorControllerNumber]]; csb↑ ← [bitmap: NIL, table: NIL]; }; RemainingHeads.Start[]; }; }.