Post Go back to editing

How to config DPD on AD9375?

Hi,

I use default DPDconfig to configure DPD on my custom board:

static mykonosDpdConfig_t dpdConfig =
{
    10,              /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/
    1,              /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/
    2,              /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/
    1,              /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/
    20,             /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/
    0,              /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */
    512,            /* Number of samples to capture (default: 512, valid 64-32768)*/
    4096,           /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/
    0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
    255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
    {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/
};

My system have multi mode BPSK, QPSK, QUAM16,QUAM64 with bandwidth 5MHz, 10MHz, 20Mhz. 

I have feedback Tx2 signal into ORX2 with power -24dbm and configure dpd follow ug992. But i don't see any different between have setup DPD and no have DPD.

Here is status that I read using MYKONOS_getDpdStatus:

 dpdStatus.dpdErrorStatus = 0,

dpdStatus.dpdExtPathDelay = 0x73B ,

dpdStatus.dpdIterCount = 0,

dpdStatus.dpdMaxAdaptation = 0,

dpdStatus.dpdModelErrorPercent = 1000,

dpdStatus.dpdTrackCount = 0

Can you suggest for me how to solve? Thanks. This is my output from tx:



dpdStatus.dpdErrorStatus = 0, dpdStatus.dpdExtPathDelay = 0x73B , dpdStatus.dpdIterCount = 0, dpdStatus.dpdMaxAdaptation = 0, dpdStatus.dpdModelErrorPercent = 1000, dpdStatus.dpdTrackCount = 0
[edited by: sonminh at 2:00 AM (GMT 0) on 24 Apr 2020]
Parents
  • HI ,

    I have mistake once post this question in to that forum, then I received this answer:

    "Moving to No-Os forum for comments on the DPD configuration"

    Because I don't know delete that question, I have post again in this forum.

    Thanks

  • Not sure why you are measuring DPD performance with 2 tone signal. What is DPD status mykonosDpdStatus_t. 

    You need to first find out Tx EVM after applying CFR No DPD . If CFR is based on hard clipping EVM & through put will deteriorate.

    From the ACLR plot with DPD that you shared previously , ACLR is improving means , EVM should improve and this should not impact through put.

  • After applying CFR with no dpd, system run at mode custom waveform QAM64 work well with 100Mbps, So, I guess Tx EVM good.

    With applying CFR with DPD, I veryfied DPDStatus every 1s. It return in order
    dpdStatus.dpdErrorStatus: ,dpdStatus.dpdExtPathDelay, dpdStatus.dpdIterCount, dpdStatus.dpdMaxAdaptation, dpdStatus.dpdModelErrorPercent, dpdStatus.dpdTrackCount

    DPDStatus: 0 0x740 0xC6 0x11D3 0x25 0xC6
    DPDStatus: 0 0x740 0xCA 0x11D3 0x26 0xCA
    DPDStatus: 0 0x740 0xCE 0x11D3 0x25 0xCE
    DPDStatus: 0 0x740 0xD2 0x11D3 0x27 0xD2
    DPDStatus: 0 0x740 0xD6 0x11D3 0x28 0xD6
    DPDStatus: 0 0x740 0xDA 0x11D3 0x27 0xDA
    DPDStatus: 0 0x740 0xDE 0x11D3 0x28 0xDE
    DPDStatus: 0 0x740 0xE2 0x11D3 0x25 0xE2
    DPDStatus: 0 0x740 0xE6 0x11D3 0x27 0xE6
    DPDStatus: 0 0x740 0xF2 0x12CE 0x24 0xF2

    Because after applying DPD, my system seems run not good as no have dpd. So i don't know how to do next. Although my system run at 20Mhz bandwidth, I still  measuring DPD performance with 2 tone signal  to can see spectrum clearly.

    Can you give solution?

  • Without Tx output EVM plot with DPD its hard to say.

    If you reduce the Tx power by 3 dB how is the performance with DPD ? 

  • Hi, In above test cases, I get status of mykonosVswrStatus and mykonosClgcStatus. I see both errorStatus and  trackCount return 0. Why trackCount = 0( Number of times clgc and vswr has successfull run since initialization calibration = 0)
    )?. Is it affect to successfull of DPD?

  • CLGC and VSWR do not impact DPD. They are seperate cal. 

    Your DPD iteration count is increasing , so set up required for DPD is correct. May be there is something wrong with CLGC configuration.

  • Hi ,

    In page 4 of ad9375 datasheet, specification of image rejection at 5500Mhz is 50dbm. But once I try with 3 tone signal 3Mhz, 6Mhz, 9Mhz on AD9375, It generate 3 image -3Mhz, -6Mhz, -9Mhz. and not pass specification.

    How to decrease or filter 3 above image signal. How to configure AD9375 to decrease image signal?

  • Can you share screenshot of your measurement. Are you running QEC tracking calibration.?

    With single tone , what is the level of image?

    What is your application ? If its 4G/5G can you test with a 4G signal at offset and measure QEC performance with tracking cals enabled? 

  • Thanks

     I implement Calib DPD with:

    trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC |
                                 TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC | TRACK_TX1_LOL | TRACK_TX2_LOL;


     initCalMaskDpd =  TX_LO_LEAKAGE_EXTERNAL | DPD_INIT | CLGC_INIT | VSWR_INIT;

    You say :"Your DPD iteration count is increasing , so set up required for DPD is correct. May be there is something wrong with CLGC configuration"

    Maybe CLGC configuration not correct because I read  status of CLGC :

    Both clgcStatus.errorStatus and  clgcStatus.trackCount return 0x00;

    I configure Clgc by api:


        mykError = MYKONOS_configClgc(&mykDevice);
        if (mykError != MYKONOS_ERR_OK) {
            errorString = getMykonosErrorMessage(mykError);
    //        goto error_11;
        }
     and clgcConfig default:

    static mykonosClgcConfig_t clgcConfig =
    {
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/
        75,             /* valid range 1-100, default 75*/
        75,             /* valid range 1-100, default 45*/
        0,              /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx1Atten automatically updated*/
        0,              /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx2Atten automatically updated*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        600,            /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        600,            /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        0,              /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
        0               /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
    };

    How to configure to run success CLGC ?

  • Your CLGC config looks fine.

    Can you please share your complete sequence? (Including CLGC init and tracking)

  • Thanks  for your reply.

    When change frequency,I run DPD and CLGC calibration follow this sequence:

    	/*************************************************************************/
    	/*****            Enable DPD calibrations                            *****/
    	/*************************************************************************/
    	uint8_t				errorFlag = 0;
    	uint8_t				errorCode = 0;
    	uint32_t			initCalsCompleted;
    
    
    	uint32_t trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC |
    							 TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC | TRACK_TX1_LOL | TRACK_TX2_LOL;
    
    	uint32_t initCalMaskDpd =  TX_LO_LEAKAGE_EXTERNAL | DPD_INIT | CLGC_INIT | VSWR_INIT;
    
    
    
    	if ((mykError = MYKONOS_radioOff(&mykDevice)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why radioOn failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, TX_PLL, u64TxFrq)) != MYKONOS_ERR_OK) {
    		return MYKONOS_ERR_FAILED;
    	}
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, RX_PLL, u64RxFrq)) != MYKONOS_ERR_OK)
    	{
    		return MYKONOS_ERR_FAILED;
    	}
    	Delay_Ms(100);
    
    
    	// Make sure PA is ON
    	if((mykError = MYKONOS_abortInitCals(&mykDevice, &initCalsCompleted)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("abortInitCals failed");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    	LREP("\r\n Mykonos ARM Initialization Calibrations for DPD");
    
    	if ((mykError = MYKONOS_runInitCals(&mykDevice, initCalMaskDpd)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_runInitCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_waitInitCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	 }
    
    	if ((mykError = MYKONOS_getEnabledTrackingCals(&mykDevice, &trackingCalMask)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_getEnabledTrackingCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    	trackingCalMask |= TRACK_TX1_DPD | TRACK_TX2_DPD | TRACK_TX1_CLGC | TRACK_TX2_CLGC | TRACK_TX1_VSWR | TRACK_TX2_VSWR;
    
    	if ((mykError = MYKONOS_enableTrackingCals(&mykDevice, trackingCalMask)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why enableTrackingCals failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    
    	MYKONOS_radioOn(&mykDevice);
    
    	/*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_RXOFF)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why setObsRxPathSource failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_INTERNALCALS)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why setObsRxPathSource failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	return MYKONOS_ERR_OK;

Reply
  • Thanks  for your reply.

    When change frequency,I run DPD and CLGC calibration follow this sequence:

    	/*************************************************************************/
    	/*****            Enable DPD calibrations                            *****/
    	/*************************************************************************/
    	uint8_t				errorFlag = 0;
    	uint8_t				errorCode = 0;
    	uint32_t			initCalsCompleted;
    
    
    	uint32_t trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC |
    							 TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC | TRACK_TX1_LOL | TRACK_TX2_LOL;
    
    	uint32_t initCalMaskDpd =  TX_LO_LEAKAGE_EXTERNAL | DPD_INIT | CLGC_INIT | VSWR_INIT;
    
    
    
    	if ((mykError = MYKONOS_radioOff(&mykDevice)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why radioOn failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, TX_PLL, u64TxFrq)) != MYKONOS_ERR_OK) {
    		return MYKONOS_ERR_FAILED;
    	}
    	if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, RX_PLL, u64RxFrq)) != MYKONOS_ERR_OK)
    	{
    		return MYKONOS_ERR_FAILED;
    	}
    	Delay_Ms(100);
    
    
    	// Make sure PA is ON
    	if((mykError = MYKONOS_abortInitCals(&mykDevice, &initCalsCompleted)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("abortInitCals failed");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    	LREP("\r\n Mykonos ARM Initialization Calibrations for DPD");
    
    	if ((mykError = MYKONOS_runInitCals(&mykDevice, initCalMaskDpd)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_runInitCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_waitInitCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	 }
    
    	if ((mykError = MYKONOS_getEnabledTrackingCals(&mykDevice, &trackingCalMask)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts("MYKONOS_getEnabledTrackingCals");
    		fflush(stdout);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    	trackingCalMask |= TRACK_TX1_DPD | TRACK_TX2_DPD | TRACK_TX1_CLGC | TRACK_TX2_CLGC | TRACK_TX1_VSWR | TRACK_TX2_VSWR;
    
    	if ((mykError = MYKONOS_enableTrackingCals(&mykDevice, trackingCalMask)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why enableTrackingCals failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    	}
    
    
    	MYKONOS_radioOn(&mykDevice);
    
    	/*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_RXOFF)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why setObsRxPathSource failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    	if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_INTERNALCALS)) != MYKONOS_ERR_OK)
    	{
    		/*** < Info: errorString will contain log error string in order to debug why setObsRxPathSource failed > ***/
    		//errorString = getMykonosErrorMessage(mykError);
    		puts(getMykonosErrorMessage(mykError));
    
    	}
    
    	return MYKONOS_ERR_OK;

Children
  • What is the Tx attenuation you are using to set the target power with CLGC? You should not use 0 dB attenuation, as CLGC need some headroom to track the target power by changing the Tx Attenuation.

    Can you please print the complete status of CLGC?

    typedef struct
    {
    uint32_t errorStatus;
    uint32_t trackCount;
    int32_t desiredGain;
    int32_t currentGain;
    uint32_t txGain;
    int32_t txRms;
    int32_t orxRms;
    } mykonosClgcStatus_t;

    You shall test CLGC by varying the ORX attenuation and see whether the Target power is maintained or not.

    Please refer to the below post for reference,

    https://ez.analog.com/wide-band-rf-transceivers/design-support-ad9371/f/q-a/163838/ad9357-clgc-custom-configuration-parameters

  • Thanks ,

    Sorry, I have mistake when get CLGC status.

     I veryfied CLGCStatus again every 1s. It return in order
    clgcStatus.errorStatus, clgcStatus.trackCount, clgcStatus.desiredGain, clgcStatus.currentGain, clgcStatus.txGain, clgcStatus.txRms, clgcStatus.orxRms

    CLGCStatus: 9 27 -2000 -809 40 -1662 -2472
    CLGCStatus: 9 29 -2000 -820 40 -1671 -2492
    CLGCStatus: 9 30 -2000 -857 40 -1685 -2543
    CLGCStatus: 9 32 -2000 -812 40 -1669 -2481
    CLGCStatus: 9 34 -2000 -843 40 -1677 -2520
    CLGCStatus: 9 35 -2000 -829 40 -1678 -2508
    CLGCStatus: 9 38 -2000 -902 40 -1710 -2612
    CLGCStatus: 9 43 -2000 -825 40 -1639 -2465
    CLGCStatus: 9 45 -2000 -854 40 -1689 -2543
    CLGCStatus: 9 47 -2000 -854 40 -1668 -2523

    I check errorStatus = 9. Thats means: "

    CLGC feature is disabled. This error is displayed when allowTx1AttenUpdates/
    allowTx2AttenUpdates are disabled


    "

    But in clgcConfig, i had enabled allowTx1AttenUpdates/allowTx2AttenUpdates

    static mykonosClgcConfig_t clgcConfig =
    {
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/
        -2000,          /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/
        0,              /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/
        75,             /* valid range 1-100, default 75*/
        75,             /* valid range 1-100, default 45*/
        1,              /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx1Atten automatically updated*/
        1,              /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements.  1=CLGC runs, and Tx2Atten automatically updated*/
        0,              /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/
        255,            /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range  1 to 8191)*/
        600,            /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        600,            /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/
        0,              /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
        0               /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/
    };

    Can you give solution?

    Thanks

  • I guess what you are seeing is correct. You need to enable allowTx1AttenUpdates/
    allowTx2AttenUpdates. 

    This thread has become too long. Can you start a new thread if CLGC issue is still not resolved.