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] ~ { 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. pKnobRotationImpl.mesa Copyright c 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 clock, dir: TerminalDefs.DownUp --Last known state Global data: 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. 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! Start the RotateKnobProcess running. ΚΓ˜šœ™Jšœ Οmœ7™BJšœ+™+J™9J™—šΟk ˜ J˜ Jšœžœ2˜?Jšœ žœ7˜EJšœ žœ˜-J˜J˜—šœž ˜Jšžœ%˜,Jšžœ ˜Jšœž˜Jšžœ˜J˜Jšœžœ˜#J˜šœžœžœ˜ Jšœ žœΟc ˜6Jšœ#Ÿ™5J˜J˜J˜J˜—J™ Jšœžœ žœ˜&Jšœ žœ žœ+˜GJšœžœ žœ+˜EJš œžœžœžœžœ ˜4Icodešœžœžœ ˜!Kšœ žœžœ ˜"š œ žœŸ œžœžœŸœžœ ˜HJšŸ œŸœ˜'JšŸ œŸœ˜(Jšœ˜—š œžœŸœ žœžœŸœ žœ ˜QJšŸœ Ÿœ Ÿœ Ÿœ ˜BJšœ˜—šœžœŸœ žœžœŸœžœŸ œ ˜WKšœ˜K˜K˜K˜Jšœ˜—Jšœ ž œ˜J˜šΟnœžœžœžœ$žœžœžœ žœžœ ˜J™“Jšžœžœžœ˜š œžœžœ˜#šžœž˜!Jšžœ ˜Jšœ˜Jšžœ˜—J˜—Jšžœ žœ˜'J˜J˜J˜J˜—J˜J˜Kš œžœžœ˜#J™kJšœA™Aš   œžœžœ žœžœžœ˜PJšžœžœžœ˜J˜5J˜—š  œžœžœžœ˜!Jšžœžœžœ˜Jšž œ ˜J˜—Kšœ˜J˜/Jšœ6Ÿ˜FšžœŸ ˜ Jšœ+˜+Kšœ!˜!šžœžœ ž˜#K˜IK˜@J˜J˜JJ˜Jšž˜—J˜ Jšž˜—J˜—J˜š œžœ˜J™$Jšžœžœ˜3J˜J˜—J˜J˜Jšžœ˜——…— ¦Ω