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.

PGA4311EVM: PGA411Q1EVM: External control of the PGA411-EVM with F28379D Control Card

Part Number: PGA4311EVM
Other Parts Discussed in Thread: PGA411-Q1, SYSCONFIG, LAUNCHXL-F28379D
  • Hellow

      I am having the same issue that  had faced in his original thread where any command request is responding with a message like 0x46. Can I know how this got resolved?

       I am trying to read the Dev_Stat5 and Dev_Stat6 registers from the PGA411Q1EVM, via the external controller (F28379D) Dev Kit. 

    F28379D is the master  

    PGA411-EVM is the slave,

    I am trying to read the register values via the J11 ping on the PGA411-EVM.

     On the scope, I am confirming that the NCS, SCK, and the SDI Pins are all valid, but the SDO output is always 0x41,0X00,0XFF,0X41

    after execution of the code I am getting a hal_assert() error. 

    Any help is appreciated.

    Respected code and pin connection are attached below 

    logic analyzer received data 

    pin connection master (f28379d) slave PGA411_Q1_EVM

    //#############################################################################
    //
    // FILE: empty_bitfield_driverlib_main.c
    //
    // TITLE: Empty Example
    //
    // Empty Bit-Field & Driverlib Example
    //
    // This example is an empty project setup for Bit-Field and Driverlib
    // development.
    //
    //#############################################################################
    // $TI Release: F2837xD Support Library v3.10.00.00 $
    // $Release Date: Tue May 26 17:13:46 IST 2020 $
    // $Copyright:
    // Copyright (C) 2013-2020 Texas Instruments Incorporated - http://www.ti.com/
    //
    // 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.
    // $
    //#############################################################################

    //
    // Included Files
    //

    #include "F28x_Project.h"
    #include "driverlib.h"
    #include "device.h"

    //FROM TIDA-00796
    #include <IQmathLib.h> /* IQ math library */
    #include <stdio.h> /* standard input output lib */
    #include <string.h> /* strings and arrays (for mcmcpy) */
    #include "hal.h" /* hardware manager */
    #include "pga411.h" /*PGA411-Q1 driver */

    #include "F2837xD_device.h"
    #include "F2837xD_Examples.h"
    #include "board1.h"

    //
    // Defines
    //
    #define START_TIMER(x) { \
    x = CpuTimer1Regs.TIM.all; \
    CpuTimer1Regs.TCR.bit.TSS = 0; \
    }

    #define STOP_TIMER(x) { \
    CpuTimer1Regs.TCR.bit.TSS = 1; \
    x = CpuTimer1Regs.TIM.all; \
    CpuTimer1Regs.TCR.bit.TRB = 1; \
    }


    #define RED_LED_LOW GPIO_WritePin(RED_LED, 1) // 1 LOW 0 HIGH
    #define RED_LED_HIGH GPIO_WritePin(RED_LED, 0) // 0 HIGH

    #define LOGIC_CHECK_LOW GPIO_WritePin(LOGIC_CHECK, 1) // 1 LOW 0 HIGH
    #define LOGIC_CHECK_HIGH GPIO_WritePin(LOGIC_CHECK, 0) // 0 HIGH
    //NOT VERIFIED
    float start_time = 0.0;
    float stop_time = 0.0;
    //
    float ticks, time_in_us, time, temp, temp1;

    char outbuf[30]; /* UART output data buffer for string conversion */
    Uint16 angle1;

    /******************************************************************************
    * INTERNAL FUNCTIONS PROTOTYPES
    *****************************************************************************/

    /* Function reads angle from the PGA411 and sends it over UART */
    void main_GetAngleAndPrint(void);

    /* Function reads velocity from the PGA411 and sends it over UART */
    void main_GetVeloAndPrint(void);

    /******************************************************************************
    * INTERNAL FUNCTIONS
    *****************************************************************************/

    /* Function reads angle from the PGA411 and sends it over UART */
    void main_GetAngleAndPrint(void)
    {


    // angle calculation for the PGA411-Q1 using IQmathLib library //
    // _iq19 stores -4096 to 4095.999998093 with 0.000001907 resolution //
    int16 angle_raw; // raw data from the PGA411-Q1 register //
    _iq angle; // IQ math angle //
    // float angle2;

    // terminal command //
    hal_PutsUART("Angle [Deg]: ");

    // read data from the PGA411-Q1 //
    angle_raw = pga411_ReadReg(DEV_STAT5);
    angle_raw &= 0x1FFF; // preserve only ORDANGLE bits //
    // multiply minimal step (LSB) with ORDANGLE value //
    angle = _IQ19mpy(_IQ19(360.0 / 4096), _IQ19(angle_raw)); // 12b example // //ORIGINAL CODE
    // angle = _IQ19mpy(_IQ19(360.0 / 1024), _IQ19(angle_raw)); // 10bit mode example //
    // convert IQ variable to string //
    _IQ19toa(outbuf, "%4.5f", angle);
    // angle1 = (int) outbuf[0];

    // print-out the buffer //
    hal_PutsUART(outbuf);
    // terminal command //
    hal_PutsUART("\t\r");


    }

    /* Function reads velocity from the PGA411 and sends it over UART */
    void main_GetVeloAndPrint(void)
    {
    /* velocity calculation for the PGA411-Q1 using IQmathLib library */
    /* _iq14 stores -131072 to 131071.999938965 with 0.000061035 resolution */
    int16 velocity_raw; /* raw data from the PGA411-Q1 register */
    float velocity_float; /* temp for 2nd complement to float conversion */
    _iq velocity; /* IQ math velocity */


    /* terminal command */
    hal_PutsUART("Velocity[RPM]: ");

    /* read data from the PGA411-Q1 */
    velocity_raw = pga411_ReadReg(DEV_STAT6);

    /* convert 2nd complement to float */
    if (velocity_raw & 0x0800) /* negative number ? */
    {
    /* convert to positive number first */
    velocity_float = (((~velocity_raw) + 1) & 0x07FF);
    velocity_float *= -1; /* and make float negative */
    }
    else
    {
    /* positive number, preserve only needed bits */
    velocity_float = (velocity_raw & 0x07FF);
    }

    velocity = _IQ14mpy(_IQ14(60 * 20000000 / 33554432), _IQ14(velocity_float + 1)); /* 12b example */ //ORIGINAL CODE
    // velocity = _IQ14mpy(_IQ14(60 * 20000000 / 2097152), _IQ14(velocity_float + 1)); /* 10b example */

    /* convert IQ variable to string */
    _IQ14toa(outbuf, "%7.5f", velocity);

    /* print-out the buffer */
    hal_PutsUART(outbuf);
    /* terminal command */
    hal_PutsUART("\n\r");
    }


    //
    // Main
    //
    void main(void)
    {
    //
    // Initializes device clock and peripherals
    //
    Device_init();

    //
    // Configures the GPIO pin as a push-pull output
    //
    Device_initGPIO();

    //
    // Initializes PIE and clears PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initializes the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Initializes board peripherals. This is generated by Sysconfig file
    //
    Board_init_1();

    // //
    // //CODE END FOR UART - SEEN ON PINS 19 & 18 on LAUNCHXL-F28379D
    // //
    GPIO_togglePin(LED1);
    DEVICE_DELAY_US(1000000);
    hal_PutsUART("\r\n hal_PutsUART function is WORKING! \n\r");
    GPIO_togglePin(LED1);
    DEVICE_DELAY_US(1000000);
    GPIO_writePin(AMODE, 0);
    GPIO_WritePin(RED_LED, 1);
    GPIO_WritePin(FAULT, 1);
    pga411_Reset();
    pga411_FaultReset();

    DELAY_US(100000); /* 100 ms delay */

    pga411_DefaultCfg(); /* default config defined in "pga411_regs" */
    DELAY_US(10000); /* 10 ms deglitch period when the exciter enables */

    /* endless loop */
    while (1)
    {

    hal_PutsUART("\r\n hal_PutsUART function is WORKING! \n\r");
    DELAY_US(100000); /* 100 ms delay */
    main_GetAngleAndPrint();
    main_GetVeloAndPrint();
    }

    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////  PGA411 INIT HADER FILE   ///////////////

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /******************************************************************************
    * TIDA-00796 Resolver Frontend based on PGA411-Q1
    * Module: PGA411 driver
    * Author: Jiri Panacek, j-panacek@ti.com
    *
    * Copyright 2016 Texas Instruments Incorporated. All rights reserved.
    ******************************************************************************/

    #include "pga411.h"
    #include "hal.h"
    #include "F2837xD_device.h"
    #include "F28x_Project.h"


    /******************************************************************************
    * MACROS
    *****************************************************************************/

    #define CRC_BITCOUNT 24 /* top 24 bits of Uint32 for CRC6 */
    #define CRC_BYTECOUNT 3 /* top 3 B of Uint32 for CRC6 */
    #define CRC_INITSEED 0x3F /* initial seed for CRC6 */
    #define CRC_POLYNOM 0x5B /* CRC = X6+X4+X3+X+1 */

    #define SPI_DUMMY 0xF0 /* dummy SPI data for read operation */

    #define EMPTY_LOOP

    /******************************************************************************
    * ENUMS
    *****************************************************************************/

    /******************************************************************************
    * TYPEDEFS
    *****************************************************************************/

    /******************************************************************************
    * VARIABLES, CONSTANTS
    *****************************************************************************/

    volatile pga411_spi_frame_t pga411_spi_frame = {.addr = 0x00,
    .dataout = 0x0000,
    .reserved = 0x0,
    .mcrc = 0x00
    };

    pga411_reg_t pga411_regs[PGA411_REG_COUNT + 1] =
    {
    /* memory constants init */
    [DEV_OVUV1] = {.read_add = 0x53, .write_add = 0x87, .def_val = 0x8B40},
    [DEV_OVUV2] = {.read_add = 0x6B, .write_add = 0x26, .def_val = 0x00ED},
    [DEV_OVUV3] = {.read_add = 0x65, .write_add = 0x17, .def_val = 0xFCFF},
    [DEV_OVUV4] = {.read_add = 0xEC, .write_add = 0x39, .def_val = 0x07F2},
    [DEV_OVUV5] = {.read_add = 0x52, .write_add = 0x75, .def_val = 0x1C00},
    [DEV_OVUV6] = {.read_add = 0xE9, .write_add = 0x83, .def_val = 0x038F},
    [DEV_TLOOP_CFG] = {.read_add = 0xA6, .write_add = 0x42, .def_val = 0x0514},
    [DEV_AFE_CFG] = {.read_add = 0xC2, .write_add = 0x91, .def_val = 0x0005},
    [DEV_PHASE_CFG] = {.read_add = 0x57, .write_add = 0x85, .def_val = 0x1400},
    [DEV_CONFIG1] = {.read_add = 0xBE, .write_add = 0xEB, .def_val = 0x0002},
    [DEV_CONTROL1] = {.read_add = 0x90, .write_add = 0x0D, .def_val = 0x0000},
    [DEV_CONTROL2] = {.read_add = 0x63, .write_add = 0x38, .def_val = 0x0000},
    [DEV_CONTROL3] = {.read_add = 0xDD, .write_add = 0xAE, .def_val = 0x0003},
    [DEV_STAT1] = {.read_add = 0x81, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT2] = {.read_add = 0x4D, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT3] = {.read_add = 0x84, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT4] = {.read_add = 0x1F, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT5] = {.read_add = 0x41, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT6] = {.read_add = 0x6F, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT7] = {.read_add = 0xE1, .write_add = 0x00, .def_val = 0x0000},
    [DEV_CLCRC] = {.read_add = 0x4F, .write_add = 0xFC, .def_val = 0x0000},
    [DEV_CRC] = {.read_add = 0x0F, .write_add = 0xE7, .def_val = 0x0000},
    [CRCCALC] = {.read_add = 0xD9, .write_add = 0xFF, .def_val = 0x0000},
    [DEV_EE_CTRL1] = {.read_add = 0xE3, .write_add = 0x6E, .def_val = 0x0000},
    [DEV_CRC_CTRL1] = {.read_add = 0x7A, .write_add = 0xB6, .def_val = 0x0000},
    [DEV_EE_CTRL4] = {.read_add = 0xBA, .write_add = 0x56, .def_val = 0x0000},
    [DEV_UNLK_CTRL1] = {.read_add = 0x64, .write_add = 0x95, .def_val = 0x0000},
    /* for continuous read we need to read 28 times. This significantly helps */
    [DUMMY_REG] = {.read_add = 0x53, .write_add = 0x87, .def_val = 0x0000},
    };

    /******************************************************************************
    * INTERNAL FUNCTIONS PROTOTYPES
    *****************************************************************************/

    /* calculate CRC6 for output data, function takes first 3B left aligned data */
    Uint16 pga411_crc2(Uint32 datin);

    /* Xmit data to PGA over SPI, for reg use defined macros, return incoming frame */
    pga411_spi_frame_t pga411_XmitSPI(Uint16 dir, Uint16 reg, Uint16 wdata);

    /******************************************************************************
    * INTERNAL FUNCTIONS
    *****************************************************************************/

    /* CRC6 calculation - optimized for PGA411 */
    Uint16 pga411_crc2(Uint32 datin)
    {
    Uint16 byte_idx, bit_idx, crc = (CRC_INITSEED << 2);

    /* byte by byte starting from most significant (3-2-1) */
    for (byte_idx = CRC_BYTECOUNT; byte_idx >= 1; byte_idx--)
    {
    /* XOR-in new byte from left to right */
    crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);

    /* bit by bit for each byte */
    for (bit_idx = 0; bit_idx < 8; bit_idx++)
    {
    crc = crc << 1 ^ (crc & 0x80 ? (CRC_POLYNOM << 2) : 0);
    }
    }

    return (crc >> 2 & CRC_INITSEED); /*restore two bit offset */
    }


    /* Write default configuration to PGA */
    void pga411_DefaultCfg(void)
    {
    int i;
    /* go to diagnostic state */
    pga411_State(DIAG);
    /* unlock registers */
    pga411_DeviceUnlock();

    /* first 12 registers to default */
    /* note: for some u need to unlocked them first ! */
    for (i = 0; i < 12; i++)
    {
    pga411_XmitSPI(WRITE, i, pga411_regs[i].def_val);
    }

    /* go to normal state */
    pga411_State(NORMAL);
    }


    /* Change state diagnostic/normal */
    void pga411_State(Uint16 state)
    {
    Uint16 temp;

    /* Enter Diagnostic state */
    if (state == DIAG)
    {
    /* read content of DEV_CONTROL3 register */
    temp = pga411_ReadReg(DEV_CONTROL3);
    temp |= 0x0004; /* set bit SPIDIAG */
    pga411_WriteReg(DEV_CONTROL3, temp); /* finish R-M-W */
    }
    /* Go back to normal state */
    else
    {
    /* read content of DEV_CONTROL1 register */
    temp = pga411_ReadReg(DEV_CONTROL1);
    temp |= 0x0001; /* set bit DIAGEXIT */
    pga411_WriteReg(DEV_CONTROL1, temp); /* finish R-M-W */
    }
    }


    /* Read data from defined register */
    Uint16 pga411_ReadReg(Uint16 reg)
    {
    /* first read returns whatever */
    pga411_XmitSPI(READ, reg, SPI_DUMMY);
    /* second read returns requested data */
    return (pga411_XmitSPI(READ, reg, SPI_DUMMY).datain);
    }

    pga411_spi_frame_t pga411_XmitSPI(Uint16 dir, Uint16 reg, Uint16 wdata)
    {
    pga411_spi_frame_t out, in;

    /* do we read data ? */
    if (dir == READ) { out.addr = pga411_regs[reg].read_add; } /* read address */
    /* or write data ? */
    else { out.addr = pga411_regs[reg].write_add; } /* write address */

    /* compose the rest of the frame */
    out.dataout = wdata; /* real data (W) or dummy data (R) */
    out.reserved = 0x00; /* always zero */
    out.mcrc = pga411_crc2(out.frame); /* calculate TX CRC */
    in.frame = hal_Xmit4BSPI(out.frame);

    /* check RX CRC */
    if (pga411_crc2(in.frame) != in.scrc)
    {
    hal_assert(); /* if error -> terminate */
    }

    return (in);
    }

    /* Write data to defined register */
    void pga411_WriteReg(Uint16 reg, Uint16 data)
    {
    /* here we just making it nice, can be macro too */
    pga411_XmitSPI(WRITE, reg, data);
    }

    /* Read all registers from PGA */
    void pga411_ReadAll(void)
    {
    int i;
    Uint16 rx_data;

    /* register by register (27+1) */
    /* PGA411 always returns previous read register value */
    /* thats why 28 reads are needed (first read returns whatever data) */
    for (i = 0; i < PGA411_REG_COUNT + 1; i++)
    {
    rx_data = pga411_XmitSPI(READ, i, SPI_DUMMY).datain;

    /*boolean trick - save data if not first cycle */
    if (i)
    {
    pga411_regs[i - 1].real_val = rx_data;
    }
    }
    }


    /* Device unlock (must be in diagnostic state) */
    void pga411_DeviceUnlock(void)
    {
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x000F);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x0055);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x00AA);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x00F0);
    }

    /* EEPROM unlock (must be in diagnostic state) */
    void pga411_EEPROMUnlock(void)
    {
    pga411_WriteReg(DEV_EE_CTRL4, 0x000F);
    pga411_WriteReg(DEV_EE_CTRL4, 0x0055);
    pga411_WriteReg(DEV_EE_CTRL4, 0x00AA);
    pga411_WriteReg(DEV_EE_CTRL4, 0x00F0);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /* PGA411-Q1 registers and their offsets */

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #define DEV_OVUV1 0x00
    #define DEV_OVUV2 0x01
    #define DEV_OVUV3 0x02
    #define DEV_OVUV4 0x03
    #define DEV_OVUV5 0x04
    #define DEV_OVUV6 0x05
    #define DEV_TLOOP_CFG 0x06
    #define DEV_AFE_CFG 0x07
    #define DEV_PHASE_CFG 0x08
    #define DEV_CONFIG1 0x09
    #define DEV_CONTROL1 0x0A /* device unlock needed */
    #define DEV_CONTROL2 0x0B /* device unlock needed */
    #define DEV_CONTROL3 0x0C
    #define DEV_STAT1 0x0D
    #define DEV_STAT2 0x0E
    #define DEV_STAT3 0x0F
    #define DEV_STAT4 0x10
    #define DEV_STAT5 0x11
    #define DEV_STAT6 0x12
    #define DEV_STAT7 0x13
    #define DEV_CLCRC 0x14
    #define DEV_CRC 0x15
    #define CRCCALC 0x16
    #define DEV_EE_CTRL1 0x17 /*EEPROM unlock needed */
    #define DEV_CRC_CTRL1 0x18
    #define DEV_EE_CTRL4 0x19
    #define DEV_UNLK_CTRL1 0x1A
    #define DUMMY_REG 0x1B /* this simplifies continus read */

    #define PGA411_REG_COUNT 27

    #define DUMMY 0x00 /* dummy for SPI read */

 
  • Hello User, 

    I will be redirecting this thread to the group that can assist with F28379D. Appreciate your patience here. 

    Thanks. 

  • Hi Arjun Prakash 

    Thank you so much for your response.

    I am waiting for that.

    Any help is appreciated.

  • Hi Arjun,

    Good Day. I would like to follow up about the query of our customer to this post. Thank you very much.

    Best Regards,

    Ray Vincent

  • Hi,

    I'm with the C2000 team.

    On the scope, I am confirming that the NCS, SCK, and the SDI Pins are all valid, but the SDO output is always 0x41,0X00,0XFF,0X41

    The line below is used to read the DEV_STAT5 register is: 

    pga411_ReadReg(DEV_STAT5)

    Just looking through the code, the frame for reading that register is formed as: 0x41, 0xF0, 0x00, and CRC. Seems to me like the C2000 code is doing what it is programmed to do. Did you expect a different output on the MOSI pin?

    Also, something with your logic analyzer setup doesn't look right. The slave is definitely not outputting all 0xFFs as is shown on your screen grab. I would double check that. 

  • To expand on my last response, here are the lines of code I looked at.

    /* Read data from defined register */
    Uint16 pga411_ReadReg(Uint16 reg)
    {
    /* first read returns whatever */
    pga411_XmitSPI(READ, reg, SPI_DUMMY);
    /* second read returns requested data */
    return (pga411_XmitSPI(READ, reg, SPI_DUMMY).datain);
    }

    pga411_spi_frame_t pga411_XmitSPI(Uint16 dir, Uint16 reg, Uint16 wdata)
    {
    pga411_spi_frame_t out, in;

    /* do we read data ? */
    if (dir == READ) { out.addr = pga411_regs[reg].read_add; } /* read address */
    /* or write data ? */
    else { out.addr = pga411_regs[reg].write_add; } /* write address */

    /* compose the rest of the frame */
    out.dataout = wdata; /* real data (W) or dummy data (R) */
    out.reserved = 0x00; /* always zero */
    out.mcrc = pga411_crc2(out.frame); /* calculate TX CRC */
    in.frame = hal_Xmit4BSPI(out.frame);

    /* check RX CRC */
    if (pga411_crc2(in.frame) != in.scrc)
    {
    hal_assert(); /* if error -> terminate */
    }

    return (in);
    }

  • Hi Gus Martinez,

    Thank you so much for your response.

    can you tell me what is the mistake I done at there I am unable to understand what mistake I did there, 

    if you need that code I can share you that?

     

    Any help is appreciated.

    /*
    * PGA411.c
    *
    * Created on: 11-Oct-2021
    * Author: Devilal
    */


    /*
    * pga411.c
    *
    * Created on: 30-Sep-2020
    * Author: Abhinav
    */

    #include "PGA411.h"
    //#include "hal.h"
    #include "F28x_Project.h"
    #include "hw_types.h"
    #include <IQmathLib.h> // IQ math library //
    #include "Communication.h"

    //
    // MACROS
    //
    #define CRC_BITCOUNT 24 // top 24 bits of Uint32 for CRC6 //
    #define CRC_BYTECOUNT 3 // top 3 B of Uint32 for CRC6 //
    #define CRC_INITSEED 0x3F // initial seed for CRC6 //
    #define CRC_POLYNOM 0x5B // CRC = X6+X4+X3+X+1 //

    #define SPI_DUMMY 0xF0 // dummy SPI data for read operation //

    #define EMPTY_LOOP

    //
    // ENUMS
    //

    //
    // TYPEDEFS
    //

    //
    // VARIABLES, CONSTANTS
    //

    volatile pga411_spi_frame_t pga411_spi_frame = {.addr = 0x00,
    .dataout = 0x0000,
    .reserved = 0x0,
    .mcrc = 0x00
    };

    pga411_reg_t pga411_regs[PGA411_REG_COUNT + 1] =
    {
    // memory constants init //
    [DEV_OVUV1] = {.read_add = 0x53, .write_add = 0x87, .def_val = 0x8B40},
    [DEV_OVUV2] = {.read_add = 0x6B, .write_add = 0x26, .def_val = 0x00ED},
    [DEV_OVUV3] = {.read_add = 0x65, .write_add = 0x17, .def_val = 0xFCFF},
    [DEV_OVUV4] = {.read_add = 0xEC, .write_add = 0x39, .def_val = 0x07E2},
    [DEV_OVUV5] = {.read_add = 0x52, .write_add = 0x75, .def_val = 0x1C00},
    [DEV_OVUV6] = {.read_add = 0xE9, .write_add = 0x83, .def_val = 0x038F},
    [DEV_TLOOP_CFG] = {.read_add = 0xA6, .write_add = 0x42, .def_val = 0x0514},
    [DEV_AFE_CFG] = {.read_add = 0xC2, .write_add = 0x91, .def_val = 0x0005},
    [DEV_PHASE_CFG] = {.read_add = 0x57, .write_add = 0x85, .def_val = 0x1800},
    [DEV_CONFIG1] = {.read_add = 0xBE, .write_add = 0xEB, .def_val = 0x0002},
    [DEV_CONTROL1] = {.read_add = 0x90, .write_add = 0x0D, .def_val = 0x0000},
    [DEV_CONTROL2] = {.read_add = 0x63, .write_add = 0x38, .def_val = 0x0000},
    [DEV_CONTROL3] = {.read_add = 0xDD, .write_add = 0xAE, .def_val = 0x0003},
    [DEV_STAT1] = {.read_add = 0x81, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT2] = {.read_add = 0x4D, .write_add = 0x00, .def_val = 0x004C},
    [DEV_STAT3] = {.read_add = 0x84, .write_add = 0x00, .def_val = 0x0000},
    [DEV_STAT4] = {.read_add = 0x1F, .write_add = 0x00, .def_val = 0x0004},
    [DEV_STAT5] = {.read_add = 0x41, .write_add = 0x00, .def_val = 0x4398},
    [DEV_STAT6] = {.read_add = 0x6F, .write_add = 0x00, .def_val = 0x3FFF},
    [DEV_STAT7] = {.read_add = 0xE1, .write_add = 0x00, .def_val = 0x004B},
    [DEV_CLCRC] = {.read_add = 0x4F, .write_add = 0xFC, .def_val = 0x00CE},
    [DEV_CRC] = {.read_add = 0x0F, .write_add = 0xE7, .def_val = 0x0000},
    [CRCCALC] = {.read_add = 0xD9, .write_add = 0xFF, .def_val = 0x00FF},
    [DEV_EE_CTRL1] = {.read_add = 0xE3, .write_add = 0x6E, .def_val = 0x0000},
    [DEV_CRC_CTRL1] = {.read_add = 0x7A, .write_add = 0xB6, .def_val = 0x0000},
    [DEV_EE_CTRL4] = {.read_add = 0xBA, .write_add = 0x56, .def_val = 0x0000},
    [DEV_UNLK_CTRL1] = {.read_add = 0x64, .write_add = 0x95, .def_val = 0x0000},
    // for continuous read we need to read 28 times. This significantly helps //
    [DUMMY_REG] = {.read_add = 0x53, .write_add = 0x87, .def_val = 0x0000},
    };


    char outbuf[30]; // UART output data buffer for string conversion //

    //
    // INTERNAL FUNCTIONS PROTOTYPES
    //

    // Function reads angle from the PGA411 and sends it over UART //
    void GetAngleAndPrint(void);

    // Function reads velocity from the PGA411 and sends it over UART //
    void GetVeloAndPrint(void);

    // calculate CRC6 for output data, function takes first 3B left aligned data //
    Uint16 pga411_crc2(Uint32 datin);

    // Xmit data to PGA over SPI, for reg use defined macros, return incoming frame //
    pga411_spi_frame_t pga411_XmitSPI(Uint16 dir, Uint16 reg, Uint16 wdata);

    //
    // INTERNAL FUNCTIONS
    //

    // Function reads angle from the PGA411 and sends it over UART //
    void GetAngleAndPrint(void)
    {
    // Angle calculation for the PGA411-Q1 using IQmathLib library //
    // _iq19 stores -4096 to 4095.999998093 with 0.000001907 resolution //
    int16 angle_raw; // raw data from the PGA411-Q1 register //
    _iq angle; // IQ math angle //
    // float angle2;

    // terminal command //
    // hal_PutsUART("Angle [Deg]: "); // Sends data to UART
    hal_PutsRS232("Angle [Deg]: "); // Sends data to RS-232

    // read data from the PGA411-Q1 //
    angle_raw = pga411_ReadReg(DEV_STAT5);
    angle_raw &= 0x1FFF; // preserve only ORDANGLE bits //

    // multiply minimal step (LSB) with ORDANGLE value //
    angle = _IQ19mpy(_IQ19(360.0 / 4096), _IQ19(angle_raw)); // 12bit mode //
    // angle2 = ((360.0 / 4096)*(angle_raw & 0x1FFF)); // 12bit mode // Can be used instead of IQ library

    // convert IQ variable to string //
    _IQ19toa(outbuf, "%4.5f", angle);

    // print-out the buffer //
    // hal_PutsUART(outbuf); // Sends data to UART
    hal_PutsRS232(outbuf); // Sends data to RS-232

    // terminal command //
    // hal_PutsUART("\n\r");
    hal_PutsRS232("\n\r");

    }


    // Function reads velocity from the PGA411 and sends it over UART //
    void GetVeloAndPrint(void)
    {
    // velocity calculation for the PGA411-Q1 using IQmathLib library //
    // _iq14 stores -131072 to 131071.999938965 with 0.000061035 resolution //
    int16 velocity_raw; // raw data from the PGA411-Q1 register //
    float velocity_float; // temp for 2nd complement to float conversion //
    _iq velocity; // IQ math velocity //


    // terminal command //
    // hal_PutsUART("Velocity[RPM]: "); // Sends data to UART
    hal_PutsRS232("Velocity[RPM]: "); // Sends data to RS-232
    // read data from the PGA411-Q1 //
    velocity_raw = pga411_ReadReg(DEV_STAT6);

    // convert 2nd complement to float //
    if (velocity_raw & 0x0800) // negative number ? //
    {
    // convert to positive number first //
    velocity_float = (((~velocity_raw) + 1) & 0x07FF);
    velocity_float *= -1; // and make float negative //
    }
    else
    {
    // positive number, preserve only needed bits //
    velocity_float = (velocity_raw & 0x07FF);
    }

    velocity = _IQ14mpy(_IQ14(60 * 20000000 / 33554432), _IQ14(velocity_float + 1)); // 12b example //

    // convert IQ variable to string //
    _IQ14toa(outbuf, "%4.5f", velocity);

    // print-out the buffer //
    // hal_PutsUART(outbuf); // Sends data to UART
    hal_PutsRS232(outbuf); // Sends data to RS-232

    // terminal command //
    // hal_PutsUART("\n\r");
    hal_PutsRS232("\n\r");
    }

    // CRC6 calculation - optimized for PGA411 //
    Uint16 pga411_crc2(Uint32 datin)
    {
    int byte_idx;
    unsigned int bit_idx,crc = 0x3F;

    for(byte_idx = 18; byte_idx>=0;byte_idx-=6)
    {
    crc^=(datin>>byte_idx)&0x3F;
    for(bit_idx=0;bit_idx<6;bit_idx++)
    {
    crc<<=1;
    crc^=(crc & 0x40) ? 0x5B:0;
    }
    }
    return (crc&0x3F);

    }


    //
    // SYSTEM INTERFACE FUNCTIONS
    //

    // Perform PGA411-Q1 reset using GPIO //
    void pga411_Reset(void)
    {
    GPIO_WritePin(NRESET, 0);
    DELAY_US(100000); // 100 ms delay //
    GPIO_WritePin(NRESET, 1);
    DELAY_US(100000); // 100 ms delay //
    }

    ///* Perform PGA411-Q1 FAULT reset using GPIO */
    void pga411_FaultReset(void)
    {
    HAL_PGA_FAULTRES_LOW; /* assert FAULTRES low - open collector */
    DELAY_US(1000); /* hold in the state for 1ms */
    HAL_PGA_FAULTRES_HIZ; /* return back to high-z*/
    }
    // Initialization PGA411-Q1 related hardware //
    //void pga411_Init(void)
    //{
    // hal_InitPgaGPIO(); // init GPIO //
    // hal_InitSPI(); // init SPI periphery //
    // pga411_Reset(); // perform PGA411 reset //
    //}

    // Perform PGA411-Q1 FAULT reset using GPIO //
    //void pga411_FaultReset(void)
    //{
    // GPIO_WritePin(FAULTRES, 0); // assert FAULTRES low - open collector //
    // DELAY_US(1000); // 1 ms delay //
    // GPIO_WritePin(FAULTRES, 1); // return back to high-z//
    // DELAY_US(1000); // 1 ms delay //
    //}


    // Xmit data to PGA over SPI, for reg use defined macros //
    pga411_spi_frame_t pga411_XmitSPI(Uint16 dir, Uint16 reg, Uint16 wdata)
    {
    pga411_spi_frame_t out, in;

    // do we read data ? //
    if (dir == READ) { out.addr = pga411_regs[reg].read_add; } // read address //
    // or write data ? //
    else { out.addr = pga411_regs[reg].write_add; } // write address //

    // compose the rest of the frame //
    out.dataout = wdata; // real data (W) or dummy data (R) //
    out.reserved = 0x00; // always zero //
    out.mcrc = pga411_crc2(out.frame); // calculate TX CRC //
    in.frame = hal_Xmit4BSPI(out.frame);

    // check RX CRC //
    if (pga411_crc2(in.frame) != in.scrc)
    {
    hal_assert(); // if error -> terminate //
    }

    return (in);
    }

    // Read data from defined register //
    Uint16 pga411_ReadReg(Uint16 reg)
    {
    // first read returns whatever //
    pga411_XmitSPI(READ, reg, SPI_DUMMY);
    // second read returns requested data //
    return (pga411_XmitSPI(READ, reg, SPI_DUMMY).datain);
    }

    // Write data to defined register //
    void pga411_WriteReg(Uint16 reg, Uint16 data)
    {
    // here we just making it nice, can be macro too //
    pga411_XmitSPI(WRITE, reg, data);
    }

    // Read all registers from PGA //
    void pga411_ReadAll(void)
    {
    int i;
    Uint16 rx_data;

    // register by register (27+1) //
    // PGA411 always returns previous read register value //
    // thats why 28 reads are needed (first read returns whatever data) //
    for (i = 0; i < PGA411_REG_COUNT + 1; i++)
    {
    rx_data = pga411_XmitSPI(READ, i, SPI_DUMMY).datain;

    //boolean trick - save data if not first cycle //
    if (i)
    {
    pga411_regs[i - 1].real_val = rx_data;
    }
    }
    }

    // Change state diagnostic/normal //
    void pga411_State(Uint16 state)
    {
    Uint16 temp;

    // Enter Diagnostic state //
    if (state == DIAG)
    {
    // read content of DEV_CONTROL3 register //
    temp = pga411_ReadReg(DEV_CONTROL3);
    temp |= 0x0004; // set bit SPIDIAG //
    pga411_WriteReg(DEV_CONTROL3, temp); // finish R-M-W //
    }
    // Go back to normal state //
    else
    {
    // read content of DEV_CONTROL1 register //
    temp = pga411_ReadReg(DEV_CONTROL1);
    temp |= 0x0001; // set bit DIAGEXIT //
    pga411_WriteReg(DEV_CONTROL1, temp); // finish R-M-W //
    }
    }

    // Device unlock (must be in diagnostic state) //
    void pga411_DeviceUnlock(void)
    {
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x000F);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x0055);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x00AA);
    pga411_WriteReg(DEV_UNLK_CTRL1, 0x00F0);
    }

    // EEPROM unlock (must be in diagnostic state) //
    void pga411_EEPROMUnlock(void)
    {
    pga411_WriteReg(DEV_EE_CTRL4, 0x000F);
    pga411_WriteReg(DEV_EE_CTRL4, 0x0055);
    pga411_WriteReg(DEV_EE_CTRL4, 0x00AA);
    pga411_WriteReg(DEV_EE_CTRL4, 0x00F0);
    }

    // Write default configuration to PGA //
    void pga411_DefaultCfg(void)
    {
    int i;
    // go to diagnostic state //
    pga411_State(DIAG);
    // unlock registers //
    pga411_DeviceUnlock();

    // first 12 registers to default //
    // note: for some u need to unlocked them first ! //
    for (i = 0; i < 12; i++)
    {
    pga411_XmitSPI(WRITE, i, pga411_regs[i].def_val);
    }

    // go to normal state //
    pga411_State(NORMAL);

    }

  • I am happy to help you answer any questions or doubts about programming the C2000 device. From my previous response, I believe the SPI is doing what the code is telling it to do. If SPI is not doing what you expect, please let me know and I can take a look. 

    Were you able to review your logic analyzer plot? As I mentioned, it looks like you are getting data on the MISO pin. That may offer some clues.