{- This program models the digital watch found in Bilung Lee's PhD thesis as a (fairly low-level) FSM model and which has also been modelled in Esterel. -} data LightState = Lon | Loff; -- Used to indicate that an event has occurred --data Event = Event; --constant LIGHT_TIMEOUT = 3s; {- There should be a way of handling timeouts here, so that if the mode button is pressed only once, there is no mode change. -} --port clock from "null" timeout 1s raise Event; -- User Buttons data Button = Adjust | Select | Update | Mode; type TDMode = bool; data TUMode = USecond | UMinute | UHour | UDay; type ADMode = (bool,bool); type AUMode = bool; -- Possible System Modes data SysMode = TimeDisplay | TimeUpdate TUMode | AlarmDisplay | AlarmUpdate AUMode; type ModeState = (Time,TDMode,ADMode); -- Actions for the status keeper data Action = ResetSec | IncrMin | IncrHr | IncrDay | IncrAlarmMin | IncrAlarmHr; -- Actions for the display unit data DisplayAction = ToggleDisplay | ToggleDisplayUpd | ToggleTimeMode | ToggleAlarmUpd | ToggleAlarmMode; -- Types for time type Seconds = int 8; type Minutes = int 8; type Hours = int 7; type Days = int 3; type Time = (Seconds,Minutes,Hours,Days); box Button in ( bi :: Button ) out ( bo1, bo2 :: Button ) match b -> (b, nextB b); nextB Adjust = Mode; nextB Mode = Select; nextB Select = Update; nextB Update = Adjust; wire Button ( Button.bo2 initially Adjust ) (mode_control.b, Button.bi); wire mode_control (mode_control.mode' initially TimeDisplay, Button.bo1, mode_control.s' initially ((0,0,0,0),false,(false,false))) (Display.act, Display.dact, mode_control.mode, mode_control.s); --stream stdin from "std_in"; stream stdout to "std_out"; --data AAction = ResetSec | IncrMin | IncrHr | IncrDay | IncrAlarmMin | IncrAlarmHr; --adjustStatus :: TUMode -> Action; adjustStatus USecond = ResetSec; adjustStatus UMinute = IncrMin; adjustStatus UHour = IncrHr; adjustStatus UDay = IncrDay; -- The mode control box -- The coster has a problem with act :: Action/AAction for some reason! box mode_control in ( mode :: SysMode, b :: a, s :: ModeState ) out ( act :: Action, dact :: DisplayAction, mode' :: SysMode, s' :: ModeState ) match -- TimeDisplay section of FSM ( TimeDisplay, Mode, s ) -> ( *, ToggleDisplay, AlarmDisplay, s ) | ( TimeDisplay, Update, s ) -> ( *, ToggleDisplayUpd, TimeUpdate USecond, s ) | ( TimeDisplay, Adjust, s ) -> ( *, ToggleTimeMode, TimeDisplay, toggleTD s ) -- TimeUpdate section of FSM --| ( t @ (TimeUpdate u), Adjust, s ) -> ( adjustStatus u, *, t, s ) | ( TimeUpdate u, Adjust, s ) -> ( adjustStatus u, *, TimeUpdate u, s ) | ( TimeUpdate u, Select, s ) -> ( *, ToggleTimeMode, TimeUpdate (nextTU u), s ) -- AlarmDisplay section of FSM | ( AlarmDisplay, Mode, s ) -> ( *, ToggleDisplay, TimeDisplay, s ) | ( AlarmDisplay, Update, s ) -> ( *, ToggleDisplayUpd, AlarmUpdate false, s ) | ( AlarmDisplay, Adjust, s ) -> ( *, ToggleAlarmMode, AlarmDisplay, nextAD s ) -- AlarmUpdate section of FSM --| ( a @ (AlarmUpdate u), Adjust, s ) -> ( if u then IncrAlarmHr else IncrAlarmMin, *, a, s ) | ( AlarmUpdate u, Adjust, s ) -> ( if u then IncrAlarmHr else IncrAlarmMin, *, AlarmUpdate u, s ) | ( AlarmUpdate u, Select, s ) -> ( *, ToggleAlarmUpd, AlarmUpdate (not u), s ) -- Ignore all other actions | ( *, _, * ) -> ( *, *, *, * ) ; nextADM :: ADMode -> ADMode; nextADM (false,false) = (true,false); nextADM (true,false) = (false,true); nextADM (false,true) = (true,true); nextADM (true,true) = (false,false); nextAD :: ModeState -> ModeState; nextAD (t,td,ad) = (t,td,nextADM ad); toggleTD :: ModeState -> ModeState; toggleTD (t,td,ad) = (t,not td,ad); nextTU :: TUMode -> TUMode; nextTU USecond = UMinute; nextTU UMinute = UHour; nextTU UHour = UDay; nextTU UDay = USecond; --not true = false; --not false = True; showAct ResetSec = "ResetSec"; showAct IncrMin = "IncrMin"; showAct IncrHr = "IncrHr"; showAct IncrDay = "IncrDay"; showAct IncrAlarmMin = "IncrAlarmMin"; showAct IncrAlarmHr = "IncrAlarmHr"; --showDAct DisplayAction = "DisplayAction"; showDAct ToggleDisplay = "ToggleDisplay"; showDAct ToggleDisplayUpd = "ToggleDisplayUpd"; showDAct ToggleTimeMode = "ToggleTimeMode"; showDAct ToggleAlarmUpd = "ToggleTimeMode"; showDAct ToggleAlarmMode = "ToggleAlarmMode"; box Display in ( act :: Action, dact :: DisplayAction ) out ( s :: string ) fair (s, *) -> showAct s ++ "\n" | (*, s) -> showDAct s ++ "\n" ; wire Display ( mode_control.act, mode_control.dact)(stdout);