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

/*! \brief  Contains the public interface to the
 *         SVPWM generator routines
 */

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

#include "common/iqmath/iqmath.h"

#ifdef __cplusplus
extern "C" {
#endif

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

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

/*! \brief  Defines the control mode of the SVGEN
 */
typedef enum
{
    SVGEN_MODE_NORMAL = 0, /*!< Normal mode of sine and trapezoid */
    SVGEN_MODE_SQUAREWAVE, /*!< Square wave mode */
} Svgen_ModeType;

/*! \brief Defines the Space Vector Generator object
 */
typedef struct _SvgenType_
{
    _iq            Ualpha; /*!< Input: reference alpha-axis phase voltage */
    _iq            Ubeta;  /*!< Input: reference beta-axis phase voltage */

    Svgen_ModeType mode;   /*!< Parameter: the working mode */

    _iq            Ta;     /*!< Output: reference phase-a switching function */
    _iq            Tb;     /*!< Output: reference phase-b switching function */
    _iq            Tc;     /*!< Output: reference phase-c switching function */

} SvgenType;

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

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

/*! \brief The main process function of Svgen
 *
 * This function runs Svgen function, perform motor control functions
 *
 * \param[in] obj : pointer to Svgen instance
 */
static inline void Svgen_Run(SvgenType *obj)
{
    _iq Vmax, Vmin, Vcom;
    _iq Vref1, Vref2, Vref3;
    _iq Va_tmp = -_IQdiv2(obj->Ualpha);
    _iq Vb_tmp = _IQmpy(IQMATH_SQRT_THREE_OVER_TWO, obj->Ubeta);

    Vref1 = obj->Ualpha;    /* alpha */
    Vref2 = Va_tmp + Vb_tmp; /* -0.5*alpha + sqrt(3)/2 * beta; */
    Vref3 = Va_tmp - Vb_tmp; /* -0.5*alpha - sqrt(3)/2 * beta; */

    Vmax = 0;
    Vmin = 0;

    /* find order Vmin,Vmid,Vmax */
    if(Vref1 > Vref2)
    {
        Vmax = Vref1;
        Vmin = Vref2;
    }
    else
    {
        Vmax = Vref2;
        Vmin = Vref1;
    }

    if(Vref3 > Vmax)
    {
        Vmax = Vref3;
    }
    else if(Vref3 < Vmin)
    {
        Vmin = Vref3;
    }

    Vcom = _IQmpy(Vmax + Vmin, _IQ(0.5));

    /* Subtract common-mode term to achieve SV modulation */
    obj->Ta = (Vref1 - Vcom);
    obj->Tb = (Vref2 - Vcom);
    obj->Tc = (Vref3 - Vcom);

    /* If in SquareWave mode, the outputs is not continuous */
    if(obj->mode == SVGEN_MODE_SQUAREWAVE)
    {
        if(obj->Ta > 0)
        {
            obj->Ta = _IQ(0.5);
        }
        if(obj->Ta < 0)
        {
            obj->Ta = -_IQ(0.5);
        }
        if(obj->Tb > 0)
        {
            obj->Tb = _IQ(0.5);
        }
        if(obj->Tb < 0)
        {
            obj->Tb = -_IQ(0.5);
        }
        if(obj->Tc > 0)
        {
            obj->Tc = _IQ(0.5);
        }
        if(obj->Tc < 0)
        {
            obj->Tc = -_IQ(0.5);
        }
    }
}

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

#endif /* _SVGEN_H_ */
