/**************************************************************************** Module d:\me218bTNG\Lectures\Lecture31\SMTemplate.c Revision 1.0.1 Description This is a template file for implementing state machines. Notes History When Who What/Why -------------- --- -------- 02/20/07 21:37 jec converted to use enumerated type for events & states 02/13/05 19:38 jec added support for self-transitions, reworked to eliminate repeated transition code 02/11/05 16:54 jec converted to implment hierarchy explicitly 02/25/03 10:32 jec converted to take a passed event parameter 02/18/99 10:19 jec built template from MasterMachine.c 02/14/99 10:34 jec Began Coding ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ #include "GlobalHeader.h" #include "SMGameState.h" #include "SMOffensiveCoordinator.h" /*----------------------------- Module Defines ----------------------------*/ #define GAME_STATUS_QUERY_INTERVAL 1000//ms #define GAME_TIMER_TICK 3750 // = 10ms per timer tick. 12000 ticks per 2 min /*---------------------------- Module Functions ---------------------------*/ static Event_t DuringPaused( Event_t Event); static Event_t DuringOn( Event_t Event); static void GameTimerInit(void); /*---------------------------- Module Variables ---------------------------*/ static GameState_t CurrentState; static unsigned int Game_ElapsedTime = 0; //Game timer static unsigned char Game_StartFlag = 0; static unsigned char Game_PauseFlag = 0; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function QueryGameStartFlag Parameters none Returns 1 if StartFlag set, 0 otherwise Description indicates whether we need to transition to Game_On state. ****************************************************************************/ unsigned char QueryGameStartFlag(void) { unsigned char ReturnVal = Game_StartFlag; Game_StartFlag = 0; return ReturnVal; } /**************************************************************************** Function QueryGamePauseFlag Parameters none Returns 1 if PauseFlag set, 0 otherwise Description indicates whether we need to transition to Game_paused state. ****************************************************************************/ unsigned char QueryGamePauseFlag(void) { unsigned char ReturnVal = Game_PauseFlag; Game_PauseFlag = 0; return ReturnVal; } /**************************************************************************** Function QueryGameTime Parameters none Returns unsigned int - time passed while game was in state Game_On, in 10s of ms. Description Returns value of game timer, in 10s of ms. ****************************************************************************/ unsigned int QueryGameTime(void) { return Game_ElapsedTime; } /**************************************************************************** Function GameTimerInit Parameters none Returns none Description Initializes output compare for game timer. Notes Output compare timer is shared with that of the OC module. prescales need to be identical. ****************************************************************************/ static void GameTimerInit(void) { //Shares timer with OC. make sure prescales match. TIM2_TSCR1 |= _S12_TEN; TIM2_TSCR2 |= (_S12_PR2 | _S12_PR1) ; //Prescale of 64. 375kHz TIM2_TCTL1 &= ~(_S12_OL4 | _S12_OM4); //no output change TIM2_TIOS |= _S12_IOS4; //P4 output compare TIM2_TIE &= ~_S12_C4I; //Start with interrupt disabled //don't enable yet, since game hasn't started TIM2_TFLG1 = _S12_C4F; //clear flag } /**************************************************************************** Function RunGameSM Parameters Event_t Returns Event_t Description Runs Gamestate State machine. switches between game_on and game_paused. ****************************************************************************/ Event_t RunGameSM( Event_t CurrentEvent ) { unsigned char MakeTransition = FALSE;/* are we making a state transition? */ GameState_t NextState = CurrentState; switch ( CurrentState ) { case Game_Paused : CurrentEvent = DuringPaused(CurrentEvent); //process any events if ( CurrentEvent != EV_NO_EVENT ) //If an event is active { switch (CurrentEvent) { case EV_OC_NewResponse : if (QueryOCLastCommand() == OC_QueryGameStatus) { switch(QueryOCResponse()) { case OC_GameRunning: //if game_state paused and response is game_running Game_StartFlag = 1; break; } } break; case EV_Game_On : NextState = Game_On; //Decide what the next state will be MakeTransition = TRUE; //mark that we are taking a transition break; } } break; case Game_On : CurrentEvent = DuringOn(CurrentEvent); //process any events if ( CurrentEvent != EV_NO_EVENT ) //If an event is active { switch (CurrentEvent) { case EV_OC_NewResponse : if (QueryOCLastCommand() == OC_QueryGameStatus) { switch(QueryOCResponse()) { case OC_GamePaused: //if game_state is on and response is game_paused case OC_GameWonRed: case OC_GameWonGreen: Game_PauseFlag = 1; break; } } break; case EV_Game_Pause : NextState = Game_Paused;//Decide what the next state will be MakeTransition = TRUE; //mark that we are taking a transition break; } } break; } // If we are making a state transition if (MakeTransition == TRUE) { // Execute exit function for current state (void)RunGameSM(EV_EXIT); CurrentState = NextState; //Modify state variable printf("Next Game State %d\r\n",NextState); // Execute entry function for new state (void)RunGameSM(EV_ENTRY); } return(CurrentEvent); } /**************************************************************************** Function StartGameSM Parameters Event_t Returns none Description Starts Gamestate state machine ****************************************************************************/ void StartGameSM ( Event_t CurrentEvent ) { GameTimerInit(); // CurrentState = Game_On; //start on CurrentState = Game_Paused; //start paused printf("Entering Gamestate SM\r\n"); // call the entry function (if any) for the ENTRY_STATE (void)RunGameSM(EV_ENTRY); } /**************************************************************************** Function QueryGameSM Parameters none Returns GameState_t - state of machine Description returns state of state machine ****************************************************************************/ GameState_t QueryGameSM ( void ) { return(CurrentState); } /*************************************************************************** private functions ***************************************************************************/ /**************************************************************************** Function DuringPaused Parameters Event_t Returns Event_t Description Constantly queries to see if game has started. Also checks color and halfcourt switches. ****************************************************************************/ static Event_t DuringPaused( Event_t Event) { // process EV_ENTRY & EV_EXIT events if ( Event == EV_ENTRY) { }else if ( Event == EV_EXIT) { }else // do the 'during' function for this state { if (QueryOCQueueLength()==0) OC_AddCommand(OC_QueryGameStatus,0); //check if game has started SetColor(); SetHalfCourt(); } return(Event); } /**************************************************************************** Function DuringOn Parameters Event_t Returns Event_t Description On entry, starts game timer, as well as Gameplay, Sensors, and Drivetrain SMs. Normally updates these SMs, and checks to see if game has been paused. On exit, pauses game timer by disabling interrupt. ****************************************************************************/ static Event_t DuringOn( Event_t Event) { // process EV_ENTRY & EV_EXIT events if ( Event == EV_ENTRY) { //Resume Timer TIM2_TC4 = TIM2_TCNT + GAME_TIMER_TICK; //Set Timer TIM2_TFLG1 = _S12_C4F; //clear flag TIM2_TIE |= _S12_C4I; //Enable Interrupt StartPlaySM(Event); StartSensorsSM(Event); StartDriveSM(Event); SetColor(); }else if ( Event == EV_EXIT) { (void)RunPlaySM(Event); (void)RunSensorsSM(Event); (void)RunDriveSM(Event); TIM2_TIE &= ~_S12_C4I; //Pause timer }else // do the 'during' function for this state { static unsigned int LastTime; unsigned int CurrentTime = TMRS12_GetTime(); if (CurrentTime - LastTime >= GAME_STATUS_QUERY_INTERVAL) { LastTime = CurrentTime; OC_AddCommand(OC_QueryGameStatus,0); //check if game has paused } (void)RunPlaySM(Event); (void)RunSensorsSM(Event); (void)RunDriveSM(Event); } return(Event); } /**************************************************************************** Interrupt GameTimerTick Description Increments game timer ****************************************************************************/ void interrupt _Vec_tim2ch4 GameTimerTick(void) //port P4 { Game_ElapsedTime += 1; TIM2_TC4 += GAME_TIMER_TICK; TIM2_TFLG1 = _S12_C4F; }