/**************************************************************************** Module GameSM.c Revision 2.0.1 Description This is a source file for implementing state machines for GameSM. Notes ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ // Basic includes for a program using the Events and Services Framework #include "ES_Configure.h" #include "ES_Framework.h" #include "DriveMotors.h" /* include header files for this state machine as well as any machines at the next lower level in the hierarchy that are sub-machines to this machine */ #include "GameSM.h" #include "ServoControl.h" #include "Pins.h" #include "LauncherControl.h" //Lower Level SM: #include "JoustSM.h" #include "SimpleDriveToASM.h" #include "SimpleDriveToBSM.h" #include "Round2DriveSM.h" #include "Recess2SM.h" #include "Round3DriveSM.h" /*----------------------------- Module Defines ----------------------------*/ // define constants for the states for this machine // and any other local defines /*---------------------------- Module Functions ---------------------------*/ /* prototypes for private functions for this machine, things like during functions, entry & exit functions.They should be functions relevant to the behavior of this state machine */ //static ES_Event DuringStateOne( ES_Event Event); //static ES_Event DuringGameSM( ES_Event Event); static ES_Event DuringRound1( ES_Event Event); static ES_Event DuringRecess1( ES_Event Event); static ES_Event DuringRound2( ES_Event Event); static ES_Event DuringRecess2( ES_Event Event); static ES_Event DuringRound3( ES_Event Event); static ES_Event DuringRecess3(ES_Event Event); static ES_Event DuringSuddenDeath( ES_Event Event); /*---------------------------- Module Variables ---------------------------*/ // everybody needs a state variable, you may need others as well static GameState_t CurrentState; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function RunGameSM Parameters ES_Event: the event to process Returns ES_Event: an event to return Description add your description here Notes uses nested switch/case to implement the machine. Author Chih-Wei Tang, 2/11/05, 10:45AM ****************************************************************************/ ES_Event RunGameSM( ES_Event CurrentEvent ) { unsigned char MakeTransition = false;/* are we making a state transition? */ GameState_t NextState = CurrentState; ES_Event ReturnEvent = CurrentEvent; // assume we are not consuming event ES_Event EntryEventKind = {ES_ENTRY, 0}; switch ( CurrentState ) { case Idle : // TODO:Execute During function for state one. ES_ENTRY & ES_EXIT are // processed here allow the lowere level state machines to re-map // or consume the event // Debug //printf("Idle\r\n"); //process any events if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_PAS_DARMES : //If event is match underway // Debug printf("Event: EV_PAS_DARMES, Next State: Round 1\r\n"); // Execute action function for state one : event one NextState = Round1;//Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; }//end switch }// end current type break; case Round1: //process during function for Round1 CurrentEvent = DuringRound1(CurrentEvent); // Debug //printf("Round 1\r\n"); //process any events if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_RECESS : //If event is RECESS //Debug printf("Event: EV_RECESS, Next State: Recess 1\r\n"); // Execute action function for state one : event one NextState = Recess1;//Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition // Enter Recess 1 with History EntryEventKind.EventType = ES_ENTRY_HISTORY; ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; }//end switch event type } // end if there is event break; // break state switch case case Recess1: //Process during function for Recess1 CurrentEvent = DuringRecess1(CurrentEvent); //process any events if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_PAS_DARMES : //If event is match underway //Debug printf("Event: EV_PAS_DARMES, Next State: Round 2\r\n"); // Execute action function for state one : event one NextState = Round2;//Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; case ES_TIMEOUT: if(SWING_TIMER == CurrentEvent.EventParam){ //Retract the lance LanceServoToPosition(RETRACTED_POSITION); } break; } //end switch } // end if there is no event break; //break state switch case case Round2: //TODO:process during function for Round2 //process any events CurrentEvent = DuringRound2(CurrentEvent); if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_RECESS : //If event is RECESS //Debug printf("Event: EV_RECESS, Next State: Recess 2\r\n"); // Execute action function for Round2: go to recess2 NextState = Recess2;//Go to next Recess2 state // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; }//end switch event type } // end if there is event break; case Recess2: //TODO: process during function for Recess2 //process any events CurrentEvent = DuringRecess2(CurrentEvent); if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_PAS_DARMES : //If event is match underway //Debug printf("Event: EV_PAS_DARMES, Next State: Round 3\r\n"); // go to next state: Round3 NextState = Round3;//Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; case ES_TIMEOUT: if(SWING_TIMER == CurrentEvent.EventParam){ //Retract the lance LanceServoToPosition(RETRACTED_POSITION); } break; } //end switch } // end if there is no event break; case Round3: //TODO: process during function for Round3 //process any events CurrentEvent = DuringRound3(CurrentEvent); if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_RECESS : //If event is RECESS //Debug printf("Event: EV_RECESS, Next State: Recess 3\r\n"); // Execute action function for Round3: go to recess3, prepare for sudden death NextState = Recess3;//Go to next Recess2 state // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; }//end switch event type } // end if there is event break; case Recess3: //TODO: process during function for Recess3 //process any events CurrentEvent = DuringRecess3(CurrentEvent); if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { switch (CurrentEvent.EventType) { case EV_SUDDEN_DEATH : //If event is match underway //Debug printf("Event: EV_SUDDEN_DEATH, Next State: Sudden Death\r\n"); // go to next state: Round3 NextState = SuddenDeath;//Decide what the next state will be // for internal transitions, skip changing MakeTransition MakeTransition = true; //mark that we are taking a transition ReturnEvent.EventType = ES_NO_EVENT; //consume the event at current level break; case ES_TIMEOUT: if(SWING_TIMER == CurrentEvent.EventParam){ //Retract the lance LanceServoToPosition(RETRACTED_POSITION); } break; } //end switch } // end if there is no event break; case SuddenDeath: CurrentEvent = DuringSuddenDeath(CurrentEvent); if ( ES_NO_EVENT != CurrentEvent.EventType ) //If an event is active { } // end if there is event break; // repeat state pattern as required for other states } // If we are making a state transition if (true == MakeTransition) { // Execute exit function for current state CurrentEvent.EventType = ES_EXIT; RunGameSM(CurrentEvent); CurrentState = NextState; //Modify state variable // Execute entry function for new state // set event type to ES_ENTRY RunGameSM(EntryEventKind); } return(ReturnEvent); } /**************************************************************************** Function StartGameSM Parameters None Returns None Description Does any required initialization for this state machine Notes Author Chih-Wei Tang 2/18/99, 10:38AM ****************************************************************************/ void StartGameSM ( ES_Event CurrentEvent ) { // local variable to get debugger to display the value of CurrentEvent ES_Event LocalEvent = CurrentEvent; // to implement entry to a history state or directly to a substate // you can modify the initialization of the CurrentState variable // otherwise just start in the entry state every time the state machine // is started if ( ES_ENTRY_HISTORY != CurrentEvent.EventType ) { CurrentState = Idle; printf("CurrentState: IDLE \n\r"); } // call the entry function (if any) for the ENTRY_STATE RunGameSM(CurrentEvent); } /**************************************************************************** Function QueryGameSM Parameters None Returns GameState_t The current state of the GameSM state machine Description returns the current state of the GameSM state machine Notes Author J. Edward Carryer, 2/11/05, 10:38AM ****************************************************************************/ GameState_t QueryGameSM ( void ) { return(CurrentState); } /*************************************************************************** private functions ***************************************************************************/ static ES_Event DuringRound1( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartSimpleDriveToBSM(Event); StartJoustSM(Event); //Turn on Status LED PORT_STATUS_LED |= PIN_STATUS_LED; }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunSimpleDriveToBSM(Event); RunJoustSM(Event); }else // do the 'during' function for this state { RunSimpleDriveToBSM(Event); RunJoustSM(Event); // run any lower level state machine } return(Event); } static ES_Event DuringRecess1( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY || Event.EventType == ES_ENTRY_HISTORY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartSimpleDriveToBSM(Event); //Turn on Launcher Motor StartLauncherMotor(); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunSimpleDriveToBSM(Event); }else // do the 'during' function for this state { Event = RunSimpleDriveToBSM(Event); // run any lower level state machine } return(Event); } static ES_Event DuringRound2( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartRound2DriveSM(Event); StartJoustSM(Event); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunRound2DriveSM(Event); RunJoustSM(Event); }else // do the 'during' function for this state { RunRound2DriveSM(Event); RunJoustSM(Event); } return(Event); } static ES_Event DuringRecess2( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY || Event.EventType == ES_ENTRY_HISTORY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartRecess2SM(Event); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunRecess2SM(Event); }else // do the 'during' function for this state { Event = RunRecess2SM(Event); } return(Event); } static ES_Event DuringRound3( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartRound3DriveSM(Event); StartJoustSM(Event); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunRound3DriveSM(Event); RunJoustSM(Event); }else // do the 'during' function for this state { RunRound3DriveSM(Event); RunJoustSM(Event); } return(Event); } static ES_Event DuringRecess3( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY || Event.EventType == ES_ENTRY_HISTORY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartSimpleDriveToBSM(Event); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first Event = RunSimpleDriveToBSM(Event); }else // do the 'during' function for this state { Event = RunSimpleDriveToBSM(Event); } return(Event); } static ES_Event DuringSuddenDeath( ES_Event Event ) { // process ES_ENTRY & ES_EXIT events if ( Event.EventType == ES_ENTRY) { // implement any entry actions required for this state machine // after that start any lower level machines that run in this state StartSimpleDriveToASM(Event); StartJoustSM(Event); }else if ( Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunSimpleDriveToASM(Event); RunJoustSM(Event); }else // do the 'during' function for this state { RunSimpleDriveToASM(Event); RunJoustSM(Event); } return(Event); }