/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright (c) 2016-2021, NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "Defines.h"
#include "UserInterface.h"
#include "Timer.h"
#include "MeteringLPRT.h"
#include "Application.h"
#include "RTCDriver.h"
#include "ComPortDriver.h"
#include "EEPROMDriver.h"
#include "PowerModes.h"
#include "MeteringInterface3Ph.h"
#include "IOControls.h"
#include "fsl_qtmr.h"
#include "UpgradeFW.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define GPTimerEventHandler                     TMR1_IRQHandler
/*******************************************************************************
* Prototypes
******************************************************************************/
uint8  MeterUnlockTimer;
uint8  BattPBDisabled;
uint8  SecTmrCtr;

void SecondTimerCallback(void);

/*******************************************************************************
 * Code
 ******************************************************************************/
 /*!
 * @brief Initializes a tick timer and second timer which are used for various 
 * timing and control for meter application.
 */
void GPTimerModuleInit(void)
{
  uint32 ModValue = 0;
  qtmr_config_t qtmrConfig;
  
  /*
  Initliazing the Configurable timer
  It will use Quad Timer 1
  Enable the Quad Timer Clock
  Interrupt Frequency Desired= 25ms
  Interrupt Frequency in terms of Bus Clock= (Interrupt Time*Bus Freq)
  Configuring the timer in Free Running Mode
   */
  ModValue = SystemState.BusClk/1000 ;

  switch (SystemState.PowerMode)
  {
    case POWERMODE_RUN:
      ModValue = ModValue / 128;
      ModValue=ModValue* INTERRUPT_FREQUENCY;
      QTMR_GetDefaultConfig(&qtmrConfig);
      
      /* Set clock prescaler */
      qtmrConfig.primarySource = kQTMR_ClockDivide_128;
      QTMR_Init(TMR1, &qtmrConfig);
      
      QTMR_SetTimerPeriod(TMR1, ModValue);
      
      /* Enable timer compare interrupt */
      QTMR_EnableInterrupts(TMR1, kQTMR_CompareInterruptEnable);
      
      /* Enable at the NVIC */
      NVIC_SetPriority(TMR1_IRQn, TMR1_INTERRUPT_PRIORITY);
      EnableIRQ(TMR1_IRQn);
      
      /* Start timer */
      QTMR_StartTimer(TMR1, kQTMR_PriSrcRiseEdge);
      
      break;

    case POWERMODE_BAT:
      BattPBDisabled = TRUE;
      ModValue=ModValue* INTERRUPT_FREQUENCY;
      
      QTMR_GetDefaultConfig(&qtmrConfig);
      
      /* Set clock prescaler */
      qtmrConfig.primarySource = kQTMR_ClockDivide_1;
      QTMR_Init(TMR1, &qtmrConfig);
      
      QTMR_SetTimerPeriod(TMR1, ModValue);
      
      /* Enable timer compare interrupt */
      QTMR_EnableInterrupts(TMR1, kQTMR_CompareInterruptEnable);
      
      /* Enable at the NVIC */
      NVIC_SetPriority(TMR1_IRQn, TMR1_INTERRUPT_PRIORITY);
      EnableIRQ(TMR1_IRQn);
      
      /* Start timer */
      QTMR_StartTimer(TMR1, kQTMR_PriSrcRiseEdge);
      break;
  }
  SecTmrCtr = CNTS_IN_SEC;
}

 /*!
* @brief Implements the callback function of high resoution timing for timing 
* and control of meter application.
*/
void GPTimerEventHandler(void)
{
  /* Clear interrupt flag.*/
  QTMR_ClearStatusFlags(TMR1, kQTMR_CompareFlag);
  
  if (I2CTimeout)
  {
    I2CTimeout--;
  }
  
  DownScrollDebouncer <<= 1;
  if (GPIO_GET_PBD == PBD_ACTIVE_LEVEL)
  {
    DownScrollDebouncer |= 1;
    if (DownScrollDebouncer == 0x03)
    {
      if (DownDetected == FALSE)
      {
        DownScroll = TRUE;
        DownDetected = TRUE;
      }
    }
  }
  else
  {
    if (DownScrollDebouncer == 0x00)
    {
      DownDetected = FALSE;
    }
  }
  
  UpScrollDebouncer <<= 1;
  if (GPIO_GET_PBU == PBU_ACTIVE_LEVEL)
  {
    UpScrollDebouncer |= 1;
    if (UpScrollDebouncer == 0x03)
    {
      if (UpDetected == FALSE)
      {
        UpScroll = TRUE;
        UpDetected = TRUE;
      }
    }
  }
  else
  {
    if (UpScrollDebouncer == 0x00)
    {
      UpDetected = FALSE;
      BattPBDisabled = FALSE;
    }
  }
  
  
  if (SecTmrCtr)
  {
    SecTmrCtr--;
    if (SecTmrCtr == 0)
    {
      SecTmrCtr = CNTS_IN_SEC;
      SecondTimerCallback();
    }
  }
  SDK_ISR_EXIT_BARRIER;
}

 /*!
 * @brief Implements the callback of a timer with tick-a-second resoluton, 
 * used to time and control various activities in the meter application.
 */
void SecondTimerCallback(void)
{
  uint8 i;
  
  /* ESD */
  if (SystemState.PowerMode == POWERMODE_RUN)
  {
    if (NoMetTO)
    {
      NoMetTO--;
      if (NoMetTO == 0)
      {
        ResetPLL = TRUE;
      }
    }
  }
  
#ifdef MDRESETBUTTON
  
#endif
  
  /*
   LCD refresh timeout
   */
  if (lcd_refresh_count)
  {
    lcd_refresh_count--;
  }

  /*
   LCD scrolling timeout.
   */
  if (lcd_scroll_count)
  {
    lcd_scroll_count--;
  }

  /* Battery mode settle down time */
  if (SystemState.PowerMode == POWERMODE_BAT)
  {
    if (BattModeTimeout)
    {
      BattModeTimeout--;
      if (BattModeTimeout == 0)
      {
        TurnLatchOff = TRUE;
      }
    }
  }

 /* Communications */
  for(i=0; i<NUM_UART_CHANNEL; i++)
  {
    if (UARTTimeout[i])
    {
      UARTTimeout[i]--;
    }
    else
    {
      UartPortStatus[i] = UART_IDLE;
    }
  } 
  
  if(DontCheckEOLTimeout)
  {
    DontCheckEOLTimeout--;
    
    if(DontCheckEOLTimeout == 0)
    {
      DontCheckEOLCount = 0;
      UartPortStatus[UART_OPTICAL_INDEX] = UART_IDLE;
    }
  }
  
  if (MeterUnlockTimer)
  {
    MeterUnlockTimer--;
    if (MeterUnlockTimer == 0)
    {
      MeterUnlocked = FALSE;
    }
  }
  
}

