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
Last edit by Maxwell on December 9, 1983 8:31 am
DIRECTORY
Basics USING [LongDivMod, LongMult],
ColorDisplayFace USING [Color, DisplayType, Mode],
DeviceCleanup USING [Await, Item, Reason],
D0InputOutput
USING [ControllerNumber, ControllerType, GetNextController, IOPage,
nullControllerNumber, Output],
PrincOps USING [PageCount, PageNumber, wordsPerPage],
ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses];
ColorDisplayHeadD0: PROGRAM
IMPORTS Basics, DeviceCleanup, D0InputOutput, ProcessorFace
EXPORTS ColorDisplayFace = {
ErrorHalt: PROC = {ERROR};
Base: TYPE = LONG BASE POINTER;
RPtr: TYPE = Base RELATIVE POINTER; -- relative to absolute address 0
rpNIL: RPtr = LOOPHOLE[0];
Mode: TYPE = ColorDisplayFace.Mode;
Color: TYPE = ColorDisplayFace.Color;
DisplayType: TYPE = ColorDisplayFace.DisplayType;
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 = Basics.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 NAT ← 0; -- for Initialize
displayType: PUBLIC DisplayType ← none; -- display type
pixelsPerInch: PUBLIC NAT ← 0; -- Size of a pixel
width,height: PUBLIC NAT ← 0; -- Dimensions of current raster in pixels
baseA,baseB: PUBLIC LONG POINTER ← NIL; -- bitmap addresses
bplA,bplB: PUBLIC NAT ← 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:
LONG
POINTER] = {
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] ← Basics.LongDivMod[words,PrincOps.wordsPerPage];
RETURN[IF r>0 THEN q+1 ELSE q] };
WordsForPages:
PROC[pages:
CARDINAL]
RETURNS[
LONG
CARDINAL] =
INLINE {
RETURN[Basics.LongMult[pages,PrincOps.wordsPerPage]] };
LPFromPage:
PROC[page: PrincOps.PageNumber]
RETURNS[
LONG
POINTER] =
INLINE {
RETURN[LOOPHOLE[Basics.LongMult[page, PrincOps.wordsPerPage]]] };
HasMode:
PUBLIC
PROC[mode: Mode]
RETURNS[
BOOLEAN] = {
IF displayType = none 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[PrincOps.PageCount] = {
RETURN[PagesForWords[tableSize + screenSize]];
};
Connect:
PUBLIC
PROC [mode: Mode,
firstPage: PrincOps.PageNumber, nPages: PrincOps.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:
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:
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[];
};
}.