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.

TMDSHVMTRINSPIN: Unable to run motorware Lab01b (Open loop control for hardware integrity

Part Number: TMDSHVMTRINSPIN
Other Parts Discussed in Thread: MOTORWARE, HVPMSMMTR

Greetings,
 
I have been following this document and I was trying to implement Lab 01b on the TMDSHVMTRINSPIN high-voltage motor control kit and the F28069 isolated controlCARD. 

I am not able to reproduce the space vector graphs as depicted in the documentation, or the angle output and phase current waveforms.

I am not able to pick them up on the scope through the DACs ([Main]-J14, DAC-1 to 4). I am also not able to view them through the datalog graphs in CCS.

I have tried following this thread - link - but I am still not seeing anything, both on the scope and the CCS graphs.

Kindly support.

Thanks & Regards 

  • Please take a look at the related documentation for using this kit

    qsg_hw_hvmtr_r1p1.pdf

    C:\ti\motorware\motorware_1_01_00_18\docs\boards\drive\hvkit_rev1p1\docs

    Also, please take a look at guides in the folders below in motorWare, and follow the guides to set up the kits and run the lab.

    C:\ti\motorware\motorware_1_01_00_18\docs\labs\instaspin_labs.pdf

  • I have already done QSG and used the GUI to run the kit and the HVPMSMMTR (Estun EMJ-04APA22). 

    I have changed the jumpers appropriately after doing QSG, so that the kit works in debug mode with CCS. 


    The second document which you have shared is the one I am following. I have followed each step properly. Yet I am unable to see any waveforms.

    I will share some of source code files.

    /*
    // TI File $Revision: /main/3 $
    // Checkin $Date: March 3, 2011   13:45:43 $
    //###########################################################################
    //
    // FILE:    28069_RAM_lnk.cmd
    //
    // TITLE:   Linker Command File For F28069 examples that run out of RAM
    //
    //          This ONLY includes all SARAM blocks on the F28069 device.
    //          This does not include flash or OTP.
    //
    //          Keep in mind that L0,L1,L2,L3 and L4 are protected by the code
    //          security module.
    //
    //          What this means is in most cases you will want to move to
    //          another memory map file which has more memory defined.
    //
    //###########################################################################
    // $TI Release: $ 
    // $Release Date: $ 
    //###########################################################################
    */
    
    /* ======================================================
    // For Code Composer Studio V2.2 and later
    // ---------------------------------------
    // In addition to this memory linker command file,
    // add the header linker command file directly to the project.
    // The header linker command file is required to link the
    // peripheral structures to the proper locations within
    // the memory map.
    //
    // The header linker files are found in <base>\F2806x_headers\cmd
    //
    // For BIOS applications add:      F2806x_Headers_BIOS.cmd
    // For nonBIOS applications add:   F2806x_Headers_nonBIOS.cmd
    ========================================================= */
    
    /* ======================================================
    // For Code Composer Studio prior to V2.2
    // --------------------------------------
    // 1) Use one of the following -l statements to include the
    // header linker command file in the project. The header linker
    // file is required to link the peripheral structures to the proper
    // locations within the memory map                                    */
    
    /* Uncomment this line to include file only for non-BIOS applications */
    /* -l F2806x_Headers_nonBIOS.cmd */
    
    /* Uncomment this line to include file only for BIOS applications */
    /* -l F2806x_Headers_BIOS.cmd */
    
    /* 2) In your project add the path to <base>\F2806x_headers\cmd to the
       library search path under project->build options, linker tab,
       library search path (-i).
    /*========================================================= */
    
    /* Define the memory block start/length for the F2806x
       PAGE 0 will be used to organize program sections
       PAGE 1 will be used to organize data sections
    
       Notes:
             Memory blocks on F28069 are uniform (ie same
             physical memory) in both PAGE 0 and PAGE 1.
             That is the same memory region should not be
             defined for both PAGE 0 and PAGE 1.
             Doing so will result in corruption of program
             and/or data.
    
             Contiguous SARAM memory blocks can be combined
             if required to create a larger memory block.
    */
    
    MEMORY
    {
    PAGE 0 :
       /* BEGIN is used for the "boot to SARAM" bootloader mode   */
    
       BEGIN       : origin = 0x000000, length = 0x000002
       RAMM0       : origin = 0x000050, length = 0x0003B0
       // RAML0_L3    : origin = 0x008000, length = 0x002000	 /* RAML0-3 combined for size of .text */
       														 /* in Example_F2806xSWPrioritezedInterrupts */
       // RAML0_L5    : origin = 0x008000, length = 0x006000  /* L0-L5 combined for .text (24 KB) */
    
       RAML0_L4    : origin = 0x008000, length = 0x004000  /* L0-L4 combined for .text (16 KB) */
    
       RESET       : origin = 0x3FFFC0, length = 0x000002
       /* FPUTABLES   : origin = 0x3FD860, length = 0x0006A0 */	 /* FPU Tables in Boot ROM */
       /* IQTABLES    : origin = 0x3FDF00, length = 0x000B50    */ /* IQ Math Tables in Boot ROM */
       /* IQTABLES2   : origin = 0x3FEA50, length = 0x00008C    */ /* IQ Math Tables in Boot ROM */
       /* IQTABLES3   : origin = 0x3FEADC, length = 0x0000AA	 */ /* IQ Math Tables in Boot ROM */
    
       FPUTABLES   : origin = 0x3FD590, length = 0x0006A0    /* FPU Tables in Boot ROM */
       IQTABLES    : origin = 0x3FDC30, length = 0x000B50    /* IQ Math Tables in Boot ROM */
       IQTABLES2   : origin = 0x3FE780, length = 0x00008C    /* IQ Math Tables in Boot ROM */
       IQTABLES3   : origin = 0x3FE80C, length = 0x0000AA    /* IQ Math Tables in Boot ROM */
    
       BOOTROM    : origin = 0x3FF3B0, length = 0x000C10
    
    
    PAGE 1 :
    
       BOOT_RSVD   : origin = 0x000002, length = 0x00004E     /* Part of M0, BOOT rom will use this for stack */
       RAMM1       : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
       // RAML4       : origin = 0x00A000, length = 0x002000     /* on-chip RAM block L4 */
       /* Note: L4 removed from PAGE 1 because it is used for code in PAGE 0 */
       RAML5       : origin = 0x00C000, length = 0x002000     /* on-chip RAM block L5 */
       RAML6       : origin = 0x00E000, length = 0x002000     /* on-chip RAM block L6 */
       RAML7       : origin = 0x010000, length = 0x002000     /* on-chip RAM block L7 */
       RAML8       : origin = 0x012000, length = 0x002000     /* on-chip RAM block L8 */
       USB_RAM     : origin = 0x040000, length = 0x000800     /* USB RAM		  */
    }
    
    
    SECTIONS
    {
       /* Setup for "boot to SARAM" mode:
          The codestart section (found in DSP28_CodeStartBranch.asm)
          re-directs execution to the start of user code.  */
       codestart        : > BEGIN,      PAGE = 0
       
    #ifdef __TI_COMPILER_VERSION__
       #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc : {} > RAMM0,      PAGE = 0
        ramfuncs         : > RAMM0,      PAGE = 0
       #else
       ramfuncs         : > RAMM0,      PAGE = 0   
       #endif
    #endif 
       
       .text            : > RAML0_L4,   PAGE = 0
       .cinit           : > RAMM0,      PAGE = 0
       .pinit           : > RAMM0,      PAGE = 0
       .switch          : > RAMM0,      PAGE = 0
       .reset           : > RESET,      PAGE = 0, TYPE = DSECT /* not used, */
    
       .stack           : > RAMM1,      PAGE = 1
       .ebss            : > RAML6,      PAGE = 1
       .econst          : > RAML6,      PAGE = 1
       .esysmem         : > RAML6,      PAGE = 1
    
       IQmath           : > RAML0_L4,   PAGE = 0
       IQmathTables     : > IQTABLES,   PAGE = 0, TYPE = NOLOAD
       
       /* Allocate FPU math areas: */
       FPUmathTables    : > FPUTABLES,  PAGE = 0, TYPE = NOLOAD
       
       DMARAML5	        : > RAML5,      PAGE = 1
       DMARAML6	        : > RAML6,      PAGE = 1
       DMARAML7	        : > RAML7,      PAGE = 1
       DMARAML8	        : > RAML8,      PAGE = 1   
    
      /* Uncomment the section below if calling the IQNexp() or IQexp()
          functions from the IQMath.lib library in order to utilize the
          relevant IQ Math table in Boot ROM (This saves space and Boot ROM
          is 1 wait-state). If this section is not uncommented, IQmathTables2
          will be loaded into other memory (SARAM, Flash, etc.) and will take
          up space, but 0 wait-state is possible.
       */
       /*
       IQmathTables2    : > IQTABLES2, PAGE = 0, TYPE = NOLOAD
       {
    
                  IQmath.lib<IQNexpTable.obj> (IQmathTablesRam)
    
       }
       */
       /* Uncomment the section below if calling the IQNasin() or IQasin()
          functions from the IQMath.lib library in order to utilize the
          relevant IQ Math table in Boot ROM (This saves space and Boot ROM
          is 1 wait-state). If this section is not uncommented, IQmathTables2
          will be loaded into other memory (SARAM, Flash, etc.) and will take
          up space, but 0 wait-state is possible.
       */
       /*
       IQmathTables3    : > IQTABLES3, PAGE = 0, TYPE = NOLOAD
       {
    
                  IQmath.lib<IQNasinTable.obj> (IQmathTablesRam)
    
       }
       */
    
       graph_data          : > RAML0_L4,    PAGE = 0
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */

    /* --COPYRIGHT--,BSD
     * 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/src/proj_lab01b.c
    //! \brief  open loop control to check hardware
    //!
    //! (C) Copyright 2011, Texas Instruments, Inc.
    
    //! \defgroup PROJ_LAB01b PROJ_LAB01b
    //@{
    
    //! \defgroup PROJ_LAB01b_OVERVIEW Project Overview
    //!
    //! Open loop control to check hardware integrity
    //!
    
    // **************************************************************************
    // the includes
    
    // system includes
    #include <math.h>
    #include "main.h"
    
    #ifdef FLASH
    #pragma CODE_SECTION(mainISR,"ramfuncs");
    #endif
    
    // Include header files used in the main function
    
    
    // **************************************************************************
    // the defines
    
    #define LED_BLINK_FREQ_Hz   5
    
    
    // **************************************************************************
    // the globals
    
    uint_least16_t gCounter_updateGlobals = 0;
    
    bool Flag_Latch_softwareUpdate = true;
    
    CTRL_Handle ctrlHandle;
    
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(halHandle,"rom_accessed_data");
    #endif
    HAL_Handle halHandle;
    
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(gUserParams,"rom_accessed_data");
    #endif
    USER_Params gUserParams;
    
    HAL_PwmData_t gPwmData = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};
    
    HAL_AdcData_t gAdcData;
    
    _iq gMaxCurrentSlope = _IQ(0.0);
    
    #ifdef FAST_ROM_V1p6
    CTRL_Obj *controller_obj;
    #else
    #ifdef CSM_ENABLE
    #pragma DATA_SECTION(ctrl,"rom_accessed_data");
    #endif
    CTRL_Obj *controller_obj;		//
    CTRL_Obj ctrl;				//v1p7 format
    #endif
    
    uint16_t gLEDcnt = 0;
    
    volatile MOTOR_Vars_t gMotorVars = MOTOR_Vars_INIT;
    
    #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
    
    
    #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
    
    // define CPU time
    CPU_TIME_Handle  cpu_timeHandle;
    CPU_TIME_Obj     cpu_time;
    
    //#ifndef F2802xF
    HAL_DacData_t gDacData;
    //#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;
    
    // define Angle Generate
    ANGLE_GEN_Handle angle_genHandle;
    ANGLE_GEN_Obj    angle_gen;
    
    // define Vs per Freq
    VS_FREQ_Handle vs_freqHandle;
    VS_FREQ_Obj    vs_freq;
    
    // **************************************************************************
    // the functions
    
    void main(void)
    {
      uint_least8_t estNumber = 0;
    
    #ifdef FAST_ROM_V1p6
      uint_least8_t ctrlNumber = 1;
    #endif
    
      // 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 user parameters
      USER_setParams(&gUserParams);
    
    
      // set the hardware abstraction layer parameters
      HAL_setParams(halHandle,&gUserParams);
    
    
      // initialize the controller
    #ifdef FAST_ROM_V1p6
      ctrlHandle = CTRL_initCtrl(ctrlNumber, estNumber);  		//v1p6 format (06xF and 06xM devices)
    #else
      ctrlHandle = CTRL_initCtrl(estNumber,&ctrl,sizeof(ctrl));	//v1p7 format default
    #endif
    
      controller_obj = (CTRL_Obj *)ctrlHandle;
    
      {
        CTRL_Version version;
    
        // get the version number
        CTRL_getVersion(ctrlHandle,&version);
    
        gMotorVars.CtrlVersion = version;
      }
    
    
      // set the default controller parameters
      CTRL_setParams(ctrlHandle,&gUserParams);
    
      // initialize the angle generate module
      angle_genHandle = ANGLE_GEN_init(&angle_gen,sizeof(angle_gen));
      ANGLE_GEN_setParams(angle_genHandle, gUserParams.iqFullScaleFreq_Hz, gUserParams.ctrlPeriod_sec);
    
      // initialize the Vs per Freq module
      vs_freqHandle = VS_FREQ_init(&vs_freq,sizeof(vs_freq));
      VS_FREQ_setParams(vs_freqHandle,  gUserParams.iqFullScaleFreq_Hz, gUserParams.iqFullScaleVoltage_V, gUserParams.maxVsMag_pu);
      VS_FREQ_setProfile(vs_freqHandle, USER_MOTOR_FREQ_LOW, USER_MOTOR_FREQ_HIGH, USER_MOTOR_VOLT_MIN, USER_MOTOR_VOLT_MAX);
    
      // initialize the CPU usage module
      cpu_timeHandle = CPU_TIME_init(&cpu_time,sizeof(cpu_time));
      CPU_TIME_setParams(cpu_timeHandle, PWM_getPeriod(halHandle->pwmHandle[0]));
    
    //#ifndef F2802xF
      // set DAC parameters
    
      gDacData.ptrData[0] = &gPwmData.Tabc.value[0];
      gDacData.ptrData[1] = &gPwmData.Tabc.value[1];
      gDacData.ptrData[2] = &gPwmData.Tabc.value[2];
      gDacData.ptrData[3] = &gAdcData.V.value[0];
    
    //  gDacData.ptrData[0] = &angle_gen.Angle_pu;
    //  gDacData.ptrData[1] = &gAdcData.I.value[0];
    //  gDacData.ptrData[2] = &gPwmData.Tabc.value[0];
    //  gDacData.ptrData[3] = &gAdcData.V.value[0];
    
      HAL_setDacParameters(halHandle, &gDacData);
    //#endif
    
    //#ifndef F2802xF
      // Initialize Datalog
      datalogHandle = DATALOG_init(&datalog,sizeof(datalog));
    
      // Connect inputs of the datalog module
      datalog.iptr[0] = &gPwmData.Tabc.value[0];		// datalogBuff[0]
      datalog.iptr[1] = &gPwmData.Tabc.value[1];		// datalogBuff[1]
      datalog.iptr[2] = &gPwmData.Tabc.value[2];		// datalogBuff[2]
    
    //  datalog.iptr[0] = &angle_gen.Angle_pu;		// datalogBuff[0]
    //  datalog.iptr[1] = &gAdcData.I.value[0];		// datalogBuff[1]
    //  datalog.iptr[2] = &gAdcData.V.value[0];		// datalogBuff[2]
    
      datalog.Flag_EnableLogData = true;
      datalog.Flag_EnableLogOneShot = false;
    //#endif
    
      // 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);
    
    
    #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
    
    
      // enable DC bus compensation
      CTRL_setFlag_enableDcBusComp(ctrlHandle, true);
    
    
      // 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();
    
      for(;;)
      {
        // Waiting for enable system flag to be set
        while(!(gMotorVars.Flag_enableSys));
    
        // Enable the Library internal PI.  Iq is referenced by the speed PI now
        CTRL_setFlag_enableSpeedCtrl(ctrlHandle, true);
    
        // loop while the enable system flag is true
        while(gMotorVars.Flag_enableSys)
          {
            CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle;
    
            // increment counters
            gCounter_updateGlobals++;
    
            // enable/disable the use of motor parameters being loaded from user.h
            CTRL_setFlag_enableUserMotorParams(ctrlHandle,gMotorVars.Flag_enableUserParams);
    
            // enable/disable Rs recalibration during motor startup
            EST_setFlag_enableRsRecalc(obj->estHandle,gMotorVars.Flag_enableRsRecalc);
    
            // enable/disable automatic calculation of bias values
            CTRL_setFlag_enableOffset(ctrlHandle,gMotorVars.Flag_enableOffsetcalc);
    
    
            if(CTRL_isError(ctrlHandle))
              {
                // set the enable controller flag to false
                CTRL_setFlag_enableCtrl(ctrlHandle,false);
    
                // set the enable system flag to false
                gMotorVars.Flag_enableSys = false;
    
                // disable the PWM
                HAL_disablePwm(halHandle);
              }
            else
              {
                // update the controller state
                bool flag_ctrlStateChanged = CTRL_updateState(ctrlHandle);
    
                // enable or disable the control
                CTRL_setFlag_enableCtrl(ctrlHandle, gMotorVars.Flag_Run_Identify);
    
                if(flag_ctrlStateChanged)
                  {
                    CTRL_State_e ctrlState = CTRL_getState(ctrlHandle);
    
                    if(ctrlState == CTRL_State_OffLine)
                      {
                        // enable the PWM
                        HAL_enablePwm(halHandle);
                      }
                    else if(ctrlState == CTRL_State_OnLine)
                      {
                        if(gMotorVars.Flag_enableOffsetcalc == true)
                        {
                          // update the ADC bias values
                          HAL_updateAdcBias(halHandle);
                        }
                        else
                        {
                          // set the current bias
                          HAL_setBias(halHandle,HAL_SensorType_Current,0,_IQ(I_A_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Current,1,_IQ(I_B_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Current,2,_IQ(I_C_offset));
    
                          // set the voltage bias
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,0,_IQ(V_A_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,1,_IQ(V_B_offset));
                          HAL_setBias(halHandle,HAL_SensorType_Voltage,2,_IQ(V_C_offset));
                        }
    
                        // Return the bias value for currents
                        gMotorVars.I_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Current,0);
                        gMotorVars.I_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Current,1);
                        gMotorVars.I_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Current,2);
    
                        // Return the bias value for voltages
                        gMotorVars.V_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Voltage,0);
                        gMotorVars.V_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Voltage,1);
                        gMotorVars.V_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Voltage,2);
    
                        // set flag to disable speed controller
                       CTRL_setFlag_enableSpeedCtrl(ctrlHandle, false);
    
                       // set flag to disable current controller
                       CTRL_setFlag_enableCurrentCtrl(ctrlHandle, false);
    
                        // enable the PWM
                        HAL_enablePwm(halHandle);
                      }
                    else if(ctrlState == CTRL_State_Idle)
                      {
                        // disable the PWM
                        HAL_disablePwm(halHandle);
                        gMotorVars.Flag_Run_Identify = false;
                      }
    
                    if((CTRL_getFlag_enableUserMotorParams(ctrlHandle) == true) &&
                      (ctrlState > CTRL_State_Idle) &&
                      (gMotorVars.CtrlVersion.minor == 6))
                      {
                        // call this function to fix 1p6
                        USER_softwareUpdate1p6(ctrlHandle);
                      }
    
                  }
              }
    
    
            if(EST_isMotorIdentified(obj->estHandle))
              {
                // set the current ramp
                EST_setMaxCurrentSlope_pu(obj->estHandle,gMaxCurrentSlope);
                gMotorVars.Flag_MotorIdentified = true;
    
                // set the speed reference
                CTRL_setSpd_ref_krpm(ctrlHandle,gMotorVars.SpeedRef_krpm);
    
                // set the speed acceleration
                CTRL_setMaxAccel_pu(ctrlHandle,_IQmpy(MAX_ACCEL_KRPMPS_SF,gMotorVars.MaxAccel_krpmps));
                if(Flag_Latch_softwareUpdate)
                {
                  Flag_Latch_softwareUpdate = false;
    
                  USER_calcPIgains(ctrlHandle);
    
                  // initialize the watch window kp and ki current values with pre-calculated values
                  gMotorVars.Kp_Idq = CTRL_getKp(ctrlHandle,CTRL_Type_PID_Id);
                  gMotorVars.Ki_Idq = CTRL_getKi(ctrlHandle,CTRL_Type_PID_Id);
    
                  // initialize the watch window kp and ki values with pre-calculated values
                  gMotorVars.Kp_spd = CTRL_getKp(ctrlHandle,CTRL_Type_PID_spd);
                  gMotorVars.Ki_spd = CTRL_getKi(ctrlHandle,CTRL_Type_PID_spd);
                }
    
              }
            else
              {
                Flag_Latch_softwareUpdate = true;
    
                // the estimator sets the maximum current slope during identification
                gMaxCurrentSlope = EST_getMaxCurrentSlope_pu(obj->estHandle);
              }
    
    
            // when appropriate, update the global variables
            if(gCounter_updateGlobals >= NUM_MAIN_TICKS_FOR_GLOBAL_VARIABLE_UPDATE)
              {
                // reset the counter
                gCounter_updateGlobals = 0;
    
                updateGlobalVariables_motor(ctrlHandle);
              }
    
    
            // update Kp and Ki gains
            updateKpKiGains(ctrlHandle);
    
            // enable/disable the forced angle
            EST_setFlag_enableForceAngle(obj->estHandle,gMotorVars.Flag_enableForceAngle);
    
            // enable or disable power warp
            CTRL_setFlag_enablePowerWarp(ctrlHandle,gMotorVars.Flag_enablePowerWarp);
    
    #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);
    
        // set the default controller parameters (Reset the control to re-identify the motor)
        CTRL_setParams(ctrlHandle,&gUserParams);
        gMotorVars.Flag_Run_Identify = false;
    
      } // end of for(;;) loop
    
    } // end of main() function
    
    
    interrupt void mainISR(void)
    {
      // toggle status LED
      if(++gLEDcnt >= (uint_least32_t)(USER_ISR_FREQ_Hz / LED_BLINK_FREQ_Hz))
      {
        HAL_toggleLed(halHandle,(GPIO_Number_e)HAL_Gpio_LED2);
        gLEDcnt = 0;
      }
    
      // acknowledge the ADC interrupt
      HAL_acqAdcInt(halHandle,ADC_IntNumber_1);
    
      // convert the ADC data
      HAL_readAdcData(halHandle,&gAdcData);
    
      // run the controller
      uint_least16_t count_isr = CTRL_getCount_isr(ctrlHandle);
      uint_least16_t numIsrTicksPerCtrlTick = CTRL_getNumIsrTicksPerCtrlTick(ctrlHandle);
    
      // if needed, run the controller
      if(count_isr >= numIsrTicksPerCtrlTick)
        {
          CTRL_State_e ctrlState = CTRL_getState(ctrlHandle);
    
          // reset the isr count
          CTRL_resetCounter_isr(ctrlHandle);
    
          // increment the state counter
          CTRL_incrCounter_state(ctrlHandle);
    
          // increment the trajectory count
          CTRL_incrCounter_traj(ctrlHandle);
    
          // run the appropriate controller
          if(ctrlState == CTRL_State_OnLine)
            {
              // increment the current count
              CTRL_incrCounter_current(ctrlHandle);
    
              // increment the speed count
              CTRL_incrCounter_speed(ctrlHandle);
    
              MATH_vec2 phasor;
    
             // run Clarke transform on current
             CLARKE_run(controller_obj->clarkeHandle_I,&gAdcData.I,CTRL_getIab_in_addr(ctrlHandle));
    
             // run Clarke transform on voltage
             CLARKE_run(controller_obj->clarkeHandle_V,&gAdcData.V,CTRL_getVab_in_addr(ctrlHandle));
    
             controller_obj->speed_ref_pu = TRAJ_getIntValue(controller_obj->trajHandle_spd);
    
             //
             ANGLE_GEN_run(angle_genHandle, controller_obj->speed_ref_pu);
             VS_FREQ_run(vs_freqHandle, controller_obj->speed_ref_pu);
    
             // generate the motor electrical angle
           	 controller_obj->angle_pu = ANGLE_GEN_getAngle_pu(angle_genHandle);
    
    	 	 controller_obj->Vdq_out.value[0] = vs_freq.Vdq_out.value[0];
    	 	 controller_obj->Vdq_out.value[1] = vs_freq.Vdq_out.value[1];
    
             // compute the sin/cos phasor
             CTRL_computePhasor(controller_obj->angle_pu,&phasor);
    
             // set the phasor in the Park transform
             PARK_setPhasor(controller_obj->parkHandle,&phasor);
    
             // run the Park transform
             PARK_run(controller_obj->parkHandle,CTRL_getIab_in_addr(ctrlHandle),CTRL_getIdq_in_addr(ctrlHandle));
    
    
             // set the phasor in the inverse Park transform
             IPARK_setPhasor(controller_obj->iparkHandle,&phasor);
    
             // run the inverse Park module
             IPARK_run(controller_obj->iparkHandle,CTRL_getVdq_out_addr(ctrlHandle),CTRL_getVab_out_addr(ctrlHandle));
    
             // run the space Vector Generator (SVGEN) module
             SVGEN_run(controller_obj->svgenHandle,CTRL_getVab_out_addr(ctrlHandle),&(gPwmData.Tabc));
            }
          else if(ctrlState == CTRL_State_OffLine)
            {
              // run the offline controller
              CTRL_runOffLine(ctrlHandle,halHandle,&gAdcData,&gPwmData);
            }
          else if(ctrlState == CTRL_State_Idle)
            {
              // set all pwm outputs to zero
        	  gPwmData.Tabc.value[0] = _IQ(0.0);
        	  gPwmData.Tabc.value[1] = _IQ(0.0);
        	  gPwmData.Tabc.value[2] = _IQ(0.0);
            }
        }
      else
        {
          // increment the isr count
          CTRL_incrCounter_isr(ctrlHandle);
        }
    
    
      // write the PWM compare values
      HAL_writePwmData(halHandle,&gPwmData);
    
    
      // setup the controller
      CTRL_setup(ctrlHandle);
    
    //#ifndef F2802xF
      DATALOG_update(datalogHandle);
    //#endif
    
    //#ifndef F2802xF
      // connect inputs of the PWMDAC module.
      gDacData.value[0] = (*gDacData.ptrData[0]); 	//
      gDacData.value[1] = (*gDacData.ptrData[1]); 	//
      gDacData.value[2] = (*gDacData.ptrData[2]); 	//
      gDacData.value[3] = (*gDacData.ptrData[3]); 	//
    
      HAL_writeDacData(halHandle,&gDacData);
    //#endif
    
      return;
    } // end of mainISR() function
    
    
    void updateGlobalVariables_motor(CTRL_Handle handle)
    {
      CTRL_Obj *obj = (CTRL_Obj *)handle;
    
      // get the speed estimate
      gMotorVars.Speed_krpm = EST_getSpeed_krpm(obj->estHandle);
    
      // get the real time speed reference coming out of the speed trajectory generator
      gMotorVars.SpeedTraj_krpm = _IQmpy(CTRL_getSpd_int_ref_pu(handle),EST_get_pu_to_krpm_sf(obj->estHandle));
    
      // get the torque estimate
      gMotorVars.Torque_Nm = USER_computeTorque_Nm(handle, gTorque_Flux_Iq_pu_to_Nm_sf, gTorque_Ls_Id_Iq_pu_to_Nm_sf);
    
      // get the magnetizing current
      gMotorVars.MagnCurr_A = EST_getIdRated(obj->estHandle);
    
      // get the rotor resistance
      gMotorVars.Rr_Ohm = EST_getRr_Ohm(obj->estHandle);
    
      // get the stator resistance
      gMotorVars.Rs_Ohm = EST_getRs_Ohm(obj->estHandle);
    
      // get the stator inductance in the direct coordinate direction
      gMotorVars.Lsd_H = EST_getLs_d_H(obj->estHandle);
    
      // get the stator inductance in the quadrature coordinate direction
      gMotorVars.Lsq_H = EST_getLs_q_H(obj->estHandle);
    
      // get the flux in V/Hz in floating point
      gMotorVars.Flux_VpHz = EST_getFlux_VpHz(obj->estHandle);
    
      // get the flux in Wb in fixed point
      gMotorVars.Flux_Wb = USER_computeFlux(handle, gFlux_pu_to_Wb_sf);
    
      // get the controller state
      gMotorVars.CtrlState = CTRL_getState(handle);
    
      // get the estimator state
      gMotorVars.EstState = EST_getState(obj->estHandle);
    
      // Get the DC buss voltage
      gMotorVars.VdcBus_kV = _IQmpy(gAdcData.dcBus,_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0));
    
      return;
    } // end of updateGlobalVariables_motor() function
    
    
    void updateKpKiGains(CTRL_Handle handle)
    {
      if((gMotorVars.CtrlState == CTRL_State_OnLine) && (gMotorVars.Flag_MotorIdentified == true) && (Flag_Latch_softwareUpdate == false))
        {
          // set the kp and ki speed values from the watch window
          CTRL_setKp(handle,CTRL_Type_PID_spd,gMotorVars.Kp_spd);
          CTRL_setKi(handle,CTRL_Type_PID_spd,gMotorVars.Ki_spd);
    
          // set the kp and ki current values for Id and Iq from the watch window
          CTRL_setKp(handle,CTRL_Type_PID_Id,gMotorVars.Kp_Idq);
          CTRL_setKi(handle,CTRL_Type_PID_Id,gMotorVars.Ki_Idq);
          CTRL_setKp(handle,CTRL_Type_PID_Iq,gMotorVars.Kp_Idq);
          CTRL_setKi(handle,CTRL_Type_PID_Iq,gMotorVars.Ki_Idq);
    	}
    
      return;
    } // end of updateKpKiGains() function
    
    
    //@} //defgroup
    // end of file
    
    
    
    

    #ifndef _HAL_H_
    #define _HAL_H_
    /* --COPYRIGHT--,BSD
     * 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.h
    //! \brief  Contains public interface to various functions related
    //!         to the HAL object
    //!
    //! (C) Copyright 2011, Texas Instruments, Inc.
    
    
    // **************************************************************************
    // the includes
    
    
    // modules
    
    
    // platforms
    #include "hal_obj.h"
    #include "sw/modules/svgen/src/32b/svgen_current.h"
    
    
    //!
    //!
    //! \defgroup HAL HAL
    //!
    //@{
    
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    // **************************************************************************
    // the defines
    
    #define Device_cal (void   (*)(void))0x3D7C80
    
    //! \brief Defines used in oscillator calibration functions
    //! \brief Defines the scale factor for Q15 fixed point numbers (2^15)
    #define FP_SCALE 32768
    
    //! \brief Defines the quantity added to Q15 numbers before converting to integer to round the number
    #define FP_ROUND FP_SCALE/2
    
    //! \brief Defines the amount to add to Q16.15 fixed point number to shift from a fine trim range of
    //! \brief (-31 to 31) to (1 to 63).  This guarantees that the trim is positive and can
    //! \brief therefore be efficiently rounded
    #define OSC_POSTRIM 32
    #define OSC_POSTRIM_OFF FP_SCALE*OSC_POSTRIM
    
    //! \brief The following functions return reference values stored in OTP.
    
    //! \brief Defines the slope used to compensate oscillator 1 (fine trim steps / ADC code). Stored in fixed point Q15 format
    #define getOsc1FineTrimSlope() (*(int16_t (*)(void))0x3D7E90)()
    
    //! \brief Defines the oscillator 1 fine trim at high temp
    #define getOsc1FineTrimOffset() (*(int16_t (*)(void))0x3D7E93)()
    
    //! \brief Defines the oscillator 1 coarse trim
    #define getOsc1CoarseTrim() (*(int16_t (*)(void))0x3D7E96)()
    
    //! \brief Defines the slope used to compensate oscillator 2 (fine trim steps / ADC code). Stored
    //! \brief in fixed point Q15 format.
    #define getOsc2FineTrimSlope() (*(int16_t (*)(void))0x3D7E99)()
    
    //! \brief Defines the oscillator 2 fine trim at high temp
    #define getOsc2FineTrimOffset() (*(int16_t (*)(void))0x3D7E9C)()
    
    //! \brief Defines the oscillator 2 coarse trim
    #define getOsc2CoarseTrim() (*(int16_t (*)(void))0x3D7E9F)()
    
    //! \brief Defines the ADC reading of temperature sensor at reference temperature for compensation
    #define getRefTempOffset() (*(int16_t (*)(void))0x3D7EA2)()
    
    //! \brief Defines the PWM deadband falling edge delay count (system clocks)
    //!
    #define HAL_PWM_DBFED_CNT         (uint16_t)(2.0 * (float_t)USER_SYSTEM_FREQ_MHz)            // 2 usec
    
    
    //! \brief Defines the PWM deadband rising edge delay count (system clocks)
    //!
    #define HAL_PWM_DBRED_CNT        (uint16_t)(2.0 * (float_t)USER_SYSTEM_FREQ_MHz)            // 2 usec
    
    
    //! \brief Defines the function to turn LEDs off
    //!
    #define HAL_turnLedOff            HAL_setGpioHigh
    
    
    //! \brief Defines the function to turn LEDs on
    //!
    #define HAL_turnLedOn             HAL_setGpioLow
    
    //! \brief Defines the function to turn LEDs on
    //!
    #define HAL_toggleLed             HAL_toggleGpio
    
    // **************************************************************************
    // the typedefs
    
    
    //! \brief Enumeration for the QEP setup
    //!
    typedef enum
    {
      HAL_Qep_QEP1=0,  //!< Select QEP1
      HAL_Qep_QEP2=1   //!< Select QEP2
    } HAL_QepSelect_e;
    
    
    //! \brief Enumeration for the LED numbers
    //!
    typedef enum
    {
      HAL_Gpio_LED2=GPIO_Number_31,  //!< GPIO pin number for ControlCARD LED 2
      HAL_Gpio_LED3=GPIO_Number_34   //!< GPIO pin number for ControlCARD LED 3
    } HAL_LedNumber_e;
      
    // select whether to use the hall input on connector QEP or CAP of the EVM
    #define JH_QEP
    //#define JH_CAP
    
    #ifdef JH_QEP
    //! \brief Enumeration for the Hall GPIO numbers
    //!
    typedef enum
    {
      HAL_HallGpio_A=GPIO_Number_20,  //!< GPIO pin number for Hall Sensor A
      HAL_HallGpio_B=GPIO_Number_21,  //!< GPIO pin number for Hall Sensor B
      HAL_HallGpio_C=GPIO_Number_23   //!< GPIO pin number for Hall Sensor C
    } HAL_HallGpio_e;
    
    #else
    //! \brief Enumeration for the Hall GPIO numbers
    //!
    typedef enum
    {
      HAL_HallGpio_A=GPIO_Number_24,  //!< GPIO pin number for Hall Sensor A
      HAL_HallGpio_B=GPIO_Number_13,  //!< GPIO pin number for Hall Sensor B
      HAL_HallGpio_C=GPIO_Number_14   //!< GPIO pin number for Hall Sensor C
    } HAL_HallGpio_e;
    #endif
    
    //! \brief Enumeration for the sensor types
    //!
    typedef enum
    {
      HAL_SensorType_Current=0,      //!< Enumeration for current sensor
      HAL_SensorType_Voltage         //!< Enumeration for voltage sensor
    } HAL_SensorType_e;
    
    
    // **************************************************************************
    // the globals
    
    extern interrupt void mainISR(void);
    
    
    // **************************************************************************
    // the function prototypes
    
    
    //! \brief     Acknowledges an interrupt from the ADC so that another ADC interrupt can 
    //!            happen again.
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    //! \param[in] intNumber  The interrupt number
    static inline void HAL_acqAdcInt(HAL_Handle handle,const ADC_IntNumber_e intNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // clear the ADC interrupt flag
      ADC_clearIntFlag(obj->adcHandle,intNumber);
    
    
      // Acknowledge interrupt from PIE group 10 
      PIE_clearInt(obj->pieHandle,PIE_GroupNumber_10);
    
      return;
    } // end of HAL_acqAdcInt() function
    
    
    //! \brief     Acknowledges an interrupt from the PWM so that another PWM interrupt can
    //!            happen again.
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    //! \param[in] pwmNumber  The PWM number
    static inline void HAL_acqPwmInt(HAL_Handle handle,const PWM_Number_e pwmNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // clear the PWM interrupt flag
      PWM_clearIntFlag(obj->pwmHandle[pwmNumber]);
    
    
      // clear the SOCA flag
      PWM_clearSocAFlag(obj->pwmHandle[pwmNumber]);
    
    
      // Acknowledge interrupt from PIE group 3
      PIE_clearInt(obj->pieHandle,PIE_GroupNumber_3);
    
      return;
    } // end of HAL_acqPwmInt() function
    
    
    //! \brief      Executes calibration routines
    //! \details    Values for offset and gain are programmed into OTP memory at
    //!             the TI factory.  This calls and internal function that programs
    //!             these offsets and gains into the ADC registers.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_cal(HAL_Handle handle);
    
    
    //! \brief      Disables global interrupts
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_disableGlobalInts(HAL_Handle handle);
    
    
    //! \brief      Disables the watch dog
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_disableWdog(HAL_Handle handle);
    
    
    //! \brief      Disables the PWM device
    //! \details    Turns off the outputs of the EPWM peripherals which will put
    //!             the power switches into a high impedance state.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_disablePwm(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_1]);
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_2]);
      PWM_setOneShotTrip(obj->pwmHandle[PWM_Number_3]);
    
      return;
    } // end of HAL_disablePwm() function
    
    
    //! \brief      Enables the ADC interrupts
    //! \details    Enables the ADC interrupt in the PIE, and CPU.  Enables the 
    //!             interrupt to be sent from the ADC peripheral.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_enableAdcInts(HAL_Handle handle);
    
    
    //! \brief      Enables the debug interrupt
    //! \details    The debug interrupt is used for the real-time debugger.  It is
    //!             not needed if the real-time debugger is not used.  Clears
    //!             bit 1 of ST1.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_enableDebugInt(HAL_Handle handle);
    
    
    //! \brief     Enables global interrupts
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_enableGlobalInts(HAL_Handle handle);
    
    
    //! \brief      Enables the PWM devices
    //! \details    Turns on the outputs of the EPWM peripheral which will allow 
    //!             the power switches to be controlled.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_enablePwm(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_1]);
      PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_2]);
      PWM_clearOneShotTrip(obj->pwmHandle[PWM_Number_3]);
    
      return;
    } // end of HAL_enablePwm() function
    
    
    //! \brief     Enables the PWM interrupt
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_enablePwmInt(HAL_Handle handle);
    
    
    //! \brief     Gets the ADC delay value
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    //! \param[in] socNumber  The ADC SOC number
    //! \return    The ADC delay value
    static inline ADC_SocSampleDelay_e HAL_getAdcSocSampleDelay(HAL_Handle handle,
                                                                const ADC_SocNumber_e socNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      return(ADC_getSocSampleDelay(obj->adcHandle,socNumber));
    } // end of HAL_getAdcSocSampleDelay() function
    
    
    //! \brief      Gets the ADC bias value
    //! \details    The ADC bias contains the feedback circuit's offset and bias.
    //!             Bias is the mathematical offset used when a bi-polar signal
    //!             is read into a uni-polar ADC.
    //! \param[in]  handle        The hardware abstraction layer (HAL) handle
    //! \param[in]  sensorType    The sensor type
    //! \param[in]  sensorNumber  The sensor number
    //! \return     The ADC bias value
    static inline _iq HAL_getBias(HAL_Handle handle,
                                  const HAL_SensorType_e sensorType,
                                  uint_least8_t sensorNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      _iq bias = _IQ(0.0);
    
      if(sensorType == HAL_SensorType_Current)
        {
          bias = obj->adcBias.I.value[sensorNumber];
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          bias = obj->adcBias.V.value[sensorNumber];
        }
    
      return(bias);
    } // end of HAL_getBias() function
    
    
    //! \brief      Gets the current scale factor
    //! \details    The current scale factor is defined as
    //!             USER_ADC_FULL_SCALE_CURRENT_A/USER_IQ_FULL_SCALE_CURRENT_A.
    //!             This scale factor is not used when converting between PU amps
    //!             and real amps.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    //! \return     The current scale factor
    static inline _iq HAL_getCurrentScaleFactor(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      return(obj->current_sf);
    } // end of HAL_getCurrentScaleFactor() function
    
    
    //! \brief     Gets the number of current sensors
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    //! \return    The number of current sensors
    static inline uint_least8_t HAL_getNumCurrentSensors(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      return(obj->numCurrentSensors);
    } // end of HAL_getNumCurrentSensors() function
    
    
    //! \brief     Gets the number of voltage sensors
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    //! \return    The number of voltage sensors
    static inline uint_least8_t HAL_getNumVoltageSensors(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      return(obj->numVoltageSensors);
    } // end of HAL_getNumVoltageSensors() function
    
    
    //! \brief      Gets the value used to set the low pass filter pole for offset estimation
    //! \details    An IIR single pole low pass filter is used to find the feedback circuit's
    //!             offsets.  This function returns the value of that pole.
    //! \param[in]  handle        The hardware abstraction layer (HAL) handle
    //! \param[in]  sensorType    The sensor type
    //! \param[in]  sensorNumber  The sensor number
    //! \return     The value used to set the low pass filter pole, pu
    static inline _iq HAL_getOffsetBeta_lp_pu(HAL_Handle handle,
                                              const HAL_SensorType_e sensorType,
                                              const uint_least8_t sensorNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      _iq beta_lp_pu = _IQ(0.0);
      
      if(sensorType == HAL_SensorType_Current)
        {
          beta_lp_pu = OFFSET_getBeta(obj->offsetHandle_I[sensorNumber]);
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          beta_lp_pu = OFFSET_getBeta(obj->offsetHandle_V[sensorNumber]);
        }
    
      return(beta_lp_pu);
    } // end of HAL_getOffsetBeta_lp_pu() function
    
    
    //! \brief      Gets the offset value
    //! \details    The offsets that are calculated during the feedback circuits calibrations
    //!             are returned from the IIR filter object.
    //! \param[in]  handle        The hardware abstraction layer (HAL) handle
    //! \param[in]  sensorType    The sensor type
    //! \param[in]  sensorNumber  The sensor number
    //! \return     The offset value
    static inline _iq HAL_getOffsetValue(HAL_Handle handle,
                                         const HAL_SensorType_e sensorType,
                                         const uint_least8_t sensorNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      _iq offset = _IQ(0.0);
      
      if(sensorType == HAL_SensorType_Current)
        {
          offset = OFFSET_getOffset(obj->offsetHandle_I[sensorNumber]);
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          offset = OFFSET_getOffset(obj->offsetHandle_V[sensorNumber]);
        }
    
      return(offset);
    } // end of HAL_getOffsetValue() function
    
    
    //! \brief      Gets the voltage scale factor
    //! \details    The voltage scale factor is defined as
    //!             USER_ADC_FULL_SCALE_VOLTAGE_V/USER_IQ_FULL_SCALE_VOLTAGE_V.
    //!             This scale factor is not used when converting between PU volts
    //!             and real volts.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    //! \return     The voltage scale factor
    static inline _iq HAL_getVoltageScaleFactor(HAL_Handle handle)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      return(obj->voltage_sf);
    } // end of HAL_getVoltageScaleFactor() function
    
    
    //! \brief      Configures the fault protection logic
    //! \details    Sets up the trip zone inputs so that when a comparator
    //!             signal from outside the micro-controller trips a fault,
    //!             the EPWM peripheral blocks will force the
    //!             power switches into a high impedance state.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupFaults(HAL_Handle handle);
    
    
    //! \brief      Initializes the hardware abstraction layer (HAL) object
    //! \details    Initializes all handles to the microcontroller peripherals.
    //!             Returns a handle to the HAL object.
    //! \param[in]  pMemory   A pointer to the memory for the hardware abstraction layer object
    //! \param[in]  numBytes  The number of bytes allocated for the hardware abstraction layer object, bytes
    //! \return     The hardware abstraction layer (HAL) object handle
    extern HAL_Handle HAL_init(void *pMemory,const size_t numBytes);
    
    
    //! \brief      Initializes the interrupt vector table
    //! \details    Points the ISR to the function mainISR.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_initIntVectorTable(HAL_Handle handle)
     {
      HAL_Obj *obj = (HAL_Obj *)handle;
      PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;
    
    
      ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    
      pie->ADCINT1 = &mainISR;
    
      DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
      return;
     } // end of HAL_initIntVectorTable() function
    
    
    //! \brief      Reads the ADC data
    //! \details    Reads in the ADC result registers, adjusts for offsets, and
    //!             scales the values according to the settings in user.h.  The
    //!             structure gAdcData holds three phase voltages, three line
    //!             currents, and one DC bus voltage.
    //! \param[in]  handle    The hardware abstraction layer (HAL) handle
    //! \param[in]  pAdcData  A pointer to the ADC data buffer
    static inline void HAL_readAdcData(HAL_Handle handle,HAL_AdcData_t *pAdcData)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      _iq value;
      _iq current_sf = HAL_getCurrentScaleFactor(handle);
      _iq voltage_sf = HAL_getVoltageScaleFactor(handle);
    
    
      // convert current A
      // sample the first sample twice due to errata sprz342f, ignore the first sample
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_1);
      value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[0];      // divide by 2^numAdcBits = 2^12
      pAdcData->I.value[0] = value;
    
      // convert current B
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_2);
      value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[1];      // divide by 2^numAdcBits = 2^12
      pAdcData->I.value[1] = value;
    
      // convert current C
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_3);
      value = _IQ12mpy(value,current_sf) - obj->adcBias.I.value[2];      // divide by 2^numAdcBits = 2^12
      pAdcData->I.value[2] = value;
    
      // convert voltage A
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_4);
      value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[0];      // divide by 2^numAdcBits = 2^12
      pAdcData->V.value[0] = value;
    
      // convert voltage B
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_5);
      value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[1];      // divide by 2^numAdcBits = 2^12
      pAdcData->V.value[1] = value;
    
      // convert voltage C
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_6);
      value = _IQ12mpy(value,voltage_sf) - obj->adcBias.V.value[2];      // divide by 2^numAdcBits = 2^12
      pAdcData->V.value[2] = value;
    
      // read the dcBus voltage value
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_7);     // divide by 2^numAdcBits = 2^12
      value = _IQ12mpy(value,voltage_sf);
      pAdcData->dcBus = value;
    
      return;
    } // end of HAL_readAdcData() function
    
    
    //! \brief      Reads the ADC data
    //! \details    Reads in the ADC result registers, and
    //!             scales the values according to the settings in user.h.  The
    //!             structure gAdcData holds three phase voltages, three line
    //!             currents, and one DC bus voltage.
    //! \param[in]  handle    The hardware abstraction layer (HAL) handle
    //! \param[in]  pAdcData  A pointer to the ADC data buffer
    static inline void HAL_readAdcDataWithOffsets(HAL_Handle handle,HAL_AdcData_t *pAdcData)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      _iq value;
      _iq current_sf = HAL_getCurrentScaleFactor(handle);
      _iq voltage_sf = HAL_getVoltageScaleFactor(handle);
    
    
      // convert current A
      // sample the first sample twice due to errata sprz342f, ignore the first sample
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_1);
      value = _IQ12mpy(value,current_sf);
      pAdcData->I.value[0] = value;
    
      // convert current B
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_2);
      value = _IQ12mpy(value,current_sf);
      pAdcData->I.value[1] = value;
    
      // convert current C
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_3);
      value = _IQ12mpy(value,current_sf);
      pAdcData->I.value[2] = value;
    
      // convert voltage A
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_4);
      value = _IQ12mpy(value,voltage_sf);
      pAdcData->V.value[0] = value;
    
      // convert voltage B
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_5);
      value = _IQ12mpy(value,voltage_sf);
      pAdcData->V.value[1] = value;
    
      // convert voltage C
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_6);
      value = _IQ12mpy(value,voltage_sf);
      pAdcData->V.value[2] = value;
    
      // read the dcBus voltage value
      value = (_iq)ADC_readResult(obj->adcHandle,ADC_ResultNumber_7);
      value = _IQ12mpy(value,voltage_sf);
      pAdcData->dcBus = value;
    
      return;
    } // end of HAL_readAdcDataWithOffsets() function
    
    
    //! \brief     Reads the timer count
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    //! \return    The timer count
    static inline uint32_t HAL_readTimerCnt(HAL_Handle handle,const uint_least8_t timerNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      uint32_t timerCnt = TIMER_getCount(obj->timerHandle[timerNumber]);
    
      return(timerCnt);
    } // end of HAL_readTimerCnt() function
    
    
    //! \brief     Reloads the timer
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    static inline void HAL_reloadTimer(HAL_Handle handle,const uint_least8_t timerNumber)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      // reload the specified timer
      TIMER_reload(obj->timerHandle[timerNumber]);
    
      return;
    }  // end of HAL_reloadTimer() function
    
    
    //! \brief     Starts the timer
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    static inline void HAL_startTimer(HAL_Handle handle,const uint_least8_t timerNumber)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      // start the specified timer
      TIMER_start(obj->timerHandle[timerNumber]);
    
      return;
    }  // end of HAL_startTimer() function
    
    
    //! \brief     Stops the timer
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    static inline void HAL_stopTimer(HAL_Handle handle,const uint_least8_t timerNumber)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      // stop the specified timer
      TIMER_stop(obj->timerHandle[timerNumber]);
    
      return;
    }  // end of HAL_stopTimer() function
    
    
    //! \brief     Sets the timer period
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    //! \param[in] period       The timer period
    static inline void HAL_setTimerPeriod(HAL_Handle handle,const uint_least8_t timerNumber, const uint32_t period)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      // set the period
      TIMER_setPeriod(obj->timerHandle[timerNumber], period);
    
      return;
    }  // end of HAL_setTimerPeriod() function
    
    
    //! \brief     Gets the timer period
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] timerNumber  The timer number, 0,1 or 2
    //! \return    The timer period
    static inline uint32_t HAL_getTimerPeriod(HAL_Handle handle,const uint_least8_t timerNumber)
    {
      HAL_Obj  *obj = (HAL_Obj *)handle;
    
      uint32_t timerPeriod = TIMER_getPeriod(obj->timerHandle[timerNumber]);
    
      return(timerPeriod);
    }  // end of HAL_getTimerPeriod() function
    
    
    //! \brief     Sets the ADC SOC sample delay value
    //! \param[in] handle       The hardware abstraction layer (HAL) handle
    //! \param[in] socNumber    The SOC number
    //! \param[in] sampleDelay  The delay value for the ADC
    static inline void HAL_setAdcSocSampleDelay(HAL_Handle handle,
                                                const ADC_SocNumber_e socNumber,
                                                const ADC_SocSampleDelay_e sampleDelay)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      ADC_setSocSampleDelay(obj->adcHandle,socNumber,sampleDelay);
    
      return;
    } // end of HAL_setAdcSocSampleDelay() function
    
    
    //! \brief     Sets the ADC bias value
    //! \param[in] handle        The hardware abstraction layer (HAL) handle
    //! \param[in] sensorType    The sensor type
    //! \param[in] sensorNumber  The sensor number
    //! \param[in] bias          The ADC bias value
    static inline void HAL_setBias(HAL_Handle handle,
                                   const HAL_SensorType_e sensorType,
                                   uint_least8_t sensorNumber,
                                   const _iq bias)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      if(sensorType == HAL_SensorType_Current)
        {
          obj->adcBias.I.value[sensorNumber] = bias;
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          obj->adcBias.V.value[sensorNumber] = bias;
        }
    
      return;
    } // end of HAL_setBias() function
    
    
    //! \brief      Sets the GPIO pin high
    //! \details    Takes in the enumeration GPIO_Number_e and sets that GPIO
    //!             pin high.
    //! \param[in]  handle      The hardware abstraction layer (HAL) handle
    //! \param[in]  gpioNumber  The GPIO number
    static inline void HAL_setGpioHigh(HAL_Handle handle,const GPIO_Number_e gpioNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      // set GPIO high
      GPIO_setHigh(obj->gpioHandle,gpioNumber);
    
      return;
    } // end of HAL_setGpioHigh() function
    
    //! \brief      Reads the specified GPIO pin
    //! \details    Takes in the enumeration GPIO_Number_e and reads that GPIO
    //! \param[in]  handle      The hardware abstraction layer (HAL) handle
    //! \param[in]  gpioNumber  The GPIO number
    static inline bool HAL_readGpio(HAL_Handle handle,const GPIO_Number_e gpioNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // read GPIO
      return(GPIO_read(obj->gpioHandle,gpioNumber));
    } // end of HAL_readGpio() function
    
    //! \brief      Toggles the GPIO pin
    //! \details    Takes in the enumeration GPIO_Number_e and toggles that GPIO
    //!             pin.
    //! \param[in]  handle      The hardware abstraction layer (HAL) handle
    //! \param[in]  gpioNumber  The GPIO number
    static inline void HAL_toggleGpio(HAL_Handle handle,const GPIO_Number_e gpioNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
    
      // set GPIO high
      GPIO_toggle(obj->gpioHandle,gpioNumber);
    
      return;
    } // end of HAL_setGpioHigh() function
    
    
    //! \brief      Sets the GPIO pin low
    //! \details    Takes in the enumeration GPIO_Number_e and clears that GPIO
    //!             pin low.
    //! \param[in]  handle      The hardware abstraction layer (HAL) handle
    //! \param[in]  gpioNumber  The GPIO number
    static inline void HAL_setGpioLow(HAL_Handle handle,const GPIO_Number_e gpioNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      // set GPIO low
      GPIO_setLow(obj->gpioHandle,gpioNumber);
    
      return;
    } // end of HAL_setGpioLow() function
    
    
    //! \brief     Sets the current scale factor in the hardware abstraction layer
    //! \param[in] handle      The hardware abstraction layer (HAL) handle
    //! \param[in] current_sf  The current scale factor
    static inline void HAL_setCurrentScaleFactor(HAL_Handle handle,const _iq current_sf)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      obj->current_sf = current_sf;
    
      return;
    } // end of HAL_setCurrentScaleFactor() function
    
    
    //! \brief     Sets the number of current sensors
    //! \param[in] handle             The hardware abstraction layer (HAL) handle
    //! \param[in] numCurrentSensors  The number of current sensors
    static inline void HAL_setNumCurrentSensors(HAL_Handle handle,const uint_least8_t numCurrentSensors)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      obj->numCurrentSensors = numCurrentSensors;
    
      return;
    } // end of HAL_setNumCurrentSensors() function
    
    
    //! \brief     Sets the number of voltage sensors
    //! \param[in] handle             The hardware abstraction layer (HAL) handle
    //! \param[in] numVoltageSensors  The number of voltage sensors
    static inline void HAL_setNumVoltageSensors(HAL_Handle handle,const uint_least8_t numVoltageSensors)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
    
      obj->numVoltageSensors = numVoltageSensors;
    
      return;
    } // end of HAL_setNumVoltageSensors() function
    
    
    //! \brief     Sets the value used to set the low pass filter pole for offset estimation
    //! \param[in] handle        The hardware abstraction layer (HAL) handle
    //! \param[in] sensorType    The sensor type
    //! \param[in] sensorNumber  The sensor number
    //! \param[in] beta_lp_pu    The value used to set the low pass filter pole, pu
    static inline void HAL_setOffsetBeta_lp_pu(HAL_Handle handle,
                                               const HAL_SensorType_e sensorType,
                                               const uint_least8_t sensorNumber,
                                               const _iq beta_lp_pu)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      if(sensorType == HAL_SensorType_Current)
        {
          OFFSET_setBeta(obj->offsetHandle_I[sensorNumber],beta_lp_pu);
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          OFFSET_setBeta(obj->offsetHandle_V[sensorNumber],beta_lp_pu);
        }
    
      return;
    } // end of HAL_setOffsetBeta_lp_pu() function
    
    
    //! \brief     Sets the offset initial condition value for offset estimation
    //! \param[in] handle        The hardware abstraction layer (HAL) handle
    //! \param[in] sensorType    The sensor type
    //! \param[in] sensorNumber  The sensor number
    //! \param[in] initCond      The initial condition value
    static inline void HAL_setOffsetInitCond(HAL_Handle handle,
                                             const HAL_SensorType_e sensorType,
                                             const uint_least8_t sensorNumber,
                                             const _iq initCond)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      if(sensorType == HAL_SensorType_Current)
        {
          OFFSET_setInitCond(obj->offsetHandle_I[sensorNumber],initCond);
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          OFFSET_setInitCond(obj->offsetHandle_V[sensorNumber],initCond);
        }
    
      return;
    } // end of HAL_setOffsetInitCond() function
    
    
    //! \brief     Sets the initial offset value for offset estimation
    //! \param[in] handle        The hardware abstraction layer (HAL) handle
    //! \param[in] sensorType    The sensor type
    //! \param[in] sensorNumber  The sensor number
    //! \param[in] value         The initial offset value
    static inline void HAL_setOffsetValue(HAL_Handle handle,
                                          const HAL_SensorType_e sensorType,
                                          const uint_least8_t sensorNumber,
                                          const _iq value)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      if(sensorType == HAL_SensorType_Current)
        {
          OFFSET_setOffset(obj->offsetHandle_I[sensorNumber],value);
        }
      else if(sensorType == HAL_SensorType_Voltage)
        {
          OFFSET_setOffset(obj->offsetHandle_V[sensorNumber],value);
        }
    
      return;
    } // end of HAL_setOffsetValue() function
    
    
    //! \brief     Sets the voltage scale factor in the hardware abstraction layer
    //! \param[in] handle      The hardware abstraction layer (HAL) handle
    //! \param[in] voltage_sf  The voltage scale factor
    static inline void HAL_setVoltageScaleFactor(HAL_Handle handle,const _iq voltage_sf)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
      
      obj->voltage_sf = voltage_sf;
    
      return;
    } // end of HAL_setVoltageScaleFactor() function
    
    
    //! \brief      Sets the hardware abstraction layer parameters
    //! \details    Sets up the microcontroller peripherals.  Creates all of the scale
    //!             factors for the ADC voltage and current conversions.  Sets the initial
    //!             offset values for voltage and current measurements.
    //! \param[in]  handle       The hardware abstraction layer (HAL) handle
    //! \param[in]  pUserParams  The pointer to the user parameters
    extern void HAL_setParams(HAL_Handle handle,const USER_Params *pUserParams);
    
    
    //! \brief      Sets up the ADCs (Analog to Digital Converters)
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupAdcs(HAL_Handle handle);
    
    
    //! \brief      Sets up the clocks
    //! \details    Sets up the micro-controller's main oscillator
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupClks(HAL_Handle handle);
    
    
    //! \brief     Sets up the FLASH.
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupFlash(HAL_Handle handle);
    
    
    //! \brief     Sets up the GPIO (General Purpose I/O) pins
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupGpios(HAL_Handle handle);
    
    
    //! \brief     Sets up the peripheral clocks
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupPeripheralClks(HAL_Handle handle);
    
    
    //! \brief     Sets up the PIE (Peripheral Interrupt Expansion)
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupPie(HAL_Handle handle);
    
    
    //! \brief     Sets up the PLL (Phase Lock Loop)
    //! \param[in] handle   The hardware abstraction layer (HAL) handle
    //! \param[in] clkFreq  The clock frequency
    extern void HAL_setupPll(HAL_Handle handle,const PLL_ClkFreq_e clkFreq);
    
    
    //! \brief     Sets up the PWMs (Pulse Width Modulators)
    //! \param[in] handle          The hardware abstraction layer (HAL) handle
    //! \param[in] systemFreq_MHz  The system frequency, MHz
    //! \param[in] pwmPeriod_usec  The PWM period, usec
    //! \param[in] numPwmTicksPerIsrTick  The number of PWM clock ticks per ISR clock tick
    extern void HAL_setupPwms(HAL_Handle handle,
                       const float_t systemFreq_MHz,
                       const float_t pwmPeriod_usec,
                       const uint_least16_t numPwmTicksPerIsrTick);
    
    
    //! \brief     Sets up the PWM DACs (Pulse Width Modulator Digital to Analof Converters)
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupPwmDacs(HAL_Handle handle);
    
    
    //! \brief     Sets up the QEP peripheral
    //! \param[in] handle  The hardware abstraction layer (HAL) handle
    extern void HAL_setupQEP(HAL_Handle handle,HAL_QepSelect_e qep);
    
    
    //! \brief     Sets up the timers
    //! \param[in] handle          The hardware abstraction layer (HAL) handle
    //! \param[in] systemFreq_MHz  The system frequency, MHz
    void HAL_setupTimers(HAL_Handle handle,const float_t systemFreq_MHz);
    
    
    //! \brief      Updates the ADC bias values
    //! \details    This function is called before the motor is started.  It sets the voltage
    //!             and current measurement offsets.
    //! \param[in]  handle  The hardware abstraction layer (HAL) handle
    static inline void HAL_updateAdcBias(HAL_Handle handle)
    {
      uint_least8_t cnt;
      HAL_Obj *obj = (HAL_Obj *)handle;
      _iq bias;
    
    
      // update the current bias
      for(cnt=0;cnt<HAL_getNumCurrentSensors(handle);cnt++)
        {
          bias = HAL_getBias(handle,HAL_SensorType_Current,cnt);
          
          bias += OFFSET_getOffset(obj->offsetHandle_I[cnt]);
    
          HAL_setBias(handle,HAL_SensorType_Current,cnt,bias);
        }
    
    
      // update the voltage bias
      for(cnt=0;cnt<HAL_getNumVoltageSensors(handle);cnt++)
        {
          bias = HAL_getBias(handle,HAL_SensorType_Voltage,cnt);
    
          bias += OFFSET_getOffset(obj->offsetHandle_V[cnt]);
    
          HAL_setBias(handle,HAL_SensorType_Voltage,cnt,bias);
        }
    
      return;
    } // end of HAL_updateAdcBias() function
    
    
    //! \brief     Writes DAC data to the PWM comparators for DAC (digital-to-analog conversion) output
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pDacData  The pointer to the DAC data
    static inline void HAL_writeDacData(HAL_Handle handle,HAL_DacData_t *pDacData)
    {
    //  HAL_Obj *obj = (HAL_Obj *)handle;
    //
    //  // convert values from _IQ to _IQ15
    //  int16_t dacValue_1 = (int16_t)_IQtoIQ15(pDacData->value[0]);
    //  int16_t dacValue_2 = (int16_t)_IQtoIQ15(pDacData->value[1]);
    //  int16_t dacValue_3 = (int16_t)_IQtoIQ15(pDacData->value[2]);
    //  int16_t dacValue_4 = (int16_t)_IQtoIQ15(pDacData->value[3]);
    //
    //  // write the DAC data
    //  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_1],dacValue_1);
    //  PWMDAC_write_CmpB(obj->pwmDacHandle[PWMDAC_Number_1],dacValue_2);
    //  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_2],dacValue_3);
    //  PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_3],dacValue_4);
    //
    //  return;
    
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // convert values from _IQ to _IQ15
      uint_least8_t cnt;
      _iq period;
      _iq dacData_sat_dc;
      _iq value;
      uint16_t cmpValue[4];
    
      period = (_iq)pDacData->PeriodMax;
    
      for(cnt=0;cnt<4;cnt++)
      {
          dacData_sat_dc = _IQmpy(pDacData->value[cnt], pDacData->gain[cnt]) + pDacData->offset[cnt];
          value = _IQmpy(dacData_sat_dc, period);
          cmpValue[cnt] = (uint16_t)_IQsat(value, period, 0);
      }
    
      // write the DAC data
      PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_1],cmpValue[0]);
      PWMDAC_write_CmpB(obj->pwmDacHandle[PWMDAC_Number_1],cmpValue[1]);
      PWMDAC_write_CmpA(obj->pwmDacHandle[PWMDAC_Number_2],cmpValue[2]);
      PWMDAC_write_CmpB(obj->pwmDacHandle[PWMDAC_Number_2],cmpValue[3]);
    
      return;
    } // end of HAL_writeDacData() function
    
    
    //! \brief     Writes PWM data to the PWM comparators for motor control
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pPwmData  The pointer to the PWM data
    static inline void HAL_writePwmData(HAL_Handle handle,HAL_PwmData_t *pPwmData)
    {
      uint_least8_t cnt;
      HAL_Obj *obj = (HAL_Obj *)handle;
      PWM_Obj *pwm;
      _iq period;
      _iq pwmData_neg;
      _iq pwmData_sat;
      _iq pwmData_sat_dc;
      _iq value;
      uint16_t value_sat;
    
      for(cnt=0;cnt<3;cnt++)
        {
          pwm = (PWM_Obj *)obj->pwmHandle[cnt];
          period = (_iq)pwm->TBPRD;
          pwmData_neg = _IQmpy(pPwmData->Tabc.value[cnt],_IQ(-1.0));
          pwmData_sat = _IQsat(pwmData_neg,_IQ(0.5),_IQ(-0.5));
          pwmData_sat_dc = pwmData_sat + _IQ(0.5);
          value = _IQmpy(pwmData_sat_dc, period);
          value_sat = (uint16_t)_IQsat(value, period, _IQ(0.0));
    
          // write the PWM data
          PWM_write_CmpA(obj->pwmHandle[cnt],value_sat);
        }
    
      return;
    } // end of HAL_writePwmData() function
    
    
    //! \brief     Reads PWM compare register A
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pwmNumber  The PWM number
    //! \return    The PWM compare value
    static inline uint16_t HAL_readPwmCmpA(HAL_Handle handle,const PWM_Number_e pwmNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // the compare value to be returned
      uint16_t pwmValue;
    
      pwmValue = PWM_get_CmpA(obj->pwmHandle[pwmNumber]);
    
      return(pwmValue);
    } // end of HAL_readPwmCmpA() function
    
    
    //! \brief     Reads PWM compare mirror register A
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pwmNumber  The PWM number
    //! \return    The PWM compare value
    static inline uint16_t HAL_readPwmCmpAM(HAL_Handle handle,const PWM_Number_e pwmNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // the compare value to be returned
      uint16_t pwmValue;
    
      pwmValue = PWM_get_CmpAM(obj->pwmHandle[pwmNumber]);
    
      return(pwmValue);
    } // end of HAL_readPwmCmpAM() function
    
    
    //! \brief     Reads PWM compare register B
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pwmNumber  The PWM number
    //! \return    The PWM compare value
    static inline uint16_t HAL_readPwmCmpB(HAL_Handle handle,const PWM_Number_e pwmNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // the compare value to be returned
      uint16_t pwmValue;
    
      pwmValue = PWM_get_CmpB(obj->pwmHandle[pwmNumber]);
    
      return(pwmValue);
    } // end of HAL_readPwmCmpB() function
    
    
    //! \brief     Reads PWM period register
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pwmNumber  The PWM number
    //! \return    The PWM period value
    static inline uint16_t HAL_readPwmPeriod(HAL_Handle handle,const PWM_Number_e pwmNumber)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      // the period value to be returned
      uint16_t pwmPeriodValue;
    
      pwmPeriodValue = PWM_getPeriod(obj->pwmHandle[pwmNumber]);
    
      return(pwmPeriodValue);
    } // end of HAL_readPwmPeriod() function
    
    
    //! \brief     Set trigger point in the middle of the low side pulse
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] ignoreShunt  The low side shunt that should be ignored
    //! \param[in] midVolShunt  The middle length of output voltage
    static inline void HAL_setTrigger(HAL_Handle handle,const SVGENCURRENT_IgnoreShunt_e ignoreShunt,
    									const SVGENCURRENT_VmidShunt_e midVolShunt)
    {
      HAL_Obj *obj = (HAL_Obj *)handle;
    
      PWM_Obj *pwm1 = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
      PWM_Obj *pwm2 = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
      PWM_Obj *pwm3 = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
      PWM_Obj *pwm;
    
      uint16_t nextPulse1 = (pwm1->CMPA + pwm1->CMPAM) / 2;
      uint16_t nextPulse2 = (pwm2->CMPA + pwm2->CMPAM) / 2;
      uint16_t nextPulse3 = (pwm3->CMPA + pwm3->CMPAM) / 2;
      uint16_t pwmCMPA1 = pwm1->CMPA;
      uint16_t pwmCMPA2 = pwm2->CMPA;
      uint16_t pwmCMPA3 = pwm3->CMPA;
    
      if(ignoreShunt == use_all)
        {
          if((nextPulse1 <= nextPulse2) && (nextPulse1 <= nextPulse3))
            {
              pwm = pwm1;
            }
          else if((nextPulse2 <= nextPulse1) && (nextPulse2 <= nextPulse3))
            {
              pwm = pwm2;
            }
          else
            {
              pwm = pwm3;
            }
        }
      else
      {
    	  if(midVolShunt == Vmid_a)
    	  {
    		  pwm = pwm1;
    	  }
    	  else if(midVolShunt == Vmid_b)
    	  {
    		  pwm = pwm2;
    	  }
    	  else
    	  {
    		  pwm = pwm3;
    	  }
      }
    
      pwmCMPA1 = pwm->CMPA;
      pwmCMPA2 = pwm->CMPAM;
    
      if(pwmCMPA2 >= (pwmCMPA1 + pwm->DBFED))
      {
    	  pwmCMPA3 = (pwmCMPA2 - (pwmCMPA1 + pwm->DBFED)) / 2 + 1;
    	  if(pwmCMPA3 < (pwm1->TBPRD>>1))
    	  {
    		  pwm1->CMPB = pwmCMPA3;
    	  }
    	  else
    	  {
    		  pwm1->CMPB = (pwm1->TBPRD>>1);
    	  }
    	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);
      }
      else
      {
    	  pwmCMPA3 = ((pwmCMPA1 + pwm->DBFED) - pwmCMPA2 ) / 2 + 1;
    	  if(pwmCMPA3 < (pwm1->TBPRD>>1))
    	  {
    		  pwm1->CMPB = pwmCMPA3;
    	  }
    	  else
    	  {
    		  pwm1->CMPB = (pwm1->TBPRD>>1);
    	  }
    	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);
      }
    
      return;
    } // end of HAL_setTrigger() function
    
    #ifdef QEP
    //! \brief     Returns the current position count from QEP
    //! \param[in] handle      The hardware abstraction layer (HAL) handle
    //! \return    the current position count from QEP
    static inline uint32_t HAL_getQepPosnCounts(HAL_Handle handle)
    {
    	HAL_Obj *obj = (HAL_Obj *)handle;
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    
    	return qep->QPOSCNT;
    }
    
    
    //! \brief     Returns the maximum position count from QEP
    //! \param[in] handle      The hardware abstraction layer (HAL) handle
    //! \return    the maximum position count from QEP
    static inline uint32_t HAL_getQepPosnMaximum(HAL_Handle handle)
    {
    	HAL_Obj *obj = (HAL_Obj *)handle;
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    
    	return qep->QPOSMAX;
    }
    #endif
    
    //! \brief     Selects the analog channel used for calibration
    //! \param[in] handle      The hardware abstraction layer (HAL) handle
    //! \param[in] chanNumber  The channel number
    void HAL_AdcCalChanSelect(HAL_Handle handle, const ADC_SocChanNumber_e chanNumber);
    
    
    //! \brief     Reads the converted value from the selected calibration channel
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    //! \return    The converted value
    uint16_t HAL_AdcCalConversion(HAL_Handle handle);
    
    
    //! \brief     Executes the offset calibration of the ADC
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    void HAL_AdcOffsetSelfCal(HAL_Handle handle);
    
    
    //! \brief     Converts coarse and fine oscillator trim values into a single 16bit word value
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    //! \param[in] coarse     The coarse trim portion of the oscillator trim
    //! \param[in] fine       The fine trim portion of the oscillator trim
    //! \return    The combined trim value
    uint16_t HAL_getOscTrimValue(int16_t coarse, int16_t fine);
    
    
    //! \brief     Executes the oscillator 1 and 2 calibration functions
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    void HAL_OscTempComp(HAL_Handle handle);
    
    
    //! \brief     Executes the oscillator 1 calibration based on input sample
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    void HAL_osc1Comp(HAL_Handle handle, const int16_t sensorSample);
    
    
    //! \brief     Executes the oscillator 2 calibration based on input sample
    //! \param[in] handle     The hardware abstraction layer (HAL) handle
    void HAL_osc2Comp(HAL_Handle handle, const int16_t sensorSample);
    
    
    //! \brief     Writes DAC data to the PWM comparators for DAC (digital-to-analog conversion) output
    //! \param[in] handle    The hardware abstraction layer (HAL) handle
    //! \param[in] pDacData  The pointer to the DAC data
    void HAL_setDacParameters(HAL_Handle handle, HAL_DacData_t *pDacData);
    
    #ifdef __cplusplus
    }
    #endif // extern "C"
    
    //@} // ingroup
    #endif // end of _HAL_H_ definition
    
    
    

    Project Structure: 


    Please support.

  • Any changes you made on the example project? Did you check if the sensing dc bus voltage and offset calibration are correct? You may follow the lab user's guide to check the related variables to check if the kit is connected and configured correctly.

    Please take a look at the lab user's guide, and set the following parameters according to the motor you used.

    #define USER_MOTOR_FREQ_LOW (10.0) // Hz - suggested to set to 10% of rated motor frequency

    #define USER_MOTOR_FREQ_HIGH (100.0) // Hz - suggested to set to 100% of rated motor frequency

    #define USER_MOTOR_FREQ_MAX (120.0) // Hz - suggested to set to 120% of rated motor frequency

    #define USER_MOTOR_VOLT_MIN (3.0) // Volt - suggested to set to 15% of rated motor voltage

    #define USER_MOTOR_VOLT_MAX (18.0) // Volt - suggested to set to 100% of rated motor voltage

    Or refer to the links below for the similar questions you have.

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1185366/tms320f28069m-problems-with-proj_lab01b-with-tms320f28069m

  • Hello Luo

    1. How do I find out the correct sensing DC bus voltage and offset calibrations?

    2. Only changes I have made are to the 28069_RAM_lnk.cmd (added correct memory addresses for IQtables and FPUtables; place .text section in custom region RAML0_L4; and create graph_data section in RAML0_L4).

    3. As mentioned before, I have also changed some functions in hal.c and hal.h according to this answer on the TI forum: TMDSHVMTRINSPIN: Getting strange DAC_PWM results from lab1b motorware tutorial  

    4.The motor I am using is the Estun EMJ-04APB22 and it's parameters have already been defined.

  • 1. How do I find out the correct sensing DC bus voltage and offset calibrations?

    Please take a look at the guides as mentioned above, that have a detailed description in the guides.  If you are using the kits supported in the motorWare, please try to run the related labs without changes first.