MonitorToolImpl.mesa
Last Edited by: Pier, January 12, 1984 2:20 pm
DIRECTORY
Buttons,
ColorDisplayHeadDorado,
Containers,
IO,
Labels,
Menus,
MessageWindow,
MonitorToolButtons,
MonitorToolOps,
Rope,
Rules,
Commander,
VFonts,
ViewerOps,
ViewerTools,
WindowManager
;
MonitorToolImpl: CEDAR PROGRAM
IMPORTS Buttons, Containers, ColorDisplayHeadDorado, IO, Labels, Menus, MessageWindow, MonitorToolButtons, MonitorToolOps, Rope, Rules, Commander, VFonts, ViewerOps, ViewerTools, WindowManager
SHARES MonitorToolOps, ColorDisplayHeadDorado = BEGIN
OPEN MTB: MonitorToolButtons;
entryHeight: CARDINAL = 15; -- how tall to make each line of items
entryVSpace: CARDINAL = 6; -- vertical leading space between lines
entryHSpace: CARDINAL = 10; -- horizontal space between items in a line
entryTabSpace: CARDINAL ← 36*3; -- horizontal tab between items in a line
ruleHeight: CARDINAL ← 4;
resultWidth: CARDINAL = 12*VFonts.CharWidth['0];-- 12 digits worth of width
default values for 1024X768 monitor
defaultScreenWidth: Rope.ROPE = "1024";
defaultScreenHeight: Rope.ROPE = "768";
defaultRefresh: Rope.ROPE = "30";
defaultHBlank: Rope.ROPE = "6";
defaultVBlank: Rope.ROPE = "850";
defaultBPP: Rope.ROPE = "8";
defaultPosition: Rope.ROPE = "right";
MakeMonitorTool: Commander.CommandProc =
TRUSTED {
myRule: Rules.Rule;
myMenu: Menus.Menu ← Menus.CreateMenu[];
my: MTB.Handle ← NEW[MTB.MTViewerRec];
Menus.AppendMenuEntry[
-- add command to the menu
menu: myMenu,
entry: Menus.CreateEntry[
name: "Calculate", -- name of the command
proc: CalculateProc, -- MenuProc associated with command
clientData: my
]
];
Menus.AppendMenuEntry[
-- add command to the menu
menu: myMenu,
entry: Menus.CreateEntry[
name: "Set", -- name of the command
proc: SetParametersProc, -- MenuProc associated with command
clientData: my
]
];
Menus.AppendMenuEntry[
-- add command to the menu
menu: myMenu,
entry: Menus.CreateEntry[
name: "TurnOff", -- name of the command
proc: TurnOffProc, -- MenuProc associated with command
clientData: my
]
];
Menus.AppendMenuEntry[
-- add command to the menu
menu: myMenu,
entry: Menus.CreateEntry[
name: "NTSC", -- name of the command
proc: NTSCProc, -- MenuProc associated with command
clientData: my
]
];
my.container ← Containers.Create[info: [
-- construct the outer container
name: "MonitorTool", -- name displayed in the caption
iconic: FALSE, -- so tool won't be iconic (small) when first created
column: left, -- initially in the left column
menu: myMenu, -- displaying our menu command
scrollable: TRUE ]]; -- allow scrolling contents
my.screenWidth ← MakeEntryViewer[handle: my, buttonName: "screen width", labelName: "visible pixels", proc: MTB.ScreenWidth, initialData: defaultScreenWidth];
my.screenHeight ← MakeEntryViewer[handle: my, buttonName: "screen height", labelName: "visible pixels", proc: MTB.ScreenHeight, initialData: defaultScreenHeight];
my.refresh ← MakeEntryViewer[handle: my, buttonName: "refresh rate", labelName: "frames per second", proc: MTB.Refresh, initialData: defaultRefresh];
my.hBlank ← MakeEntryViewer[handle: my, buttonName: "hBlank time", labelName: "microseconds", proc: MTB.HBlank, initialData: defaultHBlank];
my.vBlank ← MakeEntryViewer[handle: my, buttonName: "vBlank time", labelName: "microseconds", proc: MTB.VBlank, initialData: defaultVBlank];
my.bpp ← MakeEntryViewer[handle: my, buttonName: "bits per pixel", labelName: "{1,2,4,8,24}", proc: MTB.BitsPerPixel, initialData: defaultBPP];
my.position ← MakeEntryViewer[handle: my, buttonName: "Position", labelName: "{Left/Right}", proc: MTB.Position, initialData: defaultPosition];
my.height ← my.height + entryHeight+ entryVSpace; --space down
myRule ← Rules.Create[info: [parent: my.container, wx: my.screenWidth.button.wx, wy: my.height, ww: my.container.ww-my.screenWidth.button.wx*2, wh: ruleHeight]];
my.height ← my.height + ruleHeight+ entryVSpace; --space down
Containers.ChildXBound[my.container, myRule];
--now create output viewers
my.fieldTime ← MakeResultViewer[handle: my, leftLabelName: "field time", rightLabelName: "milliseconds"];
my.fieldFreq ← MakeResultViewer[handle: my, leftLabelName: "field freq", rightLabelName: "Hz"];
my.lineTime ← MakeResultViewer[handle: my, leftLabelName: "line time", rightLabelName: "microseconds"];
my.lineFreq ← MakeResultViewer[handle: my, leftLabelName: "line freq", rightLabelName: "KHz"];
my.pixelTime ← MakeResultViewer[handle: my, leftLabelName: "pixel time", rightLabelName: "nanoseconds"];
my.pixelFreq ← MakeResultViewer[handle: my, leftLabelName: "pixel freq", rightLabelName: "MHz"];
my.MUL ← MakeResultViewer[handle: my, leftLabelName: "MUL", rightLabelName: "[0..255]"];
my.DIV ← MakeResultViewer[handle: my, leftLabelName: "DIV", rightLabelName: "[0..15]"];
my.vControl ← MakeResultViewer[handle: my, leftLabelName: "vertical ctrl", rightLabelName: "", entryheight: 4*entryHeight, entrywidth: 3*resultWidth];
my.hControl ← MakeResultViewer[handle: my, leftLabelName: "horizontal ctrl", rightLabelName: "", entryheight: 4*entryHeight, entrywidth: 3*resultWidth];
now set up default values
CalculateProc[parent: NIL, clientData: my];
MessageWindow.Append[message: "Default Parameters for 1024x768 Monitor", clearFirst: TRUE];
ViewerOps.SetOpenHeight[my.container, my.height]; -- hint our desired height
ViewerOps.PaintViewer[my.container, all]; -- reflect above change
};
TurnOffProc: Menus.MenuProc =
TRUSTED {
WindowManager.StopColorViewers[];
};
NTSCProc: Menus.MenuProc =
TRUSTED {
this proc should only be called when a Dorado with NTSC-modified DispM board
is set up to do video tape recording. The parameters in the 24 Bpp MonitorParam below
were carefully determined by Pier and Gasbarro using trial and error on 8/24/83.
mp: MonitorToolOps.MonitorParam;
bpp: LONG CARDINAL;
full: BOOLEAN←FALSE;
my: MTB.Handle ← NARROW[clientData];
{
--for catch phrases
bpp ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.bpp.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.bpp.button.name, clearFirst: FALSE];
GOTO error};];
SELECT bpp
FROM
24 => full←TRUE;
8,4,2,1 => NULL;
ENDCASE => {
MessageWindow.Append[message: "Input Value Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.bpp.button.name, clearFirst: FALSE];
GOTO error;
};
N.B.: we will set up the monitor waveforms identicallty for all bpp values. The values are the same as the "double speed" values for 24 bpp. This guarantees locking to the NTSC frequency. For bpp#24, run the video at 1/2 resolution horizontally and double the visible pixels per line.
mp ←
NEW[MonitorToolOps.MonitorParamRec ← [
hRes: 640, vRes: 480, vc: [VBtoVS: 3, VStoVS: 3, VStoVB: 20B, VisibleLines: 240],
hc: [HRamMaxAddr: 909, HBLeadLength: 12, HSTrailAddr: 56, HBTrailLength: 202],
cc: [zero: 5, mul: 115, div: 14], lmarg: 474, truePixelFreq: 0, truePixelTime: 0]];
MonitorToolOps.SetMonitorParams[bpp: bpp, mp: mp];
IF
NOT full
THEN {
--bpp#24
ColorDisplayHeadDorado.achan.pixelsPerLine
ColorDisplayHeadDorado.achan.scan.res←half;
};
MessageWindow.Append[message: "Note: NTSC REQUIRES LATE MODEL HARDWARE", clearFirst: TRUE];
MessageWindow.Blink[]; MessageWindow.Blink[];
}; --for catch phrases
};
SetParametersProc: Menus.MenuProc =
TRUSTED {
MenuProc: TYPE = PROC [parent: REF ANY, clientData: REF ANY ← NIL,
mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE] ;
OPEN MTOps: MonitorToolOps;
my: MTB.Handle ← NARROW[clientData];
sw, sh, refresh, bpp: LONG CARDINAL;
hBlank, vBlank: REAL;
posRope: Rope.ROPE;
pos: WindowManager.ScreenPos;
mp: MTOps.MonitorParam;
{
--for catch phrases
sw ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.screenWidth.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.screenWidth.button.name, clearFirst: FALSE];
GOTO error};];
sh ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.screenHeight.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.screenHeight.button.name, clearFirst: FALSE];
GOTO error};];
refresh ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.refresh.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.refresh.button.name, clearFirst: FALSE];
GOTO error};];
bpp ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.bpp.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.bpp.button.name, clearFirst: FALSE];
GOTO error};];
hBlank ← 1E-6*
IO.GetReal[
IO.
RIS[ViewerTools.GetContents[my.hBlank.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.hBlank.button.name, clearFirst: FALSE];
GOTO error};];
vBlank ← 1E-6*
IO.GetReal[
IO.
RIS[ViewerTools.GetContents[my.vBlank.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.vBlank.button.name, clearFirst: FALSE];
GOTO error};];
posRope ← ViewerTools.GetContents[my.position.input !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.position.button.name, clearFirst: FALSE];
GOTO error};];
SELECT
TRUE
FROM
Rope.Equal[s1: posRope, s2: "left", case: FALSE] => pos ← left;
Rope.Equal[s1: posRope, s2: "right", case: FALSE] => pos ← right;
ENDCASE => {
MessageWindow.Append[message: "Input Syntax Error in Position", clearFirst: TRUE];
GOTO error};
mp ← MTOps.DoMonitorParams[sw,sh,refresh,hBlank,vBlank];
MTOps.SetMonitorParams[bpp, pos, mp];
}; --for catch phrases
};
CalculateProc: Menus.MenuProc =
TRUSTED {
OPEN MTOps: MonitorToolOps;
my: MTB.Handle ← NARROW[clientData];
sw, sh, refresh, bpp: LONG CARDINAL;
hBlank, vBlank: REAL;
mp: MTOps.MonitorParam;
{
--for catch phrases
sw ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.screenWidth.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.screenWidth.button.name, clearFirst: FALSE];
GOTO error};];
sh ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.screenHeight.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.screenHeight.button.name, clearFirst: FALSE];
GOTO error};];
refresh ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.refresh.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.refresh.button.name, clearFirst: FALSE];
GOTO error};];
bpp ←
IO.GetCard[
IO.
RIS[ViewerTools.GetContents[my.bpp.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.bpp.button.name, clearFirst: FALSE];
GOTO error};];
hBlank ← 1E-6*
IO.GetReal[
IO.
RIS[ViewerTools.GetContents[my.hBlank.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.hBlank.button.name, clearFirst: FALSE];
GOTO error};];
vBlank ← 1E-6*
IO.GetReal[
IO.
RIS[ViewerTools.GetContents[my.vBlank.input]] !
IO.Error => {
MessageWindow.Append[message: "Input Syntax Error in ", clearFirst: TRUE];
MessageWindow.Append[message: my.vBlank.button.name, clearFirst: FALSE];
GOTO error};];
}; --for catch phrases
mp ← MTOps.DoMonitorParams[sw,sh,refresh,hBlank,vBlank];
Labels.Set[label: my.fieldTime.data, value: IO.PutFR[format: "%g", v1: IO.real[1E3*MTOps.fieldTime]]];
Labels.Set[label: my.fieldFreq.data, value: IO.PutFR[format: "%g", v1: IO.real[MTOps.fieldFreq]]];
Labels.Set[label: my.lineTime.data, value: IO.PutFR[format: "%g", v1: IO.real[1E6*MTOps.trueLinetime]]];
Labels.Set[label: my.lineFreq.data, value: IO.PutFR[format: "%g", v1: IO.real[1E-3*MTOps.trueLinefreq]]];
Labels.Set[label: my.pixelTime.data, value: IO.PutFR[format: "%g", v1: IO.real[1E9*MTOps.truePixeltime]]];
Labels.Set[label: my.pixelFreq.data, value: IO.PutFR[format: "%g", v1: IO.real[1E-6*MTOps.truePixelfreq]]];
Labels.Set[label: my.MUL.data, value: IO.PutFR[format: "%g", v1: IO.card[MTOps.trueMul]]];
Labels.Set[label: my.DIV.data, value: IO.PutFR[format: "%g", v1: IO.card[MTOps.trueDiv]]];
ViewerTools.EnableUserEdits[my.hControl.data];
ViewerTools.SetContents[viewer: my.hControl.data, contents: IO.PutFR[format: "HRamMaxAddr: %g\nHBlankLeadLength: %g\nHSTrailAddr: %g\nHBTrailLength: %g", v1: IO.card[MTOps.hRamMaxAddr], v2: IO.card[MTOps.hBLeadLength], v3: IO.card[MTOps.hSTrailAddr], v4: IO.card[MTOps.hBTrailLength]]];
ViewerTools.InhibitUserEdits[my.hControl.data];
ViewerTools.EnableUserEdits[my.vControl.data];
ViewerTools.SetContents[viewer: my.vControl.data, contents: IO.PutFR[format: "VBtoVSLines: %g\nVStoVSLines: %g\nVStoVBLines: %g\nVisibleLines: %g", v1: IO.card[MTOps.vbToVS], v2: IO.card[MTOps.vsToVS], v3: IO.card[MTOps.vsToVB], v4: IO.card[MTOps.visibleLines]]];
ViewerTools.InhibitUserEdits[my.vControl.data];
};
MakeEntryViewer:
PROCEDURE [handle:
MTB.Handle, buttonName: Rope.
ROPE, labelName: Rope.
ROPE, proc: Buttons.ButtonProc, initialData: Rope.
ROPE]
RETURNS [ev:
MTB.EntryViewer] = {
--adds an entry viewer with a button, text viewer, and suffix label to the container
ev ← NEW[MTB.EntryViewerRec];
ev.button← Buttons.Create[
info: [
name: buttonName,
wy: handle.height,
default the width so that it will be computed for us --
wh: entryHeight, -- specify rather than defaulting so line is uniform
parent: handle.container,
border: FALSE ],
proc: proc,
clientData: handle]; -- this will be passed to our button proc
ev.input ← ViewerTools.MakeNewTextViewer[ [
parent: handle.container,
wx: entryTabSpace,
wy: handle.height+2,
ww: 12*VFonts.CharWidth['0], -- 12 digits worth of width
wh: entryHeight,
data: initialData, -- initial contents
scrollable: FALSE,
border: TRUE]];
ev.units ← Labels.Create[ [
name: labelName,
wx: ev.input.wx + ev.input.ww + entryHSpace,
wy: handle.height,
--default ww
wh: entryHeight,
parent: handle.container,
border: FALSE]];
handle.height ← handle.height + entryHeight+ entryVSpace; --space down for next guy
};
MakeResultViewer:
PROCEDURE [handle:
MTB.Handle, leftLabelName, rightLabelName: Rope.
ROPE, entryheight:
CARDINAL ← entryHeight, entrywidth:
CARDINAL ← resultWidth]
RETURNS [rv:
MTB.ResultViewer] = {
--adds a result viewer with a label, text viewer, and units to the container
initialData: Rope.ROPE = " ????? ";
rv ← NEW[MTB.ResultViewerRec];
rv.left ← Labels.Create[ [
name: leftLabelName,
wy: handle.height,
default the width so that it will be computed for us --
wh: entryHeight,
parent: handle.container,
scrollable: FALSE,
border: FALSE]];
rv.data ← ViewerTools.MakeNewTextViewer[ [
data: initialData,
wx: entryTabSpace,
wy: handle.height,
ww: entrywidth,
wh: entryheight,
scrollable: FALSE,
parent: handle.container,
border: TRUE]];
rv.right ← Labels.Create[ [
name: rightLabelName,
wx: rv.data.wx + rv.data.ww + entryHSpace,
wy: handle.height,
--default ww
wh: entryHeight,
parent: handle.container,
scrollable: FALSE,
border: FALSE]];
handle.height ← handle.height + entryheight+ entryVSpace; --space down for next guy
};
Commander.Register[key: "MonitorTool", proc: MakeMonitorTool,
doc: "Create a color monitor control tool" ];
[ ] ← MakeMonitorTool[NIL]; -- and create an instance
END.