/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

#ifndef _CLFF_H_
#define _CLFF_H_

/*! \brief  Contains public interface to various functions related
 *          to the Current Loop Feed-Forward (CLFF) object
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include "common/iqmath/iqmath.h"

#ifdef __cplusplus
extern "C" {
#endif

/*******************************************************************************
 * the defines
 ******************************************************************************/

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/*! \brief Defines the initial parameters for CLFF object
 */
typedef struct _Clff_ParamsType_
{
    float Rs_Ohm;     /*!< Stationary resistance in Ohm */
    float Ld_mH;      /*!< Normal D-axis inductance in mH */
    float Lq_mH;      /*!< Normal Q-axis inductance in mH */
    float flux_Wb;    /*!< The flux of rotor */
    float ratedVdc_V; /*!< Rated dc bus voltage */
    float IBase_A;    /*!< Base value of current used for P.U. */
    float VBase_V;    /*!< Base value of voltage used for P.U. */
    float fBase_Hz;   /*!< Base value of frequency used for P.U. */
    float minVdc_V;   /*!< Minimum DC voltage allowed */
    float maxVdc_V;   /*!< Maximum DC voltage allowed */
} Clff_ParamsType;

/*! \brief  Defines the dynamic parameters used to update CLFF object
 */
typedef struct _Clff_DynamicParamsType_
{
    float Rs_Ohm;  /*!< Stationary resistance in Ohm */
    float Ld_mH;   /*!< Normal D-axis inductance in mH */
    float Lq_mH;   /*!< Normal Q-axis inductance in mH */
    float flux_Wb; /*!< The flux of rotor */
    _iq   Vdc_pu;  /*!< bus voltage in P.U. */
} Clff_DynamicParamsType;

/*! \brief Defines the CLFF object
 */
typedef struct _ClffType_
{
    _iq Id_pu;      /*!< Input: Id current in P.U. */
    _iq Iq_pu;      /*!< Input: Iq current in P.U. */
    _iq eleFreq_pu; /*!< Input: electrical frequency in P.U. */

    _iq   Kf;         /*!< Parameter: coefficient determined by Back EMF */
    _iq   Kd;         /*!< Parameter: coefficient determined by Ld */
    _iq   Kq;         /*!< Parameter: coefficient determined by Lq */
    _iq   Kr;         /*!< Parameter: coefficient determined by Rs */
    float RsBase_ohm; /*!< Parameter: Base value of resistance used for P.U. */
    float LBase_mH;   /*!< Parameter: Base value of Ls used for P.U. */
    float PsiBase_Wb; /*!< Parameter: Base value of flux used for P.U. */
    _iq   minVdc_pu;  /*!< Parameter: Minimum DC voltage allowed in P.U. */
    _iq   maxVdc_pu;  /*!< Parameter: Maximum DC voltage allowed in P.U. */

    _iq Vd; /*!< Output: theoretical Vd */
    _iq Vq; /*!< Output: theoretical Vq */
} ClffType;

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the function prototypes
 ******************************************************************************/

/*! \brief Initialize the CLFF object
 *
 * This function initalizes CLFF by setting configuration parameters
 *
 * \param[in] obj : pointer to Clff instance
 * \param[in] pParams : pointer to CLFF configuration parameters
 */
extern void Clff_Init(ClffType *obj, const Clff_ParamsType *pParams);

/*! \brief Calculate the theoretical Vd, Vq
 *
 * This function runs Clff function, calculates the theoretical Vd, Vq value
 *
 * \param[in] obj : pointer to Clff instance
 */
static inline void Clff_Calc(ClffType *obj)
{
    obj->Vd = _IQmpy(obj->Kr, obj->Id_pu)
              - _IQmpy(_IQmpy(obj->Kq, obj->Iq_pu), obj->eleFreq_pu);

    obj->Vq = _IQmpy(obj->Kr, obj->Iq_pu)
              + _IQmpy(_IQmpy(obj->Kd, obj->Id_pu) + obj->Kf, obj->eleFreq_pu);
}

/*! \brief Update the parameters
 *
 * This function updates the Clff function configuration parameters dynamically
 *
 * \param[in] obj : pointer to Clff instance
 * \param[in] pParams : pointer to Clff dynamic configuration parameters instance
 */
static inline void Clff_UpdateParams(ClffType *obj, const Clff_DynamicParamsType *pParams)
{
    if(pParams->Vdc_pu >= obj->minVdc_pu && pParams->Vdc_pu <= obj->maxVdc_pu)
    {
        obj->Kd = _IQdiv(_IQ(pParams->Ld_mH / obj->LBase_mH), pParams->Vdc_pu);
        obj->Kq = _IQdiv(_IQ(pParams->Lq_mH / obj->LBase_mH), pParams->Vdc_pu);
        obj->Kf = _IQdiv(_IQ(pParams->flux_Wb / obj->PsiBase_Wb), pParams->Vdc_pu);
        obj->Kr = _IQdiv(_IQ(pParams->Rs_Ohm / obj->RsBase_ohm), pParams->Vdc_pu);
    }
    else
    {
        obj->Kd = 0;
        obj->Kq = 0;
        obj->Kf = 0;
        obj->Kr = 0;
    }
}

#ifdef __cplusplus
}
#endif /* extern "C" */

#endif /* _CLFF_H_ */
