/*
 * Copyright (c) 2010-2016, Freescale Semiconductor, Inc.
 * Copyright (c) 2016-2021, NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#ifndef __METERING1PH_H
#define __METERING1PH_H

#include "types.h"
/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define nBUFFERS 2
#define POWERTOENERGY      (74.56540444)
   
typedef enum
{
  CURRENT_PHASE,
  CURRENT_NEUTRAL,
  nCURRENTS
} CURRENTS;

typedef enum
{
  ACT_POWER,
  REACT_POWER,
  APP_POWER,
  nPOWERS
} POWERS;

typedef enum
{
  ACTI_ENERGY,
  REACTIACTI_ENERGY,
  REACTEACTI_ENERGY,
  APPI_ENERGY,
  ACTE_ENERGY,
  APPE_ENERGY,
  nENERGIES
} ENERGIES;

typedef enum
{
  METREC_FWDED,
  METREC_NET,
} METRECTYPES;

typedef struct
{
  uint32 EnerRegs[nENERGIES];
  uint16 CRC;
} tEnerStruct;

/* IRTC RAM allocations */
typedef enum
{
  IRTC_BOOTMODE         =  0,
  IRTC_ENERBACKUP       =  IRTC_BOOTMODE + 1,   /* size (nENERGIES*3) */
  IRTC_BATTPBON         =  IRTC_ENERBACKUP + (nENERGIES*3),
} IRTC_ALLOCATIONS;

typedef enum
{
  SWB_CUR_PH            = 0x01,
  SWB_CUR_NU            = 0x02,
} SWB_CUR_CHANNEL;

/*! Metering library data structure definition - 1PH METER                    */
typedef struct
{
  float     Vrms;                /*!< Calcuated RMS value of the voltage */
  float     Irms[nCURRENTS];     /*!< Calculated RMS currents - Phase and neutral */
  float     VrmsNoFudge;         /*!< RMS value of voltage w/o compensation */
  float IrmsNoFudge[nCURRENTS];  /*!< RMS value of currents w/o compensation */
  float     PFMetImax;           /*!< Calculated Power factor value during forced Imax condition */
  float ActPowers[nCURRENTS];    /*!< Calculated active power */
  float ActPowersNoFudge[nCURRENTS]; /*!< Calculated active power value w/o compensation */
  float ReactPowers[nCURRENTS];  /*!< Calculated reactive power */
  float AppPowers[nCURRENTS];    /*!< Calculated apparent power */
  float AppPowersNoFudge[nCURRENTS]; /*!< Calculated apparent power w/o compensation */
  float PowerFactors[nCURRENTS]; /*!< Calculated power factor */
  float  Frequency;              /*!< Calculated frequency */
  uint16 nSamples;               /*!< No of voltage/current samples per second - application to load */
  uint8  MetDue;                 /*!< Indicates metrology processing is due for a second */
  uint8  MetOnImax;              /*!< Indication to do meteirng with Imax condition - application to load */
  int8   ISigns[nCURRENTS];      /*!< Forward/reverse sign of currents, 1 = forward, -1 = reverse */
  uint8  ReactSampleIndex;       /*!< Reactive sample index - internal */
  uint8  CurToUse;               /*!< Indicates which current has higher value - Phase/neutral */
  uint16 nSamps;                 /*!< Indicates current sample index ~ [0-(nSamples-1)] */
  int32 VOffset;                 /*!< Calculated Voltage offset */
  int32 *pVQCycleSamps;          /*!< 90 degree phase shifted voltage samples buffer pointer - internal */
  int32  IOfstSum[nCURRENTS];    /*!< Current offset sum - internal */
  int32  IOffsets[nCURRENTS];    /*!< Calculated current offsets */
  int32  VSampsS;                /*!< Offset compensated voltage sample */
  int32  VOfstSum;               /*!< Voltage offset sum - internal */
  uint64 VrmsSums[nBUFFERS];     /*!< Square sums of the voltage samples - internal */
  uint64 IrmsSums[nBUFFERS][nCURRENTS]; /*!< Square sums of the current samples - internal */
  uint64 RelaySenseSums[nBUFFERS]; /*!< Square sums of the relay sense voltage samples - internal */
  int32  VRelayOfstSum;          /*!< Relay sense voltage offset sum - internal */
  int32  VRelayOffset;           /*!< Calculated relay voltage offset */
  float IBasic;                  /*!< Basic currnet of the meter - application to load */
  float IMax;                    /*!< Maximum current rating of the meter - application to load */
  float VHystHigh;               /*!< High threshold value of voltage to enable gain for the current measurement - application to load */
  float VHystLow;                /*!< Low threshold value of voltage to disable gain for the current measurement - application to load */
  float MaxPower;                /*!< Maximum value of calculated power to restrict power/energy count calculation - application to load */
  int32  ISamps[nCURRENTS];      /*!< Offset compensated current samples */
  float PhAngles[2];             /*!< Calculated Phase angle */
  uint8 MetRecordingType;        /*!< Power/energy recording type METREC_FWDED/METREC_NET */
  uint8  WBuffer;                /*!< Buffer index of voltage/current samples buffers for a second period */
  uint8  FirstTime;              /*!< internal use */
  uint8 IsGainEnabled;           /*!< Returns current gain is status. TRUE = enabled, FALSE = disabled */
  uint8 LastGainStatus;          /*!< Related to current gain status - internal */
  uint8  IncEnerPtrs[3];         /*!< Indicated energy pointer types active, reactive and apparent - internal */
  uint32 MetEnergyCounts[3];     /*!< Calculated energy counts for 50 periods */
  uint64 MetEnergySecCounts[3];  /*!< Calculated energy counts 1 second */
  uint8  DoFundamental;          /*!< Indicate whether fundamental frequency calculation to be done - application to load */
  uint8  fSampNo;                /*!< Used for fundamental frequency related calculations - internal */
  uint8  CalibState;             /*!< Holds calibration state CALIBSTATE_IDLE, CALIBSTATE_PROGRESS, CALIBSTATE_COMPLETE */
} tMETERLIBLPRT1PH_DATA;

#define SWB_SIGN        0xA5
#define SWB_CUR_BOTH    (SWB_CUR_PH | SWB_CUR_NU)

/*******************************************************************************
* Prototypes
******************************************************************************/
extern tMETERLIBLPRT1PH_DATA *pmlib1phdata;
extern float VFundamental1Ph;
extern float IFundamental1Ph[nCURRENTS];
extern float VTHD1Ph;
extern float ITHD1Ph[nCURRENTS];

extern float Vrelaysense;

/***************************************************************************//*!
 * @brief   Does the RMS and power calculation per voltage and current samples. 
 *          Also, does the offset calculations. Once this function finished all 
 *          samples processing for 50 periods (50 Hz signal), 
 *          tMETERLIBLPRT3PH_DATA -> MetDue is set to 'TRUE' value.
 * @note    The @ref DoPower1Ph function must be called after 1 set of voltage,
 *          current samples are received.
 ******************************************************************************/
extern void DoPower1Ph(void);

/***************************************************************************//*!
 * @brief   Re-calculates non-billing parameters once every second or 50 
 *          sinusoidal wave periods.
 * @note    The @ref DoMetering1Ph function must be called after 
 *          tMETERLIBLPRT1PH_DATA -> MetDue is set to 'TRUE' value. This 
 *          function internally clears tMETERLIBLPRT1PH_DATA -> MetDue to 
 *          'FALSE'.
 ******************************************************************************/
extern void DoMetering1Ph(void);

/***************************************************************************//*!
 * @brief   Initializes tMETERLIBLPRT1PH_DATA meteting structure object with 
 *          few application specific parameters. Typically to be called once 
 *          application run cycle.
 * @param   nSamples     No of voltage/current samples per second 
 *          - application to load.
 * @param   samplesForOffset   No of samples per second to be used for offset 
 *          calculation.
 * @param   pFreqDependentPhErr   Application defined Frequency dependent phase 
 *          correction values.
 * @param   doFundamental Application defined initialization if metering library 
 *          should perform fundamental calculation related tasks.
 * @note    The @ref MeterLibLPRT1Ph_InitParams function must be called 
 *          typically once in application initialization cycle.
 ******************************************************************************/
extern void MeterLibLPRT1Ph_InitParams(tMETERLIBLPRT1PH_DATA *mlib,  
                                       uint16 nSamples, uint16 samplesForOffset, 
                                       float *pFreqDependentPhErr, uint8 doFundamental);

/* Callbacks/hooks exported by metrology library */
/***************************************************************************//*!
 * @brief   This function is called from metering library to allow application 
 *          to further correct the phase angle to fine tune power calculation.
 * @param   currenttoUse Current phase number CURRENT_PHASE or CURRENT_NEUTRAL.
 * @note    The @ref CorrectAppPhAngle1Ph is called from DoMetering1Ph().
 ******************************************************************************/
extern void CorrectAppPhAngle1Ph(uint8 currenttoUse);

/***************************************************************************//*!
 * @brief   This function is called from metering library to allow application 
 *          to tune up non-billing parameters as per applicaiton need - for 
 *          example to clear leakage current and related parameters.
 * @note    The @ref FudgeParameters1Ph is called from DoMetering1Ph().
 ******************************************************************************/
extern void FudgeParameters1Ph(void);

/***************************************************************************//*!
 * @brief   This function is called from metering library to allow application 
 *          to check current phase voltage and indicate the metering library 
 *          to switch to low power mode measurements of non-billing parameters  
 *          through tMETERLIBLPRT1PH_DATA -> IsGainEnabled parameter.
 * @note    The @ref ChkVolLvl is called from DoMetering1Ph().
 ******************************************************************************/
extern void ChkVolLvl(void);

/***************************************************************************//*!
 * @brief   This function is called from metering library during calibration 
 *          phase only to calculate calibration coefficients during low power 
 *          operation and current gain is disabled. Application should also call
 *          this function in the context of ChkVolLvl() if the current RMS 
 *          voltage is higher than tMETERLIBLPRT1PH_DATA -> VHystLow.
 * @note    The @ref DisableGain is called from DoMetering1Ph().
 ******************************************************************************/
extern void DisableGain(void);

/***************************************************************************//*!
 * @brief   This function is called from metering library during calibration 
 *          phase only to calculate calibration coefficients after low power 
 *          operation and current gain is enabled. Application should also call
 *          this function in the context of ChkVolLvl() if the current RMS 
 *          voltage is higher than tMETERLIBLPRT1PH_DATA -> VHystHigh.
 * @note    The @ref EnableGain is called from DoMetering1Ph().
 ******************************************************************************/
extern void EnableGain(void);

/***************************************************************************//*!
 * @brief   This function is called from metering library to allow application 
 *          to save CalibStruct1Ph data structure object - once after the 
 *          calibration is done.
 * @note    The @ref CalibMemwrite1Ph is called whenever calibration is 
 *          performed.
 ******************************************************************************/
extern void CalibMemwrite1Ph(void);

#endif /* __METERING1PH_H */