/****************************************************************************
 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;
}