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

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

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

#include <stdint.h>
#include "common/iqmath/iqmath.h"
#include "common/pid/pid.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 FOC
 */
typedef enum
{
    FOC_CTRLTYPE_VVVF = 0,
    FOC_CTRLTYPE_CURRENTLOOP,
    FOC_CTRLTYPE_FULLWAVE,
    FOC_CTRLTYPE_OFFLINE,
} Foc_CtrlModeType;

/*! \brief  Defines all the parameters used to initialize FOC object
 */
typedef struct _Foc_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            runFreq_kHz;     /*!< Frequency to run FOC */
    float            fBase_Hz;        /*!< Base value of frequency used for P.U. */
    float            ratedVdc_V;      /*!< Rated dc bus voltage */
    float            VBase_V;         /*!< Base value of voltage used for P.U. */
    float            IBase_A;         /*!< Base value of current used for P.U. */
    Foc_CtrlModeType ctrlType;        /*!< Control type of FOC */
    float            switchTime_ms;   /*!< The switch time between FOC and full wave */
    float            bandWidthScale;  /*!< Current control run frequency / Bandwidth */
    float            fullwaveBWScale; /*!< Current control run frequency / Bandwidth in full wave mode */
} Foc_ParamsType;

/*! \brief  Defines the dynamic parameters used to update FOC object
 */
typedef struct _Foc_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 runFreq_kHz; /*!< Frequency to run FOC */
    _iq   Vdc_pu;      /*!< DC bus voltage */
} Foc_DynamicParamsType;

/*! \brief Defines the FOC object
 */
typedef struct _FocType_
{
    _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              Vdff;       /*!< Input: Feed-forward Vd */
    _iq              Vqff;       /*!< Input: Feed-forward Vq */

    _iq              VsMax;      /*!< Parameter: Max value of Vs */
    _iq              VdMax;      /*!< Parameter: Max value of Vd */
    Foc_CtrlModeType ctrlType;   /*!< Parameter: Control type of FOC */
    float            factorKpKi; /*!< Parameter: The factor to calculate Kp Ki in runtime */
    _iq              minVdc_pu;  /*!< Parameter: Minimum DC voltage allowed in P.U. */
    _iq              maxVdc_pu;  /*!< Parameter: Maximum DC voltage allowed in P.U. */

    PidType          pidId;      /*!< Internal variable: The PID control of Id current */
    PidType          pidIq;      /*!< Internal variable: The PID control of Iq current */
    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              Vs;         /*!< Output: Clarke transform of current */
} FocType;

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

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

/*! \brief Initialize the FOC object
 *
 * This function initalizes Foc by setting configuration parameters
 *
 * \param[in] obj : pointer to Foc instance
 * \param[in] pParams : pointer to Foc configuration parameters
 */
extern void Foc_Init(FocType *obj, const Foc_ParamsType *pParams);

/*! \brief Set the current feedback value
 *
 * This function runs Foc function, perform motor control functions
 *
 * \param[in] obj : pointer to Foc 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 Foc_SetCurrentFdb(FocType *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 Foc
 *
 * This function runs Foc function, perform motor control functions
 *
 * \param[in] obj : pointer to Foc instance
 */
extern void Foc_Run(FocType *obj);

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

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

/*! \brief Update the parameters of Foc
 *
 * This function updates the Foc function configuration parameters
 *
 * \param[in] obj : pointer to Foc instance
 * \param[in] pParams : pointer to control configuration paramter
 */
extern void Foc_UpdateParams(FocType *obj, const Foc_DynamicParamsType *pParams);

/*! \brief Change the control type of Foc
 *
 * This function updates the Foc function configuration parameters
 *
 * \param[in] obj : pointer to Foc instance
 * \param[in] ctrlType : the control type of the FOC
 */
extern void Foc_ChangeCtrlType(FocType *obj, Foc_CtrlModeType ctrlType);

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

#endif /* _FOC_H_ */
