3280 lines
139 KiB
C
Executable File
3280 lines
139 KiB
C
Executable File
/**
|
|
* \file talise.c
|
|
* \brief Contains top level functions to support initialization and ctrol of
|
|
* the Talise transceiver device.
|
|
*
|
|
* Talise API version: 3.5.0.2
|
|
*
|
|
* Copyright 2015-2017 Analog Devices Inc.
|
|
* Released under the AD9378-AD9379 API license, for more information see the "LICENSE.txt" file in this zip file.
|
|
*/
|
|
|
|
/**
|
|
* \mainpage Overview
|
|
*
|
|
* This document is intended for use by software engineering professionals
|
|
* and includes detailed information regarding the data types and
|
|
* function calls which comprise the Talise ANSI C API
|
|
*
|
|
* Copyright 2015-2017 Analog Devices Inc.
|
|
* Released under the AD9378-AD9379 API license, for more information see the "LICENSE.txt" file in this zip file.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* \page Suggested Use
|
|
* The purpose of the Talise Application Programming Interface (API) is to abstract the low-level
|
|
* SPI configuration, control, and related calculations required for the Talise family of transceiver devices
|
|
*
|
|
* Add the included source code as required to your baseband processor software build. Please reference the integration document
|
|
* as well for further instructions.
|
|
*/
|
|
|
|
/**
|
|
* \page Architecture Talise API Software Architecture
|
|
* \image html software_architecture.png
|
|
*/
|
|
|
|
/**
|
|
* \page Folders Talise API Folder Structure
|
|
* \image html folder_structure.png
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "talise.h"
|
|
#include "talise_reg_addr_macros.h"
|
|
#include "talise_arm.h"
|
|
#include "talise_hal.h"
|
|
#include "talise_user.h"
|
|
#include "talise_error.h"
|
|
#include "talise_version.h"
|
|
#include "talise_rx.h"
|
|
#include "talise_tx.h"
|
|
#include "talise_jesd204.h"
|
|
#include "talise_cals.h"
|
|
#include "talise.h"
|
|
|
|
#define DBG_TALISE_SPI_PR (1)
|
|
|
|
uint32_t TALISE_openHw(taliseDevice_t *device)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
ADIHAL_setLogLevel(device->devHalInfo, TALISE_LOGGING);
|
|
halError = ADIHAL_openHw(device->devHalInfo, 100);
|
|
if (halError != ADIHAL_OK)
|
|
{
|
|
switch(halError)
|
|
{
|
|
case ADIHAL_SPI_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_SPI,
|
|
halError, retVal, TALACT_ERR_RESET_SPI);
|
|
case ADIHAL_GPIO_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_GPIO,
|
|
halError, retVal, TALACT_ERR_RESET_GPIO);
|
|
case ADIHAL_TIMER_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_WAIT, halError,
|
|
retVal, TALACT_ERR_CHECK_TIMER);
|
|
case ADIHAL_GEN_SW:
|
|
default:
|
|
return (uint32_t)TALACT_ERR_CHECK_PARAM;
|
|
}
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_closeHw(taliseDevice_t *device)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
halError = ADIHAL_closeHw(device->devHalInfo);
|
|
|
|
if (halError != ADIHAL_OK)
|
|
{
|
|
switch(halError)
|
|
{
|
|
case ADIHAL_SPI_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_SPI,
|
|
halError, retVal, TALACT_ERR_RESET_SPI);
|
|
case ADIHAL_GPIO_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_GPIO,
|
|
halError, retVal, TALACT_ERR_RESET_GPIO);
|
|
case ADIHAL_TIMER_FAIL:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_HAL_WAIT,
|
|
halError, retVal, TALACT_ERR_CHECK_TIMER);
|
|
case ADIHAL_GEN_SW:
|
|
default:
|
|
return (uint32_t)TALACT_ERR_CHECK_PARAM;
|
|
}
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_resetDevice(taliseDevice_t *device)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_resetDevice()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
/* toggle RESETB on device with matching spi chip select index */
|
|
halError = ADIHAL_resetHw(device->devHalInfo);
|
|
if (halError == ADIHAL_WAIT_TIMEOUT)
|
|
{
|
|
/*Retry*/
|
|
halError = ADIHAL_resetHw(device->devHalInfo);
|
|
}
|
|
|
|
if (halError != ADIHAL_OK)
|
|
{
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_GPIO, halError, retVal, TALACT_ERR_RESET_GPIO);
|
|
}
|
|
|
|
/* Power down deserializers */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_0, 0xF0);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_4, 0x2F);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
device->devStateInfo.devState = TAL_STATE_POWERONRESET;
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
static talRecoveryActions_t talInitializeDdc(taliseDevice_t *device, taliseInit_t *init)
|
|
{
|
|
uint8_t totalFramerM = 0;
|
|
uint8_t combineBands = 0;
|
|
uint8_t pfirOutDecimation = 0;
|
|
uint8_t ncoPhaseAccumDivideRatio = 0;
|
|
uint8_t rxNco1PhaseAccumDivideRatio = 0;
|
|
uint8_t rxNco2PhaseAccumDivideRatio = 0;
|
|
uint8_t registerValue = 0;
|
|
uint8_t rxNcoControl = 0;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
|
|
static const uint8_t RX_DUALBAND_ENABLED = 1;
|
|
static const uint8_t RX_DUALBAND_DISABLED = 0;
|
|
static const uint8_t ENABLE_NCO1 = 0x01;
|
|
static const uint8_t ENABLE_NCO2 = 0x40;
|
|
static const uint8_t ENABLE_NCO1_REALIF = 0x20;
|
|
static const uint8_t ENABLE_NCO2_REALIF = 0x80;
|
|
static const uint8_t DDC_DEC2 = 0x04; /* Set DDC Mode and enable bit */
|
|
static const uint8_t DDC_INT2 = 0x14; /* Set DDC Mode and enable bit */
|
|
static const uint8_t DDC_LOWPASS = 0x0C; /* Set DDC Mode and enable bit */
|
|
|
|
/* Verify Null pointer to *init */
|
|
if (init == NULL)
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INITIALIZE_DDC_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) &&
|
|
(init->rx.rxChannels != TAL_RXOFF))
|
|
{
|
|
/* Phase accumulator calculation for NCO : FLOGB2(Decimation at PFIR out) - 2 */
|
|
/* The -2 is because NCO clock is divided version of the div4/5 clock */
|
|
/* For TAL_RXDDC_ZIF_TO_RIF_INT2 mode, Decimation at PFIR should be more than 8 since it is going to be interpolated */
|
|
pfirOutDecimation = init->rx.rxProfile.rxDec5Decimation * init->rx.rxProfile.rhb1Decimation * init->rx.rxProfile.rxFirDecimation;
|
|
if (((pfirOutDecimation < 4) && (init->rx.rxProfile.rxDdcMode != TAL_RXDDC_INT2)) ||
|
|
((pfirOutDecimation < 8) && (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF)) ||
|
|
(pfirOutDecimation > 40))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INITIALIZE_DDC_INV_DEC_AT_PFIR, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
else
|
|
{
|
|
pfirOutDecimation >>= 3;
|
|
for (ncoPhaseAccumDivideRatio = 0; ncoPhaseAccumDivideRatio < 3; ncoPhaseAccumDivideRatio++)
|
|
{
|
|
if (pfirOutDecimation == 0)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pfirOutDecimation >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
device->devStateInfo.rxDualBandEnabled = RX_DUALBAND_DISABLED;
|
|
device->devStateInfo.rxOutputRate_kHz = init->rx.rxProfile.rxOutputRate_kHz;
|
|
|
|
|
|
/* Dualband mode */
|
|
if ((init->rx.rxProfile.rxNcoShifterCfg.bandAInputBandWidth_kHz != 0) &&
|
|
(init->rx.rxProfile.rxNcoShifterCfg.bandBInputBandWidth_kHz != 0))
|
|
{
|
|
/* Total number of converters */
|
|
totalFramerM = (((init->rx.framerSel == TAL_FRAMER_A) || (init->rx.framerSel == TAL_FRAMER_A_AND_B)) ? init->jesd204Settings.framerA.M : 0) +
|
|
(((init->rx.framerSel == TAL_FRAMER_B) || (init->rx.framerSel == TAL_FRAMER_A_AND_B)) ? init->jesd204Settings.framerB.M : 0);
|
|
|
|
/* If one Rx enabled and M = 2, combine two bands. If M = 4, separate them */
|
|
/* If two Rx enabled and M = 4, combine two bands. If M = 8, separate them */
|
|
if ((init->rx.rxChannels == TAL_RX1) ||
|
|
(init->rx.rxChannels == TAL_RX2))
|
|
{
|
|
if ((totalFramerM != 2) && (totalFramerM != 4))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INITIALIZE_DDC_INV_TOTAL_M_2OR4, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
combineBands = (totalFramerM == 2) ? 1 : 0;
|
|
}
|
|
else /* TAL_RX1RX2 */
|
|
{
|
|
if ((totalFramerM != 4) && (totalFramerM != 8))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INITIALIZE_DDC_INV_TOTAL_M_4OR8, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
combineBands = (totalFramerM == 4) ? 1 : 0;
|
|
}
|
|
|
|
/* Phase accumulator calculation for NCO1 : FLOGB2(Decimation at PFIR out) - 2 */
|
|
rxNco1PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio;
|
|
|
|
/* Phase accumulator calculation for NCO2 : NCO1 + 1 */
|
|
rxNco2PhaseAccumDivideRatio = rxNco1PhaseAccumDivideRatio + 1;
|
|
|
|
/* Setup value of NCO1 and NCO2 */
|
|
registerValue = (rxNco2PhaseAccumDivideRatio << 4) | rxNco1PhaseAccumDivideRatio;
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_7, registerValue, 0x73, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
/* NCO configuration: NCO1 enable, DDC HB enable, DDC mode = Dec2, NCO2 enable */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_NCO_CONTROL_0, 0x45, 0xFD, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
/* Band configuration : Band A enable, Band B enable, Combine bands */
|
|
registerValue = (combineBands << 2) | 0x3;
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_BAND_CONTROL, registerValue);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
/* Select Real IF output for NCO2 */
|
|
if (init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF)
|
|
{
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_NCO_CONTROL_0, 0x80, 0x80, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
}
|
|
|
|
/* Initialize Dual Band Settings */
|
|
retVal = talSetDualBandSettings(device, init);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
device->devStateInfo.rxDualBandEnabled = RX_DUALBAND_ENABLED;
|
|
}/* end dualband */
|
|
|
|
/* Not Dualband */
|
|
else
|
|
{
|
|
/* Phase accumulator calculation for NCO1 : FLOGB2(Decimation at PFIR out) - 2 */
|
|
rxNco1PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio;
|
|
rxNcoControl = 0;
|
|
|
|
switch(init->rx.rxProfile.rxDdcMode)
|
|
{
|
|
case TAL_RXDDC_BYPASS:
|
|
case TAL_RXDDC_BYPASS_REALIF:
|
|
rxNco2PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio;
|
|
/* Leave rxNcoControl = 0 to bypass DDC HB */
|
|
break;
|
|
|
|
case TAL_RXDDC_FILTERONLY:
|
|
case TAL_RXDDC_FILTERONLY_REALIF:
|
|
rxNco2PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio;
|
|
rxNcoControl |= DDC_LOWPASS;
|
|
break;
|
|
|
|
case TAL_RXDDC_DEC2:
|
|
case TAL_RXDDC_DEC2_REALIF:
|
|
rxNco2PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio + 1;
|
|
rxNcoControl |= DDC_DEC2;
|
|
break;
|
|
|
|
case TAL_RXDDC_INT2:
|
|
case TAL_RXDDC_INT2_REALIF:
|
|
rxNco2PhaseAccumDivideRatio = ncoPhaseAccumDivideRatio - 1;
|
|
rxNcoControl |= DDC_INT2;
|
|
break;
|
|
|
|
default:
|
|
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INITIALIZE_DDC_INV_RXDDCMODE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* if nco1 shift */
|
|
if (init->rx.rxProfile.rxNcoShifterCfg.bandANco1Freq_kHz != 0)
|
|
{
|
|
rxNcoControl |= ENABLE_NCO1;
|
|
|
|
if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
|
|
{
|
|
rxNcoControl |= ENABLE_NCO1_REALIF;
|
|
}
|
|
}
|
|
|
|
/* if nco2 shift */
|
|
if (init->rx.rxProfile.rxNcoShifterCfg.bandANco2Freq_kHz != 0)
|
|
{
|
|
rxNcoControl |= ENABLE_NCO2;
|
|
|
|
if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
|
|
{
|
|
rxNcoControl &= ~ENABLE_NCO1_REALIF;
|
|
rxNcoControl |= ENABLE_NCO2_REALIF;
|
|
}
|
|
}
|
|
|
|
/* Setup value of NCO2 phase accum clock */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_7, ((rxNco2PhaseAccumDivideRatio << 4) | rxNco1PhaseAccumDivideRatio), 0x73, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
/* Set DDC HB mode, and NCO1/2 enable/disable bits */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_NCO_CONTROL_0, rxNcoControl, 0xFD, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN(retVal);
|
|
|
|
/* Initialize single band shift Settings */
|
|
retVal = talSetupNcoShifter(device, init);
|
|
IF_ERR_RETURN(retVal);
|
|
} /* end Not Dualband */
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
int check_err_state(uint32_t err_ret)
|
|
{
|
|
return ((err_ret>TALACT_WARN_RESET_GPIO)?1:0);
|
|
|
|
}
|
|
char str_err[2][6]={"-----","error"};
|
|
|
|
uint32_t TALISE_initialize(taliseDevice_t *device, taliseInit_t *init)
|
|
{
|
|
//printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
talRecoveryActions_t retValWarn = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t txChannelSettings = 0;
|
|
uint8_t rxChannelSettings = 0;
|
|
uint8_t orxChannelSettings = 0;
|
|
uint8_t dacClockRateSelect = 0;
|
|
uint8_t rxFirDecBitField = 0;
|
|
uint8_t orxFirDecBitField = 0;
|
|
uint8_t digDeviceClockDiv = 0;
|
|
uint32_t digRefClock_MHz = 0;
|
|
taliseInfo_t clearInfo = {(taliseStates_t)0,0,0,0,0,{0,0,(taliseHsDiv_t)0,0,0},
|
|
(taliseGainMode_t)0,{0,0,0,0,0,0,0,0},(taliseTxAttenStepSize_t)0,
|
|
0,0,0,0,0,0,0,(taliseRxDdc_t)0,0,0,0};
|
|
uint32_t agcClock_Hz = 0;
|
|
uint32_t gainUpdateCount = 0;
|
|
taliseAdcSampleXbar_t adcXbar = {(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0,(taliseAdcSampleXbarSelect_t)0};
|
|
taliseDacSampleXbar_t dacXbar = {(taliseDacSampleXbarSelect_t)0,(taliseDacSampleXbarSelect_t)0};
|
|
uint8_t deframerSyncPadCfg = 0;
|
|
uint16_t syncbPadCfgAddr = 0;
|
|
uint8_t framerSyncPadCfg = 0;
|
|
uint8_t sysrefCfg = 0;
|
|
uint8_t regData = 0;
|
|
int err_flg=0;
|
|
|
|
static const uint8_t ULB_THRESHOLD = 0x27;
|
|
static const uint8_t ULB2_THRESHOLD = 0x37;
|
|
static const uint8_t LLB_THRESHOLD = 0x1b;
|
|
static const uint8_t LLB2_THRESHOLD = 0x27;
|
|
static const uint8_t GPINT_MASK_AUXPLL = 1;
|
|
static const uint8_t MIN_SUPPORTED_SIREV = 0xB1;
|
|
static const uint8_t TPC_MODE_TX1_SPI = 0x01;
|
|
static const uint8_t TPC_MODE_TX2_SPI = 0x04;
|
|
|
|
/* Verify pointers to *device and *init are not NULL */
|
|
if (device == NULL)
|
|
{
|
|
/* Can not write to log since log function requires device data structure */
|
|
return (uint32_t)TALACT_ERR_CHECK_PARAM;
|
|
}
|
|
|
|
if (init == NULL)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_INIT_NULLPARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_initialize()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
//printf("[%s,%d] retVal=%d\n", __FUNCTION__, __LINE__,retVal);
|
|
retValWarn = retVal;
|
|
|
|
/* clear memory of Talise API state container */
|
|
device->devStateInfo = clearInfo;
|
|
|
|
device->devStateInfo.txAttenStepSize = init->tx.txAttenStepSize;
|
|
|
|
/* Calculate digital clocks based on information in init structure */
|
|
retVal = (talRecoveryActions_t)TALISE_calculateDigitalClocks(device, &init->clocks);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Verify Rx/Tx and ObsRx profiles are valid combinations
|
|
* and set device->devStateInfo.profilesValid member based on init struct settings
|
|
*/
|
|
retVal = (talRecoveryActions_t)TALISE_verifyProfiles(device, init);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [TALISE_verifyProfiles]\n",retVal, str_err[err_flg]);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set 3 or 4-wire SPI mode, MSBFirst/LSBfirst in device, pushes CPOL=0, CPHA=0, longInstWord=1 into device->spiSettings */
|
|
retVal = (talRecoveryActions_t)TALISE_setSpiSettings(device, &init->spiSettings);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [TALISE_setSpiSettings]\n",retVal, str_err[err_flg]);
|
|
printf("msb=%d,en=%d,auto=%d,four=%d,cmos=%d\n",init->spiSettings.MSBFirst,init->spiSettings.enSpiStreaming,
|
|
init->spiSettings.fourWireMode,init->spiSettings.cmosPadDrvStrength);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Read device silicon revision */
|
|
retVal = (talRecoveryActions_t)TALISE_getDeviceRev(device, &device->devStateInfo.deviceSiRev);
|
|
err_flg = check_err_state(retVal);
|
|
printf("deviceSiRev=0x%x (%s) [TALISE_getDeviceRev]\n",device->devStateInfo.deviceSiRev, str_err[err_flg]);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
|
|
/* Make sure Silicon is at least B1 silicon. API supports B1, C0 silicon and should work with any future silicon */
|
|
if (device->devStateInfo.deviceSiRev < MIN_SUPPORTED_SIREV)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_API_FAIL,
|
|
TAL_ERR_INV_SIREV, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
printf("[%s,%d] retVal=%d\n", __FUNCTION__, __LINE__,retVal);
|
|
|
|
/* Disable stream processor TxEnable/RxEnable pin control mode */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RADIO_CONTROL_CONFIG1, 0x00);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] retVal=%d\n", __FUNCTION__, __LINE__,retVal);
|
|
|
|
/* Enable Reference clock - Set REFCLK pad common mode voltage */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_REF_PAD_CONFIG2, 0x07);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set Master bias trim and reset bandgap */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MASTERBIAS_CONFIG1, 0x0F);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MASTERBIAS_CONFIG0, 0x30);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MASTERBIAS_CONFIG0, 0x10);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] retVal=%d\n", __FUNCTION__, __LINE__,retVal);
|
|
sysrefCfg = (((init->jesd204Settings.sysrefLvdsMode > 0) ? 1 : 0) << 1) | /* Set SYSREF PAD for LVDS mode = 1, or CMOS mode = 0 */
|
|
(((init->jesd204Settings.sysrefLvdsPnInvert > 0) ? 1 : 0) << 2) |
|
|
(((init->jesd204Settings.sysrefLvdsMode > 0) ? 1 : 0) << 4); /* Set LVDS 100 ohm input termination */
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SYSREF_PAD_CONFIG, sysrefCfg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* mask the RF PLL GP Interrupt */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GP_INTERRUPT_MASK_1, GPINT_MASK_AUXPLL, 0x04, 2);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
if (init->jesd204Settings.deframerA.deserializerLanesEnabled == 0)
|
|
{
|
|
/* If no lanes used for deframer A, do not enable SYNCB pad */
|
|
}
|
|
else
|
|
{
|
|
if (init->jesd204Settings.deframerA.syncbOutSelect == 0)
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_TX1_SYNC_PAD_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_TX2_SYNC_PAD_CONFIG;
|
|
}
|
|
|
|
/* Valid range 0-3 */
|
|
if (init->jesd204Settings.deframerA.syncbOutCmosSlewRate > 3)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_INV_DEFA_SLEWRATE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
deframerSyncPadCfg = (init->jesd204Settings.deframerA.syncbOutCmosSlewRate << 5)
|
|
| (((init->jesd204Settings.deframerA.syncbOutCmosDriveLevel > 0) ? 1 : 0) << 4)
|
|
| (0x01 << 3) /* Set tx_sync_pad_lvds_low_cm */
|
|
| (((init->jesd204Settings.deframerA.syncbOutLvdsPnInvert > 0) ? 1 : 0) << 2)
|
|
| (((init->jesd204Settings.deframerA.syncbOutLvdsMode > 0) ? 1 : 0) << 1);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, syncbPadCfgAddr, deframerSyncPadCfg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if (init->jesd204Settings.deframerB.deserializerLanesEnabled == 0)
|
|
{
|
|
/* If no lanes used for deframer B, do not enable SYNCB pad */
|
|
}
|
|
else
|
|
{
|
|
if (init->jesd204Settings.deframerB.syncbOutSelect == 0)
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_TX1_SYNC_PAD_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_TX2_SYNC_PAD_CONFIG;
|
|
}
|
|
|
|
/* Valid range 0-3 */
|
|
if (init->jesd204Settings.deframerB.syncbOutCmosSlewRate > 3)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_INV_DEFB_SLEWRATE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
deframerSyncPadCfg = (init->jesd204Settings.deframerB.syncbOutCmosSlewRate << 5)
|
|
| (((init->jesd204Settings.deframerB.syncbOutCmosDriveLevel > 0) ? 1 : 0) << 4)
|
|
| (0x01 << 3) /* Set tx_sync_pad_lvds_low_cm */
|
|
| (((init->jesd204Settings.deframerB.syncbOutLvdsPnInvert > 0) ? 1 : 0) << 2)
|
|
| (((init->jesd204Settings.deframerB.syncbOutLvdsMode > 0) ? 1 : 0) << 1);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, syncbPadCfgAddr, deframerSyncPadCfg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Look at each framer and enable the RXSYNCB used for each framer. It is possible that they use the same RXSYNCB pin */
|
|
if (init->jesd204Settings.framerA.serializerLanesEnabled == 0)
|
|
{
|
|
/* framer A disabled, do not enable SYNCB pad */
|
|
}
|
|
else
|
|
{
|
|
if (init->jesd204Settings.framerA.syncbInSelect == 0)
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_RX1_SYNC_PAD_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_RX2_SYNC_PAD_CONFIG;
|
|
}
|
|
|
|
framerSyncPadCfg = (((init->jesd204Settings.framerA.syncbInLvdsPnInvert > 0) ? 1 : 0) << 2) |
|
|
(((init->jesd204Settings.framerA.syncbInLvdsMode > 0) ? 1 : 0) << 1) |
|
|
(((init->jesd204Settings.framerA.syncbInLvdsMode > 0) ? 1 : 0) << 4); /* if LVDS mode, enable internal 100ohm termination */
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, syncbPadCfgAddr, framerSyncPadCfg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
if (init->jesd204Settings.framerB.serializerLanesEnabled == 0)
|
|
{
|
|
/* framer B disabled, do not enable SYNCB pad */
|
|
}
|
|
else
|
|
{
|
|
if (init->jesd204Settings.framerB.syncbInSelect == 0)
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_RX1_SYNC_PAD_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
syncbPadCfgAddr = TALISE_ADDR_RX2_SYNC_PAD_CONFIG;
|
|
}
|
|
|
|
framerSyncPadCfg = (((init->jesd204Settings.framerB.syncbInLvdsPnInvert > 0) ? 1 : 0) << 2) |
|
|
(((init->jesd204Settings.framerB.syncbInLvdsMode > 0) ? 1 : 0) << 1) |
|
|
(((init->jesd204Settings.framerB.syncbInLvdsMode > 0) ? 1 : 0) << 4); /* if LVDS mode, enable internal 100ohm termination */
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, syncbPadCfgAddr, framerSyncPadCfg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Set Digital device clock divider - provides clock to 1us timer logic, and some other blocks */
|
|
if (init->clocks.deviceClock_kHz <= 200000)
|
|
{
|
|
digDeviceClockDiv = 0; /* Device clock / 1 */
|
|
digRefClock_MHz = (init->clocks.deviceClock_kHz / 1000);
|
|
}
|
|
else if ((init->clocks.deviceClock_kHz <= 400000) && (init->clocks.deviceClock_kHz > 200000))
|
|
{
|
|
digDeviceClockDiv = 1; /* Device clock / 2 */
|
|
digRefClock_MHz = (((init->clocks.deviceClock_kHz / 1000) + 1) >> 1); /* /2 with round to nearest */
|
|
}
|
|
else if ((init->clocks.deviceClock_kHz <= 800000) && (init->clocks.deviceClock_kHz > 400000))
|
|
{
|
|
digDeviceClockDiv = 2; /* Device clock / 4 */
|
|
digRefClock_MHz = (((init->clocks.deviceClock_kHz / 1000) + 2) >> 2); /* /4 with round to nearest */
|
|
}
|
|
else if ((init->clocks.deviceClock_kHz <= 1600000) && (init->clocks.deviceClock_kHz > 800000))
|
|
{
|
|
digDeviceClockDiv = 3; /* Device clock / 8 */
|
|
digRefClock_MHz = (((init->clocks.deviceClock_kHz / 1000) + 4) >> 3); /* /8 with round to nearest */
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_INIT_INV_DEVCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Set Digital device clock divider */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_0, digDeviceClockDiv, 0xE0, 5);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set number of divided device clock cycles per microsecond */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_REFERENCE_CLOCK_CYCLES, (uint8_t)(digRefClock_MHz - 1));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Negate Rx2 so phase matches Rx1 */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_TX_RX_DATAPATH_INVERSION, 0x0C);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Tx Settings */
|
|
if (device->devStateInfo.profilesValid & TX_PROFILE_VALID)
|
|
{
|
|
|
|
if (init->tx.txProfile.thb3Interpolation == 2)
|
|
{
|
|
txChannelSettings |= 0x10;
|
|
}
|
|
|
|
if (init->tx.txProfile.thb2Interpolation == 2)
|
|
{
|
|
txChannelSettings |= 0x04;
|
|
}
|
|
|
|
if (init->tx.txProfile.thb1Interpolation == 2)
|
|
{
|
|
txChannelSettings |= 0x08;
|
|
}
|
|
|
|
switch (init->tx.txProfile.txFirInterpolation)
|
|
{
|
|
case 1:
|
|
txChannelSettings |= 0x01;
|
|
break;
|
|
case 2:
|
|
txChannelSettings |= 0x02;
|
|
break;
|
|
case 4:
|
|
txChannelSettings |= 0x03;
|
|
break;
|
|
}
|
|
|
|
/* Set Rx Dec5 if Int5 is enabled */
|
|
if (init->tx.txProfile.txInt5Interpolation == 5)
|
|
{
|
|
rxChannelSettings |= 0x02;
|
|
}
|
|
|
|
if (init->tx.txProfile.dacDiv == 2)
|
|
{
|
|
dacClockRateSelect = 1; /* DAC Clock = hsDigClk/2 */
|
|
}
|
|
}
|
|
|
|
/* Rx settings */
|
|
if (device->devStateInfo.profilesValid & RX_PROFILE_VALID)
|
|
{
|
|
if (init->rx.rxProfile.rxDec5Decimation == 5)
|
|
{
|
|
rxChannelSettings |= 0x02;
|
|
}
|
|
|
|
if ( init->rx.rxProfile.rhb1Decimation == 2)
|
|
{
|
|
rxChannelSettings |= 0x10;
|
|
}
|
|
|
|
switch (init->rx.rxProfile.rxFirDecimation)
|
|
{
|
|
case 1:
|
|
rxFirDecBitField |= 0x01;
|
|
break;
|
|
case 2:
|
|
rxFirDecBitField |= 0x02;
|
|
break;
|
|
case 4:
|
|
rxFirDecBitField |= 0x03;
|
|
break;
|
|
}
|
|
}
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Determine ORx channel settings */
|
|
if (device->devStateInfo.profilesValid & ORX_PROFILE_VALID)
|
|
{
|
|
if ( init->obsRx.orxProfile.rxDec5Decimation == 5)
|
|
{
|
|
rxChannelSettings |= 0x02;
|
|
}
|
|
|
|
/* Enable ORX RHB2 Wideband */
|
|
orxChannelSettings = 0x10;
|
|
|
|
if (init->obsRx.orxProfile.rhb1Decimation == 2)
|
|
{
|
|
orxChannelSettings |= 0x04;
|
|
}
|
|
|
|
switch (init->obsRx.orxProfile.rxFirDecimation)
|
|
{
|
|
case 1:
|
|
orxFirDecBitField |= 0x01;
|
|
break;
|
|
case 2:
|
|
orxFirDecBitField |= 0x02;
|
|
break;
|
|
case 4:
|
|
orxFirDecBitField |= 0x03;
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/************************************************************************
|
|
* Set channel config settings for Rx/Tx/ and ORx channels
|
|
************************************************************************/
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CONFIGURATION_CONTROL_2, txChannelSettings);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CONFIGURATION_CONTROL_4, rxChannelSettings);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CONFIGURATION_CONTROL_ORX, orxChannelSettings);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_A_SETTINGS, rxFirDecBitField, 0x03, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_B_SETTINGS, orxFirDecBitField, 0x03, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_C_SETTINGS, orxFirDecBitField, 0x03, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Enable SPI Tx Atten mode and set Atten step size. Only write bottom 6 bits */
|
|
regData = 0;
|
|
regData |= TPC_MODE_TX1_SPI;
|
|
regData |= TPC_MODE_TX2_SPI;
|
|
regData |= (init->tx.txAttenStepSize << 4);
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_TX_TPC_CONFIG, regData, 0x3F, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set DAC divider */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_1, dacClockRateSelect, 0x01, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set ADC Flash bias */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_ADC_BIAS_FLASH_VISB, 0x7D);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Set the CLKPLL with the frequency from the device data structure */
|
|
retVal = (talRecoveryActions_t)TALISE_initDigitalClocks(device, &init->clocks);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = ADIHAL_wait_us(device->devHalInfo, CLKPLL_LOCK_US);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_CHECK_TIMER);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_0, 0, 0x01, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_0, 1, 0x01, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Enable digital clocks - this is gated by the CLKPLL being locked */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_0, 1, 0x04, 2);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Wait for CLKPLL CP Cal done and CLKPLL Lock or throw error message */
|
|
retVal = (talRecoveryActions_t)TALISE_waitForEvent(device, TAL_CLKPLLCP, CLKPLL_CPCAL_TIMEOUT_US, CLKPLL_CPCAL_INTERVAL_US);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_waitForEvent(device, TAL_CLKPLL_LOCK, CLKPLL_LOCK_TIMEOUT_US, CLKPLL_LOCK_INTERVAL_US);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Toggle DEC5 divider reset bit */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_0, 0, 0x01, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Program FIR filters after CLKPLL locked */
|
|
if (device->devStateInfo.profilesValid & TX_PROFILE_VALID)
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setTxPfirSyncClk(device, &init->tx.txProfile);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
if (init->tx.txProfile.txFir.numFirCoefs > 0)
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_programFir(device, TAL_TX1TX2_FIR, &init->tx.txProfile.txFir);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
|
|
if (((device->devStateInfo.profilesValid & RX_PROFILE_VALID) > 0) ||
|
|
((device->devStateInfo.profilesValid & ORX_PROFILE_VALID) > 0))
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setRxPfirSyncClk(device, &init->rx.rxProfile, &init->obsRx.orxProfile);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
printf("[%s,%d] !\n", __FUNCTION__, __LINE__);
|
|
if (device->devStateInfo.profilesValid & RX_PROFILE_VALID)
|
|
{
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
if (init->rx.rxProfile.rxFir.numFirCoefs > 0)
|
|
{
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_programFir(device, TAL_RX1RX2_FIR, &init->rx.rxProfile.rxFir);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
/* Load Rx gain table */
|
|
retVal = (talRecoveryActions_t)TALISE_programRxGainTable(device, &rxGainTable[0], (sizeof(rxGainTable) / sizeof(taliseRxGainTable_t)), TAL_RX1RX2);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setRxManualGain(device, TAL_RX1, init->rx.rxGainCtrl.rx1GainIndex);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setRxManualGain(device, TAL_RX2, init->rx.rxGainCtrl.rx2GainIndex);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
/* Enable Digital gain for Rx and ObsRx gain tables */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DIGITAL_GAIN_CONFIG, 0x80);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
}
|
|
}
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
if (device->devStateInfo.profilesValid & ORX_PROFILE_VALID)
|
|
{
|
|
if (init->obsRx.orxProfile.rxFir.numFirCoefs > 0)
|
|
{/* if pointer to orx rxFIR is valid */
|
|
retVal = (talRecoveryActions_t)TALISE_programFir(device, TAL_OBSRX1RX2_LOOPBACK_FIR, &init->obsRx.orxProfile.rxFir);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Load ORx gain table */
|
|
retVal = (talRecoveryActions_t)TALISE_programOrxGainTable(device, &orxGainTable[0], (sizeof(orxGainTable) / sizeof(taliseOrxGainTable_t)), TAL_ORX1ORX2);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setObsRxManualGain(device, TAL_ORX1, init->obsRx.orxGainCtrl.orx1GainIndex);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setObsRxManualGain(device, TAL_ORX2, init->obsRx.orxGainCtrl.orx2GainIndex);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Enable Digital gain for Rx and ObsRx gain tables */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DIGITAL_GAIN_CONFIG, 0x80);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
printf("[%s,%d] \n", __FUNCTION__, __LINE__);
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RCAL_CONTROL, 0x07); /* Set RCAL code to nominal */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* If Valid Rx Profile or valid ObsRx profile, setup serializers */
|
|
if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) ||
|
|
(device->devStateInfo.profilesValid & ORX_PROFILE_VALID))
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setupSerializers(device, init);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) &&
|
|
(init->rx.rxChannels != TAL_RXOFF))
|
|
{
|
|
|
|
/* save the Np states for use in slicer gain compensation management */
|
|
if ((init->rx.framerSel == TAL_FRAMER_A) ||
|
|
(init->rx.framerSel == TAL_FRAMER_A_AND_B))
|
|
{
|
|
device->devStateInfo.rxFramerNp = init->jesd204Settings.framerA.Np;
|
|
}
|
|
else
|
|
{
|
|
device->devStateInfo.rxFramerNp = init->jesd204Settings.framerB.Np;
|
|
}
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setupJesd204bFramer(device, init, init->rx.framerSel);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* set the ADC crossbar: Q/I data assigned to even/odd converters to account for I/Q swap in DUT */
|
|
if (init->rx.rxChannels == TAL_RX2)
|
|
{
|
|
/* In real IF mode, send Rx2 I data to converter 0 */
|
|
if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX2_I;
|
|
adcXbar.conv1 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv2 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
adcXbar.conv3 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv4 = TAL_ADC_RX1_I;
|
|
adcXbar.conv5 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
}
|
|
else
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv1 = TAL_ADC_RX2_I;
|
|
adcXbar.conv2 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv3 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
adcXbar.conv4 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv5 = TAL_ADC_RX1_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
}
|
|
}
|
|
else if (init->rx.rxChannels == TAL_RX1)
|
|
{
|
|
/* In real IF mode, send Rx1 I data to converter 0 */
|
|
if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX1_I;
|
|
adcXbar.conv1 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv2 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv3 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv4 = TAL_ADC_RX2_I;
|
|
adcXbar.conv5 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
}
|
|
else
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv1 = TAL_ADC_RX1_I;
|
|
adcXbar.conv2 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv3 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv4 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv5 = TAL_ADC_RX2_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* In real IF mode, send Rx1 I data to converter 0, Rx2 I data on converter 1 */
|
|
if ((init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF) ||
|
|
(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX1_I;
|
|
adcXbar.conv1 = TAL_ADC_RX2_I;
|
|
adcXbar.conv2 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv3 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv4 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv5 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
}
|
|
else
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv1 = TAL_ADC_RX1_I;
|
|
adcXbar.conv2 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv3 = TAL_ADC_RX2_I;
|
|
adcXbar.conv4 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv5 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
}
|
|
}
|
|
retVal = (talRecoveryActions_t)TALISE_setupAdcSampleXbar(device, init->rx.framerSel, adcXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Initialize DDC modes */
|
|
retVal = talInitializeDdc(device, init);
|
|
IF_ERR_RETURN(retVal);
|
|
}
|
|
|
|
if (device->devStateInfo.profilesValid & ORX_PROFILE_VALID)
|
|
{
|
|
/* save the Np states for use in slicer gain compensation management */
|
|
if ((init->obsRx.framerSel == TAL_FRAMER_A) ||
|
|
(init->obsRx.framerSel == TAL_FRAMER_A_AND_B))
|
|
{
|
|
/* Only Setup JESD Framer if serializer Lanes are enabled for Framer A ORx path */
|
|
if (init->jesd204Settings.framerA.serializerLanesEnabled > 0)
|
|
{
|
|
device->devStateInfo.orxFramerNp = init->jesd204Settings.framerA.Np;
|
|
retVal = (talRecoveryActions_t)TALISE_setupJesd204bFramer(device, init, init->obsRx.framerSel);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Only Setup JESD Framer if serializer Lanes are enabled for Framer B ORx path */
|
|
if (init->jesd204Settings.framerB.serializerLanesEnabled > 0)
|
|
{
|
|
device->devStateInfo.orxFramerNp = init->jesd204Settings.framerB.Np;
|
|
retVal = (talRecoveryActions_t)TALISE_setupJesd204bFramer(device, init, init->obsRx.framerSel);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
/* set the ADC crossbar: Q/I data assigned to even/odd converters to account for I/Q swap in DUT */
|
|
if ((device->devStateInfo.orxAdcStitchingEnabled == 0 ) && (init->obsRx.obsRxChannelsEnable == TAL_ORX2))
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv1 = TAL_ADC_RX2_I;
|
|
adcXbar.conv2 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv3 = TAL_ADC_RX1_I;
|
|
adcXbar.conv4 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv5 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
}
|
|
else
|
|
{
|
|
adcXbar.conv0 = TAL_ADC_RX1_Q;
|
|
adcXbar.conv1 = TAL_ADC_RX1_I;
|
|
adcXbar.conv2 = TAL_ADC_RX2_Q;
|
|
adcXbar.conv3 = TAL_ADC_RX2_I;
|
|
adcXbar.conv4 = TAL_ADC_DUALBAND_RX1_BAND_B_Q;
|
|
adcXbar.conv5 = TAL_ADC_DUALBAND_RX1_BAND_B_I;
|
|
adcXbar.conv6 = TAL_ADC_DUALBAND_RX2_BAND_B_Q;
|
|
adcXbar.conv7 = TAL_ADC_DUALBAND_RX2_BAND_B_I;
|
|
}
|
|
retVal = (talRecoveryActions_t)TALISE_setupAdcSampleXbar(device, init->obsRx.framerSel, adcXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((device->devStateInfo.profilesValid & TX_PROFILE_VALID) &&
|
|
(init->tx.txChannels != TAL_TXOFF))
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setupDeserializers(device, init);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* set the DAC sample crossbars */
|
|
if (init->tx.deframerSel == TAL_DEFRAMER_A)
|
|
{
|
|
if ((init->tx.txChannels == TAL_TX1) ||
|
|
(init->tx.txChannels == TAL_TX1TX2))
|
|
{
|
|
dacXbar.dacChanI = TAL_DEFRAMERA_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERA_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX1, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
dacXbar.dacChanI = TAL_DEFRAMERA_OUT2;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERA_OUT3;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX2, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
}
|
|
|
|
if (init->tx.txChannels == TAL_TX2)
|
|
{
|
|
dacXbar.dacChanI = TAL_DEFRAMERA_OUT2;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERA_OUT3;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX1, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
dacXbar.dacChanI = TAL_DEFRAMERA_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERA_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX2, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
if (init->tx.deframerSel == TAL_DEFRAMER_B)
|
|
{
|
|
if ((init->tx.txChannels == TAL_TX1) ||
|
|
(init->tx.txChannels == TAL_TX1TX2))
|
|
{
|
|
dacXbar.dacChanI = TAL_DEFRAMERB_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERB_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX1, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
dacXbar.dacChanI = TAL_DEFRAMERB_OUT2;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERB_OUT3;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX2, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if (init->tx.txChannels == TAL_TX2)
|
|
{
|
|
dacXbar.dacChanI = TAL_DEFRAMERB_OUT2;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERB_OUT3;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX1, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
dacXbar.dacChanI = TAL_DEFRAMERB_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERB_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX2, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
if (init->tx.deframerSel == TAL_DEFRAMER_A_AND_B)
|
|
{
|
|
if ((init->jesd204Settings.deframerA.M == 4) ||
|
|
(init->jesd204Settings.deframerB.M == 4))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_FRAMER_A_AND_B_INV_M_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
else if ((init->tx.txChannels == TAL_TX1TX2) &&
|
|
(init->jesd204Settings.deframerA.M == 2) &&
|
|
(init->jesd204Settings.deframerB.M == 2))
|
|
{
|
|
dacXbar.dacChanI = TAL_DEFRAMERA_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERA_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX1, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
dacXbar.dacChanI = TAL_DEFRAMERB_OUT0;
|
|
dacXbar.dacChanQ = TAL_DEFRAMERB_OUT1;
|
|
retVal = (talRecoveryActions_t)TALISE_setupDacSampleXbar(device, TAL_TX2, dacXbar);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
if ((init->tx.deframerSel == TAL_DEFRAMER_A) ||
|
|
(init->tx.deframerSel == TAL_DEFRAMER_A_AND_B))
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setupJesd204bDeframer(device, init, TAL_DEFRAMER_A);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((init->tx.deframerSel == TAL_DEFRAMER_B) ||
|
|
(init->tx.deframerSel == TAL_DEFRAMER_A_AND_B))
|
|
{
|
|
retVal = (talRecoveryActions_t)TALISE_setupJesd204bDeframer(device, init, TAL_DEFRAMER_B);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_VALID_OVERRIDES, 0x88);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setTxAttenuation(device, TAL_TX1, init->tx.tx1Atten_mdB);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
retVal = (talRecoveryActions_t)TALISE_setTxAttenuation(device, TAL_TX2, init->tx.tx2Atten_mdB);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
/* Set RxFE LO Common mode */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RXFE1_LOCM, 0x30);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RXFE2_LOCM, 0x30);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Setup thresholds needed by ARM calibrations */
|
|
/* ULB threshold is set to 3db below full scale of ADC */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_UPPER_LEVEL_BLOCKER_THRESHOLD, ULB_THRESHOLD);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* ULB2 is 3db above ULB threshold */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_UPPER_LEVEL_BLOCKER_THRESHOLD2, ULB2_THRESHOLD);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* LLB is 3db below ULB threshold */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_LOWER_LEVEL_BLOCKER_THRESHOLD, LLB_THRESHOLD);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* LLB2 is 3db above LLB threshold */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_LOWER_LEVEL_BLOCKER_THRESHOLD2, LLB2_THRESHOLD);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_ULB_COUNT_THRESHOLD, 0x06);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DEC_OVERLOAD_CONFIG1, 0x91);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DEC_OVERLOAD_UPPER_THRESHOLD, 0xB5);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_ADC_HIGH_OVRG_COUNT_THRESHOLD, 0x06);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_CONFIG1, 0x04, 0x3F, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DEC_OVERLOAD_CONFIG2, 0x03, 0x03, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set gain update counter for 1ms. */
|
|
/* Calculate AGC clock rate - Use same equation as used for txAttenClock_Hz in TALISE_initDigitalClocks*/
|
|
if (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz > 500000000)
|
|
{
|
|
agcClock_Hz = (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 4); /* div 4 */
|
|
}
|
|
else if (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz > 250000000)
|
|
{
|
|
agcClock_Hz = (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 2); /* div 2 */
|
|
}
|
|
else
|
|
{
|
|
agcClock_Hz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz; /* div 1 */
|
|
}
|
|
|
|
gainUpdateCount = (agcClock_Hz / 1000);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_UPDATE_COUNTER1, (gainUpdateCount & 0xFF));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_UPDATE_COUNTER2, ((gainUpdateCount >> 8) & 0xFF));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_GAIN_UPDATE_COUNTER3, ((gainUpdateCount >> 16) & 0x3F));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SLOWLOOP_SETTLING_DELAY, 0x10);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SLOWLOOP_CONFIG, 0x00);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_AGC_UNDERRANGE1, 0x02);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX1, 1, 0x02, 1);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_AGC_MANUAL_GAIN_CONTROL_CONFIG_RX2, 1, 0x02, 1);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Options to disable Tx data if PLL unlocks */
|
|
if ((init->tx.disTxDataIfPllUnlock != TAL_TXDIS_TX_NOT_DISABLED) &&
|
|
(init->tx.disTxDataIfPllUnlock != TAL_TXDIS_TX_ZERO_DATA) &&
|
|
(init->tx.disTxDataIfPllUnlock != TAL_TXDIS_TX_RAMP_DOWN_TO_ZERO))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_DISONPLLUNLOCK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_TX_DP_MASK_CH1, (uint8_t)init->tx.disTxDataIfPllUnlock, 0x06, 1);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_TX_DP_MASK_CH2, (uint8_t)init->tx.disTxDataIfPllUnlock, 0x06, 1);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set Talise API state container information */
|
|
device->devStateInfo.devState = (taliseStates_t)(device->devStateInfo.devState | TAL_STATE_INITIALIZED);
|
|
device->devStateInfo.initializedChannels = (init->rx.rxChannels & 3);
|
|
device->devStateInfo.initializedChannels |= ((init->obsRx.obsRxChannelsEnable & 3) << 2);
|
|
device->devStateInfo.initializedChannels |= ((init->tx.txChannels & 3) << 6);
|
|
device->devStateInfo.txInputRate_kHz = init->tx.txProfile.txInputRate_kHz;
|
|
device->devStateInfo.rxDdcMode = init->rx.rxProfile.rxDdcMode;
|
|
|
|
/* Find the Rx Framer and save the Rx Framer M value */
|
|
if (init->rx.framerSel == TAL_FRAMER_A)
|
|
{
|
|
device->devStateInfo.rxTotalM = init->jesd204Settings.framerA.M;
|
|
}
|
|
else if (init->rx.framerSel == TAL_FRAMER_B)
|
|
{
|
|
device->devStateInfo.rxTotalM = init->jesd204Settings.framerB.M;
|
|
}
|
|
else if (init->rx.framerSel == TAL_FRAMER_A_AND_B)
|
|
{
|
|
device->devStateInfo.rxTotalM = init->jesd204Settings.framerA.M + init->jesd204Settings.framerB.M;
|
|
}
|
|
|
|
device->devStateInfo.rxBandwidth_Hz = init->rx.rxProfile.rfBandwidth_Hz;
|
|
device->devStateInfo.txBandwidth_Hz = init->tx.txProfile.rfBandwidth_Hz;
|
|
device->devStateInfo.orxBandwidth_Hz = init->obsRx.orxProfile.rfBandwidth_Hz;
|
|
|
|
/* If higher priority retVal has no error, allow possible lower priority warning to be returned */
|
|
if (retVal == TALACT_NO_ACTION)
|
|
{
|
|
retVal = (talRecoveryActions_t)retValWarn;
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_shutdown(taliseDevice_t *device)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
retVal = (talRecoveryActions_t)TALISE_resetDevice(device);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_getMultiChipSyncStatus(taliseDevice_t *device, uint8_t *mcsStatus)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getMultiChipSyncStatus()\n");
|
|
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
/* null pointer check */
|
|
if (mcsStatus == NULL)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_CHECKGETMCS_STATUS_NULL_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
else
|
|
{
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_MCS_STATUS, mcsStatus);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_enableMultichipSync(taliseDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t clkPllSdmBypass = 0;
|
|
uint8_t mcsEnable = 0x9B;
|
|
/* Keeps RF LO divider enabled[7]
|
|
Enable MCS[4]
|
|
reset Device Clock divider[3]
|
|
Digital clocks[1]
|
|
JESD204 SYSREF[0]
|
|
*/
|
|
int err_flg;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableMultichipSync()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
if (enableMcs > 0)
|
|
{
|
|
/* If CLKPLL SDM not bypassed, reset CLKPLL SDM as well. */
|
|
halError = ADIHAL_spiReadField(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllSdmBypass, 0x40, 6);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
if (clkPllSdmBypass == 0)
|
|
{
|
|
mcsEnable |= 0x04; /* enable MCS for CLKPLL SDM */
|
|
}
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_MCS_CONTROL, mcsEnable);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Prime the K1 input sync (clear bit 4, then set bit 4) */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_MCS_CONTROL_2, 0, 0x10, 4);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_MCS_CONTROL_2, 1, 0x10, 4);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
else
|
|
{
|
|
/* If enableMcs = 0 (MCS complete), reset JESD204 serializer */
|
|
/* Toggle Serializer SRESET */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0xFF);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Allow framer data to output to serializer (clear reset)*/
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0x0F);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d]\n",retVal, str_err[err_flg], __LINE__);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
/* if mcsStatus is a valid pointer, return the MCS status */
|
|
if (mcsStatus != NULL)
|
|
{
|
|
/*
|
|
位 (Bit) 名称 (Bit Name) 描述 (Description)
|
|
7 (保留) 未定义。
|
|
6 (保留) 未定义。
|
|
5 (保留) 未定义。
|
|
4 (保留) 未定义。
|
|
3 Device clock divider sync 此位置1表示多芯片同步设备时钟分频器同步已完成。 1
|
|
2 CLKPLL SDM sync 此位置1表示多芯片同步时钟PLL Σ-Δ调制器(分数模式)同步已完成。 0
|
|
1 Digital clocks sync 此位置1表示多芯片同步数字时钟分频器同步已完成。 1
|
|
0 JESD SYSREF sync 此位置1表示多芯片同步JESD204B SYSREF同步已完成。 1
|
|
|
|
|
|
*/
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_MCS_STATUS, mcsStatus);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
err_flg = check_err_state(retVal);
|
|
printf("retVal=0x%x (%s) [line %d] mcsStatus=0x%x\n\n",retVal, str_err[err_flg], __LINE__, (*mcsStatus));
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_programFir(taliseDevice_t *device, talisefirName_t filterToProgram, taliseFir_t *firFilter)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t firBankSel = 0;
|
|
uint8_t i = 0;
|
|
uint8_t numTapsReg = 0;
|
|
uint8_t nTapMul = 24;
|
|
uint8_t maxNumTaps = 80;
|
|
uint8_t filterGain = 0;
|
|
|
|
uint32_t addrIndex = 0;
|
|
uint32_t spiBufferSize = ((HAL_SPIWRITEARRAY_BUFFERSIZE / 6) * 6); /* Make buffer size a multiple of 6 */
|
|
uint16_t addrArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
|
|
uint8_t dataArray[HAL_SPIWRITEARRAY_BUFFERSIZE] = {0};
|
|
|
|
static const uint8_t COEF_WRITE_EN = 0x40;
|
|
static const uint8_t PROGRAM_CLK_EN = 0x80;
|
|
static const uint8_t TXFIR_BANKA = 0x01;
|
|
static const uint8_t TXFIR_BANKB = 0x02;
|
|
static const uint8_t RXFIR_BANKA = 0x04;
|
|
static const uint8_t RXFIR_BANKB = 0x08;
|
|
static const uint8_t RXFIR_BANKC = 0x10;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_programFir()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
/* Error checking, #taps less than max number of taps allowed.*/
|
|
if (firFilter->numFirCoefs == 0)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_PROGRAMFIR_COEFS_NULL, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* firBankSelect and assignment of maxNumTaps, nTapMul and address firAddr.*/
|
|
switch(filterToProgram)
|
|
{
|
|
case TAL_TX1_FIR:
|
|
maxNumTaps = 80;
|
|
firBankSel = TXFIR_BANKA;
|
|
nTapMul = 20;
|
|
break;
|
|
|
|
case TAL_TX2_FIR:
|
|
maxNumTaps = 80;
|
|
firBankSel = TXFIR_BANKB;
|
|
nTapMul = 20;
|
|
break;
|
|
|
|
case TAL_TX1TX2_FIR:
|
|
maxNumTaps = 80;
|
|
firBankSel = (TXFIR_BANKA | TXFIR_BANKB);
|
|
nTapMul = 20;
|
|
break;
|
|
|
|
case TAL_RX1_FIR: /*check for valid cases and shares the exact same code as case RX1RX2_FIR */
|
|
case TAL_RX2_FIR: /*check for valid cases and shares the exact same code as case RX1RX2_FIR */
|
|
case TAL_RX1RX2_FIR:
|
|
maxNumTaps = 72;
|
|
firBankSel = RXFIR_BANKA;
|
|
nTapMul = 24;
|
|
break;
|
|
|
|
case TAL_OBSRX1_FIR: /*check for valid cases and shares the exact same code as case OBSRX1RX2_FIR */
|
|
case TAL_OBSRX2_FIR: /*check for valid cases and shares the exact same code as case OBSRX1RX2_FIR */
|
|
case TAL_OBSRX1RX2_FIR:
|
|
maxNumTaps = 72;
|
|
firBankSel = RXFIR_BANKB;
|
|
nTapMul = 24;
|
|
break;
|
|
|
|
case TAL_LOOPBACK_FIR:
|
|
maxNumTaps = 72;
|
|
firBankSel = RXFIR_BANKC;
|
|
nTapMul = 24;
|
|
break;
|
|
|
|
case TAL_RX1RX2_LOOPBACK_FIR:
|
|
maxNumTaps = 72;
|
|
firBankSel = (RXFIR_BANKA | RXFIR_BANKC);
|
|
nTapMul = 24;
|
|
break;
|
|
|
|
case TAL_OBSRX1RX2_LOOPBACK_FIR:
|
|
maxNumTaps = 72;
|
|
firBankSel = (RXFIR_BANKB | RXFIR_BANKC);
|
|
nTapMul = 24;
|
|
break;
|
|
|
|
default:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_PROGRAMFIR_INV_FIRNAME_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Verification for the structure numFirCoefs */
|
|
if (firFilter->numFirCoefs > maxNumTaps)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Calculate register value for number of Taps */
|
|
if (((firFilter->numFirCoefs % nTapMul) == 0) &&
|
|
(firFilter->numFirCoefs > 0))
|
|
{
|
|
numTapsReg = (firFilter->numFirCoefs / nTapMul) - 1;
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Select which FIR filter to program coeffs for and enable the programming clock*/
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | firBankSel));
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* write filter coefficients */
|
|
addrIndex = 0;
|
|
for (i = 0; i < firFilter->numFirCoefs; i++)
|
|
{
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_ADDR;
|
|
dataArray[addrIndex++] = (i * 2);
|
|
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_DATA;
|
|
dataArray[addrIndex++] = (firFilter->coefs[i] & 0xFF);
|
|
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_CTL;
|
|
dataArray[addrIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | firBankSel);
|
|
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_ADDR;
|
|
dataArray[addrIndex++] = ((i * 2) + 1);
|
|
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_DATA;
|
|
dataArray[addrIndex++] = ((firFilter->coefs[i] >> 8) & 0xFF);
|
|
|
|
addrArray[addrIndex] = TALISE_ADDR_PFIR_COEFF_CTL;
|
|
dataArray[addrIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | firBankSel);
|
|
|
|
/* Send full buffer size when possible */
|
|
/* spiBufferSize set to multiple of 6 at top of function */
|
|
if (addrIndex >= spiBufferSize)
|
|
{
|
|
halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
addrIndex = 0;
|
|
}
|
|
}
|
|
|
|
if (addrIndex > 0)
|
|
{
|
|
halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], addrIndex);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
/* clear Program clock enable */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_PFIR_COEFF_CTL, firBankSel);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set filter gain to be used */
|
|
switch (firFilter->gain_dB)
|
|
{
|
|
case TAL_FIR_GAIN_NEG12_DB:
|
|
filterGain = 0x00;
|
|
break;
|
|
case TAL_FIR_GAIN_NEG6_DB:
|
|
filterGain = 0x01;
|
|
break;
|
|
case TAL_FIR_GAIN_0_DB:
|
|
filterGain = 0x02;
|
|
break;
|
|
case TAL_FIR_GAIN_POS6_DB:
|
|
filterGain = 0x03;
|
|
break;
|
|
default:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_RXFIR_INV_GAIN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* write filter gain and #taps if TX, else is RX */
|
|
if ((filterToProgram == TAL_TX1_FIR) || (filterToProgram == TAL_TX2_FIR) || (filterToProgram == TAL_TX1TX2_FIR))
|
|
{
|
|
/* Write number of Taps , Tx Filter gain*/
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_TX_FILTER_CONFIGURATION, (((numTapsReg & 0x3) << 5) | (filterGain & 0x3)));
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
else
|
|
{
|
|
if ((firBankSel & RXFIR_BANKA) == RXFIR_BANKA)
|
|
{
|
|
/* Write FIR #taps and gain */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_A_SETTINGS, (((numTapsReg & 0x3) << 4) | ((filterGain & 0x03) << 2)), 0x3C, 0);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((firBankSel & RXFIR_BANKB) == RXFIR_BANKB)
|
|
{
|
|
/* Write FIR #taps and gain */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_B_SETTINGS, (((numTapsReg & 0x3) << 4) | ((filterGain & 0x03) << 2)), 0x3C, 0);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((firBankSel & RXFIR_BANKC) == RXFIR_BANKC)
|
|
{
|
|
/* Write FIR #taps and gain */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_BANK_C_SETTINGS, (((numTapsReg & 0x3) << 4) | ((filterGain & 0x03) << 2)), 0x3C, 0);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
|
|
/* Set Mode mapping for RX, OBSRX or LOOPBACK */
|
|
if ((filterToProgram == TAL_RX1_FIR) || (filterToProgram == TAL_RX2_FIR) ||
|
|
(filterToProgram == TAL_RX1RX2_FIR) || (filterToProgram == TAL_RX1RX2_LOOPBACK_FIR))
|
|
{
|
|
if (filterToProgram == TAL_RX1RX2_LOOPBACK_FIR)
|
|
{
|
|
/* Set Mode mapping for RX1 Rx2 and Loopback FIR Bank A */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_PFIR_MODE_MAPPING1, 0x00);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
else
|
|
{
|
|
/* Set Mode mapping for RX1 Rx2 FIR Bank A */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_MODE_MAPPING1, 0x00, 0x0F, 0);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
}
|
|
else if ((filterToProgram == TAL_OBSRX1_FIR) || (filterToProgram == TAL_OBSRX2_FIR) ||
|
|
(filterToProgram == TAL_OBSRX1RX2_FIR) || (filterToProgram == TAL_OBSRX1RX2_LOOPBACK_FIR))
|
|
{
|
|
if (filterToProgram == TAL_OBSRX1RX2_LOOPBACK_FIR)
|
|
{
|
|
/* Set Mode mapping for Loopback FIR Bank B */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_MODE_MAPPING1, 0x01, 0xC0, 6);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
/* Set Mode mapping for Obs RxA and Obs RxA FIR Bank B */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_RX_PFIR_MODE_MAPPING2, 0x05);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
else if (filterToProgram == TAL_LOOPBACK_FIR)
|
|
{
|
|
/* Set Mode mapping for Loopback FIR Bank C */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_RX_PFIR_MODE_MAPPING1, 0x02, 0xC0, 6);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_calculateDigitalClocks(taliseDevice_t *device, taliseDigClocks_t *digClocks)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t hsDivTimes10 = 25;
|
|
uint8_t hsClkDivHsDigClk4or5 = 20;
|
|
uint32_t localHsDigClkDiv2_Hz = 0;
|
|
uint32_t localHsDigClk4or5_Hz = 0;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_calculateDigitalClocks()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
device->devStateInfo.clocks.clkPllVcoFreq_kHz = digClocks->clkPllVcoFreq_kHz;
|
|
device->devStateInfo.clocks.clkPllHsDiv = digClocks->clkPllHsDiv;
|
|
device->devStateInfo.clocks.deviceClock_kHz = digClocks->deviceClock_kHz;
|
|
|
|
switch(digClocks->clkPllHsDiv)
|
|
{
|
|
case TAL_HSDIV_2:
|
|
hsDivTimes10 = 20;
|
|
hsClkDivHsDigClk4or5 = 10;
|
|
break;
|
|
case TAL_HSDIV_2P5:
|
|
hsDivTimes10 = 25;
|
|
hsClkDivHsDigClk4or5 = 10;
|
|
break;
|
|
case TAL_HSDIV_3:
|
|
hsDivTimes10 = 30;
|
|
hsClkDivHsDigClk4or5 = 15;
|
|
break;
|
|
case TAL_HSDIV_4:
|
|
hsDivTimes10 = 40;
|
|
hsClkDivHsDigClk4or5 = 20;
|
|
break;
|
|
case TAL_HSDIV_5:
|
|
hsDivTimes10 = 50;
|
|
hsClkDivHsDigClk4or5 = 20;
|
|
break;
|
|
default:
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_CLKPLL_INV_HSDIV, retVal, TALACT_ERR_CHECK_PARAM );
|
|
}
|
|
|
|
localHsDigClkDiv2_Hz = (uint32_t)((((((uint64_t)(digClocks->clkPllVcoFreq_kHz) * 1000) >> 1) / hsDivTimes10) * 10) >> 1);
|
|
|
|
device->devStateInfo.clocks.hsDigClkDiv2_Hz = localHsDigClkDiv2_Hz;
|
|
|
|
localHsDigClk4or5_Hz = (uint32_t)((((uint64_t)(digClocks->clkPllVcoFreq_kHz) * 1000) >> 1) / hsClkDivHsDigClk4or5);
|
|
|
|
device->devStateInfo.clocks.hsDigClkDiv4or5_Hz = localHsDigClk4or5_Hz;
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
/**
|
|
* \brief Verifies the Rx profile members are valid (in range) and calculates HS Dig Clock require for the Rx Profile
|
|
*
|
|
* Private helper function to verify the Rx profile members are valid (in range)
|
|
* and calculates HS Dig Clock require for the Rx Profile
|
|
* If the Rx profile IQ data rate = 0, it is assumed that the Rx profile is
|
|
* not used. If Rx IQ data rate > 0, and Rx profile members are out of range,
|
|
* the function stores the error code describing the error, and returns a
|
|
* Recovery action to check the configuration settings.
|
|
*
|
|
* \pre This function is private and is not called directly by the user.
|
|
*
|
|
* \dep_begin
|
|
* \dep{device->devHalInfo}
|
|
* \dep_end
|
|
*
|
|
* \param device Structure pointer to Talise device data structure
|
|
* \param rxProfile rxProfile settings to be verified
|
|
* \param rxHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Rx profile
|
|
*
|
|
* \retval TALACT_ERR_CHECK_PARAM Recovery action for bad parameter check
|
|
* \retval TALACT_NO_ACTION Function completed successfully, no action required
|
|
*/
|
|
static talRecoveryActions_t talVerifyRxProfile(taliseDevice_t *device, taliseRxProfile_t *rxProfile, uint32_t *rxHsDigClk_kHz)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
uint8_t ddcMultiply = 1;
|
|
uint8_t ddcDivide = 1;
|
|
|
|
*rxHsDigClk_kHz = 0;
|
|
|
|
/********************************/
|
|
/* Check for a valid Rx profile */
|
|
/********************************/
|
|
if ((rxProfile->rxOutputRate_kHz < 15000) ||
|
|
(rxProfile->rxOutputRate_kHz > 370000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_IQRATE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxProfile->rfBandwidth_Hz < 15000000) ||
|
|
(rxProfile->rfBandwidth_Hz > 250000000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_RFBW, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxProfile->rhb1Decimation != 1) &&
|
|
(rxProfile->rhb1Decimation != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_RHB1, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxProfile->rxDec5Decimation != 4) &&
|
|
(rxProfile->rxDec5Decimation != 5))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_DEC5, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxProfile->rxFirDecimation != 1) &&
|
|
(rxProfile->rxFirDecimation != 2) &&
|
|
(rxProfile->rxFirDecimation != 4))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_FIR, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxProfile->rxFir.coefs == NULL) &&
|
|
(rxProfile->rxFirDecimation != 1))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_COEF, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
switch(rxProfile->rxDdcMode)
|
|
{
|
|
case TAL_RXDDC_BYPASS_REALIF:
|
|
case TAL_RXDDC_BYPASS:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 1;
|
|
break;
|
|
case TAL_RXDDC_DEC2_REALIF:
|
|
case TAL_RXDDC_DEC2:
|
|
ddcMultiply = 2;
|
|
ddcDivide = 1;
|
|
break;
|
|
case TAL_RXDDC_INT2_REALIF:
|
|
case TAL_RXDDC_INT2:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 2;
|
|
break;
|
|
case TAL_RXDDC_FILTERONLY_REALIF:
|
|
case TAL_RXDDC_FILTERONLY:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 1;
|
|
break;
|
|
default:
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERRXPFILE_INV_DDC, retVal, TALACT_ERR_CHECK_PARAM );
|
|
}
|
|
|
|
*rxHsDigClk_kHz = ( rxProfile->rxOutputRate_kHz * rxProfile->rxFirDecimation *
|
|
rxProfile->rhb1Decimation * rxProfile->rxDec5Decimation * ddcMultiply ) / ddcDivide;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* \brief Verifies the ORx profile members are valid (in range) in the init structure
|
|
*
|
|
* If the ORx profile IQ data rate = 0, it is assumed that the ORx profile is
|
|
* not used. If ORx IQ data rate > 0, and ORx profile members are out of range,
|
|
* the function stores the error code describing the error, and returns a
|
|
* Recovery action to check the configuration settings.
|
|
*
|
|
* \pre This function is private and is not called directly by the user.
|
|
*
|
|
* \dep_begin
|
|
* \dep{device->devHalInfo}
|
|
* \dep_end
|
|
*
|
|
* \param device Structure pointer to Talise device data structure
|
|
* \param orxProfile orxProfile settings to be verified
|
|
* \param orxHsDigClk_kHz Return value of the calculated HS Dig Clock required by the ORx profile
|
|
*
|
|
* \retval TALACT_ERR_CHECK_PARAM Recovery action for bad parameter check
|
|
* \retval TALACT_NO_ACTION Function completed successfully, no action required
|
|
*/
|
|
static talRecoveryActions_t talVerifyOrxProfile(taliseDevice_t *device, taliseORxProfile_t *orxProfile, uint32_t *orxHsDigClk_kHz)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
uint8_t ddcMultiply = 1;
|
|
uint8_t ddcDivide = 1;
|
|
|
|
*orxHsDigClk_kHz = 0;
|
|
|
|
/********************************/
|
|
/* Check for a valid ORx profile */
|
|
/********************************/
|
|
if ((orxProfile->orxOutputRate_kHz < 15000) ||
|
|
(orxProfile->orxOutputRate_kHz > 500000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_IQRATE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxProfile->rfBandwidth_Hz < 15000000) ||
|
|
(orxProfile->rfBandwidth_Hz > 460000000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_RFBW, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
device->devStateInfo.orxAdcStitchingEnabled = (orxProfile->rfBandwidth_Hz > 200000000) ? 1 : 0;
|
|
|
|
if ((orxProfile->rhb1Decimation != 1) &&
|
|
(orxProfile->rhb1Decimation != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_RHB1, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxProfile->rxDec5Decimation != 4) &&
|
|
(orxProfile->rxDec5Decimation != 5))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_DEC5, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxProfile->rxFirDecimation != 1) &&
|
|
(orxProfile->rxFirDecimation != 2) &&
|
|
(orxProfile->rxFirDecimation != 4))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_FIR, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxProfile->rxFir.coefs == NULL) &&
|
|
(orxProfile->rxFirDecimation != 1))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_COEF, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
switch(orxProfile->orxDdcMode)
|
|
{
|
|
case TAL_ORXDDC_DISABLED:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 1;
|
|
break;
|
|
case TAL_ORXDDC_SUBSAMPLE_BY2:
|
|
ddcMultiply = 2;
|
|
ddcDivide = 1;
|
|
break;
|
|
default:
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERORXPFILE_INV_DDC, retVal, TALACT_ERR_CHECK_PARAM );
|
|
}
|
|
|
|
*orxHsDigClk_kHz = (orxProfile->orxOutputRate_kHz * orxProfile->rxFirDecimation *
|
|
orxProfile->rhb1Decimation * orxProfile->rxDec5Decimation * ddcMultiply) / ddcDivide;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
* \brief Verifies the Tx profile members are valid (in range) in the init structure
|
|
*
|
|
* If the Tx profile IQ data rate = 0, it is assumed that the Tx profile is
|
|
* not used. If Tx IQ data rate > 0, and Tx profile members are out of range,
|
|
* the function stores the error code describing the error, and returns a
|
|
* Recovery action to check the configuration settings.
|
|
*
|
|
* \pre This function is private and is not called directly by the user.
|
|
*
|
|
* \dep_begin
|
|
* \dep{device->devHalInfo}
|
|
* \dep_end
|
|
*
|
|
* \param device Structure pointer to Talise device data structure
|
|
* \param txProfile txProfile settings to be verified
|
|
* \param txHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Tx profile
|
|
*
|
|
* \retval TALACT_ERR_CHECK_PARAM Recovery action for bad parameter check
|
|
* \retval TALACT_NO_ACTION Function completed successfully, no action required
|
|
*/
|
|
static talRecoveryActions_t talVerifyTxProfile(taliseDevice_t *device, taliseTxProfile_t *txProfile, uint32_t *txHsDigClk_kHz)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
|
|
*txHsDigClk_kHz = 0;
|
|
/********************************/
|
|
/* Check for a valid Tx profile */
|
|
/********************************/
|
|
|
|
if ((txProfile->txInputRate_kHz < 15000) ||
|
|
(txProfile->txInputRate_kHz > 500000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_IQRATE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->rfBandwidth_Hz < 15000000) ||
|
|
(txProfile->rfBandwidth_Hz > 460000000))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_RFBW, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->thb1Interpolation != 1) &&
|
|
(txProfile->thb1Interpolation != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_THB1, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->thb2Interpolation != 1) &&
|
|
(txProfile->thb2Interpolation != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_THB2, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->thb3Interpolation != 1) &&
|
|
(txProfile->thb3Interpolation != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_THB3, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->txInt5Interpolation != 1) &&
|
|
(txProfile->txInt5Interpolation != 5))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_INT5, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Int5 and thb1/2/3 should be mutually exclusive */
|
|
if (((txProfile->txInt5Interpolation == 5) &&
|
|
((txProfile->thb1Interpolation != 1) ||
|
|
(txProfile->thb2Interpolation != 1) ||
|
|
(txProfile->thb3Interpolation != 1))) ||
|
|
((txProfile->txInt5Interpolation == 1) &&
|
|
(txProfile->thb1Interpolation == 1) &&
|
|
(txProfile->thb2Interpolation == 1) &&
|
|
(txProfile->thb3Interpolation == 1)))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_HBMUTEX, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((txProfile->txFirInterpolation != 1) &&
|
|
(txProfile->txFirInterpolation != 2) &&
|
|
(txProfile->txFirInterpolation != 4))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_FIRIPL, retVal, TALACT_ERR_CHECK_PARAM);
|
|
|
|
}
|
|
|
|
if ((txProfile->txFir.coefs == NULL) &&
|
|
(txProfile->txFirInterpolation != 1))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_COEF, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if((txProfile->dacDiv != 1) &&
|
|
(txProfile->dacDiv != 2))
|
|
{
|
|
return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERTXPFILE_INV_DACDIV, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
*txHsDigClk_kHz = (txProfile->txInputRate_kHz * txProfile->txFirInterpolation *
|
|
txProfile->thb1Interpolation * txProfile->thb2Interpolation *
|
|
txProfile->thb3Interpolation * txProfile->txInt5Interpolation *
|
|
txProfile->dacDiv);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
uint32_t TALISE_verifyProfiles(taliseDevice_t *device, taliseInit_t *init)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
uint32_t rxHsDigClk_kHz = 0;
|
|
uint32_t orxHsDigClk_kHz = 0;
|
|
uint32_t txHsDigClk_kHz = 0;
|
|
uint32_t hsDigClkDiv2_Hz = 0;
|
|
uint32_t hsDigClk_kHz = 0;
|
|
taliseRxProfile_t *rxProfile = NULL;
|
|
taliseTxProfile_t *txProfile = NULL;
|
|
taliseORxProfile_t *orxProfile = NULL;
|
|
|
|
if (device == NULL)
|
|
{
|
|
/* Can not write to log since log function requires device data structure */
|
|
return (uint32_t)TALACT_ERR_CHECK_PARAM;
|
|
}
|
|
|
|
if (init == NULL)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_INV_NULL_INIT_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
device->devStateInfo.profilesValid = 0;
|
|
|
|
if(init->tx.txChannels != TAL_TXOFF)
|
|
{
|
|
txProfile = &init->tx.txProfile;
|
|
retVal = talVerifyTxProfile(device, txProfile, &txHsDigClk_kHz);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if(init->rx.rxChannels != TAL_RXOFF)
|
|
{
|
|
rxProfile = &init->rx.rxProfile;
|
|
retVal = talVerifyRxProfile(device, rxProfile, &rxHsDigClk_kHz);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if((init->obsRx.obsRxChannelsEnable != TAL_ORXOFF) || (init->tx.txChannels != TAL_TXOFF))
|
|
{
|
|
orxProfile = &init->obsRx.orxProfile;
|
|
retVal = talVerifyOrxProfile(device, orxProfile, &orxHsDigClk_kHz);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if ((init->clocks.rfPllPhaseSyncMode != TAL_RFPLLMCS_NOSYNC)
|
|
&& (init->clocks.rfPllPhaseSyncMode != TAL_RFPLLMCS_INIT_AND_SYNC)
|
|
&& (init->clocks.rfPllPhaseSyncMode != TAL_RFPLLMCS_INIT_AND_1TRACK)
|
|
&& (init->clocks.rfPllPhaseSyncMode != TAL_RFPLLMCS_INIT_AND_CONTTRACK))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_INV_RFPLLMCSMODE, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Verify HsDigClk needed by Rx/Tx/Orx profiles is possible based on CLKPLL
|
|
* settings
|
|
*/
|
|
|
|
hsDigClkDiv2_Hz = device->devStateInfo.clocks.hsDigClkDiv2_Hz;
|
|
|
|
hsDigClk_kHz = (hsDigClkDiv2_Hz / 500); /* time 2 and convert from Hz to kHz */
|
|
|
|
/* Verify Tx profile is valid */
|
|
if (txHsDigClk_kHz > 0)
|
|
{
|
|
if ((rxHsDigClk_kHz > 0) && (txHsDigClk_kHz != rxHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_TXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxHsDigClk_kHz > 0) && (txHsDigClk_kHz != orxHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_TXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if (hsDigClk_kHz != txHsDigClk_kHz)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_TXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
device->devStateInfo.profilesValid |= TX_PROFILE_VALID;
|
|
}
|
|
|
|
/* Verify Rx profile is valid */
|
|
if (rxHsDigClk_kHz > 0)
|
|
{
|
|
if ((txHsDigClk_kHz > 0) && (rxHsDigClk_kHz != txHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_RXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((orxHsDigClk_kHz > 0) && (rxHsDigClk_kHz != orxHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_RXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if (hsDigClk_kHz != rxHsDigClk_kHz)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_RXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
device->devStateInfo.profilesValid |= RX_PROFILE_VALID;
|
|
}
|
|
|
|
/* Verify ORx profile is valid */
|
|
if (orxHsDigClk_kHz > 0)
|
|
{
|
|
if ((txHsDigClk_kHz > 0) && (orxHsDigClk_kHz != txHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_ORXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if ((rxHsDigClk_kHz > 0) && (orxHsDigClk_kHz != rxHsDigClk_kHz))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_ORXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
if (hsDigClk_kHz != orxHsDigClk_kHz)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_VERPFILE_ORXHSCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
device->devStateInfo.profilesValid |= ORX_PROFILE_VALID;
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_setSpiSettings(taliseDevice_t *device, taliseSpiSettings_t *spi)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t spiReg = 0;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setSpiSettings()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
if (spi->MSBFirst == 0)
|
|
{
|
|
spiReg |= 0x42; /* SPI bit is 1 = LSB first */
|
|
}
|
|
|
|
if (spi->autoIncAddrUp > 0)
|
|
{
|
|
spiReg |= 0x24;
|
|
}
|
|
|
|
if (spi->fourWireMode > 0)
|
|
{
|
|
spiReg |= 0x18;
|
|
}
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SPI_INTERFACE_CONFIG_A, spiReg);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
printf("retVal=%d,[ talSpiWriteByte ]-TALISE_ADDR_SPI_INTERFACE_CONFIG_A\n",retVal);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
if (( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_1X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_2X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_3X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_4X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_5X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_6X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_8X) &&
|
|
( spi->cmosPadDrvStrength != TAL_CMOSPAD_DRV_10X))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETSPI_INV_CMOS_DRV_STR, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
else
|
|
{
|
|
/* Extract fields from this encoding when writing: {non_gpio_drv , spi_cmos_drv_select[3:0]} */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_GPIO_SLEW_CONTROL_BYTE3, (((uint8_t)spi->cmosPadDrvStrength) & 0x0F), 0xF0, 4);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DIGITAL_IO_CONTROL, (((uint8_t)spi->cmosPadDrvStrength) >> 4), 0x10, 4);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
if (spi->enSpiStreaming > 0)
|
|
{
|
|
/* Allow SPI streaming mode: SPI message ends when chip select de-asserts */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SPI_INTERFACE_CONFIG_B, 0x00);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
else
|
|
{
|
|
/* Force single instruction mode */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SPI_INTERFACE_CONFIG_B, 0x80);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
printf("retVal=%d,before [TALISE_verifySpiReadWrite]\n",retVal);
|
|
/* Check if SPI reads and writes work after changing settings */
|
|
retVal = (talRecoveryActions_t)TALISE_verifySpiReadWrite (device);
|
|
printf("retVal=%d,after [TALISE_verifySpiReadWrite]\n",retVal);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_verifySpiReadWrite (taliseDevice_t *device)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
uint8_t spiReg = 0;
|
|
int err_flg;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_verifySpiReadWrite()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
/* Check SPI read - VENDOR_ID_0 */
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_VENDOR_ID_0, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
#if DBG_TALISE_SPI_PR
|
|
err_flg = check_err_state(retVal);
|
|
printf("ck_spi_rd ret=%d (%s) VENDOR_ID_0=0x%x [0x56]\n", retVal, str_err[retVal], spiReg);
|
|
#endif
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0x56)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_READ_LOW_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI read - VENDOR_ID_1 */
|
|
spiReg = 0;
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_VENDOR_ID_1, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
#if DBG_TALISE_SPI_PR
|
|
err_flg = check_err_state(retVal);
|
|
printf("ck_spi_rd ret=%d (%s) VENDOR_ID_1=0x%x [0x04]\n", retVal, str_err[retVal], spiReg);
|
|
#endif
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0x04)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_READ_LOW_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI write - SCRATCHPAD : Data = 10110110 */
|
|
spiReg = 0;
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD, 0xB6);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
#if DBG_TALISE_SPI_PR
|
|
err_flg = check_err_state(retVal);
|
|
printf("ck_spi_wr ret=%d (%s) SCRATCHPAD\n", retVal, str_err[retVal]);
|
|
#endif
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
#if DBG_TALISE_SPI_PR
|
|
err_flg = check_err_state(retVal);
|
|
printf("ck_spi_rd ret=%d (%s) SCRATCHPAD=0x%x [0xB6]\n", retVal, str_err[retVal], spiReg);
|
|
#endif
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0xB6)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_WRITE_LOW_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI write - SCRATCHPAD : Data = 01001001 */
|
|
spiReg = 0;
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD, 0x49);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0x49)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_WRITE_LOW_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI read - SCRATCH_PAD_READ_ONLY_UPPER_ADDRESS_SPACE */
|
|
spiReg = 0;
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD_READ_ONLY_UPPER_ADDRESS_SPACE, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0xA5)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_READ_HIGH_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI write - SCRATCH_PAD_UPPER_ADDRESS_SPACE : Data = 10110110 */
|
|
spiReg = 0;
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, 0xB6);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0xB6)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_WRITE_HIGH_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
/* Check SPI write - SCRATCH_PAD_UPPER_ADDRESS_SPACE : Data = 01001001 */
|
|
spiReg = 0;
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, 0x49);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, &spiReg);
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
if (spiReg != 0x49)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_VERIFYSPI_WRITE_HIGH_ADDR_ERROR, retVal, TALACT_ERR_RESET_FULL);
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_initDigitalClocks(taliseDevice_t *device, taliseDigClocks_t *clockSettings)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
/* RF Synth variables */
|
|
/* pull Synth and Loop filter values from a Look Up Table */
|
|
uint8_t vcoOutLvl;
|
|
uint8_t vcoVaractor; /* [3:0] */
|
|
uint8_t vcoBiasRef; /* [2:0] */
|
|
uint8_t vcoBiasTcf; /* [1:0] */
|
|
uint8_t vcoCalOffset; /* [3:0] */
|
|
uint8_t vcoVaractorRef; /* [3:0] */
|
|
uint8_t loopFilterIcp; /* Icp[5:0] */
|
|
uint8_t loopFilterC2C1; /* C2[3:0],C1[3:0] */
|
|
uint8_t loopFilterR1C3; /* R1[3:0],C3[3:0] */
|
|
uint8_t loopFilterR3; /* R3[3:0] */
|
|
uint8_t vcoIndex;
|
|
uint8_t i;
|
|
|
|
/* RF PLL variables */
|
|
uint16_t integerWord;
|
|
uint32_t fractionalWord;
|
|
uint32_t fractionalRemainder;
|
|
uint32_t scaledRefClk_Hz;
|
|
|
|
/* common */
|
|
uint32_t hsDigClk_Hz_div2 = 0;
|
|
uint32_t scaledRefClk_kHz = 0;
|
|
uint8_t deviceClkDiv = 0;
|
|
uint8_t clkPllRefClkDiv = 0;
|
|
|
|
uint8_t clockControl2 = 0;
|
|
uint8_t clockControl5 = 0x40;
|
|
uint8_t sdmSettings = 0;
|
|
uint8_t hsDivTimes10 = 25;
|
|
|
|
uint32_t txAttenClock_Hz = 0;
|
|
uint8_t txAttenClockDiv = 0;
|
|
|
|
/******************RF Synth Section************************/
|
|
static const uint8_t icp_46p08[53] = {15, 15, 15, 16, 17, 18, 19, 20, 21, 22,
|
|
23, 24, 25, 26, 27, 27, 27, 28, 29, 30,
|
|
31, 32, 33, 32, 33, 32, 33, 33, 34, 27,
|
|
28, 29, 29, 30, 39, 29, 30, 31, 31, 30,
|
|
31, 31, 32, 30, 31, 31, 32, 32, 31, 31,
|
|
32, 32, 33};
|
|
|
|
static const uint8_t icp_61p44[53] = {13, 13, 13, 14, 15, 16, 16, 17, 18, 19,
|
|
20, 21, 22, 22, 23, 24, 24, 25, 25, 26,
|
|
27, 28, 29, 28, 29, 28, 29, 29, 30, 24,
|
|
25, 25, 26, 26, 35, 33, 34, 35, 35, 26,
|
|
27, 27, 28, 27, 27, 27, 28, 28, 27, 27,
|
|
28, 28, 29};
|
|
|
|
static const uint8_t icp_76p8[53] = { 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
|
12, 12, 13, 13, 13, 14, 14, 15, 15, 15,
|
|
16, 15, 16, 15, 16, 16, 17, 13, 14, 14,
|
|
14, 15, 19, 14, 15, 15, 15, 15, 15, 15,
|
|
15, 15, 15, 15, 15, 16, 15, 15, 15, 16,
|
|
16};
|
|
|
|
static const uint32_t vcoFreqArray_kHz [53] =
|
|
{
|
|
12605000UL, 12245000UL, 11906000UL, 11588000UL, 11288000UL,
|
|
11007000UL, 10742000UL, 10492000UL, 10258000UL, 10036000UL,
|
|
9827800UL, 9631100UL, 9445300UL, 9269800UL, 9103600UL,
|
|
8946300UL, 8797000UL, 8655300UL, 8520600UL, 8392300UL,
|
|
8269900UL, 8153100UL, 8041400UL, 7934400UL, 7831800UL,
|
|
7733200UL, 7638400UL, 7547100UL, 7459000UL, 7374000UL,
|
|
7291900UL, 7212400UL, 7135500UL, 7061000UL, 6988700UL,
|
|
6918600UL, 6850600UL, 6784600UL, 6720500UL, 6658200UL,
|
|
6597800UL, 6539200UL, 6482300UL, 6427000UL, 6373400UL,
|
|
6321400UL, 6270900UL, 6222000UL, 6174500UL, 6128400UL,
|
|
6083600UL, 6040100UL, 5997700UL
|
|
};
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_initDigitalClocks()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
/* Scaled Ref Clock at input to CLKPLL should be in range 40-80MHz.
|
|
* Slightly lower frequencies allowed for lab testing - not suggested for
|
|
* production
|
|
*/
|
|
if (clockSettings->deviceClock_kHz > 15000 &&
|
|
clockSettings->deviceClock_kHz <= 40000)
|
|
{
|
|
/* Do not use doubler because multichip sync is not valid when doubler enabled */
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz; /* total div 1 */
|
|
deviceClkDiv = 0; /* div 1 */
|
|
clkPllRefClkDiv = 0; /* div 1 */
|
|
}
|
|
else if (clockSettings->deviceClock_kHz > 40000 &&
|
|
clockSettings->deviceClock_kHz <= 80000)
|
|
{
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz; /* total div 1 */
|
|
deviceClkDiv = 0; /* div 1 */
|
|
clkPllRefClkDiv = 0; /* div 1 */
|
|
}
|
|
else if (clockSettings->deviceClock_kHz > 80000 &&
|
|
clockSettings->deviceClock_kHz <= 160000)
|
|
{
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz >> 1; /* total div 2 */
|
|
deviceClkDiv = 0; /* div 1 */
|
|
clkPllRefClkDiv = 1; /* div 2 */
|
|
}
|
|
else if (clockSettings->deviceClock_kHz > 160000 &&
|
|
clockSettings->deviceClock_kHz <= 320000)
|
|
{
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz >> 2; /* total div 4 */
|
|
deviceClkDiv = 0; /* div 1 */
|
|
clkPllRefClkDiv = 2; /* div 4 */
|
|
}
|
|
else if (clockSettings->deviceClock_kHz > 320000 &&
|
|
clockSettings->deviceClock_kHz <= 640000)
|
|
{
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz >> 3; /* total div 8 */
|
|
deviceClkDiv = 1; /* div 2 */
|
|
clkPllRefClkDiv = 2; /* div 4 */
|
|
}
|
|
else if (clockSettings->deviceClock_kHz > 640000 &&
|
|
clockSettings->deviceClock_kHz <= 1280000)
|
|
{
|
|
scaledRefClk_kHz = clockSettings->deviceClock_kHz >> 4; /* total div 16 */
|
|
deviceClkDiv = 2; /* div 4 */
|
|
clkPllRefClkDiv = 2; /* div 4 */
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM, TAL_ERR_INV_SCALEDDEVCLK_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
switch(clockSettings->clkPllHsDiv)
|
|
{
|
|
case TAL_HSDIV_2:
|
|
hsDivTimes10 = 20;
|
|
break;
|
|
case TAL_HSDIV_2P5:
|
|
hsDivTimes10 = 25;
|
|
break;
|
|
case TAL_HSDIV_3:
|
|
hsDivTimes10 = 30;
|
|
break;
|
|
case TAL_HSDIV_4:
|
|
hsDivTimes10 = 40;
|
|
break;
|
|
case TAL_HSDIV_5:
|
|
hsDivTimes10 = 50;
|
|
break;
|
|
default:
|
|
return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_CLKPLL_INV_HSDIV, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
clockControl2 = ((clkPllRefClkDiv & 0x7) << 4) | (((uint8_t)clockSettings->clkPllHsDiv) & 0x7);
|
|
|
|
/* Set TxAtten / AGC clock divider */
|
|
if (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz > 500000000)
|
|
{
|
|
txAttenClockDiv = 2; /* div 4 */
|
|
txAttenClock_Hz = (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 4);
|
|
}
|
|
else if (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz > 250000000)
|
|
{
|
|
txAttenClockDiv = 1; /* div 2 */
|
|
txAttenClock_Hz = (device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 2);
|
|
}
|
|
else
|
|
{
|
|
txAttenClockDiv = 0; /* div 1 */
|
|
txAttenClock_Hz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz;
|
|
}
|
|
|
|
/* TxAtten clock should be less than 250Mhz by design */
|
|
if (txAttenClock_Hz > 250000000)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETCLKPLL_INV_TXATTENDIV, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Tx Atten clock divider, bits [3:2], is same as AGC clock divider bits[1:0]
|
|
* bit [6] is resetb for device clock divider */
|
|
clockControl5 = 0x40 | ((deviceClkDiv & 0x3) << 4) | ((txAttenClockDiv & 0x3) << 2) | (txAttenClockDiv & 0x3);
|
|
|
|
/* find vco table index based on vco frequency and then break out of loop to assign value */
|
|
for (i = 0; clockSettings->clkPllVcoFreq_kHz < vcoFreqArray_kHz[i]; i++) {}
|
|
vcoIndex = i + 1;
|
|
|
|
if (vcoIndex < 1 || vcoIndex > 53)
|
|
{
|
|
/* vco index out of range */
|
|
return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETCLKPLL_INV_VCOINDEX, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* valid for all refclk frequencies */
|
|
vcoOutLvl = (vcoIndex <= 16) ? 13 : (vcoIndex <= 23) ? 12 : (vcoIndex <= 25) ?
|
|
11 : (vcoIndex <= 35) ? 10 : (vcoIndex <= 39) ? 9 : (vcoIndex <= 43) ?
|
|
8 : (vcoIndex <= 48) ? 7 : 6;
|
|
vcoVaractor = (vcoIndex <= 29 || vcoIndex == 35) ? 1 : 2;
|
|
vcoBiasRef = (vcoIndex <= 7 ) ? 4 : (vcoIndex <= 16) ? 6 : 7;
|
|
vcoBiasTcf = (vcoIndex <= 25 || (vcoIndex > 26 && vcoIndex <= 29) ||
|
|
(vcoIndex > 37 && vcoIndex <= 39)) || (vcoIndex > 40 && vcoIndex <= 43) ?
|
|
2 : 3;
|
|
|
|
vcoVaractorRef = (vcoIndex <= 29) ? 12 : (vcoIndex == 35) ?
|
|
14 : 13;
|
|
|
|
if (scaledRefClk_kHz >= 15000 && scaledRefClk_kHz < 53760)
|
|
{ /* scaledRefClkMhz = 46.08 MHz */
|
|
vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ?
|
|
14 :(vcoIndex <= 10 || vcoIndex > 44) ?
|
|
15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ?
|
|
12 : 13;
|
|
|
|
loopFilterIcp = icp_46p08[vcoIndex-1];
|
|
loopFilterC2C1 = 0xF9; /* C2=0xF0 */
|
|
loopFilterR1C3 = 0xD5;
|
|
loopFilterR3 = 0x0E;
|
|
}
|
|
else if (scaledRefClk_kHz >= 53760 && scaledRefClk_kHz < 69120)
|
|
{ /* scaledRefClkMhz = 61.44 MHz */
|
|
vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 29 && vcoIndex <= 34) || vcoIndex == 40 || vcoIndex == 44) ?
|
|
14 :(vcoIndex <= 10 || vcoIndex > 44) ?
|
|
15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 25) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 34 && vcoIndex <= 37)) ?
|
|
12 : (vcoIndex > 37 && vcoIndex <= 39) ? 11 : 13;
|
|
|
|
vcoVaractor = (vcoIndex > 35 && vcoIndex <= 39) ? 1 : vcoVaractor;
|
|
vcoBiasRef = (vcoIndex > 4 && vcoIndex <= 7) ? 5 : vcoBiasRef;
|
|
vcoVaractorRef = (vcoIndex > 35 && vcoIndex <= 39) ? 14 : vcoVaractorRef;
|
|
loopFilterIcp = icp_61p44[vcoIndex-1];
|
|
loopFilterC2C1 = ((vcoIndex > 2 && vcoIndex <= 6) || (vcoIndex > 8 && vcoIndex <= 13) || (vcoIndex > 14)) ? 0xFD : 0xFC; /* C2=0xF0 */
|
|
loopFilterR1C3 = 0xC5;
|
|
loopFilterR3 = (vcoIndex <= 2 || (vcoIndex > 6 && vcoIndex <= 8) || vcoIndex == 14) ? 14 : 13 ;
|
|
}
|
|
else if (scaledRefClk_kHz >= 69120 && scaledRefClk_kHz < 80000)
|
|
{ /* scaledRefClkMhz = 76.8 MHz */
|
|
vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ?
|
|
14 :(vcoIndex <= 10 || vcoIndex > 44) ?
|
|
15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ?
|
|
12 : 13;
|
|
|
|
loopFilterIcp = icp_76p8[vcoIndex-1];
|
|
loopFilterC2C1 = (vcoIndex == 20 ) ? 0xF7 : (vcoIndex == 4 || vcoIndex == 6 || vcoIndex == 8 ) ? 0xE6: 0xF6; /*C2=0xF0, C1=6 or 7 */
|
|
loopFilterR1C3 = (vcoIndex == 4 ) ? 0xE4 : 0xD5;
|
|
loopFilterR3 = 0x0E;
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETRFPLL_INV_REFCLK, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Hold CLKPLL digital logic in reset */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_4, 0x00);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set Device clock divider */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_5, clockControl5);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Set reference clock scaler + HSdiv */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_2, clockControl2);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/*Set VCO cal time */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_CAL_CONTROL, 0x02);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Write Synth Setting regs */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_F_VCOTN_BYTE1, ((vcoCalOffset & 0x0F) << 3)); /* Set VCO Cal offset[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE1, (0xC0 | (vcoVaractor & 0x0F))); /* Init ALC[3:0], VCO varactor[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE2, (0x40 | (vcoOutLvl & 0x0F))); /* VCO output level */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE9, (((vcoBiasTcf & 0x03) << 3) | (vcoBiasRef & 0x07))); /* Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_VCO_CAL_REF, 0x30); /* Set VCO cal time (compare length) + Set VCO Cal Ref Tcf[2:0]=0 */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_VCO_VAR_CTR1, 0x70); /* Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_VCO_VAR_CTR2, (vcoVaractorRef & 0x0F)); /* Set VCO Varactor Reference[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Write Loop filter */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE3, (loopFilterIcp & 0x03F)); /* Set Loop Filter Icp[5:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE6, loopFilterC2C1); /* Set Loop Filter C2[3:0] and C1[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE7, loopFilterR1C3); /* Set Loop Filter R1[3:0] and C3[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_LF_R3, (loopFilterR3 & 0x0F)); /*Set Loop Filter R3[3:0] */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Calculate PLL integer and fractional words with integer math */
|
|
scaledRefClk_Hz = scaledRefClk_kHz * 1000;
|
|
hsDigClk_Hz_div2 = (uint32_t)((((((uint64_t)(clockSettings->clkPllVcoFreq_kHz) * 1000) >> 1) / hsDivTimes10) * 10) >> 1);
|
|
integerWord = (uint16_t)(hsDigClk_Hz_div2 / scaledRefClk_Hz);
|
|
fractionalRemainder = hsDigClk_Hz_div2 % scaledRefClk_Hz;
|
|
|
|
/* +1 >>1 is rounding (add .5) */
|
|
fractionalWord = (uint32_t)(((uint64_t)fractionalRemainder * 4177920 / (uint64_t)scaledRefClk_Hz) + 1 ) >> 1;
|
|
|
|
/* if fractionalWord rounded up and == PLL modulus, fix it */
|
|
if (fractionalWord == 2088960)
|
|
{
|
|
fractionalWord = 0;
|
|
integerWord = integerWord + 1;
|
|
}
|
|
|
|
if (fractionalWord > 0)
|
|
{ /* in normal case, the fractional word should be zero and SDM bypassed */
|
|
sdmSettings = 0x20;
|
|
|
|
if (integerWord < 9)
|
|
{
|
|
/* Ndivider too small for PLL design */
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETCLKPLL_INV_NDIV, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Bypass SDM */
|
|
sdmSettings = 0xE0;
|
|
|
|
if (integerWord < 6)
|
|
{
|
|
/* Ndivider too small for PLL design */
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_SETCLKPLL_INV_NDIV, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Set PLL fractional word[22:0] */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, (fractionalWord & 0xFF));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, ((fractionalWord >> 8) & 0xFF));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, ((fractionalWord >> 16) & 0x7F));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Write PLL integer word [7:0] */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, (sdmSettings | ((integerWord >> 8) & 0x7)));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, (integerWord & 0xFF));
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Release PLL from reset, and set start VCO cal bit to 0 */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_4, 0x80);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Power up CLKPLL */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTHESIZER_POWER_DOWN, 0x00);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = ADIHAL_wait_us(device->devHalInfo, CLKPLL_POWERUP_US); /* Allow PLL time to power up */
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_WAIT, halError, retVal, TALACT_ERR_CHECK_TIMER);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Enable Charge pump cal after Charge Pump current set (Icp[5:0]) */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLK_SYNTH_BYTE5, 0x84);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
/* Start VCO Cal */
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_4, 0x80);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_4, 0x81);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_setTxPfirSyncClk(taliseDevice_t *device, taliseTxProfile_t *txProfile)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
static const uint8_t NUM_MULT_PER_ROW = 20;
|
|
static const uint8_t MAX_NUM_TAPS = 80;
|
|
uint8_t effectiveRows = 0;
|
|
uint8_t numRows = 0;
|
|
uint32_t dpClk_kHz = 0;
|
|
uint32_t syncClk_kHz = 0;
|
|
uint32_t hsDigClkDiv4or5_kHz = 0;
|
|
uint8_t syncDiv = 0;
|
|
|
|
if ((device->devStateInfo.profilesValid & TX_PROFILE_VALID) > 0)
|
|
{
|
|
|
|
/* Calculate number of FIR rows for number of Taps */
|
|
if ((txProfile->txFir.numFirCoefs % NUM_MULT_PER_ROW == 0) &&
|
|
(txProfile->txFir.numFirCoefs > 0) &&
|
|
(txProfile->txFir.numFirCoefs <= MAX_NUM_TAPS))
|
|
{
|
|
numRows = (txProfile->txFir.numFirCoefs / NUM_MULT_PER_ROW);
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_TXFIR_INV_NUMTAPS_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
effectiveRows = ((numRows + (txProfile->txFirInterpolation - 1)) / txProfile->txFirInterpolation);
|
|
|
|
/* round up to next power of 2 */
|
|
switch (effectiveRows)
|
|
{
|
|
case 1: effectiveRows = 1; break;
|
|
case 2: effectiveRows = 2; break;
|
|
case 3: /* fall through */
|
|
case 4: effectiveRows = 4; break;
|
|
default:
|
|
{
|
|
/* invalid number of FIR taps */
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_TXFIR_INV_NUMROWS, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
dpClk_kHz = (txProfile->txInputRate_kHz * txProfile->txFirInterpolation * effectiveRows);
|
|
|
|
/* FIR DPCLK can only run at max of 500MHz */
|
|
if (dpClk_kHz > 500000)
|
|
{
|
|
/* Max number of Tx PFIR taps exceeded for Tx Profile */
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_TXFIR_TAPSEXCEEDED, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* SYNC CLOCK is the PFIR output rate / 2 */
|
|
syncClk_kHz = txProfile->txInputRate_kHz * txProfile->txFirInterpolation / 2;
|
|
|
|
hsDigClkDiv4or5_kHz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 1000;
|
|
|
|
/* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */
|
|
for (syncDiv = 0; syncDiv < 5; syncDiv++)
|
|
{
|
|
if ((hsDigClkDiv4or5_kHz / (4 << syncDiv)) <= syncClk_kHz)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Write Tx PFIR SYNC Clock divider */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_6, syncDiv, 0x38, 3);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
}
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_setRxPfirSyncClk(taliseDevice_t *device, taliseRxProfile_t *rxProfile, taliseORxProfile_t *orxProfile)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
static const uint8_t NUM_MULT_PER_ROW = 24;
|
|
static const uint8_t MAX_NUM_TAPS = 72;
|
|
uint8_t ddcMultiply = 1;
|
|
uint8_t ddcDivide = 1;
|
|
uint32_t rxOutClk_kHz = 0;
|
|
uint8_t rxNumRows = 0;
|
|
uint8_t rxEffectiveNumRows = 0;
|
|
uint32_t rxDpClk_kHz = 0;
|
|
|
|
uint8_t orxDdcDecRatio = 1;
|
|
uint32_t orxOutClk_kHz = 0;
|
|
uint8_t orxNumRows = 0;
|
|
uint8_t orxEffectiveNumRows = 0;
|
|
uint32_t orxDpClk_kHz = 0;
|
|
|
|
uint32_t slowestOutputRate_kHz = 0;
|
|
uint32_t syncClk_kHz = 0;
|
|
uint32_t hsDigClkDiv4or5_kHz = 0;
|
|
uint8_t syncDiv = 0;
|
|
|
|
/**
|
|
* Calculate Rx SYNC Clock divider for Rx PFIR. Same Rx SYNC Clock is used
|
|
* for Rx and ORx PFIRs, and must be slow enough to handle the slowest
|
|
* PFIR rate.
|
|
**/
|
|
|
|
/* Calculate clocks for Rx Profile */
|
|
if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) > 0)
|
|
{
|
|
/* Calculate decimation in DDC */
|
|
switch (rxProfile->rxDdcMode)
|
|
{
|
|
case TAL_RXDDC_BYPASS_REALIF:
|
|
case TAL_RXDDC_BYPASS:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 1;
|
|
break;
|
|
case TAL_RXDDC_DEC2_REALIF:
|
|
case TAL_RXDDC_DEC2:
|
|
ddcMultiply = 2;
|
|
ddcDivide = 1;
|
|
break;
|
|
case TAL_RXDDC_INT2_REALIF:
|
|
case TAL_RXDDC_INT2:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 2;
|
|
break;
|
|
case TAL_RXDDC_FILTERONLY_REALIF:
|
|
case TAL_RXDDC_FILTERONLY:
|
|
ddcMultiply = 1;
|
|
ddcDivide = 1;
|
|
break;
|
|
default:
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_RXFIR_INV_DDC, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Calculate Rx PFIR output from Rx output and decimation */
|
|
rxOutClk_kHz = (rxProfile->rxOutputRate_kHz * ddcMultiply ) / ddcDivide;
|
|
|
|
/* Set slowestOutputRate_kHz to the Rx PFIR output rate */
|
|
slowestOutputRate_kHz = rxOutClk_kHz;
|
|
|
|
/* Calculate number of rows in Rx FIR based on taps */
|
|
if ((rxProfile->rxFir.numFirCoefs % NUM_MULT_PER_ROW == 0) &&
|
|
(rxProfile->rxFir.numFirCoefs > 0) &&
|
|
(rxProfile->rxFir.numFirCoefs <= MAX_NUM_TAPS))
|
|
{
|
|
rxNumRows = (rxProfile->rxFir.numFirCoefs / NUM_MULT_PER_ROW);
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_RXFIR_INV_NUMTAPS_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Effective number of rows is the power of 2 that's >= rows */
|
|
switch(rxNumRows)
|
|
{
|
|
case 1:
|
|
rxEffectiveNumRows = 1;
|
|
break;
|
|
case 2:
|
|
rxEffectiveNumRows = 2;
|
|
break;
|
|
case 3:
|
|
rxEffectiveNumRows = 4;
|
|
break;
|
|
default:
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_RXFIR_INV_NUMROWS, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Calculate DP clock */
|
|
rxDpClk_kHz = rxOutClk_kHz * rxEffectiveNumRows;
|
|
|
|
/* DP clock is a max of 500Mhz in Talise */
|
|
if (rxDpClk_kHz > 500000)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_RXFIR_TAPSEXCEEDED, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Calculate clocks for Orx Profile */
|
|
if ((device->devStateInfo.profilesValid & ORX_PROFILE_VALID) > 0)
|
|
{
|
|
/* Calculate decimation in DDC */
|
|
switch (orxProfile->orxDdcMode)
|
|
{
|
|
case TAL_ORXDDC_SUBSAMPLE_BY2:
|
|
orxDdcDecRatio = 2;
|
|
break;
|
|
case TAL_ORXDDC_DISABLED:
|
|
orxDdcDecRatio = 1;
|
|
break;
|
|
default:
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_ORXFIR_INV_DDC, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Calculate ORx PFIR output from Rx output and decimation */
|
|
orxOutClk_kHz = orxProfile->orxOutputRate_kHz * orxDdcDecRatio;
|
|
|
|
/* Check if the ORx PFIR output is the slowest among all output clocks */
|
|
if ((slowestOutputRate_kHz == 0) ||
|
|
(slowestOutputRate_kHz > orxOutClk_kHz))
|
|
{
|
|
slowestOutputRate_kHz = orxOutClk_kHz;
|
|
}
|
|
|
|
/* Calculate number of rows in ORx FIR based on taps */
|
|
if ((orxProfile->rxFir.numFirCoefs % NUM_MULT_PER_ROW == 0) &&
|
|
(orxProfile->rxFir.numFirCoefs > 0) &&
|
|
(orxProfile->rxFir.numFirCoefs <= MAX_NUM_TAPS))
|
|
{
|
|
orxNumRows = (orxProfile->rxFir.numFirCoefs / NUM_MULT_PER_ROW);
|
|
}
|
|
else
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_ORXFIR_INV_NUMTAPS_PARM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
/* Effective number of rows is the power of 2 that's >= rows */
|
|
switch(orxNumRows)
|
|
{
|
|
case 1:
|
|
orxEffectiveNumRows = 1;
|
|
break;
|
|
case 2:
|
|
orxEffectiveNumRows = 2;
|
|
break;
|
|
case 3:
|
|
orxEffectiveNumRows = 4;
|
|
break;
|
|
default:
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_ORXFIR_INV_NUMROWS, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* Calculate DP clock */
|
|
orxDpClk_kHz = orxOutClk_kHz * orxEffectiveNumRows;
|
|
|
|
/* DP clock is a max of 500Mhz in Talise */
|
|
if (orxDpClk_kHz > 500000)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TALISE_ERR_ORXFIR_TAPSEXCEEDED, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
}
|
|
|
|
/* SYNC CLOCK should be FIR output rate / 2 */
|
|
syncClk_kHz = (slowestOutputRate_kHz / 2);
|
|
|
|
/* Get hsDigClkDiv4or5_kHz from profile */
|
|
hsDigClkDiv4or5_kHz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz / 1000;
|
|
|
|
/* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */
|
|
for (syncDiv = 0; syncDiv < 5; syncDiv++)
|
|
{
|
|
if ((hsDigClkDiv4or5_kHz / (4 << syncDiv)) <= syncClk_kHz)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Write Rx/Orx PFIR SYNC Clock divider */
|
|
halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_6, syncDiv, 0x7, 0);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
IF_ERR_RETURN_U32(retVal);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_getApiVersion (taliseDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getApiVersion()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
if ((siVer == NULL) ||
|
|
(majorVer == NULL) ||
|
|
(minorVer == NULL) ||
|
|
(buildVer == NULL))
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_GETAPIVERSION_NULLPARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
*siVer = TAL_CURRENT_SI_VERSION;
|
|
*majorVer = TAL_CURRENT_MAJOR_VERSION;
|
|
*minorVer = TAL_CURRENT_MINOR_VERSION;
|
|
*buildVer = TAL_CURRENT_BUILD_VERSION;
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_getDeviceRev(taliseDevice_t *device, uint8_t *revision)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getDeviceRev()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
if (revision == NULL)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_GETDEVICEREV_NULLPARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_PRODUCT_ID_1, revision);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|
|
|
|
uint32_t TALISE_getProductId(taliseDevice_t *device, uint8_t *productId)
|
|
{
|
|
talRecoveryActions_t retVal = TALACT_NO_ACTION;
|
|
adiHalErr_t halError = ADIHAL_OK;
|
|
|
|
#if TALISE_VERBOSE
|
|
halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getProductId()\n");
|
|
retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
|
|
#endif
|
|
|
|
if (productId == NULL)
|
|
{
|
|
return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
|
|
TAL_ERR_GETPRODUCTID_NULLPARAM, retVal, TALACT_ERR_CHECK_PARAM);
|
|
}
|
|
|
|
halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_PRODUCT_ID_0, productId);
|
|
retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
|
|
|
|
return (uint32_t)retVal;
|
|
}
|