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: BOOLEANFALSE, data: [0..377B]];
ColorEntry: TYPE = MACHINE DEPENDENT RECORD [r,g,b: ColorData];
ColorTable: TYPE = MACHINE DEPENDENT RECORD [
front: ARRAY [0..2) OF CARDINALALL[0],
array: ARRAY [0..16) OF ColorEntry,
back: ARRAY [0..10) OF CARDINALALL[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 POINTERNIL; -- bitmap addresses
bplA,bplB: PUBLIC NAT ← 0; -- bitmap bits per line
Internal globals
initialized: BOOLEANFALSE; -- control blocks are allocated
connected: BOOLEANFALSE; -- bitmaps and tables are allocated, globals are set
turnedon: BOOLEANFALSE; -- display is on, bitmaps and tables are resident
fullmode: BOOLEANFALSE; -- connected in 24 bit per pixel mode
mapmode: BOOLEANFALSE; -- 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: BOOLEANFALSE; -- 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[];
};
Start[];
}.