This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28069F: InstaSPIN-FOC Lab11a project

Part Number: TMS320F28069F
Other Parts Discussed in Thread: MOTORWARE,

Hi Yanming Luo,

I have a question on an InstaSPIN-FOC Lab project in motorware.

Particularly it is on Lab11a.

We are presently attempting to implement the function of variable PWM frequency on Lab11a.

For this work, we need to split the source codes in mainISR() into two ISR funtions of fixed frequency and variable frequency as in the is12_variable_pwm_frequency lab in MotorControl_SDK.

Meanwhile in my previous post, you advised how to split the source codes in mainISR() into two ISR funtions; it is to run all of the speed, Id and Iq controllers in estISR().

However, with reference to the is12_variable_pwm_frequency lab in MotorControl_SDK, I have found out that the estISR() runs the speed controller while the mainISR() runs the Id and Iq controllers.

Please comment on this observation.

Thank you for your guidance.

With regards,

JS Yoo

  •  Yes, the Id and Iq PI controller can be called in either estISR or mainISR. It's better to call in mainISR(). It's better to change the Kp and Ki with PWM frequency if you need a good current control performance.

  • Hi Yanming Luo,

    Thank you for your review.

    First of all, our inverter built by using the TMS320F28069F runs very well in the environment of Lab11a.

    In order to implement the function of variable PWM frequency on Lab11a, I have completed the work of splitting the source codes in mainISR() into two ISR funtions of estISR() and mainISR() similar to is12_variable_pwm_frequency lab in MotorControl_SDK.

    All functions associated with reading the ADC result, writing PWM compare registers, the overmodulation and current reconstruction, and the Id and Iq controls  reside in mainISR(), whereas the other functions associated with the speed control and ESTrun() reside in estISR().

    Now when I attempt to run the motor with this modified Lab11a project, the motor generates noisy sound. It seems that the magnetic flux is not generated suitably.

    Therefore I compared the source codes in estISR() of the is12_variable_pwm_frequency project with those in mainISR() of the Lab11a.

    First, the source codes in estISR() of the is12_variable_pwm_frequency project are as follows:

            //
            // store the input data into a buffer
            //
            estInputData.dcBus_V = adcData.dcBus_V;
            estInputData.speed_ref_Hz = motorVars.speedTraj_Hz;
            estInputData.speed_int_Hz = motorVars.speedTraj_Hz;

            //
            // run the estimator
            //
            EST_run(estHandle, &estInputData, &estOutputData);

    The input parameters for EST_run() are provided ahead of calling the EST_run() function.

    Second, the source codes in mainISR() of the Lab11a are as follows:

      // run Clarke transform on current
      CLARKE_run(clarkeHandle_I,&gAdcData.I,&Iab_pu);

      // run Clarke transform on voltage
      CLARKE_run(clarkeHandle_V,&gAdcData.V,&Vab_pu);

      // run a trajectory for Id reference, so the reference changes with a ramp instead of a step
      TRAJ_run(trajHandle_Id);

      // run the estimator
      EST_run(estHandle,
              &Iab_pu,
              &Vab_pu,
              gAdcData.dcBus,
              TRAJ_getIntValue(trajHandle_spd));

    Two CLARKE_run() functions need to reside in mainISR() while the EST_run() function need to reside in estISR().

    The parameters for this EST_run() seem to be input parameters except the estHandle.

    In summary the ways that EST_run() function is used in the is12_variable_pwm_frequency project and Lab11a are quite different.

    Please inform us if it is impossible to implement the function of variable PWM frequency with the motorware FAST estimator library.

    We are ready to build a new inverter by using the TMS320F28004xC device and the MotorControl_SDK FAST estimator library.

    Otherwise please provide us with the modified Lab11a project which have the function of variable PWM frequency .

    Thank you for your guidance.

    With regards,

    JS Yoo

  • You might try to use the same frequency for mainISR() and EST_run() without online change PWM frequency to see what happens.

    And which frequency are you using to calculate the estimator parameters?

  • Hi Yanming Luo,

    Thank you for your review.

    What I did is as follows.

    (1) With respect to the original Lab11a, the PWM frequency was 8kHz and the inverter runs the motor very well.

    (2) With respect to the modified Lab11a, at first, the execution frequency for estISR() was set to 20kHz and the execution frequency for mainISR() was set to 8kHz. The motor does not run and generates noisy sound.

    (3) With respect to the modified Lab11a, secondly, the execution frequency for both estISR() and mainISR() was set to 8kHz. The motor does not run and generates noisy sound.

    What do mean by "to calculate the estimator parameters"?

    What are the estimator parameters?

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Please post the user.h and lab main file you used.

  • Hi Yanming Luo,

    Thank you for your review.

    Please enclosed find the source codes for estISR() and mainISR().

    I just splitted the source codes of the original mainISR() in Lab11a  into two ISR funtions of estISR() and the new mainISR().

    ------------------------------------------------------------------------------------------------------------------------------------

    _iq angle_pu = _IQ(0.0);
    _iq speed_pu = _IQ(0.0);
    MATH_vec2 Iab_pu;
    MATH_vec2 Vab_pu;
    MATH_vec2 phasor;

    //
    // the CPU timer0 interrupt as FAST estimator ISR
    //
    interrupt void estISR(void)
    {
        // acknowledge the interrupt that is set for estimator
        HAL_acqTimer0Int(halHandle);

    //    if(gTrjCnt >= gUserParams.numCtrlTicksPerTrajTick)
    //    {
    //        // clear counter
    //        gTrjCnt = 0;

            // run a trajectory for speed reference, so the reference changes with a ramp instead of a step
            TRAJ_run(trajHandle_spd);
    //    }

            // run the estimator
            EST_run(estHandle,
                    &Iab_pu,
                    &Vab_pu,
                    gAdcData.dcBus,
                    TRAJ_getIntValue(trajHandle_spd));

            // generate the motor electrical angle
            angle_pu = EST_getAngle_pu(estHandle);
            speed_pu = EST_getFm_pu(estHandle);

            // get Idq from estimator to avoid sin and cos
            EST_getIdq_pu(estHandle,&gIdq_pu);

            // run the appropriate controller
            if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
              {
                // when appropriate, run the PID speed controller
                if((pidCntSpeed++ >= gUserVars.numCtrlTicksPerSpeedTick) && (!gMotorVars.Flag_enableRsRecalc))
                  {
                    // calculate Id reference squared
                    _iq Id_ref_squared_pu = _IQmpy(PID_getRefValue(pidHandle[1]),PID_getRefValue(pidHandle[1]));

                    // Take into consideration that Iq^2+Id^2 = Is^2
                    _iq Iq_Max_pu = _IQsqrt(gIs_Max_squared_pu - Id_ref_squared_pu);

                    // clear counter
                    pidCntSpeed = 0;

                    // Set new min and max for the speed controller output
                    PID_setMinMax(pidHandle[0], -Iq_Max_pu, Iq_Max_pu);

                    // run speed controller
                    PID_run_spd(pidHandle[0],TRAJ_getIntValue(trajHandle_spd),speed_pu,&(gIdq_ref_pu.value[1]));
                  }
              }

    }


    //! \brief     The main ISR that implements the motor control.
    interrupt void mainISR(void)
    {
      _iq oneOverDcBus;

      // acknowledge the ADC interrupt
      HAL_acqAdcInt(halHandle,ADC_IntNumber_1);

      // convert the ADC data
      HAL_readAdcDataWithOffsets(halHandle,&gAdcData);

      // remove offsets
      gAdcData.I.value[0] = gAdcData.I.value[0] - gOffsets_I_pu.value[0];
      gAdcData.I.value[1] = gAdcData.I.value[1] - gOffsets_I_pu.value[1];
      gAdcData.I.value[2] = gAdcData.I.value[2] - gOffsets_I_pu.value[2];
      gAdcData.V.value[0] = gAdcData.V.value[0] - gOffsets_V_pu.value[0];
      gAdcData.V.value[1] = gAdcData.V.value[1] - gOffsets_V_pu.value[1];
      gAdcData.V.value[2] = gAdcData.V.value[2] - gOffsets_V_pu.value[2];

      // run the current reconstruction algorithm
      runCurrentReconstruction();

      // run Clarke transform on current
      CLARKE_run(clarkeHandle_I,&gAdcData.I,&Iab_pu);

      // run Clarke transform on voltage
      CLARKE_run(clarkeHandle_V,&gAdcData.V,&Vab_pu);

      // run a trajectory for Id reference, so the reference changes with a ramp instead of a step
      TRAJ_run(trajHandle_Id);

      // run the appropriate controller
      if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
        {
          _iq refValue;
          _iq fbackValue;
          _iq outMax_pu;

          // get the reference value from the trajectory module
          refValue = TRAJ_getIntValue(trajHandle_Id) + EST_getRsOnLineId_pu(estHandle);

          // get the feedback value
          fbackValue = gIdq_pu.value[0];

          // run the Id PID controller
          PID_run(pidHandle[1],refValue,fbackValue,&(gVdq_out_pu.value[0]));

          // set Iq reference to zero when doing Rs recalculation
          if(gMotorVars.Flag_enableRsRecalc) gIdq_ref_pu.value[1] = _IQ(0.0);

          // get the Iq reference value
          refValue = gIdq_ref_pu.value[1];

          // get the feedback value
          fbackValue = gIdq_pu.value[1];

          // calculate Iq controller limits, and run Iq controller
          _iq max_vs = _IQmpy(gMotorVars.OverModulation,EST_getDcBus_pu(estHandle));
          outMax_pu = _IQsqrt(_IQmpy(max_vs,max_vs) - _IQmpy(gVdq_out_pu.value[0],gVdq_out_pu.value[0]));
          PID_setMinMax(pidHandle[2],-outMax_pu,outMax_pu);
          PID_run(pidHandle[2],refValue,fbackValue,&(gVdq_out_pu.value[1]));

          // compensate angle for PWM delay
          angle_pu = angleDelayComp(speed_pu, angle_pu);

          // compute the sin/cos phasor
          phasor.value[0] = _IQcosPU(angle_pu);
          phasor.value[1] = _IQsinPU(angle_pu);

          // set the phasor in the inverse Park transform
          IPARK_setPhasor(iparkHandle,&phasor);

          // run the inverse Park module
          IPARK_run(iparkHandle,&gVdq_out_pu,&Vab_pu);

          // run the space Vector Generator (SVGEN) module
          oneOverDcBus = EST_getOneOverDcBus_pu(estHandle);
          Vab_pu.value[0] = _IQmpy(Vab_pu.value[0],oneOverDcBus);
          Vab_pu.value[1] = _IQmpy(Vab_pu.value[1],oneOverDcBus);
          SVGEN_run(svgenHandle,&Vab_pu,&(gPwmData.Tabc));

          // run the PWM compensation and current ignore algorithm
          SVGENCURRENT_compPwmData(svgencurrentHandle,&(gPwmData.Tabc),&gPwmData_prev);

    //      gTrjCnt++;
        }
      else if(gMotorVars.Flag_enableOffsetcalc == true)
        {
          runOffsetsCalculation();
        }
      else
        {
          // disable the PWM
          HAL_disablePwm(halHandle);

          // Set the PWMs to 50% duty cycle
          gPwmData.Tabc.value[0] = _IQ(0.0);
          gPwmData.Tabc.value[1] = _IQ(0.0);
          gPwmData.Tabc.value[2] = _IQ(0.0);
        }

      // write the PWM compare values
      HAL_writePwmData(halHandle,&gPwmData);

      // run function to set next trigger
      if(!gMotorVars.Flag_enableRsRecalc) runSetTrigger();

      return;
    } // end of mainISR() function


    //! \brief     Acknowledges an interrupt from Timer 0 so that another Timer 0 interrupt
    //!            can happen again.
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    static inline void HAL_acqTimer0Int(HAL_Handle handle)
    {
        HAL_Obj *obj = (HAL_Obj *)handle;

        // clear the Timer 0 interrupt flag
        TIMER_clearFlag(obj->timerHandle[0]);

        // Acknowledge interrupt from PIE group 1
        PIE_clearInt(obj->pieHandle,PIE_GroupNumber_1);

        return;
    } // end of HAL_acqTimer0Int() function

    ---------------------------------------------------------------------------------------------------------------------------

    A more explanation is as follows:

    (1) Timer0 interrupt generates the estISR(). I have confirmed that the estISR() is executed with a period of 8kHz.

    (2) The mainISR() is also executed with a period of 8kHz.

    (3) That is all. I just splitted two ISRs.

    (4) You may have to check if my splitting work is correct.

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Please upload the files user.h and proj_x.c, so we understand how do you calculate the parameters for the instaspin-foc and FAST estimator. Don't paste the code directly.

  • Hi Yanming Luo,

    Thank you for your review.

    I have uploaded four files including hal.c and hal.h.

    (I have just dragged the files into this window. Is this correct?)

    I have not yet implemented the function of the variable PWM frequency.

    I just splitted the original mainISR() into two ISRs of estISR() and mainISR() in order to confirm whether our motor runs well or not when two ISRs are employed.

    With the original mainISR(), our motor runs very well.

    Two ISRs are executed at 8kHz.

    Thank you for guidance.

    With regards,

    JS Yoo

    14607.user.h

    8838.hal.c
    /* --COPYRIGHT--,BSD (proj_lab11a_TI)
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    //! \file   solutions/instaspin_foc/boards/hvkit_rev1p1/f28x/f2806xF/src/hal.c
    //! \brief Contains the various functions related to the HAL object (everything outside the CTRL system) 
    //!
    //! (C) Copyright 2011, Texas Instruments, Inc.
    
    
    // **************************************************************************
    // the includes
    
    // drivers
    
    // modules
    
    // platforms
    #include "hal.h"
    #include "user.h"
    #include "hal_obj.h"
    
    #ifdef FLASH
    #pragma CODE_SECTION(HAL_setupFlash,"ramfuncs");
    #endif
    
    // **************************************************************************
    // the defines
    
    #define US_TO_CNT(A) ((((long double) A * (long double)USER_SYSTEM_FREQ_MHz) - 9.0L) / 5.0L)
    
    // **************************************************************************
    // the globals
    
    HAL_Obj hal;
    
    
    // **************************************************************************
    // the functions
    
    void HAL_cal(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // enable the ADC clock
      CLK_enableAdcClock(obj->clkHandle);
    
    
      // Run the Device_cal() function
      // This function copies the ADC and oscillator calibration values from TI reserved
      // OTP into the appropriate trim registers
      // This boot ROM automatically calls this function to calibrate the interal 
      // oscillators and ADC with device specific calibration data.
      // If the boot ROM is bypassed by Code Composer Studio during the development process,
      // then the calibration must be initialized by the application
      ENABLE_PROTECTED_REGISTER_WRITE_MODE;
      (*Device_cal)();
      DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
      // run offsets calibration in user's memory
      HAL_AdcOffsetSelfCal(handle);
    
      // run oscillator compensation
      HAL_OscTempComp(handle);
    
      // disable the ADC clock
      CLK_disableAdcClock(obj->clkHandle);
    
      return;
    } // end of HAL_cal() function
    
    
    void HAL_OscTempComp(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint16_t Temperature;
    
      // disable the ADCs
      ADC_disable(obj->adcHandle);
    
      // power up the bandgap circuit
      ADC_enableBandGap(obj->adcHandle);
    
      // set the ADC voltage reference source to internal
      ADC_setVoltRefSrc(obj->adcHandle,ADC_VoltageRefSrc_Int);
    
      // enable the ADC reference buffers
      ADC_enableRefBuffers(obj->adcHandle);
    
      // Set main clock scaling factor (max45MHz clock for the ADC module)
      ADC_setDivideSelect(obj->adcHandle,ADC_DivideSelect_ClkIn_by_2);
    
      // power up the ADCs
      ADC_powerUp(obj->adcHandle);
    
      // enable the ADCs
      ADC_enable(obj->adcHandle);
    
      // enable non-overlap mode
      ADC_enableNoOverlapMode(obj->adcHandle);
    
      // connect channel A5 internally to the temperature sensor
      ADC_setTempSensorSrc(obj->adcHandle, ADC_TempSensorSrc_Int);
    
      // set SOC0 channel select to ADCINA5
      ADC_setSocChanNumber(obj->adcHandle, ADC_SocNumber_0, ADC_SocChanNumber_A5);
    
      // set SOC0 acquisition period to 26 ADCCLK
      ADC_setSocSampleDelay(obj->adcHandle, ADC_SocNumber_0, ADC_SocSampleDelay_64_cycles);
    
      // connect ADCINT1 to EOC0
      ADC_setIntSrc(obj->adcHandle, ADC_IntNumber_1, ADC_IntSrc_EOC0);
    
      // clear ADCINT1 flag
      ADC_clearIntFlag(obj->adcHandle, ADC_IntNumber_1);
    
      // enable ADCINT1
      ADC_enableInt(obj->adcHandle, ADC_IntNumber_1);
    
      // force start of conversion on SOC0
      ADC_setSocFrc(obj->adcHandle, ADC_SocFrc_0);
    
      // wait for end of conversion
      while (ADC_getIntFlag(obj->adcHandle, ADC_IntNumber_1) == 0){}
    
      // clear ADCINT1 flag
      ADC_clearIntFlag(obj->adcHandle, ADC_IntNumber_1);
    
      Temperature = ADC_readResult(obj->adcHandle, ADC_ResultNumber_0);
    
      HAL_osc1Comp(handle, Temperature);
    
      HAL_osc2Comp(handle, Temperature);
    
      return;
    } // end of HAL_OscTempComp() function
    
    
    void HAL_osc1Comp(HAL_Handle handle, const int16_t sensorSample)
    {
    	int16_t compOscFineTrim;
    	HAL_Obj *obj = (HAL_Obj *)handle;
    
    	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    
        compOscFineTrim = ((sensorSample - getRefTempOffset())*(int32_t)getOsc1FineTrimSlope()
                          + OSC_POSTRIM_OFF + FP_ROUND )/FP_SCALE + getOsc1FineTrimOffset() - OSC_POSTRIM;
    
        if(compOscFineTrim > 31)
          {
            compOscFineTrim = 31;
          }
    	else if(compOscFineTrim < -31)
          {
            compOscFineTrim = -31;
          }
    
        OSC_setTrim(obj->oscHandle, OSC_Number_1, HAL_getOscTrimValue(getOsc1CoarseTrim(), compOscFineTrim));
    
        DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
        return;
    } // end of HAL_osc1Comp() function
    
    
    void HAL_osc2Comp(HAL_Handle handle, const int16_t sensorSample)
    {
    	int16_t compOscFineTrim;
    	HAL_Obj *obj = (HAL_Obj *)handle;
    
    	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    
        compOscFineTrim = ((sensorSample - getRefTempOffset())*(int32_t)getOsc2FineTrimSlope()
                          + OSC_POSTRIM_OFF + FP_ROUND )/FP_SCALE + getOsc2FineTrimOffset() - OSC_POSTRIM;
    
        if(compOscFineTrim > 31)
          {
            compOscFineTrim = 31;
          }
    	else if(compOscFineTrim < -31)
          {
            compOscFineTrim = -31;
          }
    
        OSC_setTrim(obj->oscHandle, OSC_Number_2, HAL_getOscTrimValue(getOsc2CoarseTrim(), compOscFineTrim));
    
        DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
        return;
    } // end of HAL_osc2Comp() function
    
    
    uint16_t HAL_getOscTrimValue(int16_t coarse, int16_t fine)
    {
      uint16_t regValue = 0;
    
      if(fine < 0)
        {
          regValue = ((-fine) | 0x20) << 9;
        }
      else
        {
          regValue = fine << 9;
        }
    
      if(coarse < 0)
        {
          regValue |= ((-coarse) | 0x80);
        }
      else
        {
          regValue |= coarse;
        }
    
      return regValue;
    } // end of HAL_getOscTrimValue() function
    
    
    void HAL_AdcOffsetSelfCal(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint16_t AdcConvMean;
    
      // disable the ADCs
      ADC_disable(obj->adcHandle);
    
      // power up the bandgap circuit
      ADC_enableBandGap(obj->adcHandle);
    
      // set the ADC voltage reference source to internal
      ADC_setVoltRefSrc(obj->adcHandle,ADC_VoltageRefSrc_Int);
    
      // enable the ADC reference buffers
      ADC_enableRefBuffers(obj->adcHandle);
    
      // Set main clock scaling factor (max45MHz clock for the ADC module)
      ADC_setDivideSelect(obj->adcHandle,ADC_DivideSelect_ClkIn_by_2);
    
      // power up the ADCs
      ADC_powerUp(obj->adcHandle);
    
      // enable the ADCs
      ADC_enable(obj->adcHandle);
    
      //Select VREFLO internal connection on B5
      ADC_enableVoltRefLoConv(obj->adcHandle);
    
      //Select channel B5 for all SOC
      HAL_AdcCalChanSelect(handle, ADC_SocChanNumber_B5);
    
      //Apply artificial offset (+80) to account for a negative offset that may reside in the ADC core
      ADC_setOffTrim(obj->adcHandle, 80);
    
      //Capture ADC conversion on VREFLO
      AdcConvMean = HAL_AdcCalConversion(handle);
    
      //Set offtrim register with new value (i.e remove artical offset (+80) and create a two's compliment of the offset error)
      ADC_setOffTrim(obj->adcHandle, 80 - AdcConvMean);
    
      //Select external ADCIN5 input pin on B5
      ADC_disableVoltRefLoConv(obj->adcHandle);
    
      return;
    } // end of HAL_AdcOffsetSelfCal() function
    
    
    void HAL_AdcCalChanSelect(HAL_Handle handle, const ADC_SocChanNumber_e chanNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_0,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_1,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_2,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_3,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_4,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_5,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_6,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_7,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_8,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_9,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_10,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_11,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_12,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_13,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_14,chanNumber);
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_15,chanNumber);
    
      return;
    } // end of HAL_AdcCalChanSelect() function
    
    
    uint16_t HAL_AdcCalConversion(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint16_t index, SampleSize, Mean;
      uint32_t Sum;
      ADC_SocSampleDelay_e ACQPS_Value;
    
      index       = 0;     //initialize index to 0
      SampleSize  = 256;   //set sample size to 256 (**NOTE: Sample size must be multiples of 2^x where is an integer >= 4)
      Sum         = 0;     //set sum to 0
      Mean        = 999;   //initialize mean to known value
    
      //Set the ADC sample window to the desired value (Sample window = ACQPS + 1)
      ACQPS_Value = ADC_SocSampleDelay_7_cycles;
    
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_0,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_1,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_2,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_3,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_4,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_5,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_6,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_7,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_8,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_9,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_10,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_11,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_12,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_13,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_14,ACQPS_Value);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_15,ACQPS_Value);
    
      // Enabled ADCINT1 and ADCINT2
      ADC_enableInt(obj->adcHandle, ADC_IntNumber_1);
      ADC_enableInt(obj->adcHandle, ADC_IntNumber_2);
    
      // Disable continuous sampling for ADCINT1 and ADCINT2
      ADC_setIntMode(obj->adcHandle, ADC_IntNumber_1, ADC_IntMode_EOC);
      ADC_setIntMode(obj->adcHandle, ADC_IntNumber_2, ADC_IntMode_EOC);
    
      //ADCINTs trigger at end of conversion
      ADC_setIntPulseGenMode(obj->adcHandle, ADC_IntPulseGenMode_Prior);
    
      // Setup ADCINT1 and ADCINT2 trigger source
      ADC_setIntSrc(obj->adcHandle, ADC_IntNumber_1, ADC_IntSrc_EOC6);
      ADC_setIntSrc(obj->adcHandle, ADC_IntNumber_2, ADC_IntSrc_EOC14);
    
      // Setup each SOC's ADCINT trigger source
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_0, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_1, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_2, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_3, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_4, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_5, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_6, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_7, ADC_Int2TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_8, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_9, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_10, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_11, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_12, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_13, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_14, ADC_Int1TriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_15, ADC_Int1TriggersSOC);
    
      // Delay before converting ADC channels
      usDelay(US_TO_CNT(ADC_DELAY_usec));
    
      ADC_setSocFrcWord(obj->adcHandle, 0x00FF);
    
      while( index < SampleSize )
        {
          //Wait for ADCINT1 to trigger, then add ADCRESULT0-7 registers to sum
          while (ADC_getIntFlag(obj->adcHandle, ADC_IntNumber_1) == 0){}
    
          //Must clear ADCINT1 flag since INT1CONT = 0
          ADC_clearIntFlag(obj->adcHandle, ADC_IntNumber_1);
    
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_0);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_1);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_2);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_3);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_4);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_5);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_6);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_7);
    
          //Wait for ADCINT2 to trigger, then add ADCRESULT8-15 registers to sum
          while (ADC_getIntFlag(obj->adcHandle, ADC_IntNumber_2) == 0){}
    
          //Must clear ADCINT2 flag since INT2CONT = 0
          ADC_clearIntFlag(obj->adcHandle, ADC_IntNumber_2);
    
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_8);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_9);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_10);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_11);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_12);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_13);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_14);
          Sum += ADC_readResult(obj->adcHandle, ADC_ResultNumber_15);
    
          index+=16;
    
      } // end data collection
    
      //Disable ADCINT1 and ADCINT2 to STOP the ping-pong sampling
      ADC_disableInt(obj->adcHandle, ADC_IntNumber_1);
      ADC_disableInt(obj->adcHandle, ADC_IntNumber_2);
    
      //Calculate average ADC sample value
      Mean = Sum / SampleSize;
    
      // Clear start of conversion trigger
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_0, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_1, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_2, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_3, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_4, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_5, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_6, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_7, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_8, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_9, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_10, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_11, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_12, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_13, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_14, ADC_NoIntTriggersSOC);
      ADC_setupSocTrigSrc(obj->adcHandle, ADC_SocNumber_15, ADC_NoIntTriggersSOC);
    
      //return the average
      return(Mean);
    } // end of HAL_AdcCalConversion() function
    
    
    void HAL_disableWdog(HAL_Handle halHandle)
    {
      HAL_Obj *hal = (HAL_Obj *)halHandle;
    
    
      WDOG_disable(hal->wdogHandle);
    
    
      return;
    } // end of HAL_disableWdog() function
    
    
    void HAL_disableGlobalInts(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      CPU_disableGlobalInts(obj->cpuHandle);
    
      return;
    } // end of HAL_disableGlobalInts() function
    
    
    void HAL_enableAdcInts(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // enable the PIE interrupts associated with the ADC interrupts
      PIE_enableAdcInt(obj->pieHandle,ADC_IntNumber_1);
    
    
      // enable the ADC interrupts
      ADC_enableInt(obj->adcHandle,ADC_IntNumber_1);
    
    
      // enable the cpu interrupt for ADC interrupts
      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_10);
    
      return;
    } // end of HAL_enableAdcInts() function
    
    
    void HAL_enableDebugInt(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      CPU_enableDebugInt(obj->cpuHandle);
    
      return;
    } // end of HAL_enableDebugInt() function
    
    
    void HAL_enableGlobalInts(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      CPU_enableGlobalInts(obj->cpuHandle);
    
      return;
    } // end of HAL_enableGlobalInts() function
    
    
    void HAL_enablePwmInt(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      PIE_enablePwmInt(obj->pieHandle,PWM_Number_1);
    
    
      // enable the interrupt
      PWM_enableInt(obj->pwmHandle[PWM_Number_1]);
    
    
      // enable the cpu interrupt for EPWM1_INT
      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_3);
    
      return;
    } // end of HAL_enablePwmInt() function
    
    
    void HAL_enableTimer0Int(HAL_Handle handle)
    {
        HAL_Obj *obj = (HAL_Obj *)handle;
    
        PIE_enableTimer0Int(obj->pieHandle);
    
        // enable the interrupt
        TIMER_enableInt(obj->timerHandle[0]);
    
        // enable the cpu interrupt for TINT0
        CPU_enableInt(obj->cpuHandle,CPU_IntNumber_1);
    
        return;
    } // end of HAL_enableTimer0Int() function
    
    
    void HAL_setupFaults(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint_least8_t cnt;
    
    
      // Configure Trip Mechanism for the Motor control software
      // -Cycle by cycle trip on CPU halt
      // -One shot fault trip zone
      // These trips need to be repeated for EPWM1 ,2 & 3
      for(cnt=0;cnt<3;cnt++)
        {
          PWM_enableTripZoneSrc(obj->pwmHandle[cnt],PWM_TripZoneSrc_CycleByCycle_TZ6_NOT);
    
          PWM_enableTripZoneSrc(obj->pwmHandle[cnt],PWM_TripZoneSrc_OneShot_TZ1_NOT);
    
          // What do we want the OST/CBC events to do?
          // TZA events can force EPWMxA
          // TZB events can force EPWMxB
    
          PWM_setTripZoneState_TZA(obj->pwmHandle[cnt],PWM_TripZoneState_EPWM_Low);
          PWM_setTripZoneState_TZB(obj->pwmHandle[cnt],PWM_TripZoneState_EPWM_Low);
    
          // Clear faults from flip flop
          GPIO_setLow(obj->gpioHandle,GPIO_Number_9);
          GPIO_setHigh(obj->gpioHandle,GPIO_Number_9);
        }
    
      return;
    } // end of HAL_setupFaults() function
    
    
    HAL_Handle HAL_init(void *pMemory,const size_t numBytes)
    {
      uint_least8_t cnt;
      HAL_Handle handle;
      HAL_Obj *obj;
    
    
      if(numBytes < sizeof(HAL_Obj))
        return((HAL_Handle)NULL);
    
    
      // assign the handle
      handle = (HAL_Handle)pMemory;
    
    
      // assign the object
      obj = (HAL_Obj *)handle;
    
    
      // initialize the watchdog driver
      obj->wdogHandle = WDOG_init((void *)WDOG_BASE_ADDR,sizeof(WDOG_Obj));
    
    
      // disable watchdog
      HAL_disableWdog(handle);
    
    
      // initialize the ADC
      obj->adcHandle = ADC_init((void *)ADC_BASE_ADDR,sizeof(ADC_Obj));
    
    
      // initialize the clock handle
      obj->clkHandle = CLK_init((void *)CLK_BASE_ADDR,sizeof(CLK_Obj));
    
    
      // initialize the CPU handle
      obj->cpuHandle = CPU_init(&cpu,sizeof(cpu));
    
    
      // initialize the FLASH handle
      obj->flashHandle = FLASH_init((void *)FLASH_BASE_ADDR,sizeof(FLASH_Obj));
    
    
      // initialize the GPIO handle
      obj->gpioHandle = GPIO_init((void *)GPIO_BASE_ADDR,sizeof(GPIO_Obj));
    
    
      // initialize the current offset estimator handles
      for(cnt=0;cnt<USER_NUM_CURRENT_SENSORS;cnt++)
        {
          obj->offsetHandle_I[cnt] = OFFSET_init(&obj->offset_I[cnt],sizeof(obj->offset_I[cnt]));
        }
    
    
      // initialize the voltage offset estimator handles
      for(cnt=0;cnt<USER_NUM_VOLTAGE_SENSORS;cnt++)
        {
          obj->offsetHandle_V[cnt] = OFFSET_init(&obj->offset_V[cnt],sizeof(obj->offset_V[cnt]));
        }
    
    
      // initialize the oscillator handle
      obj->oscHandle = OSC_init((void *)OSC_BASE_ADDR,sizeof(OSC_Obj));
    
    
      // initialize the PIE handle
      obj->pieHandle = PIE_init((void *)PIE_BASE_ADDR,sizeof(PIE_Obj));
    
    
      // initialize the PLL handle
      obj->pllHandle = PLL_init((void *)PLL_BASE_ADDR,sizeof(PLL_Obj));
    
    
      // initialize PWM handles
      obj->pwmHandle[0] = PWM_init((void *)PWM_ePWM1_BASE_ADDR,sizeof(PWM_Obj));
      obj->pwmHandle[1] = PWM_init((void *)PWM_ePWM2_BASE_ADDR,sizeof(PWM_Obj));
      obj->pwmHandle[2] = PWM_init((void *)PWM_ePWM3_BASE_ADDR,sizeof(PWM_Obj));
    
    
      // initialize PWM DAC handles
      obj->pwmDacHandle[0] = PWMDAC_init((void *)PWM_ePWM6_BASE_ADDR,sizeof(PWM_Obj));
      obj->pwmDacHandle[1] = PWMDAC_init((void *)PWM_ePWM5_BASE_ADDR,sizeof(PWM_Obj));
      obj->pwmDacHandle[2] = PWMDAC_init((void *)PWM_ePWM4_BASE_ADDR,sizeof(PWM_Obj));
    
    
      // initialize power handle
      obj->pwrHandle = PWR_init((void *)PWR_BASE_ADDR,sizeof(PWR_Obj));
    
    
      // initialize timer handles
      obj->timerHandle[0] = TIMER_init((void *)TIMER0_BASE_ADDR,sizeof(TIMER_Obj));
      obj->timerHandle[1] = TIMER_init((void *)TIMER1_BASE_ADDR,sizeof(TIMER_Obj));
      obj->timerHandle[2] = TIMER_init((void *)TIMER2_BASE_ADDR,sizeof(TIMER_Obj));
    
    #ifdef QEP
      // initialize QEP driver
      obj->qepHandle[0] = QEP_init((void*)QEP1_BASE_ADDR,sizeof(QEP_Obj));
    #endif
    
      return(handle);
    } // end of HAL_init() function
    
    
    void HAL_setParams(HAL_Handle handle,const USER_Params *pUserParams)
    {
      uint_least8_t cnt;
      HAL_Obj *obj = (HAL_Obj *)handle;
      _iq beta_lp_pu = _IQ(pUserParams->offsetPole_rps/(float_t)pUserParams->ctrlFreq_Hz);
    
    
      HAL_setNumCurrentSensors(handle,pUserParams->numCurrentSensors);
      HAL_setNumVoltageSensors(handle,pUserParams->numVoltageSensors);
    
    
      for(cnt=0;cnt<HAL_getNumCurrentSensors(handle);cnt++)
        {
          HAL_setOffsetBeta_lp_pu(handle,HAL_SensorType_Current,cnt,beta_lp_pu);
          HAL_setOffsetInitCond(handle,HAL_SensorType_Current,cnt,_IQ(0.0));
          HAL_setOffsetValue(handle,HAL_SensorType_Current,cnt,_IQ(0.0));
        }
    
    
      for(cnt=0;cnt<HAL_getNumVoltageSensors(handle);cnt++)
        {
          HAL_setOffsetBeta_lp_pu(handle,HAL_SensorType_Voltage,cnt,beta_lp_pu);
          HAL_setOffsetInitCond(handle,HAL_SensorType_Voltage,cnt,_IQ(0.0));
          HAL_setOffsetValue(handle,HAL_SensorType_Voltage,cnt,_IQ(0.0));
        }
    
    
      // disable global interrupts
      CPU_disableGlobalInts(obj->cpuHandle);
    
    
      // disable cpu interrupts
      CPU_disableInts(obj->cpuHandle);
    
    
      // clear cpu interrupt flags
      CPU_clearIntFlags(obj->cpuHandle);
    
    
      // setup the clocks
      HAL_setupClks(handle);
    
    
      // Setup the PLL
      HAL_setupPll(handle,PLL_ClkFreq_90_MHz);
    
    
      // setup the PIE
      HAL_setupPie(handle);
    
    
      // run the device calibration
      HAL_cal(handle);
    
    
      // setup the peripheral clocks
      HAL_setupPeripheralClks(handle);
    
    
      // setup the GPIOs
      HAL_setupGpios(handle);
    
    
      // setup the flash
      HAL_setupFlash(handle);
    
    
      // setup the ADCs
      HAL_setupAdcs(handle);
    
    
      // setup the PWMs
      HAL_setupPwms(handle,
                    (float_t)pUserParams->systemFreq_MHz,
                    pUserParams->pwmPeriod_usec,
                    USER_NUM_PWM_TICKS_PER_ISR_TICK);
    
    #ifdef QEP
      // setup the QEP
      HAL_setupQEP(handle,HAL_Qep_QEP1);
    #endif
    
      // setup the PWM DACs
      HAL_setupPwmDacs(handle);
    
    
      // setup the timers
      HAL_setupTimers(handle,
                      (float_t)pUserParams->systemFreq_MHz);
    
    
      // setup the timer for estimator
      HAL_setupEstTimer(handle, (float_t)pUserParams->systemFreq_MHz, USER_EST_FREQ_Hz);
    
    
      // set the default current bias
     {
       uint_least8_t cnt;
       _iq bias = _IQ12mpy(ADC_dataBias,_IQ(pUserParams->current_sf));
       
       for(cnt=0;cnt<HAL_getNumCurrentSensors(handle);cnt++)
         {
           HAL_setBias(handle,HAL_SensorType_Current,cnt,bias);
         }
     }
    
    
      //  set the current scale factor
     {
       _iq current_sf = _IQ(pUserParams->current_sf);
    
      HAL_setCurrentScaleFactor(handle,current_sf);
     }
    
    
      // set the default voltage bias
     {
       uint_least8_t cnt;
       _iq bias = _IQ(0.0);
       
       for(cnt=0;cnt<HAL_getNumVoltageSensors(handle);cnt++)
         {
           HAL_setBias(handle,HAL_SensorType_Voltage,cnt,bias);
         }
     }
    
    
      //  set the voltage scale factor
     {
       _iq voltage_sf = _IQ(pUserParams->voltage_sf);
    
      HAL_setVoltageScaleFactor(handle,voltage_sf);
     }
    
     return;
    } // end of HAL_setParams() function
    
    
    void HAL_setupAdcs(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // disable the ADCs
      ADC_disable(obj->adcHandle);
    
    
      // power up the bandgap circuit
      ADC_enableBandGap(obj->adcHandle);
    
    
      // set the ADC voltage reference source to internal 
      ADC_setVoltRefSrc(obj->adcHandle,ADC_VoltageRefSrc_Int);
    
    
      // enable the ADC reference buffers
      ADC_enableRefBuffers(obj->adcHandle);
    
    
      // Set main clock scaling factor (max45MHz clock for the ADC module)
      ADC_setDivideSelect(obj->adcHandle,ADC_DivideSelect_ClkIn_by_2);
    
    
      // power up the ADCs
      ADC_powerUp(obj->adcHandle);
    
    
      // enable the ADCs
      ADC_enable(obj->adcHandle);
    
    
      // set the ADC interrupt pulse generation to prior
      ADC_setIntPulseGenMode(obj->adcHandle,ADC_IntPulseGenMode_Prior);
    
    
      // set the temperature sensor source to external
      ADC_setTempSensorSrc(obj->adcHandle,ADC_TempSensorSrc_Ext);
    
    
      // configure the interrupt sources
      ADC_disableInt(obj->adcHandle,ADC_IntNumber_1);
      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_1,ADC_IntMode_ClearFlag);
      ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_1,ADC_IntSrc_EOC7);
    
    
      //configure the SOCs for hvkit_rev1p1
      // EXT IA-FB
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_0,ADC_SocChanNumber_A1);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_0,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_0,ADC_SocSampleDelay_9_cycles);
    
      // EXT IA-FB
      // Duplicate conversion due to ADC Initial Conversion bug (SPRZ342)
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_1,ADC_SocChanNumber_A1);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_1,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_1,ADC_SocSampleDelay_9_cycles);
    
      // EXT IB-FB
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_2,ADC_SocChanNumber_B1);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_2,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_2,ADC_SocSampleDelay_9_cycles);
    
      // EXT IC-FB
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_3,ADC_SocChanNumber_A3);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_3,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_3,ADC_SocSampleDelay_9_cycles);
    
      // ADC-Vhb1
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_4,ADC_SocChanNumber_B7);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_4,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_4,ADC_SocSampleDelay_9_cycles);
    
      // ADC-Vhb2
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_5,ADC_SocChanNumber_B6);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_5,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_5,ADC_SocSampleDelay_9_cycles);
    
      // ADC-Vhb3
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_6,ADC_SocChanNumber_B4);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_6,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_6,ADC_SocSampleDelay_9_cycles);
    
      // VDCBUS
      ADC_setSocChanNumber(obj->adcHandle,ADC_SocNumber_7,ADC_SocChanNumber_A7);
      ADC_setSocTrigSrc(obj->adcHandle,ADC_SocNumber_7,ADC_SocTrigSrc_EPWM1_ADCSOCA);
      ADC_setSocSampleDelay(obj->adcHandle,ADC_SocNumber_7,ADC_SocSampleDelay_9_cycles);
    
      return;
    } // end of HAL_setupAdcs() function
    
    
    void HAL_setupClks(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // enable internal oscillator 1
      CLK_enableOsc1(obj->clkHandle);
    
      // set the oscillator source
      CLK_setOscSrc(obj->clkHandle,CLK_OscSrc_Internal);
    
      // disable the external clock in
      CLK_disableClkIn(obj->clkHandle);
    
      // disable the crystal oscillator
      CLK_disableCrystalOsc(obj->clkHandle);
    
      // disable oscillator 2
      CLK_disableOsc2(obj->clkHandle);
    
      // set the low speed clock prescaler
      CLK_setLowSpdPreScaler(obj->clkHandle,CLK_LowSpdPreScaler_SysClkOut_by_1);
    
      // set the clock out prescaler
      CLK_setClkOutPreScaler(obj->clkHandle,CLK_ClkOutPreScaler_SysClkOut_by_1);
    
      return;
    } // end of HAL_setupClks() function
    
    
    void HAL_setupFlash(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      FLASH_enablePipelineMode(obj->flashHandle);
    
      FLASH_setNumPagedReadWaitStates(obj->flashHandle,FLASH_NumPagedWaitStates_3);
    
      FLASH_setNumRandomReadWaitStates(obj->flashHandle,FLASH_NumRandomWaitStates_3);
    
      FLASH_setOtpWaitStates(obj->flashHandle,FLASH_NumOtpWaitStates_5);
    
      FLASH_setStandbyWaitCount(obj->flashHandle,FLASH_STANDBY_WAIT_COUNT_DEFAULT);
    
      FLASH_setActiveWaitCount(obj->flashHandle,FLASH_ACTIVE_WAIT_COUNT_DEFAULT);
    
      return;
    } // HAL_setupFlash() function
    
    
    void HAL_setupGpios(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // PWM1
      GPIO_setMode(obj->gpioHandle,GPIO_Number_0,GPIO_0_Mode_EPWM1A);
    
      // PWM2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_1,GPIO_1_Mode_EPWM1B);
    
      // PWM3
      GPIO_setMode(obj->gpioHandle,GPIO_Number_2,GPIO_2_Mode_EPWM2A);
    
      // PWM4
      GPIO_setMode(obj->gpioHandle,GPIO_Number_3,GPIO_3_Mode_EPWM2B);
    
      // PWM5
      GPIO_setMode(obj->gpioHandle,GPIO_Number_4,GPIO_4_Mode_EPWM3A);
    
      // PWM6
      GPIO_setMode(obj->gpioHandle,GPIO_Number_5,GPIO_5_Mode_EPWM3B);
    
      // PWM-DAC4
      GPIO_setMode(obj->gpioHandle,GPIO_Number_6,GPIO_6_Mode_EPWM4A);
    
      // Input
      GPIO_setMode(obj->gpioHandle,GPIO_Number_7,GPIO_7_Mode_GeneralPurpose);
    
      // PWM-DAC3
      GPIO_setMode(obj->gpioHandle,GPIO_Number_8,GPIO_8_Mode_EPWM5A);
    
      // CLR-FAULT
      GPIO_setMode(obj->gpioHandle,GPIO_Number_9,GPIO_9_Mode_GeneralPurpose);
      GPIO_setHigh(obj->gpioHandle,GPIO_Number_9);
      GPIO_setDirection(obj->gpioHandle,GPIO_Number_9,GPIO_Direction_Output);
    
      // PWM-DAC1
      GPIO_setMode(obj->gpioHandle,GPIO_Number_10,GPIO_10_Mode_EPWM6A);
    
      // PWM-DAC2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_11,GPIO_11_Mode_EPWM6B);
    
      // TZ-1
      GPIO_setMode(obj->gpioHandle,GPIO_Number_12,GPIO_12_Mode_TZ1_NOT);
    
      // HALL-2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_13,GPIO_13_Mode_GeneralPurpose);
    
      // HALL-3
      GPIO_setMode(obj->gpioHandle,GPIO_Number_14,GPIO_14_Mode_GeneralPurpose);
    
      // LED2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_15,GPIO_15_Mode_GeneralPurpose);
    
      // Set Qualification Period for GPIO16-23, 5*2*(1/90MHz) = 0.11us
      GPIO_setQualificationPeriod(obj->gpioHandle,GPIO_Number_16,5);
    
      // SPI-SIMO
      GPIO_setMode(obj->gpioHandle,GPIO_Number_16,GPIO_16_Mode_GeneralPurpose);
    
      // SPI-SOMI
      GPIO_setMode(obj->gpioHandle,GPIO_Number_17,GPIO_17_Mode_GeneralPurpose);
    
      // SPI-CLK
      GPIO_setMode(obj->gpioHandle,GPIO_Number_18,GPIO_18_Mode_GeneralPurpose);
    
      // SPI-STE
      GPIO_setMode(obj->gpioHandle,GPIO_Number_19,GPIO_19_Mode_GeneralPurpose);
    
    #ifdef QEP
      // EQEPA
      GPIO_setMode(obj->gpioHandle,GPIO_Number_20,GPIO_20_Mode_EQEP1A);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_20,GPIO_Qual_Sample_3);
    
      // EQEPB
      GPIO_setMode(obj->gpioHandle,GPIO_Number_21,GPIO_21_Mode_EQEP1B);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_21,GPIO_Qual_Sample_3);
    
      // STATUS
      GPIO_setMode(obj->gpioHandle,GPIO_Number_22,GPIO_22_Mode_GeneralPurpose);
    
      // EQEP1I
      GPIO_setMode(obj->gpioHandle,GPIO_Number_23,GPIO_23_Mode_EQEP1I);
      GPIO_setQualification(obj->gpioHandle,GPIO_Number_23,GPIO_Qual_Sample_3);
    #else
      // EQEPA
      GPIO_setMode(obj->gpioHandle,GPIO_Number_20,GPIO_20_Mode_GeneralPurpose);
    //  GPIO_setDirection(obj->gpioHandle,GPIO_Number_20,GPIO_Direction_Input);
    
      // EQEPB
      GPIO_setMode(obj->gpioHandle,GPIO_Number_21,GPIO_21_Mode_GeneralPurpose);
    //  GPIO_setDirection(obj->gpioHandle,GPIO_Number_21,GPIO_Direction_Input);
    
      // STATUS
      GPIO_setMode(obj->gpioHandle,GPIO_Number_22,GPIO_22_Mode_GeneralPurpose);
    //  GPIO_setDirection(obj->gpioHandle,GPIO_Number_22,GPIO_Direction_Input);
    
      // EQEP1I
      GPIO_setMode(obj->gpioHandle,GPIO_Number_23,GPIO_23_Mode_GeneralPurpose);
    //  GPIO_setDirection(obj->gpioHandle,GPIO_Number_23,GPIO_Direction_Input);
    #endif
    
      // SPI SIMO B
      GPIO_setMode(obj->gpioHandle,GPIO_Number_24,GPIO_24_Mode_GeneralPurpose);
    
      // SPI SOMI B
      GPIO_setMode(obj->gpioHandle,GPIO_Number_25,GPIO_25_Mode_GeneralPurpose);
    
      // SPI CLK B
      GPIO_setMode(obj->gpioHandle,GPIO_Number_26,GPIO_26_Mode_GeneralPurpose);
    
      // SPI CSn B
      GPIO_setMode(obj->gpioHandle,GPIO_Number_27,GPIO_27_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_28,GPIO_28_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_29,GPIO_29_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_30,GPIO_30_Mode_GeneralPurpose);
    
      // ControlCARD LED2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_31,GPIO_31_Mode_GeneralPurpose);
      GPIO_setLow(obj->gpioHandle,GPIO_Number_31);
      GPIO_setDirection(obj->gpioHandle,GPIO_Number_31,GPIO_Direction_Output);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_32,GPIO_32_Mode_ADCSOCAO_NOT);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_33,GPIO_33_Mode_GeneralPurpose);
    
      // ControlCARD LED3
      GPIO_setMode(obj->gpioHandle,GPIO_Number_34,GPIO_34_Mode_GeneralPurpose);
      GPIO_setLow(obj->gpioHandle,GPIO_Number_34);
      GPIO_setDirection(obj->gpioHandle,GPIO_Number_34,GPIO_Direction_Output);
    
      // JTAG
      GPIO_setMode(obj->gpioHandle,GPIO_Number_35,GPIO_35_Mode_JTAG_TDI);
      GPIO_setMode(obj->gpioHandle,GPIO_Number_36,GPIO_36_Mode_JTAG_TMS);
      GPIO_setMode(obj->gpioHandle,GPIO_Number_37,GPIO_37_Mode_JTAG_TDO);
      GPIO_setMode(obj->gpioHandle,GPIO_Number_38,GPIO_38_Mode_JTAG_TCK);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_39,GPIO_39_Mode_GeneralPurpose);
    
      // CAP1
      GPIO_setMode(obj->gpioHandle,GPIO_Number_40,GPIO_40_Mode_GeneralPurpose);
    
      // CAP2
      GPIO_setMode(obj->gpioHandle,GPIO_Number_41,GPIO_41_Mode_GeneralPurpose);
    
      // CAP3
      GPIO_setMode(obj->gpioHandle,GPIO_Number_42,GPIO_42_Mode_GeneralPurpose);
    
      // DC_CAL
      GPIO_setMode(obj->gpioHandle,GPIO_Number_43,GPIO_43_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_44,GPIO_44_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_50,GPIO_50_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_51,GPIO_51_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_52,GPIO_52_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_53,GPIO_53_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_54,GPIO_54_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_55,GPIO_55_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_56,GPIO_56_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_57,GPIO_57_Mode_GeneralPurpose);
    
      // No Connection
      GPIO_setMode(obj->gpioHandle,GPIO_Number_58,GPIO_58_Mode_GeneralPurpose);
    
      return;
    }  // end of HAL_setupGpios() function
    
    
    void HAL_setupPie(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      PIE_disable(obj->pieHandle);
    
      PIE_disableAllInts(obj->pieHandle);
    
      PIE_clearAllInts(obj->pieHandle);
    
      PIE_clearAllFlags(obj->pieHandle);
    
      PIE_setDefaultIntVectorTable(obj->pieHandle);
    
      PIE_enable(obj->pieHandle);
    
      return;
    } // end of HAL_setupPie() function
    
    
    void HAL_setupPeripheralClks(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      CLK_enableAdcClock(obj->clkHandle);
    
      CLK_enableCompClock(obj->clkHandle,CLK_CompNumber_1);
      CLK_enableCompClock(obj->clkHandle,CLK_CompNumber_2);
      CLK_enableCompClock(obj->clkHandle,CLK_CompNumber_3);
    
      CLK_enableEcap1Clock(obj->clkHandle);
    
      CLK_disableEcanaClock(obj->clkHandle);
    
    #ifdef QEP
      CLK_enableEqep1Clock(obj->clkHandle);
      CLK_disableEqep2Clock(obj->clkHandle);
    #endif
    
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_1);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_2);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_3);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_4);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_5);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_6);
      CLK_enablePwmClock(obj->clkHandle,PWM_Number_7);
    
      CLK_disableHrPwmClock(obj->clkHandle);
    
      CLK_disableI2cClock(obj->clkHandle);
    
      CLK_disableLinAClock(obj->clkHandle);
    
      CLK_disableClaClock(obj->clkHandle);
    
      CLK_enableSciaClock(obj->clkHandle);
    
      CLK_disableSpiaClock(obj->clkHandle);
      CLK_disableSpibClock(obj->clkHandle);
      
      CLK_enableTbClockSync(obj->clkHandle);
    
      return;
    } // end of HAL_setupPeripheralClks() function
    
    
    void HAL_setupPll(HAL_Handle handle,const PLL_ClkFreq_e clkFreq)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // make sure PLL is not running in limp mode
      if(PLL_getClkStatus(obj->pllHandle) != PLL_ClkStatus_Normal)
        {
          // reset the clock detect
          PLL_resetClkDetect(obj->pllHandle);
    
          // ???????
          asm("        ESTOP0");
        }
    
    
      // Divide Select must be ClkIn/4 before the clock rate can be changed
      if(PLL_getDivideSelect(obj->pllHandle) != PLL_DivideSelect_ClkIn_by_4)
        {
          PLL_setDivideSelect(obj->pllHandle,PLL_DivideSelect_ClkIn_by_4);
        }
    
    
      if(PLL_getClkFreq(obj->pllHandle) != clkFreq)
        {
          // disable the clock detect
          PLL_disableClkDetect(obj->pllHandle);
    
          // set the clock rate
          PLL_setClkFreq(obj->pllHandle,clkFreq);
        }
    
    
      // wait until locked
      while(PLL_getLockStatus(obj->pllHandle) != PLL_LockStatus_Done) {}
    
    
      // enable the clock detect
      PLL_enableClkDetect(obj->pllHandle);
    
    
      // set divide select to ClkIn/2 to get desired clock rate
      // NOTE: clock must be locked before setting this register
      PLL_setDivideSelect(obj->pllHandle,PLL_DivideSelect_ClkIn_by_2);
    
      return;
    } // end of HAL_setupPll() function
    
    
    void HAL_setupPwms(HAL_Handle handle,
                       const float_t systemFreq_MHz,
                       const float_t pwmPeriod_usec,
                       const uint_least16_t numPwmTicksPerIsrTick)
    {
      HAL_Obj   *obj = (HAL_Obj *)handle;
      uint16_t   halfPeriod_cycles = (uint16_t)(systemFreq_MHz*pwmPeriod_usec) >> 1;
      uint_least8_t    cnt;
    
    
      // turns off the outputs of the EPWM peripherals which will put the power switches
      // into a high impedance state.
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_1]);
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_2]);
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_3]);
      // first step to synchronize the pwms
      CLK_disableTbClockSync(obj->clkHandle);
    
      for(cnt=0;cnt<3;cnt++)
        {
          // setup the Time-Base Control Register (TBCTL)
          PWM_setCounterMode(obj->pwmHandle[cnt],PWM_CounterMode_UpDown);
          PWM_disableCounterLoad(obj->pwmHandle[cnt]);
          PWM_setPeriodLoad(obj->pwmHandle[cnt],PWM_PeriodLoad_Immediate);
          PWM_setSyncMode(obj->pwmHandle[cnt],PWM_SyncMode_EPWMxSYNC);
          PWM_setHighSpeedClkDiv(obj->pwmHandle[cnt],PWM_HspClkDiv_by_1);
          PWM_setClkDiv(obj->pwmHandle[cnt],PWM_ClkDiv_by_1);
          PWM_setPhaseDir(obj->pwmHandle[cnt],PWM_PhaseDir_CountUp);
          PWM_setRunMode(obj->pwmHandle[cnt],PWM_RunMode_FreeRun);
    
          // setup the Timer-Based Phase Register (TBPHS)
          PWM_setPhase(obj->pwmHandle[cnt],0);
    
          // setup the Time-Base Counter Register (TBCTR)
          PWM_setCount(obj->pwmHandle[cnt],0);
    
          // setup the Time-Base Period Register (TBPRD)
          // set to zero initially
          PWM_setPeriod(obj->pwmHandle[cnt],0);
    
          // setup the Counter-Compare Control Register (CMPCTL)
          PWM_setLoadMode_CmpA(obj->pwmHandle[cnt],PWM_LoadMode_Zero);
          PWM_setLoadMode_CmpB(obj->pwmHandle[cnt],PWM_LoadMode_Zero);
          PWM_setShadowMode_CmpA(obj->pwmHandle[cnt],PWM_ShadowMode_Shadow);
          PWM_setShadowMode_CmpB(obj->pwmHandle[cnt],PWM_ShadowMode_Immediate);
    
          // setup the Action-Qualifier Output A Register (AQCTLA) 
          PWM_setActionQual_CntUp_CmpA_PwmA(obj->pwmHandle[cnt],PWM_ActionQual_Set);
          PWM_setActionQual_CntDown_CmpA_PwmA(obj->pwmHandle[cnt],PWM_ActionQual_Clear);
    
          // setup the Dead-Band Generator Control Register (DBCTL)
          PWM_setDeadBandOutputMode(obj->pwmHandle[cnt],PWM_DeadBandOutputMode_EPWMxA_Rising_EPWMxB_Falling);
          PWM_setDeadBandPolarity(obj->pwmHandle[cnt],PWM_DeadBandPolarity_EPWMxB_Inverted);
    
          // setup the Dead-Band Rising Edge Delay Register (DBRED)
          PWM_setDeadBandRisingEdgeDelay(obj->pwmHandle[cnt],HAL_PWM_DBRED_CNT);
    
          // setup the Dead-Band Falling Edge Delay Register (DBFED)
          PWM_setDeadBandFallingEdgeDelay(obj->pwmHandle[cnt],HAL_PWM_DBFED_CNT);
          // setup the PWM-Chopper Control Register (PCCTL)
          PWM_disableChopping(obj->pwmHandle[cnt]);
    
          // setup the Trip Zone Select Register (TZSEL)
          PWM_disableTripZones(obj->pwmHandle[cnt]);
        }
    
    
      // setup the Event Trigger Selection Register (ETSEL)
      PWM_disableInt(obj->pwmHandle[PWM_Number_1]);
      PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualZero);
      PWM_enableSocAPulse(obj->pwmHandle[PWM_Number_1]);
      
    
      // setup the Event Trigger Prescale Register (ETPS)
      if(numPwmTicksPerIsrTick == 3)
        {
          PWM_setIntPeriod(obj->pwmHandle[PWM_Number_1],PWM_IntPeriod_ThirdEvent);
          PWM_setSocAPeriod(obj->pwmHandle[PWM_Number_1],PWM_SocPeriod_ThirdEvent);
        }
      else if(numPwmTicksPerIsrTick == 2)
        {
          PWM_setIntPeriod(obj->pwmHandle[PWM_Number_1],PWM_IntPeriod_SecondEvent);
          PWM_setSocAPeriod(obj->pwmHandle[PWM_Number_1],PWM_SocPeriod_SecondEvent);
        }
      else
        {
          PWM_setIntPeriod(obj->pwmHandle[PWM_Number_1],PWM_IntPeriod_FirstEvent);
          PWM_setSocAPeriod(obj->pwmHandle[PWM_Number_1],PWM_SocPeriod_FirstEvent);
        }
    
    
      // setup the Event Trigger Clear Register (ETCLR)
      PWM_clearIntFlag(obj->pwmHandle[PWM_Number_1]);
      PWM_clearSocAFlag(obj->pwmHandle[PWM_Number_1]);
    
    
      // since the PWM is configured as an up/down counter, the period register is set to one-half 
      // of the desired PWM period
      PWM_setPeriod(obj->pwmHandle[PWM_Number_1],halfPeriod_cycles);
      PWM_setPeriod(obj->pwmHandle[PWM_Number_2],halfPeriod_cycles);
      PWM_setPeriod(obj->pwmHandle[PWM_Number_3],halfPeriod_cycles);
    
      // last step to synchronize the pwms
      CLK_enableTbClockSync(obj->clkHandle);
    
      return;
    }  // end of HAL_setupPwms() function
    
    #ifdef QEP
    void HAL_setupQEP(HAL_Handle handle,HAL_QepSelect_e qep)
    {
      HAL_Obj   *obj = (HAL_Obj *)handle;
    
    
      // hold the counter in reset
      QEP_reset_counter(obj->qepHandle[qep]);
    
      // set the QPOSINIT register
      QEP_set_posn_init_count(obj->qepHandle[qep], 0);
    
      // disable all interrupts
      QEP_disable_all_interrupts(obj->qepHandle[qep]);
    
      // clear the interrupt flags
      QEP_clear_all_interrupt_flags(obj->qepHandle[qep]);
    
      // clear the position counter
      QEP_clear_posn_counter(obj->qepHandle[qep]);
    
      // setup the max position
      QEP_set_max_posn_count(obj->qepHandle[qep], (4*USER_MOTOR_ENCODER_LINES)-1);
    
      // setup the QDECCTL register
      QEP_set_QEP_source(obj->qepHandle[qep], QEP_Qsrc_Quad_Count_Mode);
      QEP_disable_sync_out(obj->qepHandle[qep]);
      QEP_set_swap_quad_inputs(obj->qepHandle[qep], QEP_Swap_Not_Swapped);
      QEP_disable_gate_index(obj->qepHandle[qep]);
      QEP_set_ext_clock_rate(obj->qepHandle[qep], QEP_Xcr_2x_Res);
      QEP_set_A_polarity(obj->qepHandle[qep], QEP_Qap_No_Effect);
      QEP_set_B_polarity(obj->qepHandle[qep], QEP_Qbp_No_Effect);
      QEP_set_index_polarity(obj->qepHandle[qep], QEP_Qip_No_Effect);
    
      // setup the QEPCTL register
      QEP_set_emu_control(obj->qepHandle[qep], QEPCTL_Freesoft_Unaffected_Halt);
      QEP_set_posn_count_reset_mode(obj->qepHandle[qep], QEPCTL_Pcrm_Max_Reset);
      QEP_set_strobe_event_init(obj->qepHandle[qep], QEPCTL_Sei_Nothing);
      QEP_set_index_event_init(obj->qepHandle[qep], QEPCTL_Iei_Nothing);
      QEP_set_index_event_latch(obj->qepHandle[qep], QEPCTL_Iel_Rising_Edge);
      QEP_set_soft_init(obj->qepHandle[qep], QEPCTL_Swi_Nothing);
      QEP_disable_unit_timer(obj->qepHandle[qep]);
      QEP_disable_watchdog(obj->qepHandle[qep]);
    
      // setup the QPOSCTL register
      QEP_disable_posn_compare(obj->qepHandle[qep]);
    
      // setup the QCAPCTL register
      QEP_disable_capture(obj->qepHandle[qep]);
    
      // renable the position counter
      QEP_enable_counter(obj->qepHandle[qep]);
    
    
      return;
    }
    #endif
    
    void HAL_setupPwmDacs(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint16_t halfPeriod_cycles = 512;       // 3000->10kHz, 1500->20kHz, 1000-> 30kHz, 500->60kHz
      uint_least8_t    cnt;
    
    
      for(cnt=0;cnt<3;cnt++)
        {
          // initialize the Time-Base Control Register (TBCTL)
          PWMDAC_setCounterMode(obj->pwmDacHandle[cnt],PWM_CounterMode_UpDown);
          PWMDAC_disableCounterLoad(obj->pwmDacHandle[cnt]);
          PWMDAC_setPeriodLoad(obj->pwmDacHandle[cnt],PWM_PeriodLoad_Immediate);
          PWMDAC_setSyncMode(obj->pwmDacHandle[cnt],PWM_SyncMode_EPWMxSYNC);
          PWMDAC_setHighSpeedClkDiv(obj->pwmDacHandle[cnt],PWM_HspClkDiv_by_1);
          PWMDAC_setClkDiv(obj->pwmDacHandle[cnt],PWM_ClkDiv_by_1);
          PWMDAC_setPhaseDir(obj->pwmDacHandle[cnt],PWM_PhaseDir_CountUp);
          PWMDAC_setRunMode(obj->pwmDacHandle[cnt],PWM_RunMode_FreeRun);
    
          // initialize the Timer-Based Phase Register (TBPHS)
          PWMDAC_setPhase(obj->pwmDacHandle[cnt],0);
    
          // setup the Time-Base Counter Register (TBCTR)
          PWMDAC_setCount(obj->pwmDacHandle[cnt],0);
    
          // Initialize the Time-Base Period Register (TBPRD)
          // set to zero initially
          PWMDAC_setPeriod(obj->pwmDacHandle[cnt],0);
    
          // initialize the Counter-Compare Control Register (CMPCTL)
          PWMDAC_setLoadMode_CmpA(obj->pwmDacHandle[cnt],PWM_LoadMode_Zero);
          PWMDAC_setLoadMode_CmpB(obj->pwmDacHandle[cnt],PWM_LoadMode_Zero);
          PWMDAC_setShadowMode_CmpA(obj->pwmDacHandle[cnt],PWM_ShadowMode_Shadow);
          PWMDAC_setShadowMode_CmpB(obj->pwmDacHandle[cnt],PWM_ShadowMode_Shadow);
    
          // Initialize the Action-Qualifier Output A Register (AQCTLA) 
          PWMDAC_setActionQual_CntUp_CmpA_PwmA(obj->pwmDacHandle[cnt],PWM_ActionQual_Clear);
          PWMDAC_setActionQual_CntDown_CmpA_PwmA(obj->pwmDacHandle[cnt],PWM_ActionQual_Set);
    
          // account for EPWM6B
          if(cnt == 0)
            {
              PWMDAC_setActionQual_CntUp_CmpB_PwmB(obj->pwmDacHandle[cnt],PWM_ActionQual_Clear);
              PWMDAC_setActionQual_CntDown_CmpB_PwmB(obj->pwmDacHandle[cnt],PWM_ActionQual_Set);
            }
    
          // Initialize the Dead-Band Control Register (DBCTL) 
          PWMDAC_disableDeadBand(obj->pwmDacHandle[cnt]);
    
          // Initialize the PWM-Chopper Control Register (PCCTL)
          PWMDAC_disableChopping(obj->pwmDacHandle[cnt]);
    
          // Initialize the Trip-Zone Control Register (TZSEL)
          PWMDAC_disableTripZones(obj->pwmDacHandle[cnt]);
    
          // Initialize the Trip-Zone Control Register (TZCTL)
          PWMDAC_setTripZoneState_TZA(obj->pwmDacHandle[cnt],PWM_TripZoneState_HighImp);
          PWMDAC_setTripZoneState_TZB(obj->pwmDacHandle[cnt],PWM_TripZoneState_HighImp);
          PWMDAC_setTripZoneState_DCAEVT1(obj->pwmDacHandle[cnt],PWM_TripZoneState_HighImp);
          PWMDAC_setTripZoneState_DCAEVT2(obj->pwmDacHandle[cnt],PWM_TripZoneState_HighImp);
          PWMDAC_setTripZoneState_DCBEVT1(obj->pwmDacHandle[cnt],PWM_TripZoneState_HighImp);
        }
    
      // since the PWM is configured as an up/down counter, the period register is set to one-half 
      // of the desired PWM period
      PWMDAC_setPeriod(obj->pwmDacHandle[PWMDAC_Number_1],halfPeriod_cycles);
      PWMDAC_setPeriod(obj->pwmDacHandle[PWMDAC_Number_2],halfPeriod_cycles);
      PWMDAC_setPeriod(obj->pwmDacHandle[PWMDAC_Number_3],halfPeriod_cycles);
    
      return;
    }  // end of HAL_setupPwmDacs() function
    
    
    void HAL_setupEstTimer(HAL_Handle handle,
                           const float_t systemFreq_MHz,
                           const float_t estFreq_Hz)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      uint32_t temp;
    
      //
      // calculate timer period value
      //
      temp = ((uint32_t)(systemFreq_MHz *1000000.0 / estFreq_Hz)) - 1;
    
      //
      // use CPU timer 0 for estimator ISR in variable pwm frequency project
      //
      TIMER_setDecimationFactor(obj->timerHandle[0],0);
      TIMER_setEmulationMode(obj->timerHandle[0],TIMER_EmulationMode_RunFree);
      TIMER_setPeriod(obj->timerHandle[0],temp);
      TIMER_setPreScaler(obj->timerHandle[0],0);
    
      TIMER_reload(obj->timerHandle[0]);
    
      return;
    }  // end of HAL_setupEstTimer() function
    
    
    void HAL_setupTimers(HAL_Handle handle,const float_t systemFreq_MHz)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
      uint32_t  timerPeriod_0p5ms = (uint32_t)(systemFreq_MHz * (float_t)500.0) - 1;
      uint32_t  timerPeriod_10ms = (uint32_t)(systemFreq_MHz * (float_t)10000.0) - 1;
    
      // use timer 0 for frequency diagnostics
      TIMER_setDecimationFactor(obj->timerHandle[0],0);
      TIMER_setEmulationMode(obj->timerHandle[0],TIMER_EmulationMode_RunFree);
      TIMER_setPeriod(obj->timerHandle[0],timerPeriod_0p5ms);
      TIMER_setPreScaler(obj->timerHandle[0],0);
    
      // use timer 1 for CPU usage diagnostics
      TIMER_setDecimationFactor(obj->timerHandle[1],0);
      TIMER_setEmulationMode(obj->timerHandle[1],TIMER_EmulationMode_RunFree);
      TIMER_setPeriod(obj->timerHandle[1],timerPeriod_10ms);
      TIMER_setPreScaler(obj->timerHandle[1],0);
    
      // use timer 2 for CPU time diagnostics
      TIMER_setDecimationFactor(obj->timerHandle[2],0);
      TIMER_setEmulationMode(obj->timerHandle[2],TIMER_EmulationMode_RunFree);
      TIMER_setPeriod(obj->timerHandle[2],0xFFFFFFFF);
      TIMER_setPreScaler(obj->timerHandle[2],0);
    
      return;
    }  // end of HAL_setupTimers() function
    
    void HAL_setDacParameters(HAL_Handle handle, HAL_DacData_t *pDacData)
    {
    	HAL_Obj *obj = (HAL_Obj *)handle;
    
    	pDacData->PeriodMax = PWMDAC_getPeriod(obj->pwmDacHandle[PWMDAC_Number_1]);
    
    	pDacData->offset[0] = _IQ(0.5);
    	pDacData->offset[1] = _IQ(0.5);
    	pDacData->offset[2] = _IQ(0.0);
    	pDacData->offset[3] = _IQ(0.0);
    
    	pDacData->gain[0] = _IQ(1.0);
    	pDacData->gain[1] = _IQ(1.0);
    	pDacData->gain[2] = _IQ(1.0);
    	pDacData->gain[3] = _IQ(1.0);
    
    	return;
    }	//end of HAL_setDacParameters() function
    
    // end of file
    

    lab11a_VariablePWM.c
    /* --COPYRIGHT--,BSD   (lab11a_VariablePWM.c)
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    //! \file   solutions/instaspin_foc/src/proj_lab011a.c
    //! \brief A Feature Rich Example without Controller Module
    //!
    //! (C) Copyright 2015, Texas Instruments, Inc.
    
    //! \defgroup PROJ_LAB11A PROJ_LAB11A
    //@{
    
    //! \defgroup PROJ_LAB11A_OVERVIEW Project Overview
    //!
    //! A Feature Rich Example without Controller Module
    //!
    
    // **************************************************************************
    // the includes
    
    // system includes
    #include <math.h>
    #include "main.h"
    
    #ifdef FLASH
    #pragma CODE_SECTION(mainISR,"ramfuncs");
    #pragma CODE_SECTION(runSetTrigger,"ramfuncs");
    #pragma CODE_SECTION(runFieldWeakening,"ramfuncs");
    #pragma CODE_SECTION(runCurrentReconstruction,"ramfuncs");
    #pragma CODE_SECTION(angleDelayComp,"ramfuncs");
    #endif
    
    // Include header files used in the main function
    
    // **************************************************************************
    // the defines
    
    // **************************************************************************
    // the globals
    
    CLARKE_Handle   clarkeHandle_I;               //!< the handle for the current Clarke transform
    CLARKE_Obj      clarke_I;                     //!< the current Clarke transform object
    
    CLARKE_Handle   clarkeHandle_V;               //!< the handle for the voltage Clarke transform
    CLARKE_Obj      clarke_V;                     //!< the voltage Clarke transform object
    
    CPU_USAGE_Handle  cpu_usageHandle;
    CPU_USAGE_Obj     cpu_usage;
    
    EST_Handle      estHandle;                    //!< the handle for the estimator
    
    FW_Handle       fwHandle;
    FW_Obj          fw;
    
    PID_Obj         pid[3];                       //!< three handles for PID controllers 0 - Speed, 1 - Id, 2 - Iq
    PID_Handle      pidHandle[3];                 //!< three objects for PID controllers 0 - Speed, 1 - Id, 2 - Iq
    uint16_t        pidCntSpeed;                  //!< count variable to decimate the execution of the speed PID controller
    
    IPARK_Handle    iparkHandle;                  //!< the handle for the inverse Park transform
    IPARK_Obj       ipark;                        //!< the inverse Park transform object
    
    FILTER_FO_Handle  filterHandle[6];            //!< the handles for the 3-current and 3-voltage filters for offset calculation
    FILTER_FO_Obj     filter[6];                  //!< the 3-current and 3-voltage filters for offset calculation
    
    SVGENCURRENT_Obj     svgencurrent;
    SVGENCURRENT_Handle  svgencurrentHandle;
    
    SVGEN_Handle    svgenHandle;                  //!< the handle for the space vector generator
    SVGEN_Obj       svgen;                        //!< the space vector generator object
    
    TRAJ_Handle     trajHandle_Id;                //!< the handle for the id reference trajectory
    TRAJ_Obj        traj_Id;                      //!< the id reference trajectory object
    
    TRAJ_Handle     trajHandle_spd;               //!< the handle for the speed reference trajectory
    TRAJ_Obj        traj_spd;                     //!< the speed reference trajectory object
    
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(halHandle,"rom_accessed_data");
    #endif
    HAL_Handle      halHandle;                    //!< the handle for the hardware abstraction layer (HAL)
    
    HAL_PwmData_t   gPwmData = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};       //!< contains the three pwm values -1.0 - 0%, 1.0 - 100%
    
    HAL_AdcData_t   gAdcData;                     //!< contains three current values, three voltage values and one DC buss value
    
    MATH_vec3       gOffsets_I_pu = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};  //!< contains the offsets for the current feedback
    
    MATH_vec3       gOffsets_V_pu = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};  //!< contains the offsets for the voltage feedback
    
    MATH_vec2       gIdq_ref_pu = {_IQ(0.0), _IQ(0.0)};              //!< contains the Id and Iq references
    
    MATH_vec2       gVdq_out_pu = {_IQ(0.0), _IQ(0.0)};              //!< contains the output Vd and Vq from the current controllers
    
    MATH_vec2       gIdq_pu = {_IQ(0.0), _IQ(0.0)};                  //!< contains the Id and Iq measured values
    
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(gUserParams,"rom_accessed_data");
    #endif
    USER_Params     gUserParams;
    
    volatile MOTOR_Vars_t gMotorVars = MOTOR_Vars_INIT;   //!< the global motor variables that are defined in main.h and used for display in the debugger's watch window
    
    #ifdef FLASH
    // Used for running BackGround in flash, and ISR in RAM
    extern uint16_t *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart;
    
    #ifdef CSM_ENABLE
    extern uint16_t *econst_start, *econst_end, *econst_ram_load;
    extern uint16_t *switch_start, *switch_end, *switch_ram_load;
    #endif
    #endif
    
    
    MATH_vec3 gIavg = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};
    uint16_t gIavg_shift = 1;
    MATH_vec3 	    gPwmData_prev = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};
    
    #ifdef DRV8301_SPI
    // Watch window interface to the 8301 SPI
    DRV_SPI_8301_Vars_t gDrvSpi8301Vars;
    #endif
    
    #ifdef DRV8305_SPI
    // Watch window interface to the 8305 SPI
    DRV_SPI_8305_Vars_t gDrvSpi8305Vars;
    #endif
    
    _iq gFlux_pu_to_Wb_sf;
    
    _iq gFlux_pu_to_VpHz_sf;
    
    _iq gTorque_Ls_Id_Iq_pu_to_Nm_sf;
    
    _iq gTorque_Flux_Iq_pu_to_Nm_sf;
    
    _iq gSpeed_krpm_to_pu_sf = _IQ((float_t)USER_MOTOR_NUM_POLE_PAIRS * 1000.0 / (USER_IQ_FULL_SCALE_FREQ_Hz * 60.0));
    
    _iq gSpeed_hz_to_krpm_sf = _IQ(60.0 / (float_t)USER_MOTOR_NUM_POLE_PAIRS / 1000.0);
    
    _iq gIs_Max_squared_pu = _IQ((USER_MOTOR_MAX_CURRENT * USER_MOTOR_MAX_CURRENT) / (USER_IQ_FULL_SCALE_CURRENT_A * USER_IQ_FULL_SCALE_CURRENT_A));
    
    float_t gCpuUsagePercentageMin = 0.0;
    float_t gCpuUsagePercentageAvg = 0.0;
    float_t gCpuUsagePercentageMax = 0.0;
    
    uint32_t gOffsetCalcCount = 0;
    
    uint16_t gTrjCnt = 0;
    
    volatile bool gFlag_enableRsOnLine = false;
    
    volatile bool gFlag_updateRs = false;
    
    volatile _iq gRsOnLineFreq_Hz = _IQ(0.2);
    
    volatile _iq gRsOnLineId_mag_A = _IQ(0.5);
    
    volatile _iq gRsOnLinePole_Hz = _IQ(0.2);
    
    _iq angle_pu = _IQ(0.0);
    _iq speed_pu = _IQ(0.0);
    MATH_vec2 Iab_pu;
    MATH_vec2 Vab_pu;
    MATH_vec2 phasor;
    
    // **************************************************************************
    // the functions
    void main(void)
    {
      // Only used if running from FLASH
      // Note that the variable FLASH is defined by the project
      #ifdef FLASH
      // Copy time critical code and Flash setup code to RAM
      // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
      // symbols are created by the linker. Refer to the linker files.
      memCopy((uint16_t *)&RamfuncsLoadStart,(uint16_t *)&RamfuncsLoadEnd,(uint16_t *)&RamfuncsRunStart);
    
      #ifdef CSM_ENABLE
      //copy .econst to unsecure RAM
      if(*econst_end - *econst_start)
    	{
    	  memCopy((uint16_t *)&econst_start,(uint16_t *)&econst_end,(uint16_t *)&econst_ram_load);
    	}
    
      //copy .switch ot unsecure RAM
      if(*switch_end - *switch_start)
    	{
    	  memCopy((uint16_t *)&switch_start,(uint16_t *)&switch_end,(uint16_t *)&switch_ram_load);
    	}
      #endif
      #endif
    
      // initialize the hardware abstraction layer
      halHandle = HAL_init(&hal,sizeof(hal));
    
      // check for errors in user parameters
      USER_checkForErrors(&gUserParams);
    
    
      // store user parameter error in global variable
      gMotorVars.UserErrorCode = USER_getErrorCode(&gUserParams);
    
    
      // do not allow code execution if there is a user parameter error
      if(gMotorVars.UserErrorCode != USER_ErrorCode_NoError)
        {
          for(;;)
            {
              gMotorVars.Flag_enableSys = false;
            }
        }
    
      // initialize the Clarke modules
      clarkeHandle_I = CLARKE_init(&clarke_I,sizeof(clarke_I));
      clarkeHandle_V = CLARKE_init(&clarke_V,sizeof(clarke_V));
    
      // initialize the estimator
      estHandle = EST_init((void *)USER_EST_HANDLE_ADDRESS, 0x200);
    
      // initialize the user parameters
      USER_setParams(&gUserParams);
    
      // set the hardware abstraction layer parameters
      HAL_setParams(halHandle,&gUserParams);
    
    #ifdef FAST_ROM_V1p6
      {
        CTRL_Handle ctrlHandle = CTRL_init((void *)USER_CTRL_HANDLE_ADDRESS, 0x200);
        CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle;
        obj->estHandle = estHandle;
    
        // initialize the estimator through the controller
        CTRL_setParams(ctrlHandle,&gUserParams);
        CTRL_setUserMotorParams(ctrlHandle);
        CTRL_setupEstIdleState(ctrlHandle);
      }
    #else
      {
        // initialize the estimator
        EST_setEstParams(estHandle,&gUserParams);
        EST_setupEstIdleState(estHandle);
      }
    #endif
    
      // disable Rs recalculation by default
      gMotorVars.Flag_enableRsRecalc = true;
      EST_setFlag_enableRsRecalc(estHandle,false);
    
      // configure RsOnLine
      EST_setFlag_enableRsOnLine(estHandle,gFlag_enableRsOnLine);
      EST_setFlag_updateRs(estHandle,gFlag_updateRs);
      EST_setRsOnLineAngleDelta_pu(estHandle,_IQmpy(gRsOnLineFreq_Hz, _IQ(1.0/USER_ISR_FREQ_Hz)));
      EST_setRsOnLineId_mag_pu(estHandle,_IQmpy(gRsOnLineId_mag_A, _IQ(1.0/USER_IQ_FULL_SCALE_CURRENT_A)));
    
      // Calculate coefficients for all filters
      {
        _iq b0 = _IQmpy(gRsOnLinePole_Hz, _IQ(1.0/USER_ISR_FREQ_Hz));
        _iq a1 = b0 - _IQ(1.0);
        EST_setRsOnLineFilterParams(estHandle,EST_RsOnLineFilterType_Current,b0,a1,_IQ(0.0),b0,a1,_IQ(0.0));
        EST_setRsOnLineFilterParams(estHandle,EST_RsOnLineFilterType_Voltage,b0,a1,_IQ(0.0),b0,a1,_IQ(0.0));
      }
    
      // set the number of current sensors
      setupClarke_I(clarkeHandle_I,USER_NUM_CURRENT_SENSORS);
    
      // set the number of voltage sensors
      setupClarke_V(clarkeHandle_V,USER_NUM_VOLTAGE_SENSORS);
    
      // set the pre-determined current and voltage feeback offset values
      gOffsets_I_pu.value[0] = _IQ(I_A_offset);
      gOffsets_I_pu.value[1] = _IQ(I_B_offset);
      gOffsets_I_pu.value[2] = _IQ(I_C_offset);
      gOffsets_V_pu.value[0] = _IQ(V_A_offset);
      gOffsets_V_pu.value[1] = _IQ(V_B_offset);
      gOffsets_V_pu.value[2] = _IQ(V_C_offset);
    
      // initialize the PID controllers
      {
        _iq maxCurrent_pu = _IQ(USER_MOTOR_MAX_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A);
        _iq maxVoltage_pu = _IQ(USER_MAX_VS_MAG_PU * USER_VD_SF);
        float_t fullScaleCurrent = USER_IQ_FULL_SCALE_CURRENT_A;
        float_t fullScaleVoltage = USER_IQ_FULL_SCALE_VOLTAGE_V;
        float_t IsrPeriod_sec = 1.0 / USER_ISR_FREQ_Hz;
        float_t Ls_d = USER_MOTOR_Ls_d;
        float_t Ls_q = USER_MOTOR_Ls_q;
        float_t Rs = USER_MOTOR_Rs;
        float_t RoverLs_d = Rs/Ls_d;
        float_t RoverLs_q = Rs/Ls_q;
        _iq Kp_Id = _IQ((0.25*Ls_d*fullScaleCurrent)/(IsrPeriod_sec*fullScaleVoltage));
        _iq Ki_Id = _IQ(RoverLs_d*IsrPeriod_sec);
        _iq Kp_Iq = _IQ((0.25*Ls_q*fullScaleCurrent)/(IsrPeriod_sec*fullScaleVoltage));
        _iq Ki_Iq = _IQ(RoverLs_q*IsrPeriod_sec);
    
        pidHandle[0] = PID_init(&pid[0],sizeof(pid[0]));
        pidHandle[1] = PID_init(&pid[1],sizeof(pid[1]));
        pidHandle[2] = PID_init(&pid[2],sizeof(pid[2]));
    
        PID_setGains(pidHandle[0],_IQ(1.0),_IQ(0.01),_IQ(0.0));
        PID_setMinMax(pidHandle[0],-maxCurrent_pu,maxCurrent_pu);
        PID_setUi(pidHandle[0],_IQ(0.0));
        pidCntSpeed = 0;
    
        PID_setGains(pidHandle[1],Kp_Id,Ki_Id,_IQ(0.0));
        PID_setMinMax(pidHandle[1],-maxVoltage_pu,maxVoltage_pu);
        PID_setUi(pidHandle[1],_IQ(0.0));
    
        PID_setGains(pidHandle[2],Kp_Iq,Ki_Iq,_IQ(0.0));
        PID_setMinMax(pidHandle[2],_IQ(0.0),_IQ(0.0));
        PID_setUi(pidHandle[2],_IQ(0.0));
      }
    
      // initialize the speed reference in kilo RPM where base speed is USER_IQ_FULL_SCALE_FREQ_Hz
      gMotorVars.SpeedRef_krpm = _IQmpy(_IQ(10.0), gSpeed_hz_to_krpm_sf);
    
      // initialize the inverse Park module
      iparkHandle = IPARK_init(&ipark,sizeof(ipark));
    
      // initialize and configure offsets using filters
      {
        uint16_t cnt = 0;
        _iq b0 = _IQ(gUserParams.offsetPole_rps/(float_t)gUserParams.ctrlFreq_Hz);
        _iq a1 = (b0 - _IQ(1.0));
        _iq b1 = _IQ(0.0);
    
        for(cnt=0;cnt<6;cnt++)
          {
            filterHandle[cnt] = FILTER_FO_init(&filter[cnt],sizeof(filter[0]));
            FILTER_FO_setDenCoeffs(filterHandle[cnt],a1);
            FILTER_FO_setNumCoeffs(filterHandle[cnt],b0,b1);
            FILTER_FO_setInitialConditions(filterHandle[cnt],_IQ(0.0),_IQ(0.0));
          }
    
        gMotorVars.Flag_enableOffsetcalc = false;
      }
    
      // initialize the space vector generator module
      svgenHandle = SVGEN_init(&svgen,sizeof(svgen));
    
      // Initialize and setup the 100% SVM generator
      svgencurrentHandle = SVGENCURRENT_init(&svgencurrent,sizeof(svgencurrent));
    
      // setup svgen current
      {
        float_t minWidth_microseconds = 2.0;
        uint16_t minWidth_counts = (uint16_t)(minWidth_microseconds * USER_SYSTEM_FREQ_MHz);
        float_t fdutyLimit = 0.5-(2.0*minWidth_microseconds*USER_PWM_FREQ_kHz*0.001);
        _iq dutyLimit = _IQ(fdutyLimit);
    
        SVGENCURRENT_setMinWidth(svgencurrentHandle, minWidth_counts);
        SVGENCURRENT_setIgnoreShunt(svgencurrentHandle, use_all);
        SVGENCURRENT_setMode(svgencurrentHandle,all_phase_measurable);
        SVGENCURRENT_setVlimit(svgencurrentHandle,dutyLimit);
      }
    
      // set overmodulation to maximum value
      gMotorVars.OverModulation = _IQ(USER_MAX_VS_MAG_PU);
      // initialize the speed reference trajectory
      trajHandle_spd = TRAJ_init(&traj_spd,sizeof(traj_spd));
    
      // configure the speed reference trajectory
      TRAJ_setTargetValue(trajHandle_spd,_IQ(0.0));
      TRAJ_setIntValue(trajHandle_spd,_IQ(0.0));
      TRAJ_setMinValue(trajHandle_spd,_IQ(-1.0));
      TRAJ_setMaxValue(trajHandle_spd,_IQ(1.0));
      TRAJ_setMaxDelta(trajHandle_spd,_IQ(USER_MAX_ACCEL_Hzps / USER_IQ_FULL_SCALE_FREQ_Hz / USER_ISR_FREQ_Hz));
    
      // initialize the Id reference trajectory
      trajHandle_Id = TRAJ_init(&traj_Id,sizeof(traj_Id));
    
      if(USER_MOTOR_TYPE == MOTOR_Type_Pm)
        {
          // configure the Id reference trajectory
          TRAJ_setTargetValue(trajHandle_Id,_IQ(0.0));
          TRAJ_setIntValue(trajHandle_Id,_IQ(0.0));
          TRAJ_setMinValue(trajHandle_Id,_IQ(-USER_MOTOR_MAX_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
          TRAJ_setMaxValue(trajHandle_Id,_IQ(USER_MOTOR_MAX_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
          TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_RES_EST_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
    
          // Initialize field weakening
          fwHandle = FW_init(&fw,sizeof(fw));
          FW_setFlag_enableFw(fwHandle, false); // Disable field weakening
          FW_clearCounter(fwHandle); // Clear field weakening counter
          FW_setNumIsrTicksPerFwTick(fwHandle, FW_NUM_ISR_TICKS_PER_CTRL_TICK); // Set the number of ISR per field weakening ticks
          FW_setDeltas(fwHandle, FW_INC_DELTA, FW_DEC_DELTA); // Set the deltas of field weakening
          FW_setOutput(fwHandle, _IQ(0.0)); // Set initial output of field weakening to zero
          FW_setMinMax(fwHandle,_IQ(USER_MAX_NEGATIVE_ID_REF_CURRENT_A/USER_IQ_FULL_SCALE_CURRENT_A),_IQ(0.0)); // Set the field weakening controller limits
        }
      else
        {
          // configure the Id reference trajectory
          TRAJ_setTargetValue(trajHandle_Id,_IQ(0.0));
          TRAJ_setIntValue(trajHandle_Id,_IQ(0.0));
          TRAJ_setMinValue(trajHandle_Id,_IQ(0.0));
          TRAJ_setMaxValue(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
          TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
        }
    
      // initialize the CPU usage module
      cpu_usageHandle = CPU_USAGE_init(&cpu_usage,sizeof(cpu_usage));
      CPU_USAGE_setParams(cpu_usageHandle,
    		  	  	  	  HAL_getTimerPeriod(halHandle,1),     // timer period, cnts
                         (uint32_t)USER_ISR_FREQ_Hz);                  // average over 1 second of ISRs
    
      // setup faults
      HAL_setupFaults(halHandle);
    
      // initialize the interrupt vector table
      HAL_initIntVectorTable(halHandle);
    
      // enable the ADC interrupts
      HAL_enableAdcInts(halHandle);
    
      // enable global interrupts
      HAL_enableGlobalInts(halHandle);
    
      // enable debug interrupts
      HAL_enableDebugInt(halHandle);
    
      // disable the PWM
      HAL_disablePwm(halHandle);
    
      // compute scaling factors for flux and torque calculations
      gFlux_pu_to_Wb_sf = USER_computeFlux_pu_to_Wb_sf();
      gFlux_pu_to_VpHz_sf = USER_computeFlux_pu_to_VpHz_sf();
      gTorque_Ls_Id_Iq_pu_to_Nm_sf = USER_computeTorque_Ls_Id_Iq_pu_to_Nm_sf();
      gTorque_Flux_Iq_pu_to_Nm_sf = USER_computeTorque_Flux_Iq_pu_to_Nm_sf();
    
      // enable the system by default
      gMotorVars.Flag_enableSys = true;
    
    #ifdef DRV8301_SPI
      // turn on the DRV8301 if present
      HAL_enableDrv(halHandle);
      // initialize the DRV8301 interface
      HAL_setupDrvSpi(halHandle,&gDrvSpi8301Vars);
    #endif
    
    #ifdef DRV8305_SPI
      // turn on the DRV8305 if present
      HAL_enableDrv(halHandle);
      // initialize the DRV8305 interface
      HAL_setupDrvSpi(halHandle,&gDrvSpi8305Vars);
    #endif
    
      // Begin the background loop
      for(;;)
      {
        // Waiting for enable system flag to be set
        while(!(gMotorVars.Flag_enableSys));
    
        // loop while the enable system flag is true
        while(gMotorVars.Flag_enableSys)
          {
            if(gMotorVars.Flag_Run_Identify)
              {
                // disable Rs recalculation
                EST_setFlag_enableRsRecalc(estHandle,false);
    
                // update estimator state
                EST_updateState(estHandle,0);
    
                #ifdef FAST_ROM_V1p6
                  // call this function to fix 1p6
                  softwareUpdate1p6(estHandle);
                #endif
    
                // enable the PWM
                HAL_enablePwm(halHandle);
    
                // set trajectory target for speed reference
                TRAJ_setTargetValue(trajHandle_spd,_IQmpy(gMotorVars.SpeedRef_krpm, gSpeed_krpm_to_pu_sf));
    
                if(USER_MOTOR_TYPE == MOTOR_Type_Pm)
                  {
                    // set trajectory target for Id reference
                    TRAJ_setTargetValue(trajHandle_Id,gIdq_ref_pu.value[0]);
                  }
                else
                  {
                    if(gMotorVars.Flag_enablePowerWarp)
                      {
                        _iq Id_target_pw_pu = EST_runPowerWarp(estHandle,TRAJ_getIntValue(trajHandle_Id),gIdq_pu.value[1]);
                        TRAJ_setTargetValue(trajHandle_Id,Id_target_pw_pu);
                        TRAJ_setMinValue(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT * 0.3 / USER_IQ_FULL_SCALE_CURRENT_A));
                        TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT * 0.3 / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
                      }
                    else
                      {
                        // set trajectory target for Id reference
                        TRAJ_setTargetValue(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
                        TRAJ_setMinValue(trajHandle_Id,_IQ(0.0));
                        TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
                      }
                  }
              }
            else if(gMotorVars.Flag_enableRsRecalc)
              {
                // set angle to zero
                EST_setAngle_pu(estHandle,_IQ(0.0));
    
                // enable or disable Rs recalculation
                EST_setFlag_enableRsRecalc(estHandle,true);
    
                // update estimator state
                EST_updateState(estHandle,0);
    
                #ifdef FAST_ROM_V1p6
                  // call this function to fix 1p6
                  softwareUpdate1p6(estHandle);
                #endif
    
                // enable the PWM
                HAL_enablePwm(halHandle);
    
                // set trajectory target for speed reference
                TRAJ_setTargetValue(trajHandle_spd,_IQ(0.0));
    
                // set trajectory target for Id reference
                TRAJ_setTargetValue(trajHandle_Id,_IQ(USER_MOTOR_RES_EST_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
    
                // if done with Rs recalculation, disable flag
                if(EST_getState(estHandle) == EST_State_OnLine) gMotorVars.Flag_enableRsRecalc = false;
              }
            else
              {
                // set estimator to Idle
                EST_setIdle(estHandle);
    
                // disable the PWM
                if(!gMotorVars.Flag_enableOffsetcalc) HAL_disablePwm(halHandle);
    
                // clear the speed reference trajectory
                TRAJ_setTargetValue(trajHandle_spd,_IQ(0.0));
                TRAJ_setIntValue(trajHandle_spd,_IQ(0.0));
    
                // clear the Id reference trajectory
                TRAJ_setTargetValue(trajHandle_Id,_IQ(0.0));
                TRAJ_setIntValue(trajHandle_Id,_IQ(0.0));
    
                // configure trajectory Id defaults depending on motor type
                if(USER_MOTOR_TYPE == MOTOR_Type_Pm)
                  {
                    TRAJ_setMinValue(trajHandle_Id,_IQ(-USER_MOTOR_MAX_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A));
                    TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_RES_EST_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
                  }
                else
                  {
                    TRAJ_setMinValue(trajHandle_Id,_IQ(0.0));
                    TRAJ_setMaxDelta(trajHandle_Id,_IQ(USER_MOTOR_MAGNETIZING_CURRENT / USER_IQ_FULL_SCALE_CURRENT_A / USER_ISR_FREQ_Hz));
                  }
    
                // clear integral outputs
                PID_setUi(pidHandle[0],_IQ(0.0));
                PID_setUi(pidHandle[1],_IQ(0.0));
                PID_setUi(pidHandle[2],_IQ(0.0));
    
                // clear Id and Iq references
                gIdq_ref_pu.value[0] = _IQ(0.0);
                gIdq_ref_pu.value[1] = _IQ(0.0);
    
                // disable RsOnLine flags
                gFlag_enableRsOnLine = false;
                gFlag_updateRs = false;
    
                // disable PowerWarp flag
                gMotorVars.Flag_enablePowerWarp = false;
              }
    
            // update the global variables
            updateGlobalVariables(estHandle);
    
            // set field weakening enable flag depending on user's input
            FW_setFlag_enableFw(fwHandle,gMotorVars.Flag_enableFieldWeakening);
    
    		// set the speed acceleration
    		TRAJ_setMaxDelta(trajHandle_spd,_IQmpy(MAX_ACCEL_KRPMPS_SF,gMotorVars.MaxAccel_krpmps));
    
            // update CPU usage
            updateCPUusage();
    
            updateRsOnLine(estHandle);
    
            // enable/disable the forced angle
            EST_setFlag_enableForceAngle(estHandle,gMotorVars.Flag_enableForceAngle);
    
    #ifdef DRV8301_SPI
            HAL_writeDrvData(halHandle,&gDrvSpi8301Vars);
    
            HAL_readDrvData(halHandle,&gDrvSpi8301Vars);
    #endif
    #ifdef DRV8305_SPI
            HAL_writeDrvData(halHandle,&gDrvSpi8305Vars);
    
            HAL_readDrvData(halHandle,&gDrvSpi8305Vars);
    #endif
    
          } // end of while(gFlag_enableSys) loop
    
        // disable the PWM
        HAL_disablePwm(halHandle);
    
        gMotorVars.Flag_Run_Identify = false;
      } // end of for(;;) loop
    } // end of main() function
    
    
    //
    // the CPU timer0 interrupt as FAST estimator ISR
    //
    interrupt void estISR(void)
    {
        HAL_acqTimer0Int(halHandle);
    
    //    if(gTrjCnt >= gUserParams.numCtrlTicksPerTrajTick)
    //    {
    //        // clear counter
    //        gTrjCnt = 0;
    
            // run a trajectory for speed reference, so the reference changes with a ramp instead of a step
            TRAJ_run(trajHandle_spd);
    //    }
    
            // run the estimator
            EST_run(estHandle,
                    &Iab_pu,
                    &Vab_pu,
                    gAdcData.dcBus,
                    TRAJ_getIntValue(trajHandle_spd));
    
            // generate the motor electrical angle
            angle_pu = EST_getAngle_pu(estHandle);
            speed_pu = EST_getFm_pu(estHandle);
    
            // get Idq from estimator to avoid sin and cos
            EST_getIdq_pu(estHandle,&gIdq_pu);
    
            // run the appropriate controller
            if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
              {
                // when appropriate, run the PID speed controller
                if((pidCntSpeed++ >= USER_NUM_CTRL_TICKS_PER_SPEED_TICK) && (!gMotorVars.Flag_enableRsRecalc))
                  {
                    // calculate Id reference squared
                    _iq Id_ref_squared_pu = _IQmpy(PID_getRefValue(pidHandle[1]),PID_getRefValue(pidHandle[1]));
    
                    // Take into consideration that Iq^2+Id^2 = Is^2
                    _iq Iq_Max_pu = _IQsqrt(gIs_Max_squared_pu - Id_ref_squared_pu);
    
                    // clear counter
                    pidCntSpeed = 0;
    
                    // Set new min and max for the speed controller output
                    PID_setMinMax(pidHandle[0], -Iq_Max_pu, Iq_Max_pu);
    
                    // run speed controller
                    PID_run_spd(pidHandle[0],TRAJ_getIntValue(trajHandle_spd),speed_pu,&(gIdq_ref_pu.value[1]));
                  }
              }
    
    }
    
    
    //! \brief     The main ISR that implements the motor control.
    interrupt void mainISR(void)
    {
      _iq oneOverDcBus;
    
      // acknowledge the ADC interrupt
      HAL_acqAdcInt(halHandle,ADC_IntNumber_1);
    
      // convert the ADC data
      HAL_readAdcDataWithOffsets(halHandle,&gAdcData);
    
      // remove offsets
      gAdcData.I.value[0] = gAdcData.I.value[0] - gOffsets_I_pu.value[0];
      gAdcData.I.value[1] = gAdcData.I.value[1] - gOffsets_I_pu.value[1];
      gAdcData.I.value[2] = gAdcData.I.value[2] - gOffsets_I_pu.value[2];
      gAdcData.V.value[0] = gAdcData.V.value[0] - gOffsets_V_pu.value[0];
      gAdcData.V.value[1] = gAdcData.V.value[1] - gOffsets_V_pu.value[1];
      gAdcData.V.value[2] = gAdcData.V.value[2] - gOffsets_V_pu.value[2];
    
      // run the current reconstruction algorithm
      runCurrentReconstruction();
    
      // run Clarke transform on current
      CLARKE_run(clarkeHandle_I,&gAdcData.I,&Iab_pu);
    
      // run Clarke transform on voltage
      CLARKE_run(clarkeHandle_V,&gAdcData.V,&Vab_pu);
    
      // run a trajectory for Id reference, so the reference changes with a ramp instead of a step
      TRAJ_run(trajHandle_Id);
    
      // run the appropriate controller
      if((gMotorVars.Flag_Run_Identify) || (gMotorVars.Flag_enableRsRecalc))
        {
          _iq refValue;
          _iq fbackValue;
          _iq outMax_pu;
    
          // get the reference value from the trajectory module
          refValue = TRAJ_getIntValue(trajHandle_Id) + EST_getRsOnLineId_pu(estHandle);
    
          // get the feedback value
          fbackValue = gIdq_pu.value[0];
    
          // run the Id PID controller
          PID_run(pidHandle[1],refValue,fbackValue,&(gVdq_out_pu.value[0]));
    
          // set Iq reference to zero when doing Rs recalculation
          if(gMotorVars.Flag_enableRsRecalc) gIdq_ref_pu.value[1] = _IQ(0.0);
    
          // get the Iq reference value
          refValue = gIdq_ref_pu.value[1];
    
          // get the feedback value
          fbackValue = gIdq_pu.value[1];
    
          // calculate Iq controller limits, and run Iq controller
          _iq max_vs = _IQmpy(gMotorVars.OverModulation,EST_getDcBus_pu(estHandle));
          outMax_pu = _IQsqrt(_IQmpy(max_vs,max_vs) - _IQmpy(gVdq_out_pu.value[0],gVdq_out_pu.value[0]));
          PID_setMinMax(pidHandle[2],-outMax_pu,outMax_pu);
          PID_run(pidHandle[2],refValue,fbackValue,&(gVdq_out_pu.value[1]));
    
          // compensate angle for PWM delay
          angle_pu = angleDelayComp(speed_pu, angle_pu);
    
          // compute the sin/cos phasor
          phasor.value[0] = _IQcosPU(angle_pu);
          phasor.value[1] = _IQsinPU(angle_pu);
    
          // set the phasor in the inverse Park transform
          IPARK_setPhasor(iparkHandle,&phasor);
    
          // run the inverse Park module
          IPARK_run(iparkHandle,&gVdq_out_pu,&Vab_pu);
    
          // run the space Vector Generator (SVGEN) module
          oneOverDcBus = EST_getOneOverDcBus_pu(estHandle);
          Vab_pu.value[0] = _IQmpy(Vab_pu.value[0],oneOverDcBus);
          Vab_pu.value[1] = _IQmpy(Vab_pu.value[1],oneOverDcBus);
          SVGEN_run(svgenHandle,&Vab_pu,&(gPwmData.Tabc));
    
          // run the PWM compensation and current ignore algorithm
          SVGENCURRENT_compPwmData(svgencurrentHandle,&(gPwmData.Tabc),&gPwmData_prev);
    
    //      gTrjCnt++;
        }
      else if(gMotorVars.Flag_enableOffsetcalc == true)
        {
          runOffsetsCalculation();
        }
      else
        {
          // disable the PWM
          HAL_disablePwm(halHandle);
    
          // Set the PWMs to 50% duty cycle
          gPwmData.Tabc.value[0] = _IQ(0.0);
          gPwmData.Tabc.value[1] = _IQ(0.0);
          gPwmData.Tabc.value[2] = _IQ(0.0);
        }
    
      // write the PWM compare values
      HAL_writePwmData(halHandle,&gPwmData);
    
      // run function to set next trigger
      if(!gMotorVars.Flag_enableRsRecalc) runSetTrigger();
    
    //  DATALOG_update(datalogHandle);
    
      // read the timer 1 value and update the CPU usage module
    //  timer1Cnt = HAL_readTimerCnt(halHandle,1);
    //  CPU_USAGE_updateCnts(cpu_usageHandle,timer1Cnt);
    
      // run the CPU usage module
    //  CPU_USAGE_run(cpu_usageHandle);
    
      return;
    } // end of mainISR() function
    
    
    _iq angleDelayComp(const _iq fm_pu, const _iq angleUncomp_pu)
    {
      _iq angleDelta_pu = _IQmpy(fm_pu,_IQ(USER_IQ_FULL_SCALE_FREQ_Hz/(USER_PWM_FREQ_kHz*1000.0)));
      _iq angleCompFactor = _IQ(1.0 + (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK * 0.5);
      _iq angleDeltaComp_pu = _IQmpy(angleDelta_pu, angleCompFactor);
      uint32_t angleMask = ((uint32_t)0xFFFFFFFF >> (32 - GLOBAL_Q));
      _iq angleComp_pu;
      _iq angleTmp_pu;
    
      // increment the angle
      angleTmp_pu = angleUncomp_pu + angleDeltaComp_pu;
    
      // mask the angle for wrap around
      // note: must account for the sign of the angle
      angleComp_pu = _IQabs(angleTmp_pu) & angleMask;
    
      // account for sign
      if(angleTmp_pu < _IQ(0.0))
        {
          angleComp_pu = -angleComp_pu;
        }
    
      return(angleComp_pu);
    } // end of angleDelayComp() function
    
    
    void runCurrentReconstruction(void)
    {
      SVGENCURRENT_MeasureShunt_e measurableShuntThisCycle = SVGENCURRENT_getMode(svgencurrentHandle);
    
      // run the current reconstruction algorithm
      SVGENCURRENT_RunRegenCurrent(svgencurrentHandle, (MATH_vec3 *)(gAdcData.I.value));
    
      gIavg.value[0] += (gAdcData.I.value[0] - gIavg.value[0])>>gIavg_shift;
      gIavg.value[1] += (gAdcData.I.value[1] - gIavg.value[1])>>gIavg_shift;
      gIavg.value[2] += (gAdcData.I.value[2] - gIavg.value[2])>>gIavg_shift;
    
      if(measurableShuntThisCycle > two_phase_measurable)
      {
    	  gAdcData.I.value[0] = gIavg.value[0];
    	  gAdcData.I.value[1] = gIavg.value[1];
    	  gAdcData.I.value[2] = gIavg.value[2];
      }
    
      return;
    } // end of runCurrentReconstruction() function
    
    void runSetTrigger(void)
    {
      SVGENCURRENT_IgnoreShunt_e ignoreShuntNextCycle = SVGENCURRENT_getIgnoreShunt(svgencurrentHandle);
      SVGENCURRENT_VmidShunt_e midVolShunt = SVGENCURRENT_getVmid(svgencurrentHandle);
    
      // Set trigger point in the middle of the low side pulse
      HAL_setTrigger(halHandle,ignoreShuntNextCycle,midVolShunt);
    
      return;
    } // end of runSetTrigger() function
    
    void runFieldWeakening(void)
    {
      if(FW_getFlag_enableFw(fwHandle) == true)
        {
          FW_incCounter(fwHandle);
    
          if(FW_getCounter(fwHandle) > FW_getNumIsrTicksPerFwTick(fwHandle))
            {
              _iq refValue;
              _iq fbackValue;
    
              FW_clearCounter(fwHandle);
    
              refValue = gMotorVars.VsRef;
    
              fbackValue =_IQmpy(gMotorVars.Vs,EST_getOneOverDcBus_pu(estHandle));
    
              FW_run(fwHandle, refValue, fbackValue, &(gIdq_ref_pu.value[0]));
    
              gMotorVars.IdRef_A = _IQmpy(gIdq_ref_pu.value[0], _IQ(USER_IQ_FULL_SCALE_CURRENT_A));
            }
        }
      else
        {
          gIdq_ref_pu.value[0] = _IQmpy(gMotorVars.IdRef_A, _IQ(1.0/USER_IQ_FULL_SCALE_CURRENT_A));
        }
    
      return;
    } // end of runFieldWeakening() function
    
    
    void runOffsetsCalculation(void)
    {
      uint16_t cnt;
    
      // enable the PWM
      HAL_enablePwm(halHandle);
    
      for(cnt=0;cnt<3;cnt++)
        {
          // Set the PWMs to 50% duty cycle
          gPwmData.Tabc.value[cnt] = _IQ(0.0);
    
          // reset offsets used
          gOffsets_I_pu.value[cnt] = _IQ(0.0);
          gOffsets_V_pu.value[cnt] = _IQ(0.0);
    
          // run offset estimation
          FILTER_FO_run(filterHandle[cnt],gAdcData.I.value[cnt]);
          FILTER_FO_run(filterHandle[cnt+3],gAdcData.V.value[cnt]);
        }
    
      if(gOffsetCalcCount++ >= gUserParams.ctrlWaitTime[CTRL_State_OffLine])
        {
          gMotorVars.Flag_enableOffsetcalc = false;
          gOffsetCalcCount = 0;
    
          for(cnt=0;cnt<3;cnt++)
            {
              // get calculated offsets from filter
              gOffsets_I_pu.value[cnt] = FILTER_FO_get_y1(filterHandle[cnt]);
              gOffsets_V_pu.value[cnt] = FILTER_FO_get_y1(filterHandle[cnt+3]);
    
              // clear filters
              FILTER_FO_setInitialConditions(filterHandle[cnt],_IQ(0.0),_IQ(0.0));
              FILTER_FO_setInitialConditions(filterHandle[cnt+3],_IQ(0.0),_IQ(0.0));
            }
        }
    
      return;
    } // end of runOffsetsCalculation() function
    
    
    void softwareUpdate1p6(EST_Handle handle)
    {
      float_t fullScaleInductance = USER_IQ_FULL_SCALE_VOLTAGE_V/(USER_IQ_FULL_SCALE_CURRENT_A*USER_VOLTAGE_FILTER_POLE_rps);
      float_t Ls_coarse_max = _IQ30toF(EST_getLs_coarse_max_pu(handle));
      int_least8_t lShift = ceil(log(USER_MOTOR_Ls_d/(Ls_coarse_max*fullScaleInductance))/log(2.0));
      uint_least8_t Ls_qFmt = 30 - lShift;
      float_t L_max = fullScaleInductance * pow(2.0,lShift);
      _iq Ls_d_pu = _IQ30(USER_MOTOR_Ls_d / L_max);
      _iq Ls_q_pu = _IQ30(USER_MOTOR_Ls_q / L_max);
    
    
      // store the results
      EST_setLs_d_pu(handle,Ls_d_pu);
      EST_setLs_q_pu(handle,Ls_q_pu);
      EST_setLs_qFmt(handle,Ls_qFmt);
    
      return;
    } // end of softwareUpdate1p6() function
    
    //! \brief     Setup the Clarke transform for either 2 or 3 sensors.
    //! \param[in] handle             The clarke (CLARKE) handle
    //! \param[in] numCurrentSensors  The number of current sensors
    void setupClarke_I(CLARKE_Handle handle,const uint_least8_t numCurrentSensors)
    {
      _iq alpha_sf,beta_sf;
    
      // initialize the Clarke transform module for current
      if(numCurrentSensors == 3)
        {
          alpha_sf = _IQ(MATH_ONE_OVER_THREE);
          beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
        }
      else if(numCurrentSensors == 2)
        {
          alpha_sf = _IQ(1.0);
          beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
        }
      else
        {
          alpha_sf = _IQ(0.0);
          beta_sf = _IQ(0.0);
        }
    
      // set the parameters
      CLARKE_setScaleFactors(handle,alpha_sf,beta_sf);
      CLARKE_setNumSensors(handle,numCurrentSensors);
    
      return;
    } // end of setupClarke_I() function
    
    
    //! \brief     Setup the Clarke transform for either 2 or 3 sensors.
    //! \param[in] handle             The clarke (CLARKE) handle
    //! \param[in] numVoltageSensors  The number of voltage sensors
    void setupClarke_V(CLARKE_Handle handle,const uint_least8_t numVoltageSensors)
    {
      _iq alpha_sf,beta_sf;
    
      // initialize the Clarke transform module for voltage
      if(numVoltageSensors == 3)
        {
          alpha_sf = _IQ(MATH_ONE_OVER_THREE);
          beta_sf = _IQ(MATH_ONE_OVER_SQRT_THREE);
        }
     else
        {
          alpha_sf = _IQ(0.0);
          beta_sf = _IQ(0.0);
        }
    
      // set the parameters
      CLARKE_setScaleFactors(handle,alpha_sf,beta_sf);
      CLARKE_setNumSensors(handle,numVoltageSensors);
    
      return;
    } // end of setupClarke_V() function
    
    
    //! \brief     Update the global variables (gMotorVars).
    //! \param[in] handle  The estimator (EST) handle
    void updateGlobalVariables(EST_Handle handle)
    {
      // get the speed estimate
      gMotorVars.Speed_krpm = EST_getSpeed_krpm(handle);
    
      // get the torque estimate
      {
        _iq Flux_pu = EST_getFlux_pu(handle);
        _iq Id_pu = PID_getFbackValue(pidHandle[1]);
        _iq Iq_pu = PID_getFbackValue(pidHandle[2]);
        _iq Ld_minus_Lq_pu = _IQ30toIQ(EST_getLs_d_pu(handle)-EST_getLs_q_pu(handle));
        _iq Torque_Flux_Iq_Nm = _IQmpy(_IQmpy(Flux_pu,Iq_pu),gTorque_Flux_Iq_pu_to_Nm_sf);
        _iq Torque_Ls_Id_Iq_Nm = _IQmpy(_IQmpy(_IQmpy(Ld_minus_Lq_pu,Id_pu),Iq_pu),gTorque_Ls_Id_Iq_pu_to_Nm_sf);
        _iq Torque_Nm = Torque_Flux_Iq_Nm + Torque_Ls_Id_Iq_Nm;
    
        gMotorVars.Torque_Nm = Torque_Nm;
      }
    
      // get the magnetizing current
      gMotorVars.MagnCurr_A = EST_getIdRated(handle);
    
      // get the rotor resistance
      gMotorVars.Rr_Ohm = EST_getRr_Ohm(handle);
    
      // get the stator resistance
      gMotorVars.Rs_Ohm = EST_getRs_Ohm(handle);
    
      // get the online stator resistance
      gMotorVars.RsOnLine_Ohm = EST_getRsOnLine_Ohm(handle);
    
      // get the stator inductance in the direct coordinate direction
      gMotorVars.Lsd_H = EST_getLs_d_H(handle);
    
      // get the stator inductance in the quadrature coordinate direction
      gMotorVars.Lsq_H = EST_getLs_q_H(handle);
    
      // get the flux in V/Hz in floating point
      gMotorVars.Flux_VpHz = EST_getFlux_VpHz(handle);
    
      // get the flux in Wb in fixed point
      gMotorVars.Flux_Wb = _IQmpy(EST_getFlux_pu(handle),gFlux_pu_to_Wb_sf);
    
      // get the estimator state
      gMotorVars.EstState = EST_getState(handle);
    
      // Get the DC buss voltage
      gMotorVars.VdcBus_kV = _IQmpy(gAdcData.dcBus,_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0));
    
      // read Vd and Vq vectors per units
      gMotorVars.Vd = gVdq_out_pu.value[0];
      gMotorVars.Vq = gVdq_out_pu.value[1];
    
      // calculate vector Vs in per units
      gMotorVars.Vs = _IQsqrt(_IQmpy(gMotorVars.Vd, gMotorVars.Vd) + _IQmpy(gMotorVars.Vq, gMotorVars.Vq));
    
      // read Id and Iq vectors in amps
      gMotorVars.Id_A = _IQmpy(gIdq_pu.value[0], _IQ(USER_IQ_FULL_SCALE_CURRENT_A));
      gMotorVars.Iq_A = _IQmpy(gIdq_pu.value[1], _IQ(USER_IQ_FULL_SCALE_CURRENT_A));
    
      // calculate vector Is in amps
      gMotorVars.Is_A = _IQsqrt(_IQmpy(gMotorVars.Id_A, gMotorVars.Id_A) + _IQmpy(gMotorVars.Iq_A, gMotorVars.Iq_A));
    
      return;
    } // end of updateGlobalVariables() function
    
    
    void updateRsOnLine(EST_Handle handle)
    {
      // execute Rs OnLine code
      if(gMotorVars.Flag_Run_Identify == true)
        {
          if((EST_getState(handle) == EST_State_OnLine) && (gFlag_enableRsOnLine))
            {
        	  float_t RsError_Ohm = gMotorVars.RsOnLine_Ohm - gMotorVars.Rs_Ohm;
    
              EST_setFlag_enableRsOnLine(handle,true);
              EST_setRsOnLineId_mag_pu(handle,_IQmpy(gRsOnLineId_mag_A,_IQ(1.0/USER_IQ_FULL_SCALE_CURRENT_A)));
              EST_setRsOnLineAngleDelta_pu(handle,_IQmpy(gRsOnLineFreq_Hz, _IQ(1.0/USER_ISR_FREQ_Hz)));
    
              if(abs(RsError_Ohm) < (gMotorVars.Rs_Ohm * 0.05))
                {
                  EST_setFlag_updateRs(handle,true);
                }
            }
          else
            {
              EST_setRsOnLineId_mag_pu(handle,_IQ(0.0));
              EST_setRsOnLineId_pu(handle,_IQ(0.0));
              EST_setRsOnLine_pu(handle, EST_getRs_pu(handle));
              EST_setFlag_enableRsOnLine(handle,false);
              EST_setFlag_updateRs(handle,false);
              EST_setRsOnLine_qFmt(handle,EST_getRs_qFmt(handle));
            }
        }
    
      return;
    } // end of updateRsOnLine() function
    void updateCPUusage(void)
    {
      uint32_t minDeltaCntObserved = CPU_USAGE_getMinDeltaCntObserved(cpu_usageHandle);
      uint32_t avgDeltaCntObserved = CPU_USAGE_getAvgDeltaCntObserved(cpu_usageHandle);
      uint32_t maxDeltaCntObserved = CPU_USAGE_getMaxDeltaCntObserved(cpu_usageHandle);
      uint16_t pwmPeriod = HAL_readPwmPeriod(halHandle,PWM_Number_1);
      float_t  cpu_usage_den = (float_t)pwmPeriod * (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK * 2.0;
    
      // calculate the minimum cpu usage percentage
      gCpuUsagePercentageMin = (float_t)minDeltaCntObserved / cpu_usage_den * 100.0;
    
      // calculate the average cpu usage percentage
      gCpuUsagePercentageAvg = (float_t)avgDeltaCntObserved / cpu_usage_den * 100.0;
    
      // calculate the maximum cpu usage percentage
      gCpuUsagePercentageMax = (float_t)maxDeltaCntObserved / cpu_usage_den * 100.0;
    
      return;
    } // end of updateCPUusage() function
    
    
    //@} //defgroup
    // end of file
    
    
    
    
    1460.hal.h

  • As mentioned above, run all functions in estISR() except HAL_readAdcDataWithOffsets() and HAL_writePwmData(), and disable all of the additional features like over-modulation and Rs online calibration. Make sure that the estISR frequency is set correctly as the USER_ISR_FREQ_Hz.

  • Hi Yanming Luo,

    Thank you for your review.

    I need the space vector overmodulation and current reconstruction functions.

    Do you mean that the space vector overmodulation and current reconstruction functions should be abandoned if the function of variable PWM frequency has to be implemented for the F28069F DSP along with the estmator library in motorware?

    Meanwhile the is12_variable_pwm_frequency lab in MotorControl_SDK enables the space vector overmodulation and current reconstruction functions in implementing the function of variable PWM frequency for the F280049C DSP along with the estmator library in MotorControl_SDK .

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Just want you can verify if the ISR frequency is right and the estimator parameters are set correctly. Don't recommend that using over-modulation and current reconstruction for variable frequency.

  • Hi Yanming Luo,

    Thank you for your review.

    You mean that you do not recommend using over-modulation and current reconstruction for variable frequency.

    Is this associated with both F280049C and F28069F?

    You know that the is12_variable_pwm_frequency lab in MotorControl_SDK enables the space vector overmodulation and current reconstruction for variable PWM frequency on F280049C.

    Thank you for your guidance.

    With regards,

    JS Yoo

  • Yes, both although the example project uses over-modulation since the performance is not good.