ThSmartsPrivate.mesa
Last modified by D. Swinehart, July 31, 1984 7:32:58 am PDT
Last Edited by: Pier, May 3, 1984 1:04:49 pm PDT
DIRECTORY
IO USING [ STREAM ],
Lark USING [
CommandEvents, disabled, enabled, Event, LarkModel, o3i1, StatusEvent, ts0 ],
LarkRpcControl USING [ InterfaceRecord ],
Rope USING [ROPE],
BasicTime USING [ GMT ],
Thrush USING [
ConversationHandle, ConvEvent, ConvEventBody, Disposition, IntervalSpec, NetAddress, nullHandle, nullConvHandle, PartyHandle, Reason, ROPE, SHHH, SmartsHandle, StateInConv, ToneSpec, Tune, VoiceDirection, VoiceInterval ],
ThPartyPrivate USING [ SmartsData ];
ThSmartsPrivate: CEDAR DEFINITIONS = {
Copies
ConversationHandle: TYPE = Thrush.ConversationHandle;
nullConvHandle: ConversationHandle = Thrush.nullConvHandle;
PartyHandle: TYPE = Thrush.PartyHandle;
Reason: TYPE = Thrush.Reason;
ROPE: TYPE = Thrush.ROPE;
SHHH: TYPE = Thrush.SHHH;
SmartsData: TYPE = ThPartyPrivate.SmartsData;
SmartsHandle: TYPE = Thrush.SmartsHandle;
StatusEvent: TYPE = Lark.StatusEvent;
Types
States (enumerated types) and other scalars
Parser is controlled by state sequence that's largely independent of the state of the smarts in any conversation. Parser represents the user's wishes. After parsing is complete, other processing determines whether these wishes can be granted.
ParseState: TYPE = {
idle, getStr, getSeq, getFeep, getNum, inStr, inSeq, inFeep, inNum, inTossStr };
This state is essentially a superset of Thrush.StateInConv. It is used to express the user's wishes; when wish and reality coincide, it is set to the corresponding StateInConv, and quiescence follows, at least temporarily.
Control of the Lark hardware state (remaining types)
LarkState: TYPE = {
none,     -- Initial state
idle,     -- Phone not in use
talking,    -- Etherphone conversation in progress
trunkSignalling,  -- "Feeping"
trunkTalking,  -- Standard telephone conversation in progress
trunkForwarding, -- Like trunkTalking, but call is forwarded to some other Lark
trunkFlashing,  -- Implementing special switchhook flash
failed,    -- This Lark has died and its brain is dying, too.
recovering,   -- Lark is presumed not to work, but use attempts don't raise ERRORS
ringing,    -- Ringing loudly through Lark speaker
silence,    -- Dial tone has been broken, dialing in progress.
dialTone,    -- Caller hears dial tone.
ringBack,    -- Caller hears ringing.
busyTone,   -- Caller hears busy signal.
errorTone    -- Caller hears fast busy signal.
};
ProgressTones: TYPE = LarkState[dialTone..errorTone];
HookState: TYPE = { onhook, telset, spkr, sPkr, spKr, both, bOth, monitor };
TerminalType: TYPE = {std, spkr, monitor, radio};
RingDetState: TYPE = { idle, maybe, ring1, between, ring };
no ring, glitch interval, first (partial?) ring, break, nth ring
RingMode: TYPE = { -- <<obsolete??>>
internal,   -- standard ringing cadence
trunk    -- distinctive ringing for incoming back door calls
};
Orig: TYPE = { unknown, us, them };
click: Lark.Event = Lark.ts0; -- Momentary closure of speaker box switch.
LSwitches: TYPE = {
xBarAll, hook, aSwitch, sideTone, ringO, revert, revertHook, led, spMode, none };
LState: TYPE = RECORD [
voiceMode: Lark.Event←Lark.o3i1,
echoStyle: CHAR←'4, -- nonsense value to force initialization first time.
xbar: PACKED ARRAY[0..8) OF [0..256) ← ALL[0],
lSw: ARRAY LSwitches OF Lark.Event ← ALL[Lark.disabled]
];
Structures
Information used by LarkSmarts and LarkTrunkSmarts implementations
They require similar information, although the trunk does not use all of it.
SmartsInfo: TYPE = REF SmartsInfoBody;
SmartsInfoBody: TYPE = MONITORED RECORD
[
smarts: SmartsData, -- back pointer to my smarts.
otherSmarts: SmartsData←NIL, -- trunk or station smarts, depending on which this is.
larkInfo: LarkInfo,
State of Lark hardware, shared between Lark and Trunk
conversations: OpenConversations←NIL,
currentConvID: ConversationHandle←nullConvHandle, -- the one we're dealing with.
thProcess: PROCESSNIL, -- the process that manages Lark smarts
thAction: CONDITION, -- poke this when something has happened.
apprise: BOOLFALSE, -- needs to be true before waking to thAction has any meaning.
Parsing control fields
ParseEvent: PROC[smartsInfo: SmartsInfo, sEvent: StatusEvent],
Allows Lark, Lark trunk, Radio, ... smarts to parse different command languages
Command: PROC[info: SmartsInfo, val: INT𡤀]←NIL,
Command procedure to act on results of completely parsed command
Supervise: PROC[info: SmartsInfo],
Command procedure to act on results of completely parsed command
parseState: ParseState ← idle,
Independent of any notion of what's going on in eventInfo; desire of local user
arguments: ROPENIL,
argLength: NAT𡤀,
offset: NAT𡤀, -- kludge allowing more than ten touchpad commands
haveArguments, cmdOrRecip, haveOne: BOOLEANFALSE,
LarkTrunkSmarts fields; something feels pretty wrong here.
phoneNumber: Rope.ROPENIL -- signalling information for TelCo.
];
OpenConversations: TYPE = LIST OF ConvDesc;
ConvDesc: TYPE = REF ConvDescBody;
ConvDescBody: TYPE = RECORD [
cState: Thrush.ConvEventBody,  -- amalgam of useful info from reported events
desiredState: Thrush.StateInConv𡤊ny, -- what we're aiming for
desiredPartyID: PartyHandle←NULL,
desiredReason: Reason←wontSay,
desiredComment: ROPENIL,
newIntervals: LIST OF Thrush.IntervalSpec ← NIL,
iTail: LIST OF Thrush.IntervalSpec ← NIL,
originator: Orig ← unknown,
newSpec, newKeys, newAddress: BOOLFALSE,
newEvent: BOOLFALSE,
signallingStarted: BOOLFALSE,
descValid: BOOLFALSE
];
Access to the Lark hardware via the Lark interface. This monitored record is shared by the Smarts info for both the LarkSmarts and LarkTrunkSmarts. There are also some random shared fields kept here.
LarkInfo: TYPE = REF LarkInfoBody;
LarkInfoBody: TYPE = MONITORED RECORD
[
interface: LarkRpcControl.InterfaceRecord, -- here's how you make calls to Lark --
shh: SHHH, -- here's what you use to encrypt them --
netAddress: Thrush.NetAddress, -- <<needed when creating socket numbers?>> --
model: Lark.LarkModel, -- what does this Lark look like? --
debugIn: IO.STREAM, debugPrint: IO.STREAMNIL,
larkState: LarkState ← none,  -- tone/crossbar/connect state of actual Lark hardware
newActions: LIST OF REFNIL, -- queue of low-level requests to supervisor process
lastAction: LIST OF REFNIL, -- used in request-queue maintenance,
larkProcess: PROCESSNIL, -- maintains same
stateChange: CONDITION,  -- larkProcess should notice change
hookState: HookState ← onhook, -- state of switchhook/speakerphone switch...
terminalType: TerminalType ← std, -- telset, speakerphone, or monitor switching.
Special attributes. << Not clear how set >>
hotLine: BOOLFALSE, -- answers when called.
radio: BOOLFALSE, -- used with hotline; connects line in instead of telset when called.
monitor: BOOLFALSE,-- speaker repeats telset receiver in telset mode.
Click and ring detect timings
swOnTime: CARDINAL𡤀,
ringChangeTime: CARDINAL𡤀,
ringDetState: RingDetState ← idle,
ringDetWaitState: RingDetState←idle,
ringDetCondition: CONDITION,
ringDetInstance: CARDINAL𡤀, -- paranoia
Ringing control information
ringMode: RingMode ← internal, -- what kind of ringing should we do next time? <<Obsolete??>>
ringTune: Thrush.ToneSpec, -- Specification of ring tune
When a Note in a tune specifies "notify", expectedNotification is incremented (mod the lower-case letters) and sent along to the Lark. When the Lark finishes that note, it notifies the smarts, and eventually LarkOut, using that value. It's possible (though not desired) for this notification to precede the "WAIT" that pends notification. In this case, we mustn't wait. See LarkOutImpl.DoTones and ditto.WaitQ. receivedNotification is set to a value outside the range just after each WAIT opportunity terminates.
expectedNotification: Lark.Event ← 'z,
receivedNotification: Lark.Event ← 'Y,
LarkSupervisor Variables
lastTerminalType: TerminalType ← std,
lState: LState ← [lSw: ALL[Lark.enabled]],
scratchEv: Lark.CommandEvents ← NIL
];
LarkStateSpec: TYPE = RECORD [
state: LarkState,
sInfo: SmartsInfo ];
Procedures
ENTRY version
EnterLarkState: PROC
[ info: LarkInfo, newState: LarkState, sInfo: SmartsInfo ];
INTERNAL version
EnterLarkSt: PROC
[ info: LarkInfo, newState: LarkState, sInfo: SmartsInfo ];
INTERNAL version
TonesDone: PROC[ info: LarkInfo, commandEvent: Lark.StatusEvent, sInfo: SmartsInfo ];
A way to feed back tone completions, initiated by LarkOut, back to LarkOut.
Feep tones don't go through this path, since higher-levels need to know about the situation.
InterpretHookState: PROC
[ info: LarkInfo, rawEvent: Lark.StatusEvent ]
RETURNS [ processedEvent: Lark.StatusEvent ];
CheckHookState: PROC
[ info: LarkInfo]
RETURNS [ onHook: BOOLTRUE ];
Determines if user terminal appears to be offhook. May not be able to tell if there's
a "click-mode" speakerphone call in progress.
Registration of Lark trunks (back doors)
RegisterTrunk: PROC[ hostPartyID: Thrush.PartyHandle,
hostSmarts: ThPartyPrivate.SmartsData, hostInfo: SmartsInfo ]
RETURNS [ smartsID: Thrush.SmartsHandle ];
EnableSmarts: PROC[info: SmartsInfo] RETURNS[enabled: BOOL];
Deregister: PROC[info: SmartsInfo ];
LarkParseEvent: -- INTERNAL -- PROC[smartsInfo: SmartsInfo, sEvent: StatusEvent];
LarkProgress: PROC[
shh: SHHH,
smartsID: Thrush.SmartsHandle,
event: Thrush.ConvEvent,
yourParty: BOOL,
latestEvent: BOOL,
informationOnly: BOOL
] RETURNS [ d: Thrush.Disposition ];
LarkSupervise: PROC[info: SmartsInfo];
LarkSetInterval: PROC[
shh: SHHH,
smartsID: SmartsHandle,
tune: Thrush.Tune,
interval: Thrush.VoiceInterval,
direction: Thrush.VoiceDirection,
queueIt: BOOLEAN
] RETURNS [ d: Thrush.Disposition, u: Thrush.Tune ];
LarkFailed: ERROR[sInfo: SmartsInfo];
Return current state
GetSmartsInfo: PROC[smartsID: SmartsHandle←Thrush.nullHandle,
smarts: ThPartyPrivate.SmartsData←NIL]
RETURNS [info: SmartsInfo];
GetSIC: PROC[info: SmartsInfo] RETURNS [ state: Thrush.StateInConv ];
Apprise: PROC[info: SmartsInfo];
ChangeState: PROC[
info: SmartsInfo,
cDesc: ConvDesc,
state: Thrush.StateInConv ← idle,
reason: Reason ← wontSay,
comment: ROPENIL
];
GetConvDesc: PROC[info: SmartsInfo] RETURNS [ cDesc: ConvDesc←NIL ];
GetConv: PROC[info: SmartsInfo, convID: ConversationHandle, validIfNew: BOOL]
RETURNS [ cDesc: ConvDesc←NIL ];
}.