KnobRotationImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Created Tuesday, August 7, 1984 9:12 am PDT
Last edited by Eric Nickell, May 25, 1985 12:03:27 pm PDT
DIRECTORY
KnobRotation,
Process USING [Detach, Priority, priorityClient3, SetPriority],
Terminal USING [Current, GetKeys, Virtual, WaitForBWVerticalRetrace],
TerminalDefs USING [DownUp, KeyName, KeyBits]
;
KnobRotationImpl: CEDAR MONITOR
IMPORTS --IntervalTimer,-- Process, Terminal
EXPORTS KnobRotation
= BEGIN
OPEN KnobRotation;
DownUp: TYPE ~ TerminalDefs.DownUp;
KnobProcessData: TYPE ~ RECORD [
counter: INTEGER,     --Count the left and right ticks
clock, dir: TerminalDefs.DownUp    --Last known state
offset: Offset ← 0,
position: Position ← 0
];
Global data:
k: ARRAY KnobIndex OF KnobProcessData;
clockKey: ARRAY KnobIndex OF TerminalDefs.KeyName ~ [Keyset1, Keyset3];
dirKey: ARRAY KnobIndex OF TerminalDefs.KeyName ~ [Keyset2, Keyset4];
offsetDirection: ARRAY BOOLEAN OF INTEGER ~ [-1, 1];
Offset: TYPE ~ INTEGER [-3 .. 3];
Position: TYPE ~ INTEGER [0 .. 3];
greyCode: ARRAY --clock-- DownUp OF ARRAY --dir-- DownUp OF Position ~ [
--clock-- up: [--dir-- up: 2, down: 3],
--clock-- down: [--dir-- up: 1, down: 0]
];
deltaPosition: ARRAY --last-- Position OF ARRAY --this-- Position OF Position ~ [
--0-- [0,1,2,3], --1-- [3,0,1,2], --2-- [2,3,0,1], --3-- [1,2,3,0]
];
actualOffset: ARRAY --this-- Position OF ARRAY --last-- Offset OF --actual-- Offset ~ [
[0, 0, 0, 0, 0, 0, 0],
[-3, -3, -3, 1, 1, 1, 1],
[-2, -2, -2, 0, 2, 2, 2],
[-1, -1, -1, -1, 1, 1, 1]
];
KnobRotated: CONDITION;
OffsetSinceLastCall: PUBLIC ENTRY PROC [knobIndex: KnobIndex, returnZero: BOOLEANFALSE] RETURNS [offset: INTEGER, waitCycles: INT ← 0] ~ {
Returns the number of ticks since last call to this procedure. Note the offset<0 => rotation to the left, while offset>0 => rotation to the right.
ENABLE UNWIND => NULL;
WaitUntilNonZero: INTERNAL PROC ~ {
UNTIL k[knobIndex].counter # 0 DO
WAIT KnobRotated;
waitCycles ← waitCycles + 1;
ENDLOOP;
};
IF ~returnZero THEN WaitUntilNonZero[];
offset ← k[knobIndex].counter;
k[knobIndex].counter ← 0;
};
rotateKnobProcessPriorityLevel: Process.Priority ← Process.priorityClient3;
RotateKnobProcess: PROC ~ TRUSTED {
This process runs forever, periodically updating the offset information for each of the two hardware knobs.
NOTE: This procedure must execute at higher than normal priority!
AddOffset: ENTRY PROC [knobIndex: KnobIndex, offset: INTEGER] ~ TRUSTED INLINE {
ENABLE UNWIND => NULL;
k[knobIndex].counter ← k[knobIndex].counter + offset;
};
Broadcast: ENTRY PROC ~ TRUSTED {
ENABLE UNWIND => NULL;
BROADCAST KnobRotated;
};
keys: TerminalDefs.KeyBits;
current: Terminal.Virtual ~ Terminal.Current[];
Process.SetPriority[rotateKnobProcessPriorityLevel];  --Boost priority
DO  --FOREVER
Terminal.WaitForBWVerticalRetrace[current];
keys ← Terminal.GetKeys[current];
FOR knob: KnobIndex IN KnobIndex DO
position: Position ← greyCode[keys[clockKey[knob]]] [keys[dirKey[knob]]];
dPosition: Position ← deltaPosition[k[knob].position][position];
AddOffset[knob, k[knob].offset ← actualOffset[dPosition][k[knob].offset]];
k[knob].position ← position;
ENDLOOP;
Broadcast[];
ENDLOOP;
};
Init: PROC ~ {
Start the RotateKnobProcess running.
TRUSTED {Process.Detach[FORK RotateKnobProcess[]]};
};
Init[];
END.