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

#include "types.h"

#ifdef __cplusplus
extern "C"
{
#endif

/*******************************************************************************
 * Definitions
 ******************************************************************************/  
typedef enum
{
  V_R_PHASE,
  V_Y_PHASE,
  V_B_PHASE,
  nVPHASES
}VPHASES;

typedef enum
{
  I_R_PHASE,
  I_Y_PHASE,
  I_B_PHASE,
  I_N_PHASE,
  nIPHASES
}IPHASES;

typedef enum
{
  R_PHASEMASK = (1 << V_R_PHASE),
  Y_PHASEMASK = (1 << V_Y_PHASE),
  B_PHASEMASK = (1 << V_B_PHASE),
}PHASEMASKS;

typedef enum
{
  ACT_POWER_3PH,
  REACT_POWER_3PH,
  APP_POWER_3PH,
  nPOWERS_3PH
} POWERS_3PH;

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

typedef enum
{
  METREC_FWDED_3PH,
  METREC_NET_3PH,
} METRECTYPES_3PH;

typedef enum
{
  PHSEQ_FWD,
  PHSEQ_REV,
}PH_SEQ;

/*! Metering library data structure definition - 3PH METER                    */
typedef struct
{
  float Vrms[nVPHASES];                 /*!< Calcuated RMS value of the voltages */
  float Irms[nIPHASES];                 /*!< Calculated RMS currents */
  float VrmsNoFudge[nIPHASES];          /*!< RMS value of voltages w/o compensation */
  float IrmsNoFudge[nIPHASES];          /*!< RMS value of currents w/o compensation */
  float Frequency;                      /*!< Calculated frequency */
  uint16 nSamples;                      /*!< No of voltage/current samples per second - application to load */
  uint8  ReactSampleIndex;              /*!< Reactive sample index - internal */
  int16  *pVQCycleSamps[nVPHASES];      /*!< 90 degree phase shifted voltage samples buffer pointer - internal */
  uint64 VrmsSums[2][nVPHASES];         /*!< Square sums of the voltage samples - internal */
  uint64 IrmsSums[2][nIPHASES];         /*!< Square sums of the current samples - internal */
  uint8  MetDue;                        /*!< Indicates metrology processing is due for a second */
  uint8  MetOnImax;                     /*!< Indication to do meteirng with Imax condition - application to load */
  int16  VSampsS[nVPHASES];             /*!< Offset compensated voltage samples */
  uint32 VOfstSum[nVPHASES];            /*!< Voltage offset sums - internal */
  int32 IOfstSum[nIPHASES];             /*!< Current offset sums - internal */
  int32 IOffsets[nIPHASES];             /*!< Calculated current offsets */
  uint16 VOffsets[nVPHASES];            /*!< Calculated Voltage offsets */
  int32 ISamps[nIPHASES];               /*!< Offset compensated current samples */
  int8  ISigns[nVPHASES];               /*!< Forward/reverse sign of currents, 1 = forward, -1 = reverse */
  float ActPowers[nVPHASES];            /*!< Calculated active power values */
  float ReactPowers[nVPHASES];          /*!< Calculated reactive power values */
  float AppPowers[nVPHASES];            /*!< Calculated apparent power values */
  float PhPowerFactors[nVPHASES];       /*!< Calculated power factor values of three-phases */
  float PowerFactor;                    /*!< Calculated total power factor */
  float Powers[nPOWERS_3PH];            /*!< Calculated powers values per second */
  float PhAngles[nVPHASES];             /*!< Calculated Phase angles */
  float AppPowersNoFudge[nVPHASES];     /*!< Calculated apparent power values w/o compensation */
  float ActPowerNoFudge;                /*!< Calculated total active power value w/o compensation */
  float AppPowerNoFudge;                /*!< Calculated total apparent power value w/o compensation */
  float PhPFNoFudge[nIPHASES];          /*!< Calculated power factors w/o compensation */
  float PFMetImax;                      /*!< Calculated Power factor value during forced Imax condition */
  float IBasic;                         /*!< Basic currents of the meter - application to load */
  float IMax;                           /*!< Maximum current rating of the meter - application to load */
  float  MinIMagThreshold;
  float MaxPower;                       /*!< Maximum value of calculated power to restrict power/energy count calculation - application to load */
  uint8 MetRecordingType;               /*!< Power/energy recording type METREC_FWDED/METREC_NET */     
  uint8  WBuffer;                       /*!< Buffer index of voltage/current samples buffers for a second period */
  uint8  nZCurs;                        /*!< internal */
  uint8  FirstCycle;                    /*!< 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 CalibState;                     /*!< Holds calibration state CALIBSTATE_IDLE, CALIBSTATE_PROGRESS, CALIBSTATE_COMPLETE */
} tMETERLIBLPRT3PH_DATA;

/*******************************************************************************
* Prototypes
******************************************************************************/
extern tMETERLIBLPRT3PH_DATA *pmlib3phdata;
extern float VFundamental3Ph[nVPHASES];
extern float IFundamental3Ph[nVPHASES];
extern float VTHD3Ph[nVPHASES];
extern float ITHD3Ph[nVPHASES];

/***************************************************************************//*!
 * @brief   This function allows 3 phase application to process per phase 
 *          voltage, current samples.
 * @note    The @ref ProcSamples3Ph function must be called after voltage, 
 *          current samples are received for any phase.
 ******************************************************************************/
extern void ProcSamples3Ph(uint8 channel);

/***************************************************************************//*!
 * @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 DoPower3Ph function must be called once after all of 
 *          voltage, current samples are received.
 ******************************************************************************/
extern void DoPower3Ph(void);

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

/***************************************************************************//*!
 * @brief   Initializes tMETERLIBLPRT3PH_DATA meteting structure object with 
 *          few application specific parameters. Typically to be called once 
 *          applicaiton 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 MeterLibLPRT3Ph_InitParams function must be called 
 *          typically once in application initialization cycle.
 ******************************************************************************/
extern void MeterLibLPRT3Ph_InitParams(tMETERLIBLPRT3PH_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 tune up non-billing parameters as per applicaiton need - for 
 *          example to clear leakage current and related parameters.
 * @note    The @ref FudgeParameters3Ph is called from DoMetering3Ph().
 ******************************************************************************/
extern void FudgeParameters3Ph(void);

/***************************************************************************//*!
 * @brief   This function is called from metering library to allow application 
 *          to further correct the phase angle to fine tune power calculation.
 * @note    The @ref CorrectAppPhAngle3Ph is called from DoMetering1Ph().
 ******************************************************************************/
extern void CorrectAppPhAngle3Ph(uint32 phase);

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

#ifdef __cplusplus
}

#endif
#endif /* __METERING3PH_H */