ADPD4100 driver issue in adi_adpdssm_getMaxSamplSz

Hi,

I am making a custom board using ADPD4100 with Nordic nRF52840 microcontroller and I have trouble in using the chip with driver here: https://github.com/analogdevicesinc/adpd-drivers/tree/master/adpd40xx

I have two questions:

1/ Is the mentioned driver compatible with ADPD4100?

2/ I used the example code and the application stuck in the :adi_adpdssm_getMaxSamplSz because nMaximumSizeFlag doesn't flag off, since nTotalSampleSize never change to 0. Would you please help me to figure out how to fix this? I used the example and didn't change anything from the driver.

Below is my code:

tAdiAdpdDcfgInst dcfg_ADPD4000[39] =
{
  {0x0009U, 0x0085U},
  {0x000bU, 0x02faU},
  {0x000fU, 0x0006U},
  {0x000dU, 0x4E20U},
  {0x0006U, 0x0003U},
  {0x0014U, 0x8000U},
  {0x001eU, 0x0000U},
  {0x0020U, 0x0004U},
  {0x0021U, 0x0000U},
  {0x0022U, 0x0403U},
  {0x0023U, 0x0002U},
  {0x0024U, 0x0000U},
  {0x0100U, 0x0000U},
  {0x0101U, 0x41daU},
  {0x0102U, 0x0005U},
  {0x0103U, 0x5002U},
  {0x0104U, 0x03C9U},
  {0x0105U, 0x008aU},
  {0x0107U, 0x0101U},
  {0x010aU, 0x0003U},
  {0x010bU, 0x0206U},
  {0x010eU, 0x2000U},
  {0x0110U, 0x0004U},
  {0x0010U, 0x0000U},
	{0xFFFFU, 0xFFFFU}
};

static tAdiAdpdSSmInst oAdiAppInst;
uint8_t aFifoDataBuf[MAX_SAMPLES_IN_FIFO];


/**
*  @brief    Callback function.
*  \param    None
*  @retval   None
*/
static void AdpdFifoCallBack(void)
{
    //adpd4x_int_event.set(1);
}

int mainADPD(void)
{
    uint16_t nAdpdFifoLevelSize;
    ADI_ADPD_COMM_MODE bus_mode;
    uint32_t adpd_ch1 = 0U;
    uint16_t loop = 0U;
    static uint32_t tick = 0U;
    //spi_cs = 1;
    //spi.format(8, 0);
    //spi.frequency(1000000);
    //i2c.frequency(400000);
    if (adi_adpddrv_OpenDriver() != ADI_ADPD_DRV_SUCCESS)
    {
        NRF_LOG_INFO("Error: Cannot open driver. Halt.\r\n");
        DPRINT("Error: Cannot open driver. Halt.\r\n");
        //adpd4x_int_event.wait_any(0xFFFFU); // Do nothing
    }
    
    bus_mode = adi_adpddrv_GetComMode();
    if (bus_mode == E_ADI_ADPD_I2C_BUS)
    {
        DPRINT("\r\nADPD found on I2C");
    } else if (bus_mode == E_ADI_ADPD_SPI_BUS)
    {
        DPRINT("\r\nADPD found on SPI");
    } else
    {
        DPRINT("\r\nError: Unknown bus");
        //adpd4x_int_event.wait_any(0xFFFFU); // Do nothing
    }
    
    /* Load default configuration parameters */
    if (adi_adpdssm_loadDcfg(dcfg_ADPD4000, 0xFFU) != ADI_ADPD_SSM_SUCCESS)
    {
        DPRINT("Error: Cannot configure ADPD400x. Halt.\r\n");
        //adpd4x_int_event.wait_any(0xFFFFU); // Do nothing
    }
    
    //adpd4x_interrupt.fall(&AdpdFifoCallBack);
    
    /* Initialize the helper function module with driver instance */
    adi_adpdssm_slotinit(&oAdiAppInst);
	oAdiAppInst.oAdpdSlotInst.nAdpdFifoWaterMark = 1;
    DPRINT("\r\nInit Slot %d ",oAdiAppInst.oAdpdSlotInst.nAdpdFifoWaterMark);
    
    /* Set Sensor to "Go Mode" */
	 if (adi_adpdssm_setOperationMode(E_ADI_ADPD_MODE_SAMPLE) != ADI_ADPD_DRV_SUCCESS)
    {
			    DPRINT("\r\nCannot set Operation mode. Halt! ");

        while(1);
    }
    
//    while(1)
//    {
//        /* Wait for FIFO_TH Interrupt, see ADPD400x_ISR
//        *  Wait forever for event '1', auto clear 
//        */
//        adpd4x_int_event.wait_any(1U); 
//        uint32_t nRetValue = 0U;
//        // Not using ADPD400x auto clear int flag -> need to clear
//        adi_adpddrv_RegWrite(ADPD4x_REG_INT_STATUS_DATA, 0x8000);
//        /* Read the size of the data available in the FIFO */
//        nRetValue = adi_adpdssm_getFifoLvl(&nAdpdFifoLevelSize);
//        if (nRetValue != ADI_ADPD_DRV_SUCCESS)
//            continue;
//        /* Read the fifo data available in the FIFO */
//        nRetValue = adi_adpddrv_ReadFifoData(nAdpdFifoLevelSize, &aFifoDataBuf[0]);
//        if (nRetValue != ADI_ADPD_DRV_SUCCESS)
//            continue;

//        loop = 0U;
//        adpd_ch1 = 0U;
//        /* Read the data from the FIFO and print them */
//        while (nAdpdFifoLevelSize != 0u) {
//            /* Byte swapping is needed to print ADPD data in proper format */
//            adpd_ch1 = ((aFifoDataBuf[loop] << 8) +
//                        (aFifoDataBuf[loop + 1]) +
//                        (aFifoDataBuf[loop + 2] << 24) +
//                        (aFifoDataBuf[loop + 3] << 16));

//            DPRINT("%u,%u\r\n", tick, adpd_ch1);

//            nAdpdFifoLevelSize -= oAdiAppInst.oAdpdSlotInst.nTotalSlotSz;
//            loop += oAdiAppInst.oAdpdSlotInst.nTotalSlotSz;
//            tick += 1;
//        }
//    }
    DPRINT("\r\nEnd mainADPD");
    return 0;
}

SPI read/write function. I double check the SPI by write and read back register

uint16_t Adpd400x_SPI_Transmit(uint8_t *pTxData, uint16_t Size)
{

	CS_AFE_ACTIVE;

	spi2_master_tx_rx(pTxData, Size, 0, 0, 0);
	
	CS_AFE_INACTIVE;
		
	return(ADI_ADPD_DRV_SUCCESS);
}

uint16_t Adpd400x_SPI_Receive(uint8_t *pTxData, uint8_t *pRxData,
                                     uint16_t TxSize, uint16_t RxSize)
{
	CS_AFE_ACTIVE;
		
	spi2_master_tx_rx(pTxData, TxSize, pRxData, RxSize, 0);
		
	CS_AFE_INACTIVE;
		
	return(ADI_ADPD_DRV_SUCCESS);
}
void spi2_master_tx_rx(uint8_t *DataTx,  uint8_t LenTx, uint8_t *DataRx, uint8_t LenRx, uint8_t CsControl)
{
	#ifndef NODE_IN_SLEEP_MODE
		spi_xfer_done2=false;
		
		APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi2, DataTx, LenTx, DataRx, LenRx));
		while (!spi_xfer_done2){};	
			

	#endif	
}

The function that cause the problem:

static uint16_t _adi_adpdssm_getFifoLevel(uint16_t *pFifoSz)
{
  uint16_t nRet = ADI_ADPD_SSM_SUCCESS;
  /* Calculating LCM for the decimations of all 12 slots */
		DPRINT("\r\n1");

  goAdiAdpdSSmInst->oAdpdSlotInst.nLcmValue = adi_adpdssm_calculate_lcm();
  goAdiAdpdSSmInst->oAdpdSlotInst.nReadSequence = 1U;
  goAdiAdpdSSmInst->oAdpdSlotInst.nInterruptSequence = 1U;
  goAdiAdpdSSmInst->oAdpdSlotInst.nWriteSequence = 1U;
	DPRINT("\r\n%d",goAdiAdpdSSmInst->oAdpdSlotInst.nLcmValue );
  nRet = adi_adpdssm_getMaxSamplSz();// <--- this function has a do while and the program stuck there
	DPRINT("\r\n3");
	
  nRet = adi_adpdssm_getSamplSz(goAdiAdpdSSmInst->oAdpdSlotInst.nAdpdFifoWaterMark,
               &goAdiAdpdSSmInst->oAdpdSlotInst.nInterruptSequence, pFifoSz);
	DPRINT("\r\n4");
	
  return nRet;
}

Thank you so much!

Daniel



Add extra info
[edited by: DanielNguyen at 11:26 AM (GMT -4) on 22 Oct 2021]
  • Hi Daniel,

    The driver is supported for Adpd4100 device.

    Can you share the "oAdiAppInst" parameter details, I suspect the object parameter has wrong information.

    You are mentioned the code is getting stuck because of "nMaximumSizeFlag" is not cleared, this can happen if "oAdiAppInst" has wrong information.

    Regards,

    Sathishkumar K

  • Hi,

    Thank you for your response. I used example in main.cpp, I didn't change anything in oAdiAppInst. Here is the init function:

    uint16_t adi_adpdssm_slotinit(tAdiAdpdSSmInst *pAdpdInstance)
    {
    
      uint8_t nSlotIndex;
      /* Declare variable to track the status of routine */
      uint16_t nRet = ADI_ADPD_SSM_SUCCESS;
      /* Assign the adpd instance object in helper file adpd instance pointer */
      goAdiAdpdSSmInst = pAdpdInstance;
      goAdiAdpdSSmInst->oAdpdSlotInst.nTotalSlotSz = 0U;
      goAdiAdpdSSmInst->oAdpdSlotInst.nHighestSelectedSlot = 0U;
    
      for (nSlotIndex = 0U; nSlotIndex < SLOT_NUM; nSlotIndex++)  {
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nNumChEn = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nSlotFormat = 0x03U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nSlotSampRatio = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nDecimation = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nIsActive = 1U;
        nRet = _adi_adpdssm_slotSaveCurrSetting(nSlotIndex);
      }
      /* need to handle it for worst case so set as 1.*/
      goAdiAdpdSSmInst->oAdpdSlotInst.nAdpdFifoWaterMark = 80;
      goAdiAdpdSSmInst->oAdpdSlotInst.nLcmValue = 1U;
    	uint16_t aa= goAdiAdpdSSmInst->oAdpdSlotInst.nAdpdFifoWaterMark;
    
      /* Return routine status to caller function */
      return nRet;
    }

  • Hi,

    When we call "adi_adpdssm_setOperationMode" API, the Object parameters will get update. We require those details to verify why code is getting stuck in do while loop.

    Regards,

    Sathishkumar K

  • Hi,

    Thank you for your swift response.

    I traced the code, in adi_adpdssm_setOperationMode, it stucks in this function: _adi_adpdssm_CalculateMaxSamplSz, because the flag will never be turned off.

    Besides, can you please explain how the API work? In adi_adpdssm_slotinit, we init the slot but not write the init value into the chip, then call _adi_adpdssm_slotSaveCurrSetting to read current register value and save them in goAdiAdpdSSmInst->oAdpdSlotInst.aPrevSetting, but the API does not write the slot init to register. The only function that write is adi_adpdssm_slotSetActive / _adi_adpdssm_slotApplyPrevSetting but it apply PrevSetting. Also, the adi_adpdssm_slotSetActive has not been called in the example. Can you please give me an example when this should be called?

    If I understand correctly, I need to update the slot configuration by modifying tAdiAdpdDcfgInst dcfg_ADPD4000? Is it possible to manipulate the value by modifying the aPrevSetting?

    uint16_t adi_adpdssm_slotinit(tAdiAdpdSSmInst *pAdpdInstance)
    {
    
      uint8_t nSlotIndex;
      /* Declare variable to track the status of routine */
      uint16_t nRet = ADI_ADPD_SSM_SUCCESS;
      /* Assign the adpd instance object in helper file adpd instance pointer */
      goAdiAdpdSSmInst = pAdpdInstance;
      goAdiAdpdSSmInst->oAdpdSlotInst.nTotalSlotSz = 0U;
      goAdiAdpdSSmInst->oAdpdSlotInst.nHighestSelectedSlot = 0U;
    
      for (nSlotIndex = 0U; nSlotIndex < SLOT_NUM; nSlotIndex++)  {
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nNumChEn = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nSlotFormat = 0x03U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nSlotSampRatio = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nDecimation = 1U;
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nIsActive = 1U;
        nRet = _adi_adpdssm_slotSaveCurrSetting(nSlotIndex); // ------- Get slot information from the chip and store on the pointer
      }
      /* need to handle it for worst case so set as 1.*/
      goAdiAdpdSSmInst->oAdpdSlotInst.nAdpdFifoWaterMark = 80;
      goAdiAdpdSSmInst->oAdpdSlotInst.nLcmValue = 1U;
    
      /* Return routine status to caller function */
      return nRet;
    }
    
    
    uint16_t adi_adpdssm_slotSetActive(uint8_t nSlotNum, uint8_t nActive)
    {
      /* Declare variable to track the status of routine */
      uint16_t nRetCode = ADI_ADPD_SSM_SUCCESS;
      if(goAdiAdpdSSmInst == NULL)
      {
        nRetCode = ADI_ADPD_SSM_PARAM_ERROR;
      }
      else
      {
        if (nActive == 0U)
        {    /* Put a slot to Sleep */
          _adi_adpdssm_slotSaveCurrSetting(nSlotNum);
          _adi_adpdssm_slotApplySkipSetting(nSlotNum);
        }
        else
        {    /* Set a slot awake */
          _adi_adpdssm_slotApplyPrevSetting(nSlotNum); //Apply saved slot information. The current setting is not save?
        }
        goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotNum].nIsActive = nActive;
        goAdiAdpdSSmInst->oAdpdSlotInst.nTotalSlotSz = 0U;          /* reset the sum size. Indicate a slot change */
      }
      /* Return routine status to caller function */
      return nRetCode;
    }
    
    

    Regards,

    Daniel

  • Hi,

    "adi_adpdssm_loadDcfg" API will configure the device register and Init API will call after the "adi_adpdssm_loadDcfg" function. So, that the Init API will do backup register value in buffer for future use.

    Can you check the below Instance parameter value when the code stuck, As per configuration value should updated as below.

    • goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[0].oSlotDataSz.nSignDataSz = 4U;
    • goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[0].nSlotFormat  = 4U;
    • goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nDecimation = 1U;
    • goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nIsActive = 1U;
    • goAdiAdpdSSmInst->oAdpdSlotInst.aSlotInfo[nSlotIndex].nNumChEn = 1U;

    adi_adpdssm_slotSetActive API will use it for enable or disable the slot.

    Yes, we need to modify the tAdiAdpdDcfgInst dcfg_ADPD4000 for new configuration. And, it's not advisable to manipulate the aPrevSetting setting values.