/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright (c) 2016-2021, NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "Defines.h"
#include "MeteringLPRT.h"
#include "AppInterface.h"
#include "MeteringInterface3Ph.h"
#include "Calibration3Ph.h"
#include "EEPROMDriver.h"
#include "PowerModes.h"
#include "UpgradeFW.h"
#include "Flash_FTFL.h"
#include "lcd.h"
#include "ComPortDriver.h"
#include "UserInterface.h"
#include "AppCommon.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
 
/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * @brief Holds any initialization required between this interface layer which 
 * is used between application and metrology core.
 */
void AppInterfaceInit(void)
{
  mlib3phdata.IMax   = 60.0;
  mlib3phdata.IBasic = 10.0;
  mlib3phdata.MaxPower = (240.0*3.0*100.0);
}

/*!
 * @brief Restores a default calibration data object for the meter. 
 * These restored values in the calibration data structure can be tuned to close 
 * values as per meter hw.
 */

void RestoreDefCalib(void)
{
  CalibStruct3Ph.VCoeff[0] = 2.01924413E-4;
  CalibStruct3Ph.VCoeff[1] = 2.01946852E-4;
  CalibStruct3Ph.VCoeff[2] = 2.01954069E-4;
  
  CalibStruct3Ph.ActPowerCoeff[0] = 5.80252859E-11;
  CalibStruct3Ph.ActPowerCoeff[1] = 5.7914652244E-11;
  CalibStruct3Ph.ActPowerCoeff[2] = 5.8085508622E-11;
  
  CalibStruct3Ph.PhAngle[0] = 5.6935906411E-2;
  CalibStruct3Ph.PhAngle[1] = 5.80483675E-2;
  CalibStruct3Ph.PhAngle[2] = 5.68326711E-2;
  
  CalibStruct3Ph.ICoeff[0] = 2.8737454722E-7;
  CalibStruct3Ph.ICoeff[1] = 2.8677814611E-7;
  CalibStruct3Ph.ICoeff[2] = 2.8677814611E-7;
  CalibStruct3Ph.ICoeff[3] = 3.7576057822E-7;
  
  CalibStruct3Ph.VFCoeff[0] = 9.01720653E-8;
  CalibStruct3Ph.VFCoeff[1] = 4.78765294E-8;
  CalibStruct3Ph.VFCoeff[2] = 8.4903824411E-8;

  CalibStruct3Ph.IFCoeff[0] = 1.10036736E-10;
  CalibStruct3Ph.IFCoeff[1] = 1.35469136E-10;
  CalibStruct3Ph.IFCoeff[2] = 6.8210298522E-11;
	CalibStruct3Ph.IFCoeff[3] = 1.4974824211E+4;
  
  CalibStruct3Ph.FrequencyCoeff = 1.00009822;
}

void FudgeParameters3Ph(void)
{
  uint8 i;

  if (mlib3phdata.FirstCycle == TRUE)
  {
    mlib3phdata.Irms[0] = 0.0;
    mlib3phdata.Irms[1] = 0.0;
    mlib3phdata.Irms[2] = 0.0;
    mlib3phdata.Irms[3] = 0.0;
    mlib3phdata.IrmsNoFudge[0] = 0.0;
    mlib3phdata.IrmsNoFudge[1] = 0.0;
    mlib3phdata.IrmsNoFudge[2] = 0.0;
    mlib3phdata.FirstCycle = FALSE;
  }
  
  if (StopMetering == TRUE)
  {
    mlib3phdata.Irms[0] = 0.0;
    mlib3phdata.Irms[1] = 0.0;
    mlib3phdata.Irms[2] = 0.0;
    mlib3phdata.Irms[3] = 0.0;
    mlib3phdata.IrmsNoFudge[0] = 0.0;
    mlib3phdata.IrmsNoFudge[1] = 0.0;
    mlib3phdata.IrmsNoFudge[2] = 0.0;
    if ((PMC->LVDSC2 & PMC_LVDSC2_LVWF_MASK) == 0)
    {
      /* Normalcy has been restored */
      StopMetering = FALSE;
    }
  }
  
  for (i = 0; i < nVPHASES; i++)
  {
    if (mlib3phdata.Irms[i] < 0.008)
    {
      mlib3phdata.PhPowerFactors[i] = 0.0;
      mlib3phdata.PhAngles[i] = 0.0;
    }
    if (mlib3phdata.Irms[i] == 0.0)
    {
      mlib3phdata.ActPowers[i] = 0.0;
      mlib3phdata.ReactPowers[i] = 0.0;
      mlib3phdata.ISigns[i] = 1;
      mlib3phdata.PhPowerFactors[i] = 0.0;
    }
    if (mlib3phdata.Vrms[i] == 0.0)
    {
      mlib3phdata.ActPowers[i] = 0.0;
      mlib3phdata.ReactPowers[i] = 0.0;
      mlib3phdata.ISigns[i] = 1;
      mlib3phdata.PhPowerFactors[i] = 0.0;
    }
    if ((mlib3phdata.ActPowers[i] == 0.0) && (mlib3phdata.ReactPowers[i] == 0.0))
    {
      if (mlib3phdata.Irms[i] < 0.3)
      {
        mlib3phdata.Irms[i] = 0.0;
      }
      mlib3phdata.ISigns[i] = 1;
      mlib3phdata.PhPowerFactors[i] = 0.0;
      mlib3phdata.AppPowers[i] = 0.0;
    }
  }
  if (mlib3phdata.Irms[3] < 0.008)
  {
    mlib3phdata.Irms[3] = 0.0;
  }
  if (nZCurs == 3)
  {
    mlib3phdata.PowerFactor = 0.0;
  }
}

void CorrectAppPhAngle3Ph(uint32 phase)
{
  if ((mlib3phdata.PhAngles[phase] > 1.65) && (mlib3phdata.PhAngles[phase] < 3.25))
  {
    mlib3phdata.PhAngles[phase] -= Q2_PHASE_CORRECTION;
  }
  if (mlib3phdata.PhAngles[phase] > 4.625)
  {
    mlib3phdata.PhAngles[phase] += Q4_PHASE_CORRECTION;
  }
}

void SWReset(uint8 CallerId)         
{
  NVIC_SystemReset();
}

/*!
 * @brief Meter specific routine to erase partitions of EEPROM memory.
 */
void MemErase(void)
{
  uint16 i, j;
  uint32 Address;
  
  DisplayErase();
  
  j = MERASE_OFST+PAGE_BOUNDARY;
  for (i = MERASE_OFST; i < j; i++)
  {
    UARTBuffer[i] = 0;
  }

  NVWriteIIC(MemSignAddr, (uint8 *)&UARTBuffer[MERASE_OFST], 4);
  
  /* Update EEPROM erase log */
  NVReadIIC(EEPSIGNADDR, (uint8 *)&i, 2);
  if (i != EEPERASESIGN)
  {
    NVWriteIIC(EEPSIGNADDR, &UARTBuffer[MERASE_OFST], 36);
    i = EEPERASESIGN;
    NVWriteIIC(EEPSIGNADDR, (uint8 *)&i, 2);
  }
  NVReadIIC(EEPERASECNT, (uint8 *)&i, 2);
  j = i & 0x03;
    
  Address = EEPERASELOG + (8*j);
  NVWriteIIC(Address, &UARTBuffer[MERASE_OFST], 8);
  /* Count */
  i++;
  NVWriteIIC(EEPERASECNT, (uint8 *)&i, 2);

  RTCModuleInit();
  InitTime();
  
  DisplayDone();
  SDK_DelayAtLeastUs(5000000/(SYSTEM_CLOCK/1000000), SYSTEM_CLOCK);
}