Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ADMX2001.cpp
- Committer:
- nsheth
- Date:
- 2021-11-02
- Revision:
- 10:49537b1dbbd7
- Parent:
- 9:f286301109fb
- Child:
- 11:071709f5f7d4
File content as of revision 10:49537b1dbbd7:
/* Copyright (c) 2021 Analog Devices, Inc. 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.
- Modified versions of the software must be conspicuously marked as such.
- This software is licensed solely and exclusively for use with processors/products
manufactured by or for Analog Devices, Inc.
- This software may not be combined or merged with other code in any manner
that would cause the software to become subject to terms and conditions which
differ from those listed here.
- Neither the name of Analog Devices, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
- The use of this software may or may not infringe the patent rights of one or
more patent holders. This license does not release you from the requirement
that you obtain separate licenses from these patent holders to use this software.
THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL
PROPERTY RIGHTS INFRINGEMENT; 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.
2021-01-10-7CBSD SLA
*/
/**
* @file ADMX2001.cpp
* @brief This file contains admx200x APIs for sdpk1 host
* @addtogroup SDPK1
* @{
*/
/*============= I N C L U D E S =============*/
#include "ADMX2001.h"
#include "ADMX2001_commands.h"
#include "message.h"
#include <stdlib.h>
#include <string.h>
static uint32_t SwapEndian(uint32_t *pData);
/** milli second delay**/
static void Admx200xDelay(uint32_t msec);
/**
* Swaps endian of a 32 bit number
* @param data - 32 bit number
* @return
*/
uint32_t SwapEndian(uint32_t *pData)
{
uint8_t *pDataU8 = (uint8_t *)pData;
return (uint32_t)pDataU8[0] << 24 | (uint32_t)pDataU8[1] << 16 |
(uint32_t)pDataU8[2] << 8 | (uint32_t)pDataU8[3];
}
/**
* @brief Initializes the ADMX200X.
*
* @param pDevice - The device structure.
* @param pSpiDesc - Pointer to spi device
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xInit(Admx200xDev *pDevice, spi_desc *pSpiDesc)
{
int32_t ret = 0;
pDevice->pSpiDesc = pSpiDesc;
return ret;
}
/**
* Wrapper fro delay
* @param msecs - delay in milliseconds
*/
void Admx200xDelay(uint32_t msecs)
{
mdelay(msecs);
}
/**
* @brief Create a command payload in buffer with inputs.
*
* @param pCmdId - Command ID.
* @param pAddr - Sub commands addresses.
* @param pData - Data to wildcat.
* @param pBuffer - Data to wildcat.
*
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xCreateCmdPayload(uint8_t *pCmdId, uint16_t *pAddr,
uint32_t *pData, uint8_t *pBuffer)
{
int32_t ret = 0;
//DEBUG_MSG("cmd:%d,addr:%d, data: 0x%x\n\r", *pCmdId, *pAddr, *pData);
pBuffer[0] = pCmdId[0];
pBuffer[1] = ((uint8_t *)pAddr)[1];
pBuffer[2] = ((uint8_t *)pAddr)[0];
pBuffer[3] = ((uint8_t *)pData)[3];
pBuffer[4] = ((uint8_t *)pData)[2];
pBuffer[5] = ((uint8_t *)pData)[1];
pBuffer[6] = ((uint8_t *)pData)[0];
return ret;
}
/**
* @brief Parse the payload to get cmdID, addr and data.
* @param[in] pBuffer - Data from wildcat.
* @param[out] pCmdId - Pointer to store Command ID.
* @param[out] pAddr - Pointer to store addresses.
* @param[out] pData - Pointer to store Data
*
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xParseCmdPayload(uint8_t *pBuffer, uint8_t *pCmdId,
uint16_t *pAddr, uint32_t *pData)
{
int32_t ret = 0;
*pCmdId = pBuffer[0];
*pAddr = ((uint16_t)pBuffer[1] << 8) | ((uint16_t)pBuffer[2]);
*pData = SwapEndian((uint32_t *)&pBuffer[3]);
return ret;
}
/**
* @brief Waits till done bit is set in the status
*
* @param pDevice - The handler of the instance of the driver.
* @param timeout - Count representing the number of polls to be done until the
* function returns if no new data is available.
* @param reqStatus - The status to be checked is passed via this argument.
* @param pStatReg - Get the status word in pStatReg.
*
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xWaitForStatus(Admx200xDev *pDevice, uint32_t timeout,
uint32_t reqStatus, uint32_t *pStatReg)
{
int32_t status = ADMX_STATUS_SUCCESS;
int8_t done = 0;
uint8_t cmdId = CMD_STATUS_READ;
if (pDevice != NULL)
{
while (!done && --timeout)
{
status = Admx200xReadData(pDevice, cmdId, pStatReg);
if (status == 0)
{
/* Check the DONE bit in the Status Register */
if (((*pStatReg) & reqStatus) == reqStatus)
{
done = 1;
if (*pStatReg & ADMX200X_STATUS_ERROR_BITM)
{
status = *pStatReg & ADMX200X_STATUS_CODE_BITM;
if (status & ADMX_STATUS_LOG_ZERO_ERROR)
{
ERROR_MSG("sweep_start/sweep_end cannot be zero "
"for logarithmic sweep");
status &= (~ADMX_STATUS_LOG_ZERO_ERROR);
}
if (status & ADMX_STATUS_LOG_SIGN_ERROR)
{
ERROR_MSG("sweep_start and sweep_end need to have "
"the same sign "
"for logarithmic sweep");
status &= (~ADMX_STATUS_LOG_SIGN_ERROR);
}
if (status & ADMX_STATUS_VOLT_ADC_ERROR)
{
ERROR_MSG("Voltage ADC Saturated\n");
status &= (~ADMX_STATUS_VOLT_ADC_ERROR);
}
if (status & ADMX_STATUS_CURR_ADC_ERROR)
{
ERROR_MSG("Current ADC Saturated\n");
status &= (~ADMX_STATUS_CURR_ADC_ERROR);
}
if (status & ADMX_STATUS_FIFO_ERROR)
{
ERROR_MSG(
"FIFO either Overflowed or Underflowed\n");
status &= (~ADMX_STATUS_FIFO_ERROR);
}
if (status & ADMX_STATUS_COUNT_EXCEEDED)
{
ERROR_MSG("Sweep count exceeded maximum value");
status &= (~ADMX_STATUS_COUNT_EXCEEDED);
}
}
}
}
}
if (!timeout)
{
status = ADMX_STATUS_TIMEOUT;
}
}
else
{
status = ADMX_STATUS_FAILED;
}
return status;
}
/**
* @brief Sends teh command to ADMX200x and wait till done bit is set
* @param pDevice - Device Handle
* @param pCmdId - The command ID
* @param pAddr - Address
* @param pData - Data
* @param pStatReg - Status register info
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xSendCmd(Admx200xDev *pDevice, uint8_t *pCmdId, uint16_t *pAddr,
uint32_t *pData, uint32_t *pStatReg)
{
int32_t status = ADMX_STATUS_SUCCESS;
uint8_t cmdPayload[ADMX200X_CMD_LENGTH];
Admx200xCreateCmdPayload(pCmdId, pAddr, pData, &cmdPayload[0]);
status = spi_write_and_read(pDevice->pSpiDesc, &cmdPayload[0],
ADMX200X_CMD_LENGTH);
Admx200xDelay(100);
// printf("CMD :%02x ADDR: %04x DATA: %08x\n\r",*pCmdId, *pAddr, *pData);
if (!status)
{
/** Wait for status done = 1,Warn/error/command result = 0 from result
*/
status = Admx200xWaitForStatus(pDevice, SPI_TIMEOUT,
ADMX200X_STATUS_DONE_BITM, pStatReg);
//printf("Stat Reg: %08x\n\r", *pStatReg);
if (status == ADMX_STATUS_SUCCESS)
{
status = *pStatReg & ADMX200X_STATUS_CODE_BITM;
}
}
if (status == ADMX_STATUS_TIMEOUT)
{
ERROR_MSG("SPI interface timed out : Not responding");
}
return status;
}
/**
* @brief Read result register from the WILDCAT
* @param pDevice - Device Handle
* @param cmdId - This determines where the data is read from - result
* register, status register or Fifo
* @param pResult - The data in the result register
* @return Returns 0 for success or negative error code.
*/
int32_t Admx200xReadData(Admx200xDev *pDevice, uint8_t cmdId, uint32_t *pResult)
{
int32_t ret = ADMX_STATUS_SUCCESS;
uint8_t cmdTemp;
uint16_t addrTemp;
uint16_t addr;
uint32_t data;
uint8_t cmdPayload[ADMX200X_CMD_LENGTH];
/*FIXME: Insert checks here. Not all command IDs are accepted here */
addr = 0;
data = 0;
Admx200xCreateCmdPayload(&cmdId, &addr, &data, &cmdPayload[0]);
/* Send command and Read response from the slave */
ret = spi_write_and_read(pDevice->pSpiDesc, &cmdPayload[0],
ADMX200X_CMD_LENGTH);
Admx200xDelay(100);
Admx200xParseCmdPayload(&cmdPayload[0], &cmdTemp, &addrTemp, pResult);
return ret;
}
/**
* @brief Read array of datatype doube from the fifo of the WILDCAT
* @param pDevice - Device Handle
* @param pFifo - Double array that stores the data
* @param pCount - Stores the number of double values stored in the pFifo array
*/
int32_t Admx200xReadFifo(Admx200xDev *pDevice, double *pFifo, int32_t *pCount)
{
int32_t status = ADMX_STATUS_SUCCESS;
int32_t i;
uint32_t *pData = (uint32_t *)pFifo;
uint8_t cmdId = CMD_STATUS_READ;
uint32_t statusReg;
int32_t numDoublesInFifo;
status = Admx200xReadData(pDevice, cmdId, &statusReg);
/* Fifo depth in doubles */
numDoublesInFifo = (statusReg & ADMX200X_STATUS_FIFO_DEPTH_BITM) >> 17;
if (numDoublesInFifo < *pCount)
{
*pCount = numDoublesInFifo;
}
for (i = 0; i < *pCount; i++)
{
/* Read a double -- Split it into two reads for redability*/
Admx200xReadData(pDevice, CMD_FIFO_READ, &pData[2 * i]);
Admx200xReadData(pDevice, CMD_FIFO_READ, &pData[2 * i + 1]);
}
return status;
}
/**
* @brief Clears the Admx2001 SPI FIFO & errors
*
* @param pDevice - Device Handle
* @return Returns 0 for success or error code.
*/
int32_t Admx200xClearSPI(Admx200xDev *pDevice)
{
int32_t status = ADMX_STATUS_SUCCESS;
uint8_t cmdID;
uint16_t addr = 0;
uint32_t statReg = 0;
uint32_t data = 0;
cmdID = CMD_CLEAR_ERROR;
status = Admx200xSendCmd(pDevice, &cmdID, &addr, &data, &statReg);
return status;
}
/**
* @}
*/
