<> <> <> <> <<>> 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 <> offset: Offset _ 0, position: Position _ 0 ]; <> 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] ~ { < 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 { <> <> 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 ~ { <> TRUSTED {Process.Detach[FORK RotateKnobProcess[]]}; }; Init[]; END.