Nisarg Sheth / ADMX2001
Revision:
2:4af4940055a7
Parent:
1:416c87ab2f9f
Child:
4:eb7a23c25751
--- a/ADMX2001.cpp	Tue May 25 15:45:50 2021 +0000
+++ b/ADMX2001.cpp	Tue Oct 05 10:31:50 2021 +0000
@@ -0,0 +1,325 @@
+/******************************************************************************
+ Copyright (c) 2020 - 2021  Analog Devices Inc. All Rights Reserved.
+ This software is proprietary & confidential to Analog Devices, Inc.
+ and its licensors.
+******************************************************************************/
+/**
+ * @file     admx200x.c
+ * @brief    This file contains admx200x APIs for sdpk1 host
+ * @addtogroup SDPK1
+ * @{
+ */
+/*=============  I N C L U D E S   =============*/
+#include "admx200x.h"
+#include "admx200x_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;
+}
+
+/**
+ * @}
+ */