-- 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[];
};
}.