/*
 * Copyright 2021 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#include <math.h>
#include "pin_mux.h"
#include "board.h"
#include "Metering1Ph.h"
#include "Calibration1Ph.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define _PI   3.14159265358979323846	/* pi */
#define NSAMPLES 3000                  /*!< Sample frequency in Hz                    */
#define I_MAX                 141.421  /*!< Maximal current I-peak in amperes         */
#define U_MAX                 350.000  /*!< Maximal voltage U-peak in volts           */
#define PHASE_PHERR_PERHZ                       0.0f
#define NEUTRAL_PHERR_PERHZ                     0.0f

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/
/* static data definitions                                                    */
static tMETERLIBLPRT1PH_DATA mlib1phdata;
tCalibPoint1Ph CalibPoint;
float FreqDependentPhErr[nCURRENTS] = { PHASE_PHERR_PERHZ, NEUTRAL_PHERR_PERHZ};
static volatile frac32  u24_sample, i24_sample;
static double  time = 0.0, U_ANGLE = (60.0/180.0)*_PI, I_SHIFT = (-5.5/180.0)*_PI;

void RestoreDefCalib(void);
void AppInterfaceInit(void);

#if defined(__ICCARM__)
  #pragma diag_suppress=Pa082
#endif
/*******************************************************************************
 * Code
 ******************************************************************************/
void FudgeParameters1Ph(void)
{
}

void CorrectAppPhAngle1Ph(uint8 currenttoUse)
{
}

void ChkVolLvl(void)
{
}

void EnableGain(void)
{
  mlib1phdata.IsGainEnabled = TRUE;
}

void DisableGain(void)
{
  mlib1phdata.IsGainEnabled = FALSE;
}

void RestoreDefCalib(void)
{
  CalibStruct1Ph.FrequencyCoeff = 1.00023889;

  CalibStruct1Ph.VCoeff = 7.517977528089888e-7;
  CalibStruct1Ph.ICoeff[0] = 3.0005420511E-7;
  CalibStruct1Ph.ICoeff[1] = 3.0005420511E-7;
  CalibStruct1Ph.ActPowerCoeff[0] = 3.0870693433E-13;
  CalibStruct1Ph.ActPowerCoeff[1] = 3.0870693433E-13;
  CalibStruct1Ph.PhAngle[0] = 2.24286317E-2;
  CalibStruct1Ph.PhAngle[1] = -3.33993435E-2;
  CalibStruct1Ph.VFCoeff = 5.52673412E-13;
  CalibStruct1Ph.IFCoeff[0] = 1.12404917E-13;
  CalibStruct1Ph.IFCoeff[1] = 6.38489369E-14;
  CalibStruct1Ph.ICoeff_LP = 3.0005420511E-7;
  CalibStruct1Ph.ActPowerCoeff_LP = 3.0870693433E-13;
  
  CalibStruct1Ph.RTCCompValue = 0;
  CalibStruct1Ph.RTCCompInterval = 0;

  CalibStruct1Ph.CalibSign = CALIBNOTDONE;
}

void AppInterfaceInit(void)
{
  mlib1phdata.IMax   = 60.0;
  mlib1phdata.IBasic = 10.0;
  mlib1phdata.VHystHigh = 160.0;
  mlib1phdata.VHystLow = 155.0;
  mlib1phdata.MaxPower = 240.0 * mlib1phdata.IMax * 1.6;
}

void CalibMemwrite1Ph(void)
{
  CalibStruct1Ph.CalibSign = CALIBDONE;
}

uint32 NoOfMetDue = 0;
void main (void)
{
  BOARD_InitPins();
  BOARD_BootClockRUN();  

  MeterLibLPRT1Ph_InitParams(&mlib1phdata, NSAMPLES, (NSAMPLES*20)/100, FreqDependentPhErr, FALSE);
  mlib1phdata.Frequency = 50.0f;
  AppInterfaceInit();
  RestoreDefCalib();
  mlib1phdata.CalibState = CALIBSTATE_PROGRESS;
  CalibPoint.Voltage = 240.0;
  CalibPoint.Current = 10.0;
  CalibPoint.PhAngle = 1.04719;
  CalibPoint.PowerFactor = 0.5;
  CalibPoint.Frequency = 50.0;
  /* calibration can be done for CALIB_PHASE or CALIB_NEUTRAL - one at a time */
  CalibPoint.CalibPhase = CALIB_PHASE;
  CalibStruct1Ph.CalibSign = CALIBNOTDONE;
  
  while (1)
  {
    /* calculate phase voltage and phase current waveforms                    */
    time = time+(1.0/NSAMPLES);
    u24_sample = FRAC24(((sin(2*_PI*50.0*time+U_ANGLE)*240.0*sqrt(2)+0.0)/U_MAX));
    mlib1phdata.VOfstSum += u24_sample;
    mlib1phdata.VSampsS = u24_sample - mlib1phdata.VOffset; // Previous offset
    i24_sample = FRAC24(((sin(2*_PI*50.0*time+I_SHIFT)*10.0*sqrt(2)+0.0)/I_MAX));
    mlib1phdata.IOfstSum[0] += i24_sample;
    mlib1phdata.IOfstSum[1] += i24_sample;
    mlib1phdata.ISamps[0] = i24_sample - mlib1phdata.IOffsets[0]; // Previous offset
    mlib1phdata.ISamps[1] = i24_sample - mlib1phdata.IOffsets[1]; // Previous offset
    
    DoPower1Ph();
    
    if (mlib1phdata.MetDue == TRUE)
    {
      NoOfMetDue++;
      /* Do metering calculations */
      DoMetering1Ph();
      
      /* NoOfMetDue count to '29' to take to finish calibration */
      if (mlib1phdata.CalibState == CALIBSTATE_PROGRESS) // will break when CALIBSTATE_COMPLETE
      {
        DoCalibration1Ph(&CalibPoint);
      }
    }
  }
}
