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


/**
 * Simple digital watch example
 * M. Samek, 01/07/00
 */ 
#include  
#include  
#include "hsm.h" 
 
class Watch : public Hsm { 
  int tsec, tmin, thour, dday, dmonth; 
protected: 
  State timekeeping, time, date; 
  State setting, hour, minute, day, month; 
  State *timekeepingHist; 
public: 
  Watch(); 
  Msg const *topHndlr(Msg const *msg);   
  Msg const *timekeepingHndlr(Msg const *msg);   
  Msg const *timeHndlr(Msg const *msg);   
  Msg const *dateHndlr(Msg const *msg);   
  Msg const *settingHndlr(Msg const *msg);   
  Msg const *hourHndlr(Msg const *msg);   
  Msg const *minuteHndlr(Msg const *msg);   
  Msg const *dayHndlr(Msg const *msg);   
  Msg const *monthHndlr(Msg const *msg);   
  void tick(); 
  void showTime(); 
  void showDate(); 
}; 
 
enum WatchEvents { 
  MODE_EVT, 
  SET_EVT, 
  TICK_EVT 
}; 
 
void Watch::showTime() { 
  printf("time: %2d:%02d:%02d", thour, tmin, tsec); 
} 
 
void Watch::showDate() { 
  printf("date: %02d-%02d", dmonth, dday); 
} 
 
void Watch::tick() { 
  static int const month[] = {  
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31  
  }; 
  if (++tsec == 60) { 
    tsec = 0; 
    if (++tmin == 60) { 
      tmin = 0; 
      if (++thour == 24) { 
        thour = 0; 
        if (++dday == month[dmonth-1]+1) { 
          dday = 1; 
          if (++dmonth == 13)  
            dmonth = 1; 
        } 
      } 
    } 
  } 
} 
 
Msg const *Watch::topHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(&setting); 
    return 0; 
  case TICK_EVT: 
    if (++tsec == 60) 
      tsec = 0; 
    printf("Watch::top-TICK;"); 
    showTime(); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::timekeepingHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(timekeepingHist); 
    return 0; 
  case SET_EVT: 
    STATE_TRAN(&setting); 
    printf("Watch::timekeeping-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::timeHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case ENTRY_EVT: 
    showTime(); 
    return 0; 
  case MODE_EVT: 
    STATE_TRAN(&date); 
    printf("Watch::time-DATE;");         
    return 0; 
  case TICK_EVT: 
    printf("Watch::time-TICK;");         
    tick(); 
    showTime(); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::dateHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case ENTRY_EVT: 
    showDate(); 
    return 0; 
  case MODE_EVT: 
    STATE_TRAN(&time); 
    printf("Watch::date-DATE;");         
    return 0; 
  case TICK_EVT: 
    printf("Watch::date-TICK;");         
    tick(); 
    showDate(); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::settingHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case START_EVT: 
    STATE_START(&hour); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::hourHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(&minute); 
    printf("Watch::hour-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::minuteHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(&day); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::dayHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(&month); 
    printf("Watch::day-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Msg const *Watch::monthHndlr(Msg const *msg) { 
  switch (msg->evt) { 
  case SET_EVT: 
    STATE_TRAN(&timekeeping); 
    printf("Watch::month-SET;"); 
    return 0; 
  }  
  return msg; 
} 
 
Watch::Watch()  
: Hsm("Watch", (EvtHndlr)topHndlr), 
  timekeeping("timekeeping", &top, 
       (EvtHndlr)&Watch::timekeepingHndlr), 
  time("time", &timekeeping, (EvtHndlr)&Watch::timeHndlr), 
  date("date", &timekeeping, (EvtHndlr)&Watch::dateHndlr), 
  setting("setting", &top, (EvtHndlr)&Watch::settingHndlr), 
  hour("hour", &setting, (EvtHndlr)&Watch::hourHndlr), 
  minute("minute", &setting, (EvtHndlr)&Watch::minuteHndlr), 
  day("day", &setting, (EvtHndlr)&Watch::dayHndlr), 
  month("month", &setting, (EvtHndlr)&Watch::monthHndlr), 
  tsec(0), tmin(0), thour(0), dday(1), dmonth(1)
{
  timekeepingHist = &time;  
} 
 
const Msg watchMsg[] = {  
  MODE_EVT, 
  SET_EVT, 
  TICK_EVT 
}; 

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