/**************************************************************************** Module Gameplay_GameTasks_CollectBallsSM.c Revision 2.0.1 Description This is a sub state machine (3rd level) called CollectBalls within the GameTasks level within the Gameplay module for ME 218B project for Team 3. Implements a hierarchical state machine under the Gen2 Events and Services Framework. Notes TO IMPLEMENT: - History When Who What/Why -------------- --- -------- 02/23/19 bibit converted from template to project file 02/27/17 09:48 jec another correction to re-assign both CurrentEvent and ReturnEvent to the result of the During function this eliminates the need for the prior fix and allows the during function to-remap an event that will be processed at a higher level. 02/20/17 10:14 jec correction to Run function to correctly assign ReturnEvent in the situation where a lower level machine consumed an event. 02/03/16 12:38 jec updated comments to reflect 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 commented out references to Start & RunLowerLevelSM so that this can compile. 02/07/13 21:00 jec corrections to return variable (should have been ReturnEvent, not CurrentEvent) and several EV_xxx event names that were left over from the old version 02/08/12 09:56 jec revisions for the Events and Services Framework Gen2 02/13/10 14:29 jec revised Start and run to add new kind of entry function to make implementing history entry cleaner 02/13/10 12:29 jec added NewEvent local variable to During function and comments about using either it or Event as the return 02/11/10 15:54 jec more revised comments, removing last comment in during function that belongs in the run function 02/09/10 17:21 jec updated comments about internal transitions on During funtion 02/18/09 10:14 jec removed redundant call to RunLowerlevelSM in EV_Entry processing in During function 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 -----------------------------*/ // Basic includes for a program using the Events and Services Framework #include "ES_Configure.h" #include "ES_Framework.h" // include this module's own header file #include "Gameplay_GameTasks_CollectBallsSM.h" // include the highest level header file for this HSM #include "GameplayHSM.h" // other modules #include "MotorSM.h" /*----------------------------- Module Defines ----------------------------*/ // define constants for the states for this machine // and any other local defines #define ENTRY_STATE DrivingForward #define BackingUpTime 1000 /*---------------------------- 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_t DuringDrivingForward(ES_Event_t Event); static ES_Event_t DuringBackingUp(ES_Event_t Event); static ES_Event_t DuringTurningCW90(ES_Event_t Event); /*---------------------------- Module Variables ---------------------------*/ // everybody needs a state variable, you may need others as well static CollectBallsState_t CurrentState; /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function RunCollectBallsSM Parameters ES_Event_t: the event to process Returns ES_Event_t: an event to return Description run function for the CollectBalls state machine Notes uses nested switch/case to implement the machine. Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ ES_Event_t RunCollectBallsSM(ES_Event_t CurrentEvent) { bool MakeTransition = false; // are we making a state transition? CollectBallsState_t NextState = CurrentState; // default to normal entry to new state ES_Event_t EntryEventKind = { ES_ENTRY, 0 }; ES_Event_t ReturnEvent = CurrentEvent; // assume we are not consuming event switch (CurrentState) { case DrivingForward: // If current state is DrivingForward { printf("\r\n IN RUN COLLECT BALLS, DrivingForward CASE\r\n"); // Execute During function for DrivingForward. ES_ENTRY & ES_EXIT are // processed here to allow the lower level state machines to re-map or // consume the event ReturnEvent = CurrentEvent = DuringDrivingForward(CurrentEvent); // process any events if (CurrentEvent.EventType != ES_NO_EVENT) // if an event is active { switch (CurrentEvent.EventType) { case FRONT_LIMIT_HIT_L: // if our robot has bumped into a wall in // front left corner { // post MOTOR_COMMAND with EventParam BACKWARDS ES_Event_t PostEvent; PostEvent.EventType = MOTOR_COMMAND; PostEvent.EventParam = BACKWARDS; PostMotorSM(PostEvent); // start timer to allow robot to back away from wall ES_Timer_InitTimer(GameplayTimer, BackingUpTime); // we want to move to BackingUp state NextState = BackingUp; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; // we do not want to enter BackingUp with history, so we will // leave the default to ES_ENTRY (make no change) //EntryEventKind.EventType = ES_ENTRY_HISTORY; // consume this event for the upper state machines ReturnEvent.EventType = ES_NO_EVENT; } break; case FRONT_LIMIT_HIT_R: // if our robot has bumped into a wall in // front right corner { // post MOTOR_COMMAND with EventParam BACKWARDS ES_Event_t PostEvent; PostEvent.EventType = MOTOR_COMMAND; PostEvent.EventParam = BACKWARDS; PostMotorSM(PostEvent); // start timer to allow robot to back away from wall ES_Timer_InitTimer(GameplayTimer, BackingUpTime); // we want to move to BackingUp state NextState = BackingUp; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; // we do not want to enter BackingUp with history, so we will // leave the default to ES_ENTRY (make no change) //EntryEventKind.EventType = ES_ENTRY_HISTORY; // consume this event for the upper state machines ReturnEvent.EventType = ES_NO_EVENT; } break; } } } break; // end switch on CurrentState case for DrivingForward case BackingUp: // If current state is BackingUp { printf("\r\n IN RUN COLLECT BALLS, BackingUp CASE\r\n"); // Execute During function for BackingUp. ES_ENTRY & ES_EXIT are // processed here to allow the lower level state machines to re-map or // consume the event ReturnEvent = CurrentEvent = DuringBackingUp(CurrentEvent); // process any events if (CurrentEvent.EventType != ES_NO_EVENT) // if an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT: // if our robot has finished backing up a bit { // check that the correct timer timed out (GameplayTimer): if (CurrentEvent.EventParam == GameplayTimer) { // post MOTOR_COMMAND with EventParam CCW90 // (this will start a motor timer) ES_Event_t PostEvent; PostEvent.EventType = MOTOR_COMMAND; PostEvent.EventParam = CCW90; PostMotorSM(PostEvent); // we want to move to TurningCCW90 state NextState = TurningCCW90; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; // we do not want to enter TurningCCW90 with history, so we // will leave the default to ES_ENTRY (make no change) //EntryEventKind.EventType = ES_ENTRY_HISTORY; // consume this event for the upper state machines ReturnEvent.EventType = ES_NO_EVENT; } } break; } } } break; // end switch on CurrentState case for BackingUp case TurningCCW90: // If current state is TurningCCW90 { printf("\r\n IN RUN COLLECT BALLS, TurningCCW90 CASE\r\n"); // Execute During function for GoingAroundRobot. ES_ENTRY & ES_EXIT are // processed here to allow the lower level state machines to re-map or // consume the event ReturnEvent = CurrentEvent = DuringTurningCW90(CurrentEvent); // process any events if (CurrentEvent.EventType != ES_NO_EVENT) // if an event is active { switch (CurrentEvent.EventType) { case ES_TIMEOUT: // if our robot has finished driving around robot { // check that the correct timer timed out (MotorTimer): if (CurrentEvent.EventParam == MotorTimer) { // post MOTOR_COMMAND with EventParam FORWARD ES_Event_t PostEvent; PostEvent.EventType = MOTOR_COMMAND; PostEvent.EventParam = FORWARD; PostMotorSM(PostEvent); // we want to move to DrivingForward state NextState = DrivingForward; // mark that we are taking a transition (for internal // transitions, skip changing MakeTransition) MakeTransition = true; // we do not want to enter DrivingForward with history, so we // will leave the default to ES_ENTRY (make no change) //EntryEventKind.EventType = ES_ENTRY_HISTORY; // we will not consume this event so the upper state machines // can react on this event //ReturnEvent.EventType = ES_NO_EVENT; } } break; } } } break; // end switch on CurrentState case for TurningCCW90 } // if we are making a state transition if (MakeTransition == true) { // Execute exit function for current state CurrentEvent.EventType = ES_EXIT; RunCollectBallsSM(CurrentEvent); CurrentState = NextState; // Modify state variable // Execute entry function for new state // this defaults to ES_ENTRY RunCollectBallsSM(EntryEventKind); } return ReturnEvent; } /**************************************************************************** Function StartCollectBallsSM Parameters None Returns None Description Does any required initialization for this state machine Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ void StartCollectBallsSM(ES_Event_t 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 (CurrentEvent.EventType != ES_ENTRY_HISTORY) { CurrentState = ENTRY_STATE; } // call the entry function (if any) for the ENTRY_STATE RunCollectBallsSM(CurrentEvent); } /**************************************************************************** Function QueryCollectBallsSM Parameters None Returns CollectBallsState_t The current state of the state machine Description returns the current state of the CollectBalls state machine Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ CollectBallsState_t QueryCollectBallsSM(void) { return CurrentState; } /*************************************************************************** private functions ***************************************************************************/ /**************************************************************************** Function DuringDrivingForward Parameters ES_Event_t Event Returns ES_Event_t Description During function for the DrivingForward state. Does nothing because nothing to do for ES_ENTRY and ES_EXIT events, and doesn't have lower state machines. Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ static ES_Event_t DuringDrivingForward(ES_Event_t Event) { ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption // process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events if ((Event.EventType == ES_ENTRY) || (Event.EventType == ES_ENTRY_HISTORY)) { // no tasks to do for entry into DrivingForward // no lower level state machine to start } else if (Event.EventType == ES_EXIT) { // no lower level state machine to pass the exit to // no tasks to do for exit from DrivingForward } // this state 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 DuringBackingUp Parameters ES_Event_t Event Returns ES_Event_t Description During function for the BackingUp state. Does nothing because nothing to do for ES_ENTRY and ES_EXIT events, and doesn't have lower state machines. Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ static ES_Event_t DuringBackingUp(ES_Event_t Event) { ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption // process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events if ((Event.EventType == ES_ENTRY) || (Event.EventType == ES_ENTRY_HISTORY)) { // no tasks to do for entry into BackingUp // no lower level state machine to start } else if (Event.EventType == ES_EXIT) { // no lower level state machine to pass the exit to // no tasks to do for exit from BackingUp } // this state 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 DuringTurningCW90 Parameters ES_Event_t Event Returns ES_Event_t Description During function for the TurningCW90 state. Does nothing because nothing to do for ES_ENTRY and ES_EXIT events, and doesn't have lower state machines. Notes Author Bibit Bianchini, 2/23/2019 ****************************************************************************/ static ES_Event_t DuringTurningCW90(ES_Event_t Event) { ES_Event_t ReturnEvent = Event; // assume no re-mapping or consumption // process ES_ENTRY, ES_ENTRY_HISTORY & ES_EXIT events if ((Event.EventType == ES_ENTRY) || (Event.EventType == ES_ENTRY_HISTORY)) { // no tasks to do for entry into TurningCW90 // no lower level state machine to start } else if (Event.EventType == ES_EXIT) { // no lower level state machine to pass the exit to // no tasks to do for exit from TurningCW90 } // this state 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; } /*------------------------------- Footnotes -------------------------------*/ /*------------------------------ End of file ------------------------------*/