Part Number: LAUNCHXL-F28027F
Other Parts Discussed in Thread: C2000WARE, TMS320F280039C, LAUNCHXL-F28069M, BOOSTXL-DRV8301, MOTORWARE
Hello,
I have tried to read the absolute encoder value (AS5048A) using SPI interface.
Since I could find the AS5048A -C2000 header file on Github, I use it.
I found that the code keep run in the below while loop
" while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){} " in AS5048A.c file.
I used the other SPI code on this community that does not use the AS5048A.h file - Link, the code still goes to that while loop and cannot come out.
I think the point is below point in SPI_getRxFifoStatus function.
SPI_FifoStatus_e status = (SPI_FifoStatus_e)(spi->SPIFFRX & SPI_SPIFFRX_FIFO_ST_BITS); <-- in second picture
spi->SPIFFRX = 8196
SPI_SPIFFRX_FIFO_ST_BITS = (31<<8)


Please give me some advice to solve this issue.
Thank you.
This is main.c code
//#############################################################################
//
// AS5048A library example for C2000: LaunchXL-F28027F
// Communication using SPI with FIFO
//!
//#############################################################################
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "f2802x_common/include/adc.h"
#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/spi.h"
#include "f2802x_common/include/wdog.h"
#include "AS5048A.h"
CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
SPI_Handle mySpi;
AS5048A_Vars_t gAs5048aVars;
void main(void)
{
CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;
// Initialize all the handles needed for this application
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
mySpi = SPI_init((void *)SPIA_BASE_ADDR, sizeof(SPI_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
// Perform basic system initialization
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();
//Select the internal oscillator 1 as the clock source
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);
// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
PLL_setup(myPll, PLL_Multiplier_10, PLL_DivideSelect_ClkIn_by_2);
// Disable the PIE and all interrupts
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);
// If running from flash copy RAM only functions to RAM
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif
AS5048A_gpio_init(myGpio); // Initialize the SPI GPIOs
// Setup a debug vector table and enable the PIE
// PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);
AS5048A_spi_init(mySpi,myClk); // Initialize SPI
AS5048A_fifo_init(mySpi); // Initialize the SPI FIFOs
for(;;) {
// If error flag is high, read the error register and clear the flag
if (gAs5048aVars.errorFlag){
AS5048A_clearErrorReg(mySpi,&gAs5048aVars);
DELAY_US(500);
}
else{
//Get angle
AS5048A_getAngle(mySpi,&gAs5048aVars);
DELAY_US(500);
//Get magnitude
AS5048A_getMagnitude(mySpi,&gAs5048aVars);
DELAY_US(500);
//Read the diagnose register
AS5048A_readDiagnoseReg(mySpi,&gAs5048aVars);
DELAY_US(500);
//Write to the offset register. Examplevalue = 15.50
AS5048A_writeZeroPosReg(mySpi,15.50);
DELAY_US(500);
//Read the offset register.
AS5048A_readZeroPosReg(mySpi,&gAs5048aVars);
DELAY_US(500);
//Read the programming register
AS5048A_readProgrammingReg(mySpi,&gAs5048aVars);
DELAY_US(500);
}
}
}
//===========================================================================
// No more.
//===========================================================================
This is AS5048A.c code
#include <AS5048A.h>
AS5048A_Obj as5048a;
//! \brief Sets up the SPI for communication with the AS5048A sensor
//! \param[in] SPI_Handle, CLK_Handle
void AS5048A_spi_init(SPI_Handle spiHandle,CLK_Handle clkHandle)
{
CLK_enableSpiaClock(clkHandle);
// Reset on, rising edge, 16-bit char bits
SPI_setCharLength(spiHandle, SPI_CharLength_16_Bits);
// Enable master mode, normal phase,
SPI_setMode(spiHandle, SPI_Mode_Master);
SPI_enableTx(spiHandle);
SPI_setBaudRate(spiHandle, SPI_BaudRate_1_MBaud);
SPI_setClkPhase(spiHandle,SPI_ClkPhase_Normal);
SPI_setClkPolarity(spiHandle,SPI_ClkPolarity_OutputRisingEdge_InputFallingEdge);
SPI_disableLoopBack(spiHandle);
SPI_enable(spiHandle);
// Set so breakpoints don't disturb xmission
SPI_setPriority(spiHandle, SPI_Priority_FreeRun);//SPI_Priority_FreeRun
}
//! \brief Sets up the SPI FIFO for communication with the AS5048A sensor
//! \param[in] SPI_Handle
void AS5048A_fifo_init(SPI_Handle spiHandle)
{
// Initialize SPI FIFO registers
SPI_enableChannels(spiHandle);
SPI_enableFifoEnh(spiHandle);
SPI_resetTxFifo(spiHandle);
SPI_clearTxFifoInt(spiHandle);
SPI_resetRxFifo(spiHandle);
SPI_clearRxFifoInt(spiHandle);
SPI_setRxFifoIntLevel(spiHandle, SPI_FifoLevel_4_Words);
}
//! \brief Sets up the SPI GPIO for communication with the AS5048A sensor
//! \param[in] GPIO_Handle
void AS5048A_gpio_init(GPIO_Handle gpioHandle){
// Initalize GPIO
GPIO_setPullUp(gpioHandle, GPIO_Number_16, GPIO_PullUp_Enable);
GPIO_setPullUp(gpioHandle, GPIO_Number_17, GPIO_PullUp_Enable);
GPIO_setPullUp(gpioHandle, GPIO_Number_18, GPIO_PullUp_Enable);
GPIO_setPullUp(gpioHandle, GPIO_Number_19, GPIO_PullUp_Enable);
GPIO_setQualification(gpioHandle, GPIO_Number_16, GPIO_Qual_ASync);
GPIO_setQualification(gpioHandle, GPIO_Number_17, GPIO_Qual_ASync);
GPIO_setQualification(gpioHandle, GPIO_Number_18, GPIO_Qual_ASync);
GPIO_setQualification(gpioHandle, GPIO_Number_19, GPIO_Qual_ASync);
GPIO_setMode(gpioHandle, GPIO_Number_16, GPIO_16_Mode_SPISIMOA);
GPIO_setMode(gpioHandle, GPIO_Number_17, GPIO_17_Mode_SPISOMIA);
GPIO_setMode(gpioHandle, GPIO_Number_18, GPIO_18_Mode_SPICLKA);
GPIO_setMode(gpioHandle, GPIO_Number_19, GPIO_19_Mode_SPISTEA_NOT);
}
//! \brief Calculate the even parity of the command
//! \param[in] uint16_t value
uint16_t AS5048A_CalculateEvenParity(const uint16_t value){
uint16_t x = value;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return ((~x) & 1)<<15;
}
//! \brief Calculate the odd parity of the command
//! \param[in] uint16_t value
uint16_t AS5048A_CalculateOddParity(const uint16_t value){
uint16_t x = value;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return ((x) & 1)<<15;
}
//! \brief Sends a read command for a register and then sends an empty command to read out the feedback
//! \param[in] SPI_Handle, (uint16_t) address
uint16_t AS5048A_read(SPI_Handle spiHandle, const uint16_t address,bool *error){
//Adds parity
uint16_t recivedData;
uint16_t ctrlAddress;
ctrlAddress =address | AS5048A_CalculateEvenParity(address);
//Adds read mask
ctrlAddress |= AS5048A_RW_MASK;
// reset the Rx fifo pointer to zero
SPI_resetRxFifo(spiHandle);
SPI_enableRxFifo(spiHandle);
//Write address to read from
SPI_write(spiHandle,ctrlAddress);
while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){}
//Read last message
SPI_read(spiHandle) ;
//Write NOP to recive the new value
SPI_write(spiHandle,AS5048A_NOP);
while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){}
//Read the value from the addressed register
recivedData=SPI_read(spiHandle);
if (recivedData & 0x4000){
*error=1;
}
return recivedData & ~0xC000;
}
//! \brief Reads the programming register on the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readProgrammingReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
uint16_t newData = AS5048A_read(spiHandle,AS5048A_PROGRAMMING_CONTROL,&Spi_AS5048A_Vars->errorFlag);
Spi_AS5048A_Vars->ProgrammingRegister.PRG_Enable = (bool)(newData & (uint16_t)AS5048A_PROGRAMMING_ENABLE)?1:0;
Spi_AS5048A_Vars->ProgrammingRegister.PRG_burn = (bool)(newData & (uint16_t)AS5048A_PROGRAMMING_BURN)?1:0;
Spi_AS5048A_Vars->ProgrammingRegister.PRG_verify = (bool)(newData & (uint16_t)AS5048A_PROGRAMMING_VERIFY)?1:0;
}
//! \brief Reads the error register and clear the error flag on the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_clearErrorReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
uint16_t newData = AS5048A_read(spiHandle,AS5048A_CLEAR_ERROR_FLAG,&Spi_AS5048A_Vars->errorFlag);
Spi_AS5048A_Vars->ErrorRegister.ERR_framingError = (bool)(newData & (uint16_t)AS5048A_ERROR_FRAME)?1:0;
Spi_AS5048A_Vars->ErrorRegister.ERR_invalidCommand = (bool)(newData & (uint16_t)AS5048A_ERROR_INVALID_COMMAND)?1:0;
Spi_AS5048A_Vars->ErrorRegister.ERR_parityError = (bool)(newData & (uint16_t)AS5048A_ERROR_PARITY)?1:0;
Spi_AS5048A_Vars->errorFlag=0;
}
//! \brief Reads the diagnostics register from the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readDiagnoseReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
uint16_t newData = AS5048A_read(spiHandle,AS5048A_DIAG_AGC,&Spi_AS5048A_Vars->errorFlag);
Spi_AS5048A_Vars->DiagnoseRegister.DIAG_AGC_automaticGain = (char)newData&0xFF;
Spi_AS5048A_Vars->DiagnoseRegister.DIAG_AGC_ocf = (bool)(newData & (uint16_t)AS5048A_DIAG_AGC_OCF)?1:0;
Spi_AS5048A_Vars->DiagnoseRegister.DIAG_AGC_cof = (bool)(newData & (uint16_t)AS5048A_DIAG_AGC_COF)?1:0;
Spi_AS5048A_Vars->DiagnoseRegister.DIAG_AGC_Comp_Low = (bool)(newData & (uint16_t)AS5048A_DIAG_AGC_COMP_LOW)?1:0;
Spi_AS5048A_Vars->DiagnoseRegister.DIAG_AGC_Comp_High = (bool)(newData & (uint16_t)AS5048A_DIAG_AGC_COMP_HIGH)?1:0;
}
//! \brief Reads the zero position from the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readZeroPosReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
uint16_t newDataHigh = AS5048A_read(spiHandle,0x0016,&Spi_AS5048A_Vars->errorFlag);
uint16_t newDataLow = AS5048A_read(spiHandle,0x0017,&Spi_AS5048A_Vars->errorFlag);
Spi_AS5048A_Vars->ZeroPosition.ZERO_POS_HI = (uint16_t)newDataHigh & (uint16_t)0xFF;
Spi_AS5048A_Vars->ZeroPosition.ZERO_POS_LOW = (uint16_t)newDataLow & (uint16_t)0x3F;
Spi_AS5048A_Vars->zeroAngle = (float)((uint16_t)(Spi_AS5048A_Vars->ZeroPosition.ZERO_POS_HI<<6) | (uint16_t)(Spi_AS5048A_Vars->ZeroPosition.ZERO_POS_LOW))*360.0/16384.0;
}
//! \brief Write the zero offset position to the AS5048A
//! \param[in] SPI_Handle, float zeroAngle(degrees)
void AS5048A_writeZeroPosReg(SPI_Handle spiHandle, const float zeroAngle){
uint16_t data;
uint16_t low;
uint16_t high;
data = ((zeroAngle / 360.0)* 16384.0);
low=0x003F & data;
high=(0x3FC0 & data)>>6;
AS5048A_write(spiHandle,AS5048A_OTP_REGISTER_ZERO_POS_HIGH, high);
AS5048A_write(spiHandle,AS5048A_OTP_REGISTER_ZERO_POS_LOW ,low );
}
//! \brief Returns the absolute (multiturn) rotation. This is uses calculation from the MCU
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_getAngle(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
float angle=AS5048A_read(spiHandle,AS5048A_ANGLE,&Spi_AS5048A_Vars->errorFlag) * (360.0 / 16384.0);
float angleDiff=angle- Spi_AS5048A_Vars->angleLastCycle;
if (angleDiff>200){
Spi_AS5048A_Vars->count--;
}
else if(angleDiff<-200){
Spi_AS5048A_Vars->count++;
}
Spi_AS5048A_Vars->angleLastCycle=angle;
Spi_AS5048A_Vars->angleSingleturn = angle;
Spi_AS5048A_Vars->angleMultiturn=Spi_AS5048A_Vars->count*360.0+Spi_AS5048A_Vars->angleSingleturn;
}
//! \brief Sends a read command for a register and read the recive register.(last package)
//! \param[in] SPI_Handle, (uint16_t) address
uint16_t AS5048A_stream(SPI_Handle spiHandle, uint16_t address){
//Adds read mask
address = address | AS5048A_RW_MASK;
//Adds parity
address |= AS5048A_CalculateEvenParity(address);
SPI_write(spiHandle,address);
while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){}
return SPI_read(spiHandle) & ~0xC000;
}
//! \brief Returns the magnitude directly from the AS5048A.
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_getMagnitude(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars){
Spi_AS5048A_Vars->magnitude=AS5048A_read(spiHandle,AS5048A_MAGNITUDE,&Spi_AS5048A_Vars->errorFlag) / 16384.0;
}
//! \brief Sends a write to a register address and then sends the data to write in it
//! \param[in] SPI_Handle, (uint16_t) address, (uint16_t) data
void AS5048A_write(SPI_Handle spiHandle,const uint16_t address,const uint16_t data) {
uint16_t ctrlAddress;
uint16_t ctrlData;
uint16_t n;
//Adds parity
ctrlAddress = address | AS5048A_CalculateOddParity(address);
ctrlData = data | AS5048A_CalculateOddParity(data);
// reset the Rx fifo pointer to zero
SPI_resetRxFifo(spiHandle);
SPI_enableRxFifo(spiHandle);
SPI_write(spiHandle,ctrlAddress);
// wait for registers to update
for(n=0;n<0xdf;n++)
asm(" NOP");
while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){}
//Read last message
SPI_read(spiHandle);
SPI_write(spiHandle,ctrlData);
// wait for registers to update
for(n=0;n<0xdf;n++)
asm(" NOP");
while(SPI_getRxFifoStatus(spiHandle) == SPI_FifoStatus_Empty){}
SPI_read(spiHandle);
}
This is AS5048A.h code
#ifndef _AS5048A_H_
#define _AS5048A_H_
// **************************************************************************
// the includes
#include <stdint.h>
// drivers
//#include "sw/drivers/spi/src/32b/f28x/f2802x/spi.h" <-- dont use
//#include "sw/drivers/gpio/src/32b/f28x/f2802x/gpio.h" <-- dont use
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
//#include "f2802x_common/include/spi.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/spi.h"
#include "f2802x_common/include/clk.h"
#ifdef __cplusplus
extern "C" {
#endif
// **************************************************************************
// the defines
//! \brief Defines the R/W mask
//!
#define AS5048A_RW_MASK (1<<14)
//! \brief Defines the No Operation mask
//!
#define AS5048A_NOP (0x00)
//! \brief Defines the clear error mask
//!
#define AS5048A_CLEAR_ERROR_FLAG (0x0001)
//! \brief Defines the programming control mask
//!
#define AS5048A_PROGRAMMING_CONTROL (0x0003 )
//! \brief Defines the zero position (high) mask
//!
#define AS5048A_OTP_REGISTER_ZERO_POS_HIGH (0x0016 )
//! \brief Defines the zero position (low) mask
//!
#define AS5048A_OTP_REGISTER_ZERO_POS_LOW (0x0017)
//! \brief Defines the Diagnostics + AutomaticGain Control (AGC) a mask
//!
#define AS5048A_DIAG_AGC (0x3FFD)
//! \brief Defines the magnitude control mask
//!
#define AS5048A_MAGNITUDE (0x3FFE)
//! \brief Defines the angle control mask
//!
#define AS5048A_ANGLE (0x3FFF)
//! \brief Defines the framing error bit in the error register
//!
#define AS5048A_ERROR_FRAME (1 << 0)
//! \brief Defines the invalid command bit in the error register
//!
#define AS5048A_ERROR_INVALID_COMMAND (1 << 1)
//! \brief Defines the parity error bit in the error register
//!
#define AS5048A_ERROR_PARITY (1 << 2)
//! \brief Defines the mode bit in the programming register
//!
#define AS5048A_PROGRAMMING_ENABLE (1 << 0)
//! \brief Defines the reserved 1 bit in the programming register
//!
#define AS5048A_PROGRAMMING_RESV1 (1 << 1)
//! \brief Defines the reserved 12 bit in the programming register
//!
#define AS5048A_PROGRAMMING_RESV2 (1 << 2)
//! \brief Defines the burn bit in the programming register
//!
#define AS5048A_PROGRAMMING_BURN (1 << 3)
//! \brief Defines the reserved 3 bit in the programming register
//!
#define AS5048A_PROGRAMMING_RESV3 (1 << 4)
//! \brief Defines the reserved 4 bit in the programming register
//!
#define AS5048A_PROGRAMMING_RESV4 (1 << 5)
//! \brief Defines the verify bit in the programming register
//!
#define AS5048A_PROGRAMMING_VERIFY (1 << 6)
//! \brief Defines the OCF bit in the Diagnostics + AutomaticGain Control register
//!
#define AS5048A_DIAG_AGC_OCF (1 << 8)
//! \brief Defines the COF bit in the Diagnostics + AutomaticGain Control register
//!
#define AS5048A_DIAG_AGC_COF (1 << 9)
//! \brief Defines the Comp Low bit in the Diagnostics + AutomaticGain Control register
//!
#define AS5048A_DIAG_AGC_COMP_LOW (1 << 10)
//! \brief Defines the Comp High bit in the Diagnostics + AutomaticGain Control register
//!
#define AS5048A_DIAG_AGC_COMP_HIGH (1 << 11)
//! \brief Enumeration for the Error register. All errors are cleared by access
//!
typedef enum
{
ERR_framingError = AS5048A_ERROR_FRAME, //!< Framing error
ERR_invalidCommand = AS5048A_ERROR_INVALID_COMMAND, //!< Command Invalid
ERR_parityError = AS5048A_ERROR_PARITY, //!< Parity Error
} AS5048A_errorRegister_e;
//! \brief Enumeration for the programming register.
//! Programming must be enabled before burning the fuse(s). After programming is a
//! verification mandatory.
//!
typedef enum
{
PRG_Enable = AS5048A_PROGRAMMING_ENABLE, //!< Enable programming
PRG_RSV1 = AS5048A_PROGRAMMING_RESV1, //!< Reserved
PRG_RSV2 = AS5048A_PROGRAMMING_RESV2, //!< Reserved
PRG_burn = AS5048A_PROGRAMMING_BURN, //!< Burn
PRG_RSV3 = AS5048A_PROGRAMMING_RESV3, //!< Reserved
PRG_RSV4 = AS5048A_PROGRAMMING_RESV4, //!< Reserved
PRG_verify = AS5048A_PROGRAMMING_VERIFY, //!< Verify
} AS5048A_programmingRegister_e;
//! \brief Enumeration for the Diagnostics + AutomaticGain Control register.
//!
typedef enum
{
DIAG_AGC_ocv = AS5048A_DIAG_AGC_OCF, //!< Offset Compensation Finished
DIAG_AGC_cof = AS5048A_DIAG_AGC_COF, //!< CORDIC Overflow
DIAG_AGC_Comp_Low = AS5048A_DIAG_AGC_COMP_LOW, //!< indicates a high magnetic field. It is recommended to monitor in addition the magnitudevalue.
DIAG_AGC_Comp_High = AS5048A_DIAG_AGC_COMP_HIGH, //!< indicated a weak magnetic field. It is recommended to monitor the magnitude value.
} AS5048A_Diag_AgcRegister_e;
//! \brief Object for the programming register
//!
typedef struct _AS5048A_Error_
{
bool ERR_framingError; // Bit 0
bool ERR_invalidCommand; // Bit 1
bool ERR_parityError; // Bit 2
}AS5048A_Error_;
//! \brief Object for the programming register
//!
typedef struct _AS5048A_Programming_
{
bool PRG_Enable; // Bit 0
bool PRG_RSV1; // Bit 1
bool PRG_RSV2; // Bit 2
bool PRG_burn; // Bit 3
bool PRG_RSV3; // Bit 4
bool PRG_RSV4; // Bit 5
bool PRG_verify; // Bit 6
}AS5048A_Programming_;
//! \brief Object for the Diagnostics + AutomaticGain Control (AGC) register
//!
typedef struct _AS5048A_Diag_Agc_
{
char DIAG_AGC_automaticGain; // Bit 0-7
bool DIAG_AGC_ocf; // Bit 8
bool DIAG_AGC_cof; // Bit 9
bool DIAG_AGC_Comp_Low; // Bit 10
bool DIAG_AGC_Comp_High; // Bit 11
}AS5048A_Diag_Agc_;
//! \brief Object for the OTP Register Zero Position Low register
//!
typedef struct _AS5048A_Zero_Position_
{
uint16_t ZERO_POS_HI; // Bits 7-0
uint16_t ZERO_POS_LOW; // Bits 5-0
}AS5048A_Zero_Position_;
//! \brief Object for the AS5048A registers and commands
//!
typedef struct _AS5048A_Vars_t_
{
AS5048A_Error_ ErrorRegister;
AS5048A_Programming_ ProgrammingRegister;
AS5048A_Zero_Position_ ZeroPosition;
AS5048A_Diag_Agc_ DiagnoseRegister;
int16_t count;
float angleLastCycle;
float angleSingleturn;
float angleMultiturn;
float magnitude;
float zeroAngle;
bool errorFlag;
}AS5048A_Vars_t;
typedef struct _AS5048A_Obj_
{
float a;
}AS5048A_Obj;
//! \brief Defines the AS5048A handle
//!
typedef struct _AS5048A_Obj_ *AS5048A_Handle;
// **************************************************************************
// the functions
//! \brief Sets up the SPI for communication with the AS5048A sensor
//! \param[in] SPI_Handle, CLK_Handle
void AS5048A_spi_init(SPI_Handle spiHandle,CLK_Handle clkHandle);
//! \brief Sets up the SPI FIFO for communication with the AS5048A sensor
//! \param[in] SPI_Handle
void AS5048A_fifo_init(SPI_Handle spiHandle);
//! \brief Sets up the SPI GPIO for communication with the AS5048A sensor
//! \param[in] GPIO_Handle
void AS5048A_gpio_init(GPIO_Handle gpioHandle);
//! \brief Calculate the even parity of the command
//! \param[in] uint16_t value
uint16_t AS5048A_CalculateEvenParity(const uint16_t value);
//! \brief Calculate the odd parity of the command
//! \param[in] uint16_t value
uint16_t AS5048A_CalculateOddParity(const uint16_t value);
//! \brief Sends a read command for a register and then sends an empty command to read out the feedback
//! \param[in] SPI_Handle, (uint16_t) address
uint16_t AS5048A_read(SPI_Handle spiHandle, const uint16_t address,bool *error);
//! \brief Reads the programming register on the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readProgrammingReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Reads the error register and clear the error flag on the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_clearErrorReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Reads the diagnostics register from the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readDiagnoseReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Reads the zero position from the AS5048A
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_readZeroPosReg(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Write the zero offset position to the AS5048A
//! \param[in] SPI_Handle, float zeroAngle(degrees)
void AS5048A_writeZeroPosReg(SPI_Handle spiHandle, const float zeroAngle);
//! \brief Returns the absolute (multiturn) rotation. This is uses calculation from the MCU
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_getAngle(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Sends a read command for a register and read the recive register.(last package)
//! \param[in] SPI_Handle, (uint16_t) address
uint16_t AS5048A_stream(SPI_Handle spiHandle, uint16_t address);
//! \brief Returns the magnitude directly from the AS5048A.
//! \param[in] SPI_Handle, AS5048A_Vars_t
void AS5048A_getMagnitude(SPI_Handle spiHandle, AS5048A_Vars_t *Spi_AS5048A_Vars);
//! \brief Sends a write to a register address and then sends the data to write in it
//! \param[in] SPI_Handle, (uint16_t) address, (uint16_t) data
void AS5048A_write(SPI_Handle spiHandle, const uint16_t address, const uint16_t data);
extern AS5048A_Obj as5048a;
#endif



