/****************************************************************************
 Module
   TapeService.c

 Revision
   1.0.1

 Description
   This is the first service for the Test Harness under the
   Gen2 Events and Services Framework.

 Notes

 History
 When           Who     What/Why
 -------------- ---     --------
 10/26/17 18:26 jec     moves definition of ALL_BITS to ES_Port.h
 10/19/17 21:28 jec     meaningless change to test updating
 10/19/17 18:42 jec     removed referennces to driverlib and programmed the
                        ports directly
 08/21/17 21:44 jec     modified LED blink routine to only modify bit 3 so that
                        I can test the new new framework debugging lines on PF1-2
 08/16/17 14:13 jec      corrected ONE_SEC constant to match Tiva tick rate
 11/02/13 17:21 jec      added exercise of the event deferral/recall module
 08/05/13 20:33 jec      converted to test harness service
 01/16/12 09:58 jec      began conversion from TemplateFSM.c
****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
// This module
#include "TapeService.h"

// Hardware
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"

// Event & Services Framework
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_DeferRecall.h"
#include "ES_ShortTimer.h"
#include "ES_Port.h"

#include "GameplayHSM.h"

/*----------------------------- Module Defines ----------------------------*/
// these times assume a 1.000mS/tick timing
#define ONE_SEC 1000
#define HALF_SEC (ONE_SEC / 2)
#define TWO_SEC (ONE_SEC * 2)
#define FIVE_SEC (ONE_SEC * 5)
#define DebounceTime 20

//Define tape sensor constants
#define TAPESENSOR_HI BIT4HI

/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service.They should be functions
   relevant to the behavior of this service
*/
static void InitializeTapeSensors(void);

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

static uint8_t              LastTapeState;
static TapeDebounceState_t  CurrentState;

/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
 Function
     InitTapeService

 Parameters
     uint8_t : the priority of this service

 Returns
     bool, false if error in initialization, true otherwise

 Description
     Saves away the priority, and does any
     other required initialization for this service

 Notes

 Author
     J. Edward Carryer, 01/16/12, 10:00
****************************************************************************/
bool InitTapeService(uint8_t Priority)
{
  ES_Event_t ThisEvent;
  MyPriority = Priority;

  // set CurrentState to be Debouncing
  CurrentState = Debouncing;

  // sample the lines to initialize history state
  LastTapeState = HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA + ALL_BITS));

  // start debounce timer
  ES_Timer_InitTimer(TapeTimer, DebounceTime);

  ThisEvent.EventType = ES_INIT;
  if (ES_PostToService(MyPriority, ThisEvent) == true)
  {
    return true;
  }
  else
  {
    return false;
  }
}

/****************************************************************************
 Function
     PostTapeService

 Parameters
     ES_Event_t ThisEvent, the event to post to the queue

 Returns
     bool false if the Enqueue operation failed, true otherwise

 Description
     Posts an event to this state machine's queue

 Notes

 Author
     Bibit Bianchini, 11/02/2018
****************************************************************************/
bool PostTapeService(ES_Event_t ThisEvent)
{
  return ES_PostToService(MyPriority, ThisEvent);
}

/****************************************************************************
 Function
     RunTapeDebounce

 Parameters
     ES_Event_t

 Returns
     ES_NO_EVENT if no error detected, ES_ERROR otherwise

 Description
     Implements the 2-state state machine for debouncing the tape sensor
     signal.

 Notes

 Author
     Bibit Bianchini, 11/02/2018
****************************************************************************/
ES_Event_t RunTapeDebounce(ES_Event_t ThisEvent)
{
  // Return ES_NO_EVENT
  ES_Event_t ReturnEvent;
  ReturnEvent.EventType = ES_NO_EVENT;

  switch (CurrentState)
  {
    case Debouncing:
    {
      // If EventType is ES_TIMEOUT & parameter is tape timer number
      if ((ThisEvent.EventType == ES_TIMEOUT) &
          (ThisEvent.EventParam == TapeTimer))
      {
        // Set CurrentState to Ready2Sample
        CurrentState = Ready2Sample;
      }
    }
    break;

    case Ready2Sample:
    {
      // If EventType is ButtonDown
      if (ThisEvent.EventType == TAPE_EDGE)
      {
        // Start debounce timer
        ES_Timer_InitTimer(TapeTimer, DebounceTime);

        // Set CurrentState to Debouncing
        CurrentState = Debouncing;

        // Post that the tape was detected to gameplay
        printf("TapeDetected \n\r");
        ES_Event_t ThisEvent;
        ThisEvent.EventType = TAPE_DETECTED;
        ThisEvent.EventParam = CENTER;
        PostGameplayMasterSM(ThisEvent);
      }
    }
    break;
  }

  return ReturnEvent;
}

/****************************************************************************
 Function
    Check4Tape

 Parameters
    none

 Returns
    bool, true if an event was posted, false otherwise

 Description
    Event Checker looking for any tape detections

 Notes

 Author
   Bibit Bianchini, 3/04/2019
****************************************************************************/
bool Check4Tape(void)
{
  bool ReturnVal = false;

  // set CurrentTapeState to state read from port pin
  uint8_t CurrentTapeState = HWREG(GPIO_PORTF_BASE + (GPIO_O_DATA+ALL_BITS));

  // if the CurrentTapeState is different from the LastTapeState
  if ((CurrentTapeState & TAPESENSOR_HI) !=
      (LastTapeState & TAPESENSOR_HI))
  {
    ReturnVal = true;

    // if the current tape sensor pin is high, then we see the tape
    if ((CurrentTapeState & TAPESENSOR_HI) != 0)
    {
      // post that we saw an edge to the tape debounce service (this one)
      ES_Event_t ThisEvent;
      ThisEvent.EventType = TAPE_EDGE;
      PostTapeService(ThisEvent);
    }
  }

  // reset LastTapeState
  LastTapeState = CurrentTapeState;

  return ReturnVal;
}

/***************************************************************************
 private functions
 ***************************************************************************/

/*------------------------------- Footnotes -------------------------------*/
/*------------------------------ End of file ------------------------------*/