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:
BOOLEAN ←
FALSE]
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.