diff options
author | Lars Amsel <lars.amsel@ni.com> | 2021-06-04 08:27:50 +0200 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-06-10 12:01:53 -0500 |
commit | 2a575bf9b5a4942f60e979161764b9e942699e1e (patch) | |
tree | 2f0535625c30025559ebd7494a4b9e7122550a73 /mpm/lib/rfdc/xrfdc_mixer.c | |
parent | e17916220cc955fa219ae37f607626ba88c4afe3 (diff) | |
download | uhd-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.c | 1091 |
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; + +} + +/** @} */ |