
// Reset Button Module

/*----------------------------- Include Files -----------------------------*/
/* include header files for the framework and this service*/
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_DeferRecall.h"
#include "ES_ShortTimer.h"
#include "EventCheckers.h"

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"	// Define PART_TM4C123GH6PM in project
#include "driverlib/gpio.h"

#include "BITDEFS.H"


/*----------------------------- Module Defines ----------------------------*/
// these times assume a 1.000mS/tick timing
#define ONE_SEC 976
#define DEBOUNCE_TIME (ONE_SEC/30)
#define INPUT_HIGH 1
#define GAME_TIME 45000
#define WIN_TIME 15000
#define FULL_GAME_RESET_TIME 60000

// always access all 8 bits at a time
#define ALL_BITS (0xff<<2)

/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service.They should be functions
   relevant to the behavior of this service
*/

bool InitResetButton ( uint8_t Priority );
bool PostResetButton ( ES_Event ThisEvent );
ES_Event RunResetButton ( ES_Event ThisEvent );

/*---------------------------- Module Variables ---------------------------*/
// with the introduction of Gen2, we need a module level Priority variable
static uint8_t MyPriority;
static ResetButtonState_t CurrentState;

/*------------------------------ Module Code ------------------------------*/

// Button module (a service that implements a state machine)

// InitializeButton
// Takes a priority number, returns True
bool InitResetButton ( uint8_t Priority )
{
	// Initialize the MyPriority variable with the passed in parameter
	MyPriority = Priority;
	// Initialize the port line to monitor the button
	 // Enable GPIO Port A/ Bit 0
	HWREG (SYSCTL_RCGCGPIO) |= (SYSCTL_RCGCGPIO_R0);
	// Wait until the peripheral reports that its clock is ready
	while ((HWREG(SYSCTL_PRGPIO) & SYSCTL_PRGPIO_R0) != SYSCTL_PRGPIO_R0);
	// Write to the DEN to assign digital functions to PA2
	HWREG(GPIO_PORTA_BASE+GPIO_O_DEN) |= (GPIO_PIN_2);
	// Initialize pin 2, 2 & 3 on Port A to be an inputs
	HWREG(GPIO_PORTA_BASE+GPIO_O_DIR) &= ~(GPIO_PIN_2);
	HWREG(GPIO_PORTA_BASE+(GPIO_O_DATA + ALL_BITS)) &= ~(GPIO_PIN_2);
	
	
  // Set CurrentState to be Ready2Sample
	CurrentState = Ready2Sample;
  // Start debounce timer
	ES_Timer_InitTimer(DEBOUNCE_TIMER, DEBOUNCE_TIME);	
	// End of InitializeButton (return True)
	return true;
}

/***************************************************************************/

// Set the post function for Button that will be called by other functions
bool PostResetButton ( ES_Event ThisEvent )
{
  return ES_PostToService( MyPriority, ThisEvent);
}

/***************************************************************************/

// RunResetButton (implements a state state machine for debouncing timing)

ES_Event RunResetButton ( ES_Event ThisEvent )
{
	// Local var ReturnValue initialized to ES_NO_EVENT
	ES_Event ReturnEvent;
  ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
	
	// Based on the CurrentState, choose one of the following blocks of code
	switch (CurrentState) {
		// If CurrentState is Debouncing
		case Debouncing :
		// If EventType is ES_TIMEOUT & parameter is debounce timer number
		if ((ThisEvent.EventType == ES_TIMEOUT) &&
				(ThisEvent.EventParam == DEBOUNCE_TIMER)){
		// Start the timer for a new game
			ES_Timer_InitTimer(GAME_TIMER, GAME_TIME);
			ES_Event ThisEvent;
			ThisEvent.EventType = ES_GAME_START;
			// Post reset event to all lists
			ES_PostAll (ThisEvent);
		// Start reset timer for full game
			ES_Timer_InitTimer(RESET_TIMER, FULL_GAME_RESET_TIME);		
			printf ("\r\n ES_GAME_START event posted to all lists\r\n");
		// Set CurrentState to Ready2Sample
			CurrentState = GameStarted;
			}
			break;
	  // If CurrentState is Ready2Sample
		case Ready2Sample :
			// If EventType is ButtonUp
			if (ThisEvent.EventType == ES_BUTTON_HI){
				  // Start debounce timer
					ES_Timer_InitTimer(DEBOUNCE_TIMER, DEBOUNCE_TIME);
				  // Set CurrentState to debouncing
					CurrentState = Debouncing;
				} // End if
				break;
		// If CurrentState is GameStarted
		case GameStarted:
			// If players lose the game (45 sec) - event type is ES_TIMEOUT
			if ((ThisEvent.EventType == ES_TIMEOUT) &&
				(ThisEvent.EventParam == GAME_TIMER)){
				ES_Event ThisEvent;
				ThisEvent.EventType = ES_GAME_TIMER_OUT;
				ES_PostAll (ThisEvent);
				// Set CurrentState to WaitingForResetTimer
				CurrentState = WaitingForResetTimer;
				}
			// Else if players win the game - event type is ES_ALL_FLAME_OFF
			else if (ThisEvent.EventType == ES_ALL_FLAME_OFF) {
				// Start a timer for the win delay time
				ES_Timer_InitTimer(GAME_TIMER, WIN_TIME);
				// Change CurrentState to GameWin
				CurrentState = GameWin;
				}
			break;
		// If CurrentState is GameWin
		case GameWin:
			// If event type is ES_TIMEOUT and it's the GAME_TIMER
			if ((ThisEvent.EventType == ES_TIMEOUT) &&
				(ThisEvent.EventParam == GAME_TIMER)){
				ES_Event ThisEvent;
				ThisEvent.EventType = ES_GAME_RESET;
				// Post ES_GAME_RESET to all services
				ES_PostAll (ThisEvent);
				// Change CurrentState to Ready2Sample
				CurrentState = Ready2Sample;
				}
			break;
		// If CurrentState is WaitingForResetTimer
		case WaitingForResetTimer :
			// If the event type is ES_TIMEOUT and it is the reset timer
			if ((ThisEvent.EventType == ES_TIMEOUT) &&
				(ThisEvent.EventParam == RESET_TIMER)){
				ES_Event ThisEvent;
				ThisEvent.EventType = ES_GAME_RESET;
				// Post ES_GAME_RESET to all services
				ES_PostAll (ThisEvent);
				// Change CurrentState to Ready2Sample
				CurrentState = Ready2Sample;
			}
			break;
	   }

// Return ES_NO_EVENT 
	return ReturnEvent;
} // End of RunResetButton

