www.pudn.com > FSM_program.zip > WATCH.C


/**
 * Simple digital watch example
 * M. Samek, 01/07/00
 */ 
#include  
#include  
#include "hsm.h" 
 
typedef struct Watch Watch; 
struct Watch { 
  Hsm super; 
  State timekeeping, time, date; 
  State setting, hour, minute, day, month; 
  State *timekeepingHist; 
  int tsec, tmin, thour, dday, dmonth; 
}; 
 
enum WatchEvents { 
  MODE_EVT, 
  SET_EVT, 
  TICK_EVT 
}; 
 
void WatchShowTime(Watch *me) { 
  printf("time: %2d:%02d:%02d", 
  me->thour, me->tmin, me->tsec); 
} 
 
void WatchShowDate(Watch *me) { 
    printf("date: %02d-%02d", me->dmonth, me->dday); 
} 
 
void WatchTick(Watch *me) { 
  static int const month[] = {  
     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  
  }; 
  if (++me->tsec == 60) { 
    me->tsec = 0; 
    if (++me->tmin == 60) { 
      me->tmin = 0; 
      if (++me->thour == 24) { 
        me->thour = 0; 
        if (++me->dday == month[me->dmonth-1]+1) { 
          me->dday = 1; 
          if (++me->dmonth == 13)  
            me->dmonth = 1; 
        } 
      } 
    } 
  } 
} 
 
Msg const *Watch_top(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(me, &me->setting); 
    return 0; 
  case TICK_EVT: 
    if (++me->tsec == 60) 
      me->tsec = 0; 
    printf("Watch::top-TICK;"); 
    WatchShowTime(me); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_timekeeping(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(me, me->timekeepingHist); 
    return 0; 
  case SET_EVT: 
    STATE_TRAN(me, &me->setting); 
    printf("Watch::timekeeping-SET;"); 
    return 0; 
  case EXIT_EVT: 
    me->timekeepingHist = STATE_CURR(me); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_time(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case ENTRY_EVT: 
    WatchShowTime(me); 
    return 0; 
  case MODE_EVT: 
    STATE_TRAN(me, &me->date); 
    printf("Watch::time-DATE;");         
    return 0; 
  case TICK_EVT: 
    printf("Watch::time-TICK;");         
    WatchTick(me); 
    WatchShowTime(me); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_date(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case ENTRY_EVT: 
    WatchShowDate(me); 
    return 0; 
  case MODE_EVT: 
    STATE_TRAN(me, &me->time); 
    printf("Watch::date-DATE;");         
    return 0; 
  case TICK_EVT: 
    printf("Watch::date-TICK;");         
    WatchTick(me); 
    WatchShowDate(me); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_setting(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(me, &me->hour); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_hour(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(me, &me->minute); 
    printf("Watch::hour-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_minute(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(me, &me->day); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_day(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(me, &me->month); 
    printf("Watch::day-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch_month(Watch *me, Msg *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(me, &me->timekeeping); 
    printf("Watch::month-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
void WatchCtor(Watch *me) { 
  HsmCtor((Hsm *)me, "Watch", (EvtHndlr)Watch_top); 
  StateCtor(&me->timekeeping, "timekeeping",  
            &((Hsm *)me)->top, (EvtHndlr)Watch_timekeeping); 
    StateCtor(&me->time, "time", &me->timekeeping,  
              (EvtHndlr)Watch_time); 
    StateCtor(&me->date, "date", &me->timekeeping,  
              (EvtHndlr)Watch_date); 
  StateCtor(&me->setting, "setting", &((Hsm *)me)->top,  
            (EvtHndlr)Watch_setting); 
    StateCtor(&me->hour, "hour", &me->setting,  
              (EvtHndlr)Watch_hour); 
    StateCtor(&me->minute, "minute", &me->setting,  
              (EvtHndlr)Watch_minute); 
    StateCtor(&me->day, "day", &me->setting,  
              (EvtHndlr)Watch_day); 
    StateCtor(&me->month, "month", &me->setting,  
              (EvtHndlr)Watch_month); 

  me->timekeepingHist = &me->time;  
 
  me->tsec = me->tmin = me->thour = 0; 
  me->dday = me->dmonth = 1; 
} 
 
const Msg watchMsg[] = {  
  MODE_EVT, 
  SET_EVT, 
  TICK_EVT 
}; 

int main() {
  Watch watch;          
  WatchCtor(&watch); 
  HsmOnStart((Hsm *)&watch);
  for (;;)  {
    int i; 
    printf("\nEvent<-"); 
      scanf("%d", &i); 
      if (i < 0 || sizeof(watchMsg)/sizeof(Msg) <= i)  
        break; 
      HsmOnEvent((Hsm *)&watch, &watchMsg[i]);  
  }
  return 0;
}