Professional Documents
Culture Documents
Module
GameMasterSM.c
Revision
2.0.1
Description
This is a template for the top level Hierarchical state machine
Notes
History
When Who What/Why
-------------- --- --------
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"
#include "GameMasterSM.h"
#include "FaceOffSM.h"
#include "OffenseSM.h"
#include "DefenseSM.h"
#include "LEDs.h"
#include "DCMotor.h"
#include "ServoMotor.h"
#include "ColorSensor.h"
#define Forward 0
#define Backward 1
#define CWTurn 2
#define CCWTurn 3
#define LeftMotor 0
#define RightMotor 1
/*---------------------------- Module Functions ---------------------------*/
static ES_Event_t DuringGameNotActive( ES_Event_t Event);
static ES_Event_t DuringFaceOff(ES_Event_t Event);
static ES_Event_t DuringOffense(ES_Event_t Event);
static ES_Event_t DuringDefense(ES_Event_t Event);
Parameters
uint8_t : the priorty of this service
Returns
boolean, False if error in initialization, True otherwise
Description
Saves away the priority, and starts
the top level state machine
Notes
Author
J. Edward Carryer, 02/06/12, 22:06
****************************************************************************/
bool InitGameMasterSM ( uint8_t Priority )
{
ES_Event_t ThisEvent;
ThisEvent.EventType = ES_ENTRY;
// Start the Master State machine
StartGameMasterSM( ThisEvent );
return true;
}
/****************************************************************************
Function
PostGameMasterSM
Parameters
ES_Event 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 PostGameMasterSM( ES_Event_t ThisEvent )
{
return ES_PostToService( MyPriority, ThisEvent);
}
/****************************************************************************
Function
RunGameMasterSM
Parameters
ES_Event: the event to process
Returns
ES_Event: an event to return
Description
the run function for the top level state machine
Notes
uses nested switch/case to implement the machine.
Author
J. Edward Carryer, 02/06/12, 22:09
****************************************************************************/
ES_Event_t RunGameMasterSM( ES_Event_t CurrentEvent )
{
//set MakeTransition to false by default
bool MakeTransition = false;
GameMasterState_t NextState = CurrentState; //set NestState to CurrentState
ES_Event_t EntryEventKind = { ES_ENTRY, TEAM };// instead of default to normal
entry to new state, we set param to TEAM and pass down to lower level SM
ES_Event_t ReturnEvent = { ES_NO_EVENT, 0 }; // assume no error, for top level
sm we always need a return event set to ES_NO_ERROR
// if (CurrentEvent.EventType == DEBUG_ENCODER)
// {
// printf("From RunGameMasterSM, Encoder Time: %d \r\n",
CurrentEvent.EventParam);
// }
switch ( CurrentState )
//CurrentState can be one of: GameNotActive, FaceOff, Offense, Defense
//EventType can be one of: EV_WAIT4START, EV_FACEOFF, EV_REDPO, EV_BLUEPO,
EV_GAMEOVER. Except the first one, all other
//events need to be responded in any of FaceOff, Offense, and Defense
{
case GameNotActive : // If current state is GameNotActive
// Execute During function for GameNotActive. ES_ENTRY & ES_EXIT are
// processed here allow the lowere level state machines to re-map
// or consume the event
CurrentEvent = DuringGameNotActive(CurrentEvent);
//process any events
if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active
{
switch (CurrentEvent.EventType)
{
case EV_WAIT2START : //If event is EV_WAIT2START
// Execute action function for GameNotActive, EV_WAIT2START
NextState = GameNotActive;//Decide next state to be GameNotActive
// for internal transitions, skip changing MakeTransition
MakeTransition = false; //mark that we are not taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_FACEOFF : //If event is EV_FACEOFF
// Execute action function for GameNotActive, EV_FACEOFF
NextState = FaceOff;//Decide next state to be FaceOff
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
#ifdef TEST
MakeTransition = false;
#endif
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
#ifdef TEST
case ES_TIMEOUT:
if(CurrentEvent.EventParam == MOTOR_TIMER){
// if(counter == 1){
// LoadBall();
// }
// if(counter == 2){
// ChargeBall();
// }
// if(counter == 3){
// FireBall();
// }
// if(counter == 4){
// ResetBall();
// }
counter++;
printRPM();
NextState = GameNotActive;
MakeTransition = false;
ES_Timer_InitTimer(MOTOR_TIMER, 200);
}
break;
case EV_ANGLE_TARGET_REACHED:
//StopRobot();
printf("we turned 45 deg in GameMasterSM\n\r");
NextState = GameNotActive;
MakeTransition = false;
break;
// case EV_X_TARGET_REACHED:
// printf("we reached target \n\r");
// printRPM();
// StopRobot();
// NextState = GameNotActive;
// MakeTransition = false;
// break;
#endif
default:
;
}
}
break;
// repeat state pattern as required for other states
case FaceOff : // If current state is FaceOff
// Execute During function for FaceOff. ES_ENTRY & ES_EXIT are
// processed here allow the lowere level state machines to re-map
// or consume the event
CurrentEvent = DuringFaceOff(CurrentEvent);
//process any events
if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active
{
switch (CurrentEvent.EventType)
{
case EV_GAMEOVER : //If event is EV_GAMEOVER
// Execute action function for FaceOff, EV_GAMEOVER
NextState = GameNotActive;//Decide next state to be GameNotActive
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_REDPO : //If event is EV_REDPO
// Execute action function for FaceOff, EV_REDPO
//if we are TEAM RED, set NextState to Offense, otherwise set to
Defense
if(TEAM == RED){
NextState = Offense;
}else{
NextState = Defense;
}
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_BLUEPO : //If event is EV_BLUEPO
// Execute action function for FaceOff, EV_BLUEPO
//if we are TEAM BLUE, set NextState to Offense, otherwise set to
Defense
if(TEAM == BLUE){
NextState = Offense;
}else{
NextState = Defense;
}
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_FACEOFF : //If event is EV_FACEOFF
// Execute action function for FaceOff: EV_FACEOFF
NextState = FaceOff; //set NextState to FaceOff
// for internal transitions, skip changing MakeTransition
MakeTransition = false; //mark that we are not taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
default:
;
}
}
break;
// repeat state pattern as required for other states
case Offense : // If current state is Offense
// Execute During function for Offense. ES_ENTRY & ES_EXIT are
// processed here allow the lowere level state machines to re-map
// or consume the event
CurrentEvent = DuringOffense(CurrentEvent);
//process any events
if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active
{
switch (CurrentEvent.EventType)
{
case EV_GAMEOVER : //If event is EV_GAMEOVER
// Execute action function for Offense, EV_GAMEOVER
NextState = GameNotActive;//Decide NextState will be GameNotActive
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_REDPO : //If event is EV_REDPO
// Execute action function for Offense, EV_REDPO
//if we are TEAM RED, set NextState to Offense without transiting
state
if(TEAM == RED){
NextState = Offense;
MakeTransition = false;
}else{ //else set NextState to Defense with transiting state
NextState = Defense;
MakeTransition = true;
// ES_Timer_InitTimer(SHOTCLK, CurrentEvent.EventParam);
}
// for internal transitions, skip changing MakeTransition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_BLUEPO : //If event is EV_BLUEPO
// Execute action function for Offense, EV_BLUEPO
//if we are TEAM BLUE, set NextState to Offense without transiting
state
if(TEAM == BLUE){
NextState = Offense;
MakeTransition = false;
}else{ //else set NextState to Defense with transiting state
NextState = Defense; //Decide what the next state will be
MakeTransition = true;
// ES_Timer_InitTimer(SHOTCLK, CurrentEvent.EventParam);
}
// for internal transitions, skip changing MakeTransition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_FACEOFF : //If event is event one
// Execute action function for Offense: EV_FACEOFF
// for internal transitions, skip changing MakeTransition
//set NextState to FaceOff
NextState = FaceOff;
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
default:
;
}
}
break;
// repeat state pattern as required for other states
case Defense : // If current state is Defense
// Execute During function for Defense. ES_ENTRY & ES_EXIT are
// processed here allow the lowere level state machines to re-map
// or consume the event
CurrentEvent = DuringDefense(CurrentEvent);
//process any events
if ( CurrentEvent.EventType != ES_NO_EVENT ) //If an event is active
{
switch (CurrentEvent.EventType)
{
case EV_GAMEOVER : //If event is EV_GAMEOVE
// Execute action function for Defense, EV_GAMEOVER
NextState = GameNotActive;//Decide next state to be GameNotActive
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_REDPO : //If event is EV_REDPO
// Execute action function for Defense, EV_REDPO
//if we are TEAM RED, set NextState to Offense with transiting state
if(TEAM == RED){
NextState = Offense;
MakeTransition = true;
}else{ //else set NextState to Defense without transiting state
NextState = Defense;
MakeTransition = false;
}
// for internal transitions, skip changing MakeTransition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_BLUEPO : //If event is EV_BLUEPO
// Execute action function for Defense, EV_BLUEPO
//if we are TEAM BLUE, set NextState to Offense with transiting state
if(TEAM == BLUE){
NextState = Offense; //Decide what the next state will be
MakeTransition = true;
}else{ //else set NextState to Defense without transiting state
NextState = Defense; //Decide what the next state will be
MakeTransition = false;
}
// for internal transitions, skip changing MakeTransition
//MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case EV_FACEOFF : //If event is EV_FACEOFF
// Execute action function for Defense, EV_FACEOFF
//set NextState to FaceOff
NextState = FaceOff;
// for internal transitions, skip changing MakeTransition
MakeTransition = true; //mark that we are taking a transition
// if transitioning to a state with history change kind of entry
EntryEventKind.EventType = ES_ENTRY_HISTORY; //we will decide if we
need a history state or not
break;
// repeat cases as required for relevant events
case ES_TIMEOUT: //if event is ES_TIMEOUT
if(CurrentEvent.EventParam == SHOTCLK){
#ifdef TEST
printf("SHOTCLK timeout received\n\r");
#endif
//set NextState to FaceOff
NextState = FaceOff;
MakeTransition = true; //mark that we are making a transition
EntryEventKind.EventType = ES_ENTRY_HISTORY;
}
break;
default:
;
}
}
break;
}
// If we are making a state transition
if (MakeTransition == true)
{
// Execute exit function for current state
CurrentEvent.EventType = ES_EXIT;
RunGameMasterSM(CurrentEvent);
/****************************************************************************
Function
StartGameMasterSM
Parameters
ES_Event CurrentEvent
Returns
nothing
Description
Does any required initialization for this state machine
Notes
Author
J. Edward Carryer, 02/06/12, 22:15
****************************************************************************/
void StartGameMasterSM ( ES_Event_t CurrentEvent )
{
// if there is more than 1 state to the top level machine you will need
// to initialize the state variable
//init CurrentState to GameNotActive
CurrentState = GameNotActive;
// 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
RunGameMasterSM(CurrentEvent);
return;
}
/***************************************************************************
private functions
***************************************************************************/
//Init DCMotors
InitMotors();
StopRobot();
#ifdef TEST
counter++;
printf("we are in GameNotActive\n\r");
//SetRobotDir(Forward);
//SetRobotSpeed(LeftMotor, 15);
//SetRobotSpeed(RightMotor, 15);
//SetTargetPosition(150, 150);
SetRobotDir(Forward);
SetRobotSpeed(LeftMotor, 13);
SetRobotSpeed(RightMotor, 15);
SetTargetHeading(0);
printRPM();
ES_Timer_InitTimer(MOTOR_TIMER, 200);
printf("finished\r\n");
#endif
// after that start any lower level machines that run in this state
//StartLowerLevelSM( Event );
// repeat the StartxxxSM() functions for concurrent state machines
// on the lower level
}
else if ( Event.EventType == ES_EXIT )
{
// on exit, give the lower levels a chance to clean up first
//RunLowerLevelSM(Event);
// repeat for any concurrently running state machines
// now do any local exit functionality
}else
// do the 'during' function for this state
{
// run any lower level state machine
// ReturnEvent = RunLowerLevelSM(Event);
// after that start any lower level machines that run in this state
StartFaceOffSM( Event );
}else
// do the 'during' function for this state
{
// run any lower level state machine
ReturnEvent = RunFaceOffSM(Event);
// repeat for any concurrent lower level machines
// after that start any lower level machines that run in this state
StartOffenseSM( Event ); //Event.EventParam = TEAM
// repeat the StartxxxSM() functions for concurrent state machines
// on the lower level
}
else if ( Event.EventType == ES_EXIT )
{
// on exit, give the lower levels a chance to clean up first
RunOffenseSM(Event);
// repeat for any concurrently running state machines
// now do any local exit functionality
}else
// do the 'during' function for this state
{
// run any lower level state machine
ReturnEvent = RunOffenseSM(Event);
// after that start any lower level machines that run in this state
StartDefenseSM( Event ); //Event.EventParam = TEAM
// repeat the StartxxxSM() functions for concurrent state machines
// on the lower level
}
else if ( Event.EventType == ES_EXIT )
{
// on exit, give the lower levels a chance to clean up first
RunDefenseSM(Event);
// repeat for any concurrently running state machines
// now do any local exit functionality
}else
// do the 'during' function for this state
{
// run any lower level state machine
ReturnEvent = RunDefenseSM(Event);
// repeat for any concurrent lower level machines