/**************************************************************************** Module GameplayHSM.c Revision 2.0.1 Description This is the Gameplay module for ME 218B project for Team 3. Implements a hierarchical state machine under the Gen2 Events and Services Framework. Notes History When Who What/Why -------------- --- -------- 02/20/19 bibit converted from template to project file 02/20/17 14:30 jec updated to remove sample of consuming an event. We always want to return ES_NO_EVENT at the top level unless there is a non-recoverable error at the framework level 02/03/16 15:27 jec updated comments to reflect small changes made in '14 & '15 converted unsigned char to bool where appropriate spelling changes on true (was True) to match standard removed local var used for debugger visibility in 'C32 removed Microwave specific code and replaced with generic 02/08/12 01:39 jec converted from MW_MasterMachine.c 02/06/12 22:02 jec converted to Gen 2 Events and Services Framework 02/13/10 11:54 jec converted During functions to return Event_t so that they match the template 02/21/07 17:04 jec converted to pass Event_t to Start...() 02/20/07 21:37 jec converted to use enumerated type for events 02/21/05 15:03 jec Began Coding ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ /* 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 "ES_Configure.h" #include "ES_Framework.h" // this module's own header file #include "GameplayHSM.h" // next lowest level header files #include "Gameplay_GameTasksSM.h" // other modules #include "MotorSM.h" #include "PWM_Module.h" #include "inc/hw_pwm.h" #include "inc/hw_gpio.h" #include "inc/hw_sysctl.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_nvic.h" #include "inc/hw_Timer.h" #include "driverlib/gpio.h" #include "driverlib/sysctl.h" #include "driverlib/pin_map.h" #include "driverlib/pwm.h" /*----------------------------- Module Defines ----------------------------*/ // time for backing away from other robot before turning around #define BackAwayTime 1000 /*---------------------------- Module Functions ---------------------------*/ static ES_Event_t DuringIdleState(ES_Event_t Event); static ES_Event_t DuringGameTasksState(ES_Event_t Event); static void StopConveyor(void); static void StartConveyor(void); /*---------------------------- Module Variables ---------------------------*/ // everybody needs a state variable, though if the top level state machine // is just a single state container for orthogonal regions, you could get // away without it static GameplayState_t CurrentState; // with the introduction of Gen2, we need a module level Priority var as well static uint8_t MyPriority; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function InitGameplayMasterSM Parameters uint8_t : the priority of this service Returns boolean, False if error in initialization, True otherwise Description Saves away the priority, and starts the top level state machine. Also sets initial state for the conveyor motor. Notes Author Bibit Bianchini, 2/20/2019 ****************************************************************************/ bool InitGameplayMasterSM(uint8_t Priority) { ES_Event_t ThisEvent; MyPriority = Priority; // save our priority // start with the conveyor motor stopped StopConveyor(); ThisEvent.EventType = ES_ENTRY; // Start the Master State machine StartGameplayMasterSM(ThisEvent); return true; } /**************************************************************************** Function PostGameplayMasterSM Parameters ES_Event_t ThisEvent, the event to post to the queue Returns boolean False if the post operation failed, True otherwise Description Posts an event to this state machine's queue Notes Author J. Edward Carryer, 10/23/11, 19:25 ****************************************************************************/ bool PostGameplayMasterSM(ES_Event_t ThisEvent) { return ES_PostToService(MyPriority, ThisEvent); } /**************************************************************************** Function RunGameplayMasterSM Parameters ES_Event_t: the event to process Returns ES_Event_t: an event to return Description the run function for the top level Gameplay state machine Notes uses nested switch/case to implement the machine Author Bibit Bianchini, 2/20/2019 ****************************************************************************/ ES_Event_t RunGameplayMasterSM(ES_Event_t CurrentEvent) { bool MakeTransition = false; // are we making a state transition? GameplayState_t NextState = CurrentState; // default to normal entry to new state ES_Event_t EntryEventKind = { ES_ENTRY, 0 }; ES_Event_t ReturnEvent = { ES_NO_EVENT, 0 }; // assume no error switch (CurrentState) { case IdleGame: // If current state is Idle { // execute During function for Idle state. ES_ENTRY & ES_EXIT are // processed there to allow the lower level state machines to re-map or // consume the event CurrentEvent = DuringIdleState(CurrentEvent); // process any events if (CurrentEvent.EventType != ES_NO_EVENT) // if an event is active { switch (CurrentEvent.EventType) { case GAME_STARTED: // if the game has started { // we want to move to GameTasks state NextState = GameTasks; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; // we do not want to enter GameTasks with history, so we will // leave the default to ES_ENTRY (make no change) //EntryEventKind.EventType = ES_ENTRY_HISTORY; } break; } } } break; case GameTasks: // If current state is GameTasks { // execute During function for GameTasks state. ES_ENTRY & ES_EXIT are // processed there to allow the lower level state machines to re-map or // consume the event CurrentEvent = DuringGameTasksState(CurrentEvent); // process any events if (CurrentEvent.EventType != ES_NO_EVENT) // if an event is active { switch (CurrentEvent.EventType) { case GAME_OVER: // if the game has ended { // we want to move to Idle state NextState = IdleGame; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; } break; } } } break; } // end of switch on CurrentState // if we are making a state transition if (MakeTransition == true) { // execute exit function for current state CurrentEvent.EventType = ES_EXIT; RunGameplayMasterSM(CurrentEvent); CurrentState = NextState; // modify state variable // execute entry function for new state (this defaults to ES_ENTRY) RunGameplayMasterSM(EntryEventKind); } // in the absence of an error the top level state machine should // always return ES_NO_EVENT, which we initialized at the top of function return ReturnEvent; } /**************************************************************************** Function StartGameplayMasterSM Parameters ES_Event_t CurrentEvent Returns none Description Does any required initialization for this state machine Notes Author Bibit Bianchini, 2/20/2019 ****************************************************************************/ void StartGameplayMasterSM(ES_Event_t CurrentEvent) { // initialize the CurrentState variable to start in Idle state CurrentState = IdleGame; // now we need to let the Run function init the lower level state machines // use LocalEvent to keep the compiler from complaining about unused var RunGameplayMasterSM(CurrentEvent); return; } /**************************************************************************** Function QueryGameplayHSM Parameters None Returns GameplayState_t The current state of the state machine Description returns the current state of the Gameplay state machine Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ GameplayState_t QueryGameplayHSM(void) { return CurrentState; } /*************************************************************************** private functions ***************************************************************************/ /**************************************************************************** Function DuringIdleState Parameters ES_Event_t Event Returns ES_Event_t Description During function for the Idle state. Processes ES_ENTRY and ES_EXIT events, but has no lower state machine to call. Notes Author Bibit Bianchini, 2/20/2019 ****************************************************************************/ static ES_Event_t DuringIdleState(ES_Event_t Event) { ES_Event_t ReturnEvent = Event; // assume no re-mapping or comsumption // process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events if ((Event.EventType == ES_ENTRY) || (Event.EventType == ES_ENTRY_HISTORY)) { // stop conveyor belt StopConveyor(); // no lower state machines to start } else if (Event.EventType == ES_EXIT) { // no lower state machines to give the chance to clean up // start conveyor belt StartConveyor(); } // this state machine doesn't have a lower state machine to run // return either Event, if you don't want to allow the lower level machine // to remap the current event, or ReturnEvent if you do want to allow it. return ReturnEvent; } /**************************************************************************** Function DuringGameTasksState Parameters ES_Event_t Event Returns ES_Event_t Description During function for the GameTasks state. Processes ES_ENTRY and ES_EXIT events, and calls lower state machines. Notes Author Bibit Bianchini, 2/20/2019 ****************************************************************************/ static ES_Event_t DuringGameTasksState(ES_Event_t Event) { ES_Event_t ReturnEvent = Event; // assume no re-mapping or comsumption // process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events if ((Event.EventType == ES_ENTRY) || (Event.EventType == ES_ENTRY_HISTORY)) { // no actions for entering this state // after that start the lower level machine that runs in this state StartGameTasksSM(Event); } else if (Event.EventType == ES_EXIT) { // on exit, give the lower levels a chance to clean up first RunGameTasksSM(Event); // no actions for exiting this state } else // do the 'during' function for this state { // run any lower level state machine ReturnEvent = RunGameTasksSM(Event); } // return either Event, if you don't want to allow the lower level machine // to remap the current event, or ReturnEvent if you do want to allow it. return ReturnEvent; } /**************************************************************************** Collection of Functions StopConveyor StartConveyor Parameters none Returns none Description Stops/starts the conveyor belt. Notes Author Bibit Bianchini, 3/01/2019 ****************************************************************************/ static void StopConveyor(void) { // set the conveyor output pin low HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA + ALL_BITS)) &= BIT0LO; } static void StartConveyor(void) { // set the conveyor output pin high HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA + ALL_BITS)) |= BIT0HI; } /*------------------------------- Footnotes -------------------------------*/ /*------------------------------ End of file ------------------------------*/