/*
 * 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 _EFOC_H_
#define _EFOC_H_

/*! \brief  Contains public interface to various functions related
 *          to the Enhanced Field-Oriented Control (EFOC) object
 */

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

#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "md_lib/clarke/clarke.h"
#include "md_lib/park/park.h"
#include "md_lib/ipark/ipark.h"
#include "md_lib/svgen/svgen.h"
#include "md_lib/fullwave/fullwave.h"

#ifdef __cplusplus
extern "C" {
#endif

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

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

/*! \brief  Defines the control type of the EFOC
 */
typedef enum
{
    EFOC_CTRLTYPE_VVVF = 0,
    EFOC_CTRLTYPE_CURRENTLOOP,
    EFOC_CTRLTYPE_FULLWAVE,
    EFOC_CTRLTYPE_OFFLINE,
} EFoc_CtrlModeType;

/*! \brief  Defines all the parameters used to initialize EFOC object
 */
typedef struct _EFoc_ParamsType_
{
    float             VsMax_pu;        /*!< Max allowed Vs */
    float             VdMaxScale;      /*!< Max allowed Vd scale factor based on Vs. */
    float             minVdc_V;        /*!< Minimum DC voltage allowed */
    float             maxVdc_V;        /*!< Maximum DC voltage allowed */
    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             runFreq_kHz;     /*!< Frequency to run FOC */
    float             fBase_Hz;        /*!< Base value of frequency used for P.U. */
    float             VBase_V;         /*!< Base value of voltage used for P.U. */
    float             ratedVdc_V;      /*!< Rated dc bus voltage */
    float             IBase_A;         /*!< Base value of current used for P.U. */
    EFoc_CtrlModeType ctrlType;        /*!< Control type of FOC */
    float             switchTime_ms;   /*!< The switch time between FOC and full wave */
    float             fullwaveBWScale; /*!< Current control run frequency / Bandwidth in full wave mode */
    float             lambda;          /*!< Control parameter for the decouple network */
    float             alpha;           /*!< Control parameter for the Ls */
    float             beta;            /*!< Control parameter for the Rs */
} EFoc_ParamsType;

/*! \brief  Defines the dynamic parameters used to update EFOC object
 */
typedef struct _EFoc_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 */
    float runFreq_kHz; /*!< Frequency to run FOC */
    _iq   Vdc_pu;      /*!< DC bus voltage */
    float lambda;      /*!< Control parameter for the decouple network */
    float alpha;       /*!< Control parameter for the Ls */
    float beta;        /*!< Control parameter for the Rs */
} EFoc_DynamicParamsType;

/*! \brief Defines the EFOC object
 */
typedef struct _EFocType_
{
    _iq               Ia_pu;       /*!< Input: The phase-A current */
    _iq               Ib_pu;       /*!< Input: The phase-B current */
    _iq               Ic_pu;       /*!< Input: The phase-C current */
    _iq               parkSinTh;   /*!< Input: The sin value for PARK transform */
    _iq               parkCosTh;   /*!< Input: The cos value for PARK transform */
    _iq               iparkSinTh;  /*!< Input: The sin value for IPARK transform */
    _iq               iparkCosTh;  /*!< Input: The cos value for IPARK transform */
    _iq               Vref;        /*!< Input: Only used in VVVF mode */
    _iq               IdRef;       /*!< Input: The Id reference */
    _iq               IqRef;       /*!< Input: The Iq reference */
    _iq               speed_pu;    /*!< Input: Feedback speed in P.U. */
    _iq               compVd;      /*!< Input: The compensation value of Vd, normally is 0 */
    _iq               compVq;      /*!< Input: The compensation value of Vq, normally is 0 */

    _iq               VsMax;       /*!< Parameters: Max value of Vs */
    _iq               VdMax;       /*!< Parameters: Max value of Vd */
    EFoc_CtrlModeType ctrlType;    /*!< Parameters: Control type of FOC */
    _iq               minVdc_pu;   /*!< Parameter: Minimum DC voltage allowed in P.U. */
    _iq               maxVdc_pu;   /*!< Parameter: Maximum DC voltage allowed in P.U.*/

    _iq               Kr;          /*!< Internal variable: coefficient determined by Rs */
    _iq               Kd_Vd;       /*!< Internal variable: coefficient determined by Ld in Vd equation */
    _iq               Kq_Vd;       /*!< Internal variable: coefficient determined by Lq in Vd equation */
    _iq               Kq_Vq;       /*!< Internal variable: coefficient determined by Lq in Vq equation */
    _iq               Kd_Vq;       /*!< Internal variable: coefficient determined by Ld in Vq equation */
    _iq               Kf;          /*!< Internal variable: coefficient determined by flux in Vq equation */
    float             factorR;     /*!< Internal variable: factor of IBase/VBase */
    float             factorL;     /*!< Internal variable: factor of fBase*IBase/VBase */
    float             factorBemf;  /*!< Internal variable: factor of fBase/VBase */
    ClarkeType        clarkeI;     /*!< Internal variable: Clarke transform of current */
    ParkType          park;        /*!< Internal variable: Part transform */
    IparkType         ipark;       /*!< Internal variable: iPark transform */
    SvgenType         svgen;       /*!< Internal variable: SVPWM generator */
    FullWaveType      fullwave;    /*!< Internal variable: Full wave control */
    _iq               Vd;          /*!< Internal variable: Vd */
    _iq               Vq;          /*!< Internal variable: Vq */
    _iq               lastErrorId; /*!< Internal variable: Last error of Id */
    _iq               lastErrorIq; /*!< Internal variable: Last error of Iq */
    _iq               VdAccum;     /*!< Internal variable: The accumulator of Vd */
    _iq               VqAccum;     /*!< Internal variable: The accumulator of Vq */

    _iq               Vs;          /*!< Output: Clarke transform of current */
} EFocType;

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

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

/*! \brief Initialize the EFOC object
 *
 * This function initalizes EFoc by setting configuration parameters
 *
 * \param[in] obj : pointer to EFoc instance
 * \param[in] pParams : pointer to EFoc configuration parameters
 * \return the MCUs authorized evaluation
 *         - -1 : Functions not available
 *         -  0 : Functions available
 */
extern int32_t EFoc_Init(EFocType *obj, const EFoc_ParamsType *pParams);

/*! \brief Set the current feedback value
 *
 * This function sets current feedback value
 *
 * \param[in] obj : pointer to EFoc instance
 * \param[in] Ia_pu : The phase-A current in P.U.
 * \param[in] Ib_pu : The phase-B current in P.U.
 * \param[in] Ic_pu : The phase-C current in P.U.
 */
static inline void EFoc_SetCurrentFdb(EFocType *obj, _iq Ia_pu, _iq Ib_pu, _iq Ic_pu)
{
    obj->Ia_pu = Ia_pu;
    obj->Ib_pu = Ib_pu;
    obj->Ic_pu = Ic_pu;
}

/*! \brief The main process function of EFoc
 *
 * This function runs EFoc function, perform motor control functions
 *
 * \param[in] obj : pointer to EFoc instance
 * \return the MCUs authorized evaluation
 *         - -1 : Functions not available
 *         -  0 : Functions available
 */
extern int32_t EFoc_Run(EFocType *obj);

/*! \brief Get the PWM compare value of EFoc
 *
 * This function gets three phase duty
 *
 * \param[in] obj : pointer to EFoc instance
 * \param[out] Ta : the phase-A duty
 * \param[out] Tb : the phase-B duty
 * \param[out] Tc : the phase-C duty
 */
extern void EFoc_GetPwmCompareValue(EFocType *obj, _iq *Ta, _iq *Tb, _iq *Tc);

/*! \brief Reset the EFoc object
 *
 * This function resets the EFoc relevant calculation parameters
 *
 * \param[in] obj : pointer to EFoc instance
 */
extern void EFoc_Reset(EFocType *obj);

/*! \brief Update the parameters of EFoc
 *
 * This function updates the EFoc function configuration parameters
 *
 * \param[in] obj : pointer to EFoc instance
 * \param[in] pParams : pointer to control configuration paramter
 * \return the MCUs authorized evaluation
 *         - -1 : Functions not available
 *         -  0 : Functions available
 */
extern int32_t EFoc_UpdateParams(EFocType *obj, const EFoc_DynamicParamsType *pParams);

/*! \brief Change the control type of EFoc
 *
 * This function updates the EFoc function configuration parameters
 *
 * \param[in] obj : pointer to EFoc instance
 * \param[in] ctrlType : the control type of the EFOC
 * \return the MCUs authorized evaluation
 *         - -1 : Functions not available
 *         -  0 : Functions available
 */
extern int32_t EFoc_ChangeCtrlType(EFocType *obj, EFoc_CtrlModeType ctrlType);

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

#endif /* _EFOC_H_ */
