aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/lib/rfdc/xrfdc_mixer.c
diff options
context:
space:
mode:
authorLars Amsel <lars.amsel@ni.com>2021-06-04 08:27:50 +0200
committerAaron Rossetto <aaron.rossetto@ni.com>2021-06-10 12:01:53 -0500
commit2a575bf9b5a4942f60e979161764b9e942699e1e (patch)
tree2f0535625c30025559ebd7494a4b9e7122550a73 /mpm/lib/rfdc/xrfdc_mixer.c
parente17916220cc955fa219ae37f607626ba88c4afe3 (diff)
downloaduhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.gz
uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.tar.bz2
uhd-2a575bf9b5a4942f60e979161764b9e942699e1e.zip
uhd: Add support for the USRP X410
Co-authored-by: Lars Amsel <lars.amsel@ni.com> Co-authored-by: Michael Auchter <michael.auchter@ni.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Cristina Fuentes <cristina.fuentes-curiel@ni.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Virendra Kakade <virendra.kakade@ni.com> Co-authored-by: Lane Kolbly <lane.kolbly@ni.com> Co-authored-by: Max Köhler <max.koehler@ni.com> Co-authored-by: Andrew Lynch <andrew.lynch@ni.com> Co-authored-by: Grant Meyerhoff <grant.meyerhoff@ni.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Thomas Vogel <thomas.vogel@ni.com>
Diffstat (limited to 'mpm/lib/rfdc/xrfdc_mixer.c')
-rw-r--r--mpm/lib/rfdc/xrfdc_mixer.c1091
1 files changed, 1091 insertions, 0 deletions
diff --git a/mpm/lib/rfdc/xrfdc_mixer.c b/mpm/lib/rfdc/xrfdc_mixer.c
new file mode 100644
index 000000000..747e180a4
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_mixer.c
@@ -0,0 +1,1091 @@
+/******************************************************************************
+*
+* Copyright (C) 2018-2019 Xilinx, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xrfdc_mixer.c
+* @addtogroup xrfdc_v6_0
+* @{
+*
+* Contains the interface functions of the Mixer Settings in XRFdc driver.
+* See xrfdc.h for a detailed description of the device and driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 5.0 sk 08/06/18 Initial release
+* 5.1 cog 01/29/19 Replace structure reference ADC checks with
+* function.
+* cog 01/29/19 XRFdc_SetCoarseMixer and MixerRangeCheck now need
+* Tile_id as a parameter.
+* cog 01/29/19 Rename DataType to MixerInputDataType for
+* readability.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "mpm/rfdc/xrfdc.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+static void XRFdc_SetFineMixer(XRFdc *InstancePtr, u32 BaseAddr,
+ XRFdc_Mixer_Settings *MixerSettingsPtr);
+static void XRFdc_SetCoarseMixer(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 Tile_Id, u32 Block_Id, u32 CoarseMixFreq, XRFdc_Mixer_Settings *MixerSettingsPtr);
+static u32 XRFdc_MixerRangeCheck(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_Mixer_Settings *MixerSettingsPtr);
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+* The API is used to update various mixer settings, fine, coarse, NCO etc.
+* Mixer/NCO settings passed are used to update the corresponding
+* block level registers. Driver structure is updated with the new values.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not enabled.
+*
+* @note FineMixerScale in Mixer_Settings structure can have 3 values.
+* XRFDC_MIXER_SCALE_* represents the valid values.
+* XRFDC_MIXER_SCALE_AUTO - If mixer mode is R2C, Mixer Scale is
+* set to 1 and for other modes mixer scale is set to 0.7
+* XRFDC_MIXER_SCALE_1P0 - To set fine mixer scale to 1.
+* XRFDC_MIXER_SCALE_0P7 - To set fine mixer scale to 0.7.
+*
+******************************************************************************/
+u32 XRFdc_SetMixerSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+ u16 ReadReg;
+ u32 BaseAddr;
+ double SamplingRate;
+ s64 Freq;
+ s32 PhaseOffset;
+ u32 NoOfBlocks;
+ u32 Index;
+ XRFdc_Mixer_Settings *MixerConfigPtr;
+ u8 CalibrationMode = 0U;
+ u32 CoarseMixFreq;
+ double NCOFreq;
+ u32 NyquistZone = 0U;
+ u32 Offset;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(MixerSettingsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ Status = XRFdc_MixerRangeCheck(InstancePtr, Type, Tile_Id, MixerSettingsPtr);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ Index = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ NoOfBlocks = XRFDC_NUM_OF_BLKS2;
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Index = XRFDC_BLK_ID2;
+ NoOfBlocks = XRFDC_NUM_OF_BLKS4;
+ }
+ } else {
+ NoOfBlocks = Block_Id + 1U;
+ }
+
+ for (; Index < NoOfBlocks; Index++) {
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ MixerConfigPtr = &InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].Mixer_Settings;
+ SamplingRate = InstancePtr->ADC_Tile[Tile_Id].
+ PLL_Settings.SampleRate;
+ } else {
+ /* DAC */
+ MixerConfigPtr = &InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].Mixer_Settings;
+ SamplingRate = InstancePtr->DAC_Tile[Tile_Id].
+ PLL_Settings.SampleRate;
+ }
+
+ BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Index);
+
+ if (SamplingRate <= 0) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Incorrect Sampling "
+ "rate in %s\r\n", __func__);
+ goto RETURN_PATH;
+ } else {
+ metal_log(METAL_LOG_DEBUG, "\n Sampling "
+ "rate is %2.4f in %s\r\n", SamplingRate, __func__);
+ }
+
+ SamplingRate *= XRFDC_MILLI;
+ /* Set MixerInputDataType for ADC and DAC */
+ if (Type == XRFDC_DAC_TILE) {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_ITERP_DATA_OFFSET);
+ ReadReg &= ~XRFDC_DAC_INTERP_DATA_MASK;
+ InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].MixerInputDataType =
+ XRFDC_DATA_TYPE_REAL;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ ReadReg |= XRFDC_DAC_INTERP_DATA_MASK;
+ InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_IQ;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_DAC_ITERP_DATA_OFFSET, ReadReg);
+ } else {
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DECI_CONFIG_OFFSET);
+ ReadReg &= ~XRFDC_DEC_CFG_MASK;
+ if (XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) {
+ ReadReg |= XRFDC_DEC_CFG_4GSPS_MASK;
+ } else if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C)) {
+ ReadReg |= XRFDC_DEC_CFG_IQ_MASK;
+ } else {
+ ReadReg |= XRFDC_DEC_CFG_CHA_MASK;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_DECI_CONFIG_OFFSET, ReadReg);
+ if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) {
+ InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_IQ;
+ }
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R)) {
+ InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Index].
+ MixerInputDataType = XRFDC_DATA_TYPE_REAL;
+ }
+ }
+
+ /* Set NCO Phase Mode */
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if ((Index == XRFDC_BLK_ID0) || (Index == XRFDC_BLK_ID2)) {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_PHASE_MOD_OFFSET,
+ XRFDC_NCO_PHASE_MOD_EVEN);
+ } else {
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_PHASE_MOD_OFFSET,
+ XRFDC_NCO_PHASE_MODE_ODD);
+ }
+ }
+
+ /* Update NCO, CoarseMix freq based on calibration mode */
+ CoarseMixFreq = MixerSettingsPtr->CoarseMixFreq;
+ NCOFreq = MixerSettingsPtr->Freq;
+ if (Type == XRFDC_ADC_TILE) {
+ Status = XRFdc_GetCalibrationMode(InstancePtr,
+ Tile_Id, Block_Id, &CalibrationMode);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+ if (CalibrationMode == XRFDC_CALIB_MODE1) {
+ switch (CoarseMixFreq) {
+ case XRFDC_COARSE_MIX_BYPASS:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ break;
+ case XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ break;
+ default:
+ CoarseMixFreq =
+ XRFDC_COARSE_MIX_OFF;
+ break;
+ }
+ NCOFreq -= SamplingRate / 2.0;
+ }
+ }
+
+ if ((NCOFreq < -(SamplingRate / 2.0)) ||
+ (NCOFreq > (SamplingRate / 2.0))) {
+ Status = XRFdc_GetNyquistZone(InstancePtr, Type,
+ Tile_Id, Block_Id, &NyquistZone);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+ do {
+ if (NCOFreq < -(SamplingRate / 2.0)) {
+ NCOFreq += SamplingRate;
+ }
+ if (NCOFreq > (SamplingRate / 2.0)) {
+ NCOFreq -= SamplingRate;
+ }
+ } while ((NCOFreq < -(SamplingRate / 2.0)) ||
+ (NCOFreq > (SamplingRate / 2.0)));
+
+ if ((NyquistZone == XRFDC_EVEN_NYQUIST_ZONE) &&
+ (NCOFreq != 0)) {
+ NCOFreq *= -1;
+ }
+ }
+
+ /* NCO Frequency */
+ if (NCOFreq < 0) {
+ Freq = ((NCOFreq * XRFDC_NCO_FREQ_MIN_MULTIPLIER) /
+ SamplingRate);
+ } else {
+ Freq = ((NCOFreq * XRFDC_NCO_FREQ_MULTIPLIER) /
+ SamplingRate);
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_LOW_OFFSET, (u16)Freq);
+ ReadReg = (Freq >> XRFDC_NCO_FQWD_MID_SHIFT) & XRFDC_NCO_FQWD_MID_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_MID_OFFSET, (u16)ReadReg);
+ ReadReg = (Freq >> XRFDC_NCO_FQWD_UPP_SHIFT) & XRFDC_NCO_FQWD_UPP_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_UPP_OFFSET, (u16)ReadReg);
+
+ /* Phase Offset */
+ PhaseOffset = ((MixerSettingsPtr->PhaseOffset *
+ XRFDC_NCO_PHASE_MULTIPLIER) / XRFDC_MIXER_PHASE_OFFSET_UP_LIMIT);
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_NCO_PHASE_LOW_OFFSET,
+ (u16)PhaseOffset);
+
+ ReadReg = (PhaseOffset >> XRFDC_NCO_PHASE_UPP_SHIFT) &
+ XRFDC_NCO_PHASE_UPP_MASK;
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_NCO_PHASE_UPP_OFFSET,
+ ReadReg);
+
+ if (MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) {
+ XRFdc_SetCoarseMixer(InstancePtr, Type, BaseAddr, Tile_Id,
+ Index, CoarseMixFreq, MixerSettingsPtr);
+ } else {
+ XRFdc_SetFineMixer(InstancePtr, BaseAddr, MixerSettingsPtr);
+ }
+
+ /* Fine Mixer Scale */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_MXR_MODE_OFFSET);
+ if (MixerSettingsPtr->FineMixerScale == XRFDC_MIXER_SCALE_1P0) {
+ ReadReg |= XRFDC_FINE_MIX_SCALE_MASK;
+ InstancePtr->UpdateMixerScale = 0x1U;
+ } else if (MixerSettingsPtr->FineMixerScale == XRFDC_MIXER_SCALE_0P7) {
+ ReadReg &= ~XRFDC_FINE_MIX_SCALE_MASK;
+ InstancePtr->UpdateMixerScale = 0x1U;
+ } else {
+ InstancePtr->UpdateMixerScale = 0x0U;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ ReadReg);
+
+ /* Event Source */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_NCO_UPDT_OFFSET,
+ XRFDC_NCO_UPDT_MODE_MASK, MixerSettingsPtr->EventSource);
+ if (MixerSettingsPtr->EventSource == XRFDC_EVNT_SRC_IMMEDIATE) {
+ if (Type == XRFDC_ADC_TILE) {
+ Offset = XRFDC_ADC_UPDATE_DYN_OFFSET;
+ } else {
+ Offset = XRFDC_DAC_UPDATE_DYN_OFFSET;
+ }
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, Offset,
+ XRFDC_UPDT_EVNT_MASK, XRFDC_UPDT_EVNT_NCO_MASK);
+ }
+
+ /* Update the instance with new values */
+ MixerConfigPtr->EventSource = MixerSettingsPtr->EventSource;
+ MixerConfigPtr->PhaseOffset = MixerSettingsPtr->PhaseOffset;
+ MixerConfigPtr->MixerMode = MixerSettingsPtr->MixerMode;
+ MixerConfigPtr->CoarseMixFreq = MixerSettingsPtr->CoarseMixFreq;
+ MixerConfigPtr->Freq = MixerSettingsPtr->Freq;
+ MixerConfigPtr->MixerType = MixerSettingsPtr->MixerType;
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+
+}
+
+/*****************************************************************************/
+/**
+* Static API used to do the Mixer Settings range check.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if mixer settings are within the range.
+* - XRFDC_FAILURE if mixer settings are not in valid range
+*
+* @note None
+*
+******************************************************************************/
+static u32 XRFdc_MixerRangeCheck(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+
+ if ((MixerSettingsPtr->PhaseOffset >=
+ XRFDC_MIXER_PHASE_OFFSET_UP_LIMIT) ||
+ (MixerSettingsPtr->PhaseOffset <=
+ XRFDC_MIXER_PHASE_OFFSET_LOW_LIMIT)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid phase offset value "
+ "in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->EventSource > XRFDC_EVNT_SRC_PL) ||
+ ((MixerSettingsPtr->EventSource == XRFDC_EVNT_SRC_MARKER) &&
+ (Type == XRFDC_ADC_TILE))) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid event source "
+ "selection in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (MixerSettingsPtr->MixerMode > XRFDC_MIXER_MODE_R2R) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid fine mixer mode "
+ "in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->CoarseMixFreq != XRFDC_COARSE_MIX_OFF) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR) &&
+ (MixerSettingsPtr->CoarseMixFreq !=
+ XRFDC_COARSE_MIX_BYPASS)) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid coarse mix "
+ "frequency value in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+ if (MixerSettingsPtr->FineMixerScale > XRFDC_MIXER_SCALE_0P7) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer Scale in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if (((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) &&
+ (Type == XRFDC_DAC_TILE)) ||
+ ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R) &&
+ (Type == XRFDC_ADC_TILE))) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType != XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerType != XRFDC_MIXER_TYPE_COARSE)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Mixer Type in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE) &&
+ ((MixerSettingsPtr->EventSource == XRFDC_EVNT_SRC_SLICE) ||
+ (MixerSettingsPtr->EventSource ==
+ XRFDC_EVNT_SRC_IMMEDIATE))) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Event Source, event "
+ "source is not supported in 4GSPS ADC %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if (((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->CoarseMixFreq == XRFDC_COARSE_MIX_OFF)) ||
+ ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_OFF))) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer settings in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_OFF)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_FINE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+ if ((MixerSettingsPtr->MixerType == XRFDC_MIXER_TYPE_COARSE) &&
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2R) &&
+ (MixerSettingsPtr->CoarseMixFreq != XRFDC_COARSE_MIX_BYPASS)) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Invalid Combination of "
+ "Mixer type and Mixer mode in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ Status = XRFDC_SUCCESS;
+
+RETURN_PATH:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* Static API used to set the Fine Mixer.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param BaseAddr is ADC or DAC base address.
+* @param CoarseMixFreq is ADC or DAC Coarse mixer frequency.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - None
+*
+* @note Static API
+*
+******************************************************************************/
+static void XRFdc_SetFineMixer(XRFdc *InstancePtr, u32 BaseAddr,
+ XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+
+ if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_SEL_I_IQ_MASK | XRFDC_SEL_Q_IQ_MASK |
+ XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK),
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK |
+ XRFDC_I_IQ_COS_MINSIN | XRFDC_Q_IQ_SIN_COS));
+ } else if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_SEL_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK),
+ (XRFDC_EN_I_IQ_MASK | XRFDC_I_IQ_COS_MINSIN));
+ } else if (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_R2C) {
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK |
+ XRFDC_SEL_I_IQ_MASK | XRFDC_SEL_Q_IQ_MASK |
+ XRFDC_FINE_MIX_SCALE_MASK), (XRFDC_EN_I_IQ | XRFDC_EN_Q_IQ |
+ XRFDC_I_IQ_COS_MINSIN | XRFDC_Q_IQ_SIN_COS |
+ XRFDC_FINE_MIX_SCALE_MASK));
+ } else {
+ /* Fine mixer mode is OFF */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ XRFDC_MIXER_MODE_OFF);
+ }
+
+ /* Coarse Mixer is OFF */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_OFF);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG1_OFFSET,
+ XRFDC_MIX_CFG1_MASK, XRFDC_CRSE_MIX_OFF);
+}
+
+/*****************************************************************************/
+/**
+* Static API used to set the Coarse Mixer.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param BaseAddr is ADC or DAC base address.
+* @param Block_Id is ADC/DAC block number inside the tile.
+* @param CoarseMixFreq is ADC or DAC Coarse mixer frequency.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - None
+*
+* @note Static API
+*
+******************************************************************************/
+static void XRFdc_SetCoarseMixer(XRFdc *InstancePtr, u32 Type, u32 BaseAddr,
+ u32 Tile_Id, u32 Block_Id, u32 CoarseMixFreq, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u16 ReadReg;
+
+ if (CoarseMixFreq == XRFDC_COARSE_MIX_BYPASS) {
+ /* Coarse Mix BYPASS */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_BYPASS);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ ReadReg |= XRFDC_CRSE_MIX_BYPASS;
+ } else {
+ ReadReg |= XRFDC_CRSE_MIX_OFF;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO) {
+ /* Coarse Mix freq Fs/2 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_Q_FSBYTWO;
+ } else {
+ if ((Block_Id % 2U) == 0U) {
+ ReadReg |= XRFDC_CRSE_MIX_BYPASS;
+ } else {
+ ReadReg |= XRFDC_CRSE_4GSPS_ODD_FSBYTWO;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_Q_FSBYTWO;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_BYPASS :
+ XRFDC_CRSE_4GSPS_ODD_FSBYTWO;
+ }
+ } else {
+ ReadReg |= XRFDC_CRSE_MIX_OFF;
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR) {
+ /* Coarse Mix freq Fs/4 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_I_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_OFF;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_Q_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_Q_FSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_OFF :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR) {
+ /* Coarse Mix freq -Fs/4 */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG0_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_I_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_I_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_OFF;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, (u16)ReadReg);
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET);
+ ReadReg &= ~XRFDC_MIX_CFG1_MASK;
+ if ((MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2C) ||
+ (MixerSettingsPtr->MixerMode == XRFDC_MIXER_MODE_C2R)) {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_Q_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_I_Q_FSBYTWO :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ } else {
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ ReadReg |= XRFDC_CRSE_MIX_R_Q_MINFSBYFOUR;
+ } else {
+ ReadReg |= ((Block_Id % 2U) == 0U) ?
+ XRFDC_CRSE_MIX_OFF :
+ XRFDC_CRSE_MIX_I_ODD_FSBYFOUR;
+ }
+ }
+ XRFdc_WriteReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, (u16)ReadReg);
+ } else if (CoarseMixFreq == XRFDC_COARSE_MIX_OFF) {
+ /* Coarse Mix OFF */
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG0_OFFSET,
+ XRFDC_MIX_CFG0_MASK, XRFDC_CRSE_MIX_OFF);
+ XRFdc_ClrSetReg(InstancePtr, BaseAddr, XRFDC_ADC_MXR_CFG1_OFFSET,
+ XRFDC_MIX_CFG1_MASK, XRFDC_CRSE_MIX_OFF);
+ } else {
+ metal_log(METAL_LOG_ERROR, "\n Invalid Coarse "
+ "Mixer frequency in %s\r\n", __func__);
+ }
+
+ /* Fine mixer mode is OFF */
+ XRFdc_WriteReg16(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ XRFDC_MIXER_MODE_OFF);
+}
+
+/*****************************************************************************/
+/**
+*
+* The API returns back Mixer/NCO settings to the caller.
+*
+* @param InstancePtr is a pointer to the XRfdc instance.
+* @param Type is ADC or DAC. 0 for ADC and 1 for DAC
+* @param Tile_Id Valid values are 0-3.
+* @param Block_Id is ADC/DAC block number inside the tile. Valid values
+* are 0-3.
+* @param MixerSettingsPtr Pointer to the XRFdc_Mixer_Settings structure
+* in which the Mixer/NCO settings are passed.
+*
+* @return
+* - XRFDC_SUCCESS if successful.
+* - XRFDC_FAILURE if Block not enabled.
+*
+* @note FineMixerScale in Mixer_Settings structure can have 3 values.
+* XRFDC_MIXER_SCALE_* represents the valid values.
+* XRFDC_MIXER_SCALE_AUTO - If mixer mode is R2C, Mixer Scale is
+* set to 1 and for other modes mixer scale is set to 0.7
+* XRFDC_MIXER_SCALE_1P0 - To set fine mixer scale to 1.
+* XRFDC_MIXER_SCALE_0P7 - To set fine mixer scale to 0.7.
+*
+******************************************************************************/
+u32 XRFdc_GetMixerSettings(XRFdc *InstancePtr, u32 Type, u32 Tile_Id,
+ u32 Block_Id, XRFdc_Mixer_Settings *MixerSettingsPtr)
+{
+ u32 Status;
+ u32 BaseAddr;
+ u64 ReadReg;
+ u64 ReadReg_Mix1;
+ double SamplingRate;
+ s64 Freq;
+ s32 PhaseOffset;
+ u32 Block;
+ u8 CalibrationMode = 0U;
+ XRFdc_Mixer_Settings *MixerConfigPtr;
+ u32 NyquistZone = 0U;
+ double NCOFreq;
+ u32 FineMixerMode;
+ u32 CoarseMixerMode = 0x0;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(MixerSettingsPtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XRFDC_COMPONENT_IS_READY);
+
+ Status = XRFdc_CheckDigitalPathEnabled(InstancePtr, Type, Tile_Id, Block_Id);
+ if (Status != XRFDC_SUCCESS) {
+ goto RETURN_PATH;
+ }
+
+ Block = Block_Id;
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 1) &&
+ (Type == XRFDC_ADC_TILE)) {
+ if (Block_Id == XRFDC_BLK_ID1) {
+ Block_Id = XRFDC_BLK_ID3;
+ }
+ if (Block_Id == XRFDC_BLK_ID0) {
+ Block_Id = XRFDC_BLK_ID1;
+ }
+ }
+
+ if (Type == XRFDC_ADC_TILE) {
+ /* ADC */
+ SamplingRate = InstancePtr->ADC_Tile[Tile_Id].PLL_Settings.
+ SampleRate;
+ MixerConfigPtr = &InstancePtr->ADC_Tile[Tile_Id].
+ ADCBlock_Digital_Datapath[Block_Id].Mixer_Settings;
+ } else {
+ /* DAC */
+ SamplingRate = InstancePtr->DAC_Tile[Tile_Id].PLL_Settings.
+ SampleRate;
+ MixerConfigPtr = &InstancePtr->DAC_Tile[Tile_Id].
+ DACBlock_Digital_Datapath[Block_Id].Mixer_Settings;
+ }
+
+ if (SamplingRate <= 0) {
+ Status = XRFDC_FAILURE;
+ metal_log(METAL_LOG_ERROR, "\n Incorrect Sampling rate "
+ "in %s\r\n", __func__);
+ goto RETURN_PATH;
+ }
+
+ BaseAddr = XRFDC_BLOCK_BASE(Type, Tile_Id, Block_Id);
+ SamplingRate *= XRFDC_MILLI;
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG0_OFFSET, XRFDC_MIX_CFG0_MASK);
+ ReadReg_Mix1 = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_ADC_MXR_CFG1_OFFSET, XRFDC_MIX_CFG1_MASK);
+ MixerSettingsPtr->CoarseMixFreq = 0x20;
+
+ /* Identify CoarseMixFreq and CoarseMixerMode */
+ if (ReadReg == XRFDC_CRSE_MIX_BYPASS) {
+ if (ReadReg_Mix1 == XRFDC_CRSE_MIX_BYPASS) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2R;
+ if (MixerConfigPtr->MixerMode == XRFDC_MIXER_MODE_R2C) {
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ }
+ }
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_I_Q_FSBYTWO) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_Q_FSBYTWO)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_Q_FSBYTWO)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if (ReadReg == XRFDC_CRSE_4GSPS_ODD_FSBYTWO) {
+ if (ReadReg_Mix1 == XRFDC_CRSE_4GSPS_ODD_FSBYTWO) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg_Mix1 == XRFDC_CRSE_MIX_OFF) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ }
+ }
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_I_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 ==
+ XRFDC_CRSE_MIX_R_Q_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_R_I_MINFSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if ((ReadReg == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+
+ }
+
+ if ((XRFdc_IsHighSpeedADC(InstancePtr, Tile_Id) == 0) ||
+ (Type == XRFDC_DAC_TILE)) {
+ if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_I_FSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_Q_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg_Mix1 == XRFDC_CRSE_MIX_R_Q_MINFSBYFOUR) &&
+ (ReadReg == XRFDC_CRSE_MIX_R_I_MINFSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+ } else {
+ if ((ReadReg == XRFDC_CRSE_MIX_Q_ODD_FSBYFOUR) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if ((ReadReg == XRFDC_CRSE_MIX_OFF) &&
+ (ReadReg_Mix1 == XRFDC_CRSE_MIX_I_ODD_FSBYFOUR)) {
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ CoarseMixerMode = XRFDC_MIXER_MODE_R2C;
+ }
+
+ }
+
+ if ((ReadReg == XRFDC_CRSE_MIX_OFF) && (ReadReg_Mix1 ==
+ XRFDC_CRSE_MIX_OFF)) {
+ MixerSettingsPtr->CoarseMixFreq = XRFDC_COARSE_MIX_OFF;
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2C;
+ }
+ if (MixerSettingsPtr->CoarseMixFreq == 0x20U) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Coarse mixer settings not match any of the modes %s\r\n",
+ __func__);
+ }
+ if ((MixerConfigPtr->MixerMode == XRFDC_MIXER_MODE_C2R) &&
+ (CoarseMixerMode == XRFDC_MIXER_MODE_C2C)) {
+ CoarseMixerMode = XRFDC_MIXER_MODE_C2R;
+ }
+
+ /* Identify FineMixerMode */
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr, XRFDC_MXR_MODE_OFFSET,
+ (XRFDC_EN_I_IQ_MASK | XRFDC_EN_Q_IQ_MASK));
+ if (ReadReg == 0xFU) {
+ FineMixerMode = XRFDC_MIXER_MODE_C2C;
+ } else if (ReadReg == 0x3U) {
+ FineMixerMode = XRFDC_MIXER_MODE_C2R;
+ } else if (ReadReg == 0x5U) {
+ FineMixerMode = XRFDC_MIXER_MODE_R2C;
+ } else {
+ FineMixerMode = XRFDC_MIXER_MODE_OFF;
+ }
+
+ if (FineMixerMode == XRFDC_MIXER_MODE_OFF) {
+ MixerSettingsPtr->MixerType = XRFDC_MIXER_TYPE_COARSE;
+ MixerSettingsPtr->MixerMode = CoarseMixerMode;
+ } else {
+ MixerSettingsPtr->MixerType = XRFDC_MIXER_TYPE_FINE;
+ MixerSettingsPtr->MixerMode = FineMixerMode;
+ }
+
+ /* Identify Fine Mixer Scale */
+ ReadReg = XRFdc_RDReg(InstancePtr, BaseAddr,
+ XRFDC_MXR_MODE_OFFSET, XRFDC_FINE_MIX_SCALE_MASK);
+ if (InstancePtr->UpdateMixerScale == 0x0U) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_AUTO;
+ } else if ((ReadReg != 0U) &&
+ (InstancePtr->UpdateMixerScale == 0x1U)) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_1P0;
+ } else if (InstancePtr->UpdateMixerScale == 0x1U) {
+ MixerSettingsPtr->FineMixerScale =
+ XRFDC_MIXER_SCALE_0P7;
+ } else {
+ metal_log(METAL_LOG_ERROR,
+ "\n Invalid Fine mixer scale in %s\r\n", __func__);
+ Status = XRFDC_FAILURE;
+ goto RETURN_PATH;
+ }
+
+ /* Phase Offset */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_PHASE_UPP_OFFSET);
+ PhaseOffset = ReadReg << XRFDC_NCO_PHASE_UPP_SHIFT;
+ PhaseOffset |= XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_PHASE_LOW_OFFSET);
+ PhaseOffset &= XRFDC_NCO_PHASE_MASK;
+ PhaseOffset = ((PhaseOffset << 14) >> 14);
+ MixerSettingsPtr->PhaseOffset = ((PhaseOffset * 180.0) /
+ XRFDC_NCO_PHASE_MULTIPLIER);
+
+ /* NCO Frequency */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_UPP_OFFSET);
+ Freq = ReadReg << XRFDC_NCO_FQWD_UPP_SHIFT;
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_MID_OFFSET);
+ Freq |= ReadReg << XRFDC_NCO_FQWD_MID_SHIFT;
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_ADC_NCO_FQWD_LOW_OFFSET);
+ Freq |= ReadReg;
+ Freq &= XRFDC_NCO_FQWD_MASK;
+ Freq = (Freq << 16) >> 16;
+ if (Freq < 0) {
+ MixerSettingsPtr->Freq = ((Freq * SamplingRate) /
+ XRFDC_NCO_FREQ_MIN_MULTIPLIER);
+ } else {
+ MixerSettingsPtr->Freq = ((Freq * SamplingRate) /
+ XRFDC_NCO_FREQ_MULTIPLIER);
+ }
+
+ /* Event Source */
+ ReadReg = XRFdc_ReadReg16(InstancePtr, BaseAddr,
+ XRFDC_NCO_UPDT_OFFSET);
+ MixerSettingsPtr->EventSource = ReadReg & XRFDC_NCO_UPDT_MODE_MASK;
+
+ /* Update NCO, CoarseMix freq based on calibration mode */
+ NCOFreq = MixerConfigPtr->Freq;
+ if (Type == XRFDC_ADC_TILE) {
+ Status = XRFdc_GetCalibrationMode(InstancePtr, Tile_Id,
+ Block, &CalibrationMode);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+
+ if (CalibrationMode == XRFDC_CALIB_MODE1) {
+ switch (MixerSettingsPtr->CoarseMixFreq) {
+ case XRFDC_COARSE_MIX_BYPASS:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR;
+ break;
+ case XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_TWO:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_BYPASS;
+ break;
+ case XRFDC_COARSE_MIX_MIN_SAMPLE_FREQ_BY_FOUR:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_SAMPLE_FREQ_BY_FOUR;
+ break;
+ default:
+ MixerSettingsPtr->CoarseMixFreq =
+ XRFDC_COARSE_MIX_OFF;
+ break;
+ }
+ NCOFreq = (MixerConfigPtr->Freq -
+ (SamplingRate / 2.0));
+ }
+ }
+
+ if ((NCOFreq > (SamplingRate / 2.0)) ||
+ (NCOFreq < -(SamplingRate / 2.0))) {
+ Status = XRFdc_GetNyquistZone(InstancePtr,
+ Type, Tile_Id, Block, &NyquistZone);
+ if (Status != XRFDC_SUCCESS) {
+ return XRFDC_FAILURE;
+ }
+
+ if ((NyquistZone == XRFDC_EVEN_NYQUIST_ZONE) &&
+ (MixerSettingsPtr->Freq != 0)) {
+ MixerSettingsPtr->Freq *= -1;
+ }
+
+ do {
+ if (NCOFreq < -(SamplingRate / 2.0)) {
+ NCOFreq += SamplingRate;
+ MixerSettingsPtr->Freq -= SamplingRate;
+ }
+ if (NCOFreq > (SamplingRate / 2.0)) {
+ NCOFreq -= SamplingRate;
+ MixerSettingsPtr->Freq += SamplingRate;
+ }
+ } while ((NCOFreq > (SamplingRate / 2.0)) ||
+ (NCOFreq < -(SamplingRate / 2.0)));
+ }
+ if ((Type == XRFDC_ADC_TILE) &&
+ (CalibrationMode == XRFDC_CALIB_MODE1)) {
+ MixerSettingsPtr->Freq += (SamplingRate / 2.0);
+ }
+
+ Status = XRFDC_SUCCESS;
+RETURN_PATH:
+ return Status;
+
+}
+
+/** @} */