/****************************************************************************
 Module
   BeaconSense.c

 Revision
   1.0.1

 Description
   This is an IR sensing input capture interrupt module for ME218B Project
   for Team 3.

 Notes


 History
 When           Who     What/Why
 -------------- ---     --------
 02/25/2019     bibit   converted from lab 8 to project module
 02/04/2019     bibit   created file
****************************************************************************/

/*----------------------------- 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 "GameplayHSM.h"
#include "Gameplay_GameTasksSM.h"
#include "BeaconSense.h"

#include "ES_Types.h"
#include "termio.h"
#include "BITDEFS.H"
#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_pwm.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_nvic.h"
#include "inc/hw_Timer.h"

#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"

/*----------------------------- Module Defines ----------------------------*/

// beacon definitions
#define ConsecutivePulses 3
#define TicksPerMs 40000
#define MeasurementError 20   // increase this if the IR signal isn't very
                              // clean or consistent. Value of 10 = 1% error

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

/*---------------------------- Module Variables ---------------------------*/
// everybody needs a state variable, you may need others as well.
// type of state variable should match htat of enum in header file

static uint32_t LastCaptureRear;
static uint32_t PeriodRear;
static bool     CanCalculatePeriodRear = false;
static uint8_t  PulseCount = 0;

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

/****************************************************************************
 Function
     InitializeBeaconSense

 Parameters
     none

 Returns
     none

 Description
     Does the final initialization steps for the beacon sensor.  Most of the
     initialization occurs in HardwareInitialize, so this is just a simple
     last step of ensuring the interrupts are enabled in the NVIC but
     disabled with the local interrupt mask.

 Notes
     Uses Wide Timer 2, Timer B.  Interrupts for this timers is enabled/
     disabled in NVIC EN3 bit 3.

 Author
     Bibit Bianchini, 2/25/2019
****************************************************************************/
void InitializeBeaconSense(void)
{
  // disable in the local interrupt mask
  HWREG(WTIMER2_BASE + TIMER_O_IMR) &= ~TIMER_IMR_CBEIM;

  // ensure that the interrupts are enabled in the NVIC
  HWREG(NVIC_EN3) |= (BIT3HI | BIT4HI);
}

/****************************************************************************
 Function
     BeaconRearISR

 Parameters
     none

 Returns
     none

 Description
     Interrupt response routine for beacon detection in rear-facing detector.
     When proper pulse is detected a certain number of times in a row, this
     ISR disables its own interrupt, tells itself to reset period calculations
     for next time, and posts BEACON_DETECTED [REAR] event to GameplayHSM
     module.

 Notes
     Uses Wide Timer 2, Timer B.
     Interrupts for this timer are enabled/disabled in NVIC EN3 bit 3.

 Author
     Bibit Bianchini, 2/25/2019
****************************************************************************/
void BeaconRearISR(void)
{
  uint32_t ThisCapture;

  // start by clearing the source of the interrupt
  HWREG(WTIMER2_BASE + TIMER_O_ICR) = TIMER_ICR_CBECINT;

  // grab the captured value
  ThisCapture = HWREG(WTIMER2_BASE + TIMER_O_TBR);

  // check to see if we can capture the pulse yet
  if (CanCalculatePeriodRear == false)
  {
    // we can't calculate the period now, but we can next time
    CanCalculatePeriodRear = true;
  }
  else
  {
    // calculate the period
    PeriodRear = ThisCapture - LastCaptureRear;

    // get the beacon signal we are trying to see
    uint16_t BeaconFrequency = QueryBeaconRearFreq();

    // see if this period is within that of the known beacon signal
    // (if it matches exactly, PeriodInMS * Frequency should = 1000)
    if (((PeriodRear * BeaconFrequency) / TicksPerMs <= (1000 + MeasurementError))
        & ((PeriodRear * BeaconFrequency) / TicksPerMs >= (1000 - MeasurementError)))
    {
      // found beacon once, save success to safety value
      PulseCount++;
    }
    else
    {
      // value doesn't correspond to measurement, reset our count
      PulseCount = 0;
    }

    if (PulseCount == ConsecutivePulses)
    {
      //Signal has been located!
      // --> disable interrupts
      DisableRearBeaconInterrupts();
      // --> reset CanCalculatePeriodRear
      CanCalculatePeriodRear = false;
      //Set GuardCondition to 0
      PulseCount = 0;
      // --> send BEACON_DETECTED event with param REAR to GameplayHSM module
      ES_Event_t PostEvent;
      PostEvent.EventType = BEACON_DETECTED;
      PostEvent.EventParam = REAR;
      PostGameplayMasterSM(PostEvent);
    }
  }

  // update LastCaptureRear to prepare for the next edge
  LastCaptureRear = ThisCapture;
}

/****************************************************************************
 Function
     EnableRearBeaconInterrupts

 Parameters
     none

 Returns
     none

 Description
     Enables interrupts for the beacon detector.

 Notes
     Uses Wide Timer 2, Timer B.  Interrupts for this timer is enabled in
     NVIC EN3 bits 3.

 Author
     Bibit Bianchini, 2/25/2019
****************************************************************************/
void EnableRearBeaconInterrupts(void)
{
  HWREG(WTIMER2_BASE + TIMER_O_IMR) |= TIMER_IMR_CBEIM;
}


/***************************************************************************
 private functions
 ***************************************************************************/
/****************************************************************************
 Function
     DisableRearBeaconInterrupts

 Parameters
     none

 Returns
     none

 Description
     Disables interrupts for the beacon detector.

 Notes
     Uses Wide Timer 2, Timer B.  Interrupts for this timer is enabled in
     NVIC EN3 bits 3.

 Author
     Bibit Bianchini, 2/25/2019
****************************************************************************/
static void DisableRearBeaconInterrupts(void)
{
  HWREG(WTIMER2_BASE + TIMER_O_IMR) &= ~TIMER_IMR_CBEIM;
}

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