Telephone.sm
// // The contents of this file are subject to the Mozilla Public // License Version 1.1 (the "License"); you may not use this file // except in compliance with the License. You may obtain a copy of // the License at http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or // implied. See the License for the specific language governing // rights and limitations under the License. // // The Original Code is State Machine Compiler (SMC). // // The Initial Developer of the Original Code is Charles W. Rapp. // Portions created by Charles W. Rapp are // Copyright (C) 2000. Charles W. Rapp. // All Rights Reserved. // // Contributor(s): // // Name // Telephone.sm // // Description // Runs a plain old telphone. That means the proper sounds at // the proper time. // // RCS ID // $Id: TelephoneSrc.htm,v 1.4 2008/05/23 17:30:02 fperrad Exp $ // // CHANGE LOG // $Log: TelephoneSrc.htm,v $ // Revision 1.4 2008/05/23 17:30:02 fperrad // - remove duplicated XML declaration : %map CallMap %% Initialized { Start OnHook {} // Ignore all other transitions. Default nil {} } OnHook Entry { updateClock(); startClockTimer(); } Exit {stopTimer("ClockTimer");} { // We are handling the caller's side of the connection. OffHook Dialing/push(PhoneNumber::DialTone) { clearDisplay(); setReceiver("on hook", "Put down receiver");} } // Dialing errors. LeftOffHook LeftOffHook {} // Time to update the clock's display. ClockTimer nil { updateClock(); startClockTimer(); } } // The number is being dialed. Dialing { // Dialing successfully completed. DialingDone(callType: int, areaCode: String, exhange: String, local: String) Routing {routeCall(callType, areaCode, exchange, local);} InvalidDigit InvalidDigit {} } // The call is now being routed. Routing { Emergency PlayingMessage {playEmergency();} NYCTemp NYCTemp {} Time Time {} DepositMoney DepositMoney {} LineBusy BusySignal {} InvalidNumber PlayingMessage {playInvalidNumber();} } NYCTemp Entry { loop("ringing"); startTimer("RingTimer", 10000); } Exit {stopLoop("ringing");} { RingTimer PlayingMessage {playNYCTemp();} } Time Entry { loop("ringing"); startTimer("RingTimer", 10000); } Exit {stopLoop("ringing");} { RingTimer PlayingMessage {playTime();} } DepositMoney Entry { loop("ringing"); startTimer("RingTimer", 5000); } Exit {stopLoop("ringing");} { RingTimer PlayingMessage {playDepositMoney();} } BusySignal Entry {loop("busy");} Exit {stopLoop("busy");} { // Wait for on hook only. } PlayingMessage { // If caller hangs up while a message is being played, // be sure to stop the playback. OnHook OnHook { stopPlayback(); setReceiver("off hook", "Pick up receiver"); clearDisplay(); } Stop Initialized { stopPlayback(); setReceiver("off hook", "Pick up receiver"); clearDisplay(); } PlaybackDone MessagePlayed {} } MessagePlayed Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { OffHookTimer LeftOffHook {} } //--------------------------------------------------------------- // Error States. // // Let someone know the phone has been left off the hook. LeftOffHook Entry { startTimer("LoopTimer", 10000); loop("phone_off_hook"); } Exit { stopTimer("LoopTimer"); stopLoop("phone_off_hook"); } { LoopTimer WaitForOnHook {} Default nil {} } InvalidDigit Entry { startTimer("LoopTimer", 10000); loop("fast_busy"); } Exit { stopTimer("LoopTimer"); stopLoop("fast_busy"); } { LoopTimer WaitForOnHook {} Default nil {} } // Stay in this state until the telephone is on hook. WaitForOnHook { Default nil {} } Default { // Ignore any dialings after a phone number has been // collected. Digit(n : String) nil {} // No matter when it happens, when the phone is hung // up, this call is OVER! OnHook OnHook { setReceiver("off hook", "Pick up receiver"); clearDisplay(); } Stop Initialized { setReceiver("off hook", "Pick up receiver"); clearDisplay(); } // Ignore the clock timer outside of the OnHook state. ClockTimer nil {} } %% // This map processes dialed digits. It either returns success // when %map PhoneNumber %% DialTone Entry { loop("dialtone"); startTimer("OffHookTimer", 10000); } Exit { stopTimer("OffHookTimer"); stopLoop("dialtone"); } { // If the first digit is 1, then this is a long distance // phone call. Don't save this first digit. Digit(n : String) [equal(n, 1);] LongDistance { playTT(n); setType(Telephone.LONG_DISTANCE); saveAreaCode(n); addDisplay("-"); } // Check for 911. Digit(n : String) [equal(n, 9);] OneOneStart { playTT(n); saveExchange(n); } Digit(n : String) Exchange { playTT(n); setType(Telephone.LOCAL); saveExchange(n); } } // Collect the area and then move on to the local number. LongDistance Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { Digit(n : String) [!isCodeComplete();] nil { playTT(n); saveAreaCode(n); resetTimer("OffHookTimer"); } Digit(n : String) Exchange { playTT(n); saveAreaCode(n); addDisplay("-"); } } // Check if this is a 911 call. OneOneStart Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { Digit(n : String) [equal(n, 1);] NineOne { playTT(n); saveExchange(n); } Digit(n : String) Exchange { playTT(n); setType(Telephone.LOCAL); saveExchange(n); } } // Almost there. NineOne Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { Digit(n : String) [equal(n, 1);] pop(DialingDone) { playTT(n); setType(Telephone.EMERGENCY); saveExchange(n); } Digit(n : String) LocalCall { playTT(n); setType(Telephone.LOCAL); saveExchange(n); addDisplay("-"); } } // Collect the three digit exchange. Exchange Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { Digit(n : String) [!isExchangeComplete();] nil { playTT(n); saveExchange(n); resetTimer("OffHookTimer"); } Digit(n : String) LocalCall { playTT(n); saveExchange(n); addDisplay("-"); } } // Process a local call. LocalCall Entry {startTimer("OffHookTimer", 10000);} Exit {stopTimer("OffHookTimer");} { Digit(n : String) [!isLocalComplete();] nil { playTT(n); saveLocal(n); resetTimer("OffHookTimer"); } Digit(n : String) pop(DialingDone) { playTT(n); saveLocal(n); } } Default { // If an invalid digit is dialed, give up collecting // digits immediately. Digit(n : String) [!isDigitValid(n);] pop(InvalidDigit) {clearDisplay();} // Caller has stopped dialing and left the phone // off hook. OffHookTimer pop(LeftOffHook) {clearDisplay();} // Pass this event up. OnHook pop(OnHook) {clearDisplay();} Stop pop(Stop) {clearDisplay();} // Ignore the clock timer outside of the OnHook state. ClockTimer nil {} } %%