Post Go back to editing

How to Configure DPD correctly?

Hello, 

I have a ton of questions to ask about DPD configuration on the ADRV9025 chip. I am trying to configure DPD without the PA connected between the Tx-ORx path solely for testing purposes. I have gone through all the steps required in setting up DPD but there seems to be no signal in the ORx path. The  dpdErrorCode I get shifts between 0x3405 and 0x340E. 

My setup is as follows:

I am running a 2T-2R-2ORx setup utilizing TX3/TX2, RX3/RX2, and ORX3/ORX1. With this setup, I am running DPD on the TX2, connecting the output of the TX2 via a splitter to the ORX1 port and a spectrum analyzer (So as to monitor the TX2-ORX1 path).

For the DPD Tracking Cal Bring up Sequence, I followed the following steps. Note that I have supplied only the necessary snippets to avoid cluttering up this page:

1a. Program the device and run initial calibrations 

1b. Run TxQEC initial calibration after chip initialization (for some reason, the programming failed when I tried to run the tx_qec init cal as part of the POSTMCS during initialization, see code snippet)

recoveryAct = adi_init_tx_cals_run( adrv9025Device, 
                                    ADI_ADRV9025_TX2,  
                                    ( ADI_ADRV9025_TX_QEC_INIT | ADI_ADRV9025_INTERNAL_PATH_DELAY | ADI_ADRV9025_TX_LO_LEAKAGE_INTERNAL )                                        
                                ) ;

2. Disabled ORX channels mapped TX2 to ORX1 and called the adi_adrv9025_RadioCtrlCfgSet function, setting all control modes to SPI (see code snippet)

printf("*** Disabling ORx Channels ***\n") ;
recoveryAct = adi_adrv9025_RxTxEnableSet ( adrv9025Device, 0x06, 0x06 ) ;

rxChannelMaskGet = 0 ;
txChannelMaskGet = 0 ;
usleep(1) ;
recoveryAct = adi_adrv9025_RxTxEnableGet(adrv9025Device, &rxChannelMaskGet, &txChannelMaskGet) ;

recoveryAct = adi_adrv9025_TxToOrxMappingSet(device,ADI_ADRV9025_ORX1, ADI_ADRV9025_TX2);

adrv9025PostMcsInitInst.radioCtrlInit.radioCtrlModeCfg.orxRadioCtrlModeCfg.orxEnableMode = ADI_ADRV9025_ORX_EN_SPI_MODE; //ADI_ADRV9025_ORX_EN_SINGLE_CH_2PIN_MODE;
adrv9025PostMcsInitInst.radioCtrlInit.radioCtrlModeCfg.rxRadioCtrlModeCfg.rxEnableMode = ADI_ADRV9025_RX_EN_SPI_MODE ; //ADI_ADRV9025_RX_EN_PIN_MODE;
adrv9025PostMcsInitInst.radioCtrlInit.radioCtrlModeCfg.txRadioCtrlModeCfg.txEnableMode = ADI_ADRV9025_TX_EN_SPI_MODE ;//ADI_ADRV9025_TX_EN_PIN_MODE;
recoveryAct = adi_adrv9025_RadioCtrlCfgSet(adrv9025Device, &adrv9025PostMcsInitInst.radioCtrlInit.radioCtrlModeCfg);
	

3. Adjusted ORX1 gain, using gain index of 0xFF (see code snippet)

rx_gain.gainIndex       = 0xFF ;
rx_gain.rxChannelMask   = ADI_ADRV9025_ORX1 ;
    
recoveryAct = adi_adrv9025_RxGainSet  (device, &rx_gain, 1);

4. Run the external path delay for TX2 (see code snippet)

adrv9025PostMcsInitInst.initCals.calMask 		= 0x00200000; //external path delay
adrv9025PostMcsInitInst.initCals.channelMask 	= ADI_ADRV9025_TX2 ;
adrv9025PostMcsInitInst.initCals.warmBoot		= 0 ;
recoveryAct = adi_adrv9025_InitCalsRun(device, &adrv9025PostMcsInitInst.initCals);

recoveryAct = adi_adrv9025_InitCalsWait(device, 60000, &initCalsError);

5. Run the Tx external LOL init cals (see code snippet)

adrv9025PostMcsInitInst.initCals.calMask        = 0x00000800; //external LOL
adrv9025PostMcsInitInst.initCals.channelMask 	= ADI_ADRV9025_TX2 ;
adrv9025PostMcsInitInst.initCals.warmBoot		= 0 ;

recoveryAct = adi_adrv9025_InitCalsRun(device, &adrv9025PostMcsInitInst.initCals);

recoveryAct = adi_adrv9025_InitCalsWait(device, 60000, &initCalsError);

6. Configured the CFR settings (adi_adrv9025_CfrCtrlConfigSet,  adi_adrv9025_CfrCorrectionPulseWrite_v2, adi_adrv9025_CfrEnableSet, adi_adrv9025_CfrHardClipperConfigSet, see code snippet)

7. Run the CFR Init Cals (with 60s wait time passed to the adi_adrv9025_InitCalsWait function)

8. Loaded the PA model (see code snippet)

dpdModelConfigInst.txChannelMask = ADI_ADRV9025_TX2 ; 
dpdModelConfigInst.dpdNumFeatures = 22;

char* dpd_model = "/media/sddata/defaultDpdModel.txt"  ;
FILE *fp = fopen(dpd_model, "r");

for(int n = 0; n <dpdModelConfigInst.dpdNumFeatures ; n++)
{
    fscanf(fp, "%d %d %d %d %f %f",
    	&dpdModelConfigInst.dpdFeatures[n].i,
    	&dpdModelConfigInst.dpdFeatures[n].j,
    	&dpdModelConfigInst.dpdFeatures[n].k,
    	&dpdModelConfigInst.dpdFeatures[n].lut,
    	&dpdModelConfigInst.dpdFeatures[n].coeffReal,
    	&dpdModelConfigInst.dpdFeatures[n].coeffImaginary);
    
    printf("\n%d %d %d %d %f %f\n",
    	dpdModelConfigInst.dpdFeatures[n].i,
    	dpdModelConfigInst.dpdFeatures[n].j,
    	dpdModelConfigInst.dpdFeatures[n].k,
    	dpdModelConfigInst.dpdFeatures[n].lut,
    	dpdModelConfigInst.dpdFeatures[n].coeffReal,
    	dpdModelConfigInst.dpdFeatures[n].coeffImaginary);
}
adi_adrv9025_TxChannels_e tx_channels ;
fclose(fp);
recoveryAct = adi_adrv9025_DpdModelConfigSet(adrv9025Device, &dpdModelConfigInst);

--- My DPD MODEL ---

   0  0  0   0       0            0
   0  0  1   0       0            0
   0  0  2   0       0            0
   0  0  3   0       0            0
   0  0  4   0       0            0
   0  0  5   0       0            0
   1  1  1   2       0            0
   1  1  2   2       0            0
   1  1  3   2       0            0
   1  1  4   2       0            0
   1  1  5   2       0            0
   0  1  0   8       0            0
   0  1  1   8       0            0
   0  1  2   8       0            0
   0  1  3   8       0            0
   0  1  4   8       0            0
   0  1  5   8       0            0
   2  2  1  26       0            0
   2  2  2  26       0            0
   2  2  3  26       0            0
   2  2  4  26       0            0
   2  2  5  26       0            0

9. Asserted DPD Reset  (ADI_ADRV9025_DPD_RESET_FULL, see code snippet)

recoveryAct = adi_adrv9025_DpdReset(adrv9025Device, ADI_ADRV9025_TX2, ADI_ADRV9025_DPD_RESET_FULL);
if (recoveryAct != ADI_COMMON_ACT_NO_ACTION)
{
    printf("ERROR: : %s:%u has failed.\n", __func__, __LINE__);
    return recoveryAct;
}

10. Run DPD Tracking configuration (see code snippet)

int32_t MThreshold_dBFS                 = -21; 
int16_t DpdLowPowerThreshold_dBFS       = -36;
int16_t DpdLowPowerThresholdORx_dBFS    = -36;

int32_t temp                            = pow(10,(MThreshold_dBFS/20.0))*FULL_SCALE_CODE;
int32_t dpdMThreshold_val               = pow(temp,2);
int16_t minAvgSignalLevel_val           = pow(10,(DpdLowPowerThreshold_dBFS/20.0))*FULL_SCALE_CODE;
int16_t minAvgSignalLevelOrx_val        = pow(10,(DpdLowPowerThresholdORx_dBFS/20.0))*FULL_SCALE_CODE;

dpdTrackingConfigInst.txChannelMask                             = ADI_ADRV9025_TX2; 
dpdTrackingConfigInst.minAvgSignalLevel                         = minAvgSignalLevel_val;
dpdTrackingConfigInst.minAvgSignalLevelOrx                      = minAvgSignalLevelOrx_val;
dpdTrackingConfigInst.dpdMThreshold                             = temp ;
dpdTrackingConfigInst.dpdPeakSearchWindowSize                   = 65536;
dpdTrackingConfigInst.dpdIndirectRegularizationValue            = 30;
dpdTrackingConfigInst.dpdDirectRegularizationValue              = 30; 
dpdTrackingConfigInst.dpdSamples                                = 16384;
dpdTrackingConfigInst.dpdUpdateMode                             = ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_0;
dpdTrackingConfigInst.dpdIndirectRegularizationLowPowerValue    = 20;
dpdTrackingConfigInst.dpdFilterSel                              = 0; 
dpdTrackingConfigInst.enableDirectLearning                      = 0;
dpdTrackingConfigInst.dpdMu                                     = 50;

recoveryAct = adi_adrv9025_DpdTrackingConfigSet(adrv9025Device, &dpdTrackingConfigInst);

11. Setup closed-loop gain control configurations (for monitoring purposes. See code snippet)

adi_adrv9025_ClgcConfig_t clgc_config   ;
clgc_config.clgcEnableGainControl   = 0 ;
clgc_config.txChannelMask           = ADI_ADRV9025_TX2 ;

recoveryAct = adrv9025_ClgcConfigSet( adrv9025Device, &clgc_config, 1) ;

12. Enabled TX QEC and TX LOL tracking Calibrations (See code snippet)

recoveryAct = adi_adrv9025_TrackingCalsEnableSet (  adrv9025Device, 
                                                        ( ADI_ADRV9025_TRACK_TX2_QEC | ADI_ADRV9025_TRACK_TX2_LOL ), 
                                                        ADI_ADRV9025_TRACKING_CAL_ENABLE
                                                    );

13. Enabled DPD Tracking Calibration (See code snippet)

adi_adrv9025_TrackingCalsEnableSet (device, ADI_ADRV9025_TRACK_TX2_DPD, ADI_ADRV9025_TRACKING_CAL_ENABLE);

14. Enabled CLGC Tracking Calibration  (See code snippet)

recoveryAct = adi_adrv9025_TrackingCalsEnableSet (  adrv9025Device, 
                                                        ADI_ADRV9025_TRACK_TX2_CLGC, 
                                                        ADI_ADRV9025_TRACKING_CAL_ENABLE
                                                    );

15.  Started monitoring DPD tracking calibration (See code snippet)

//Wait for some time before getting the status
sleep(20);


adi_adrv9025_DpdStatus_t dpdStatus;
int32_t recoveryAction = 0;
recoveryAction = adi_adrv9025_DpdStatusGet (device, txChannel, &dpdStatus);

printf ("dpdErrorCode		:0x%x\n",dpdStatus.dpdErrorCode);
printf ("dpdPercentComplete	:%d\n",dpdStatus.dpdPercentComplete);
printf ("dpdPerformanceMetric	:%d\n",dpdStatus.dpdPerformanceMetric);
printf ("dpdIterCount		:%d\n",dpdStatus.dpdIterCount);
printf ("dpdUpdateCount		:%d\n",dpdStatus.dpdUpdateCount);

printf ("dpdSyncStatus		:%d\n",dpdStatus.dpdSyncStatus);


float meanTu = dpdStatus.dpdStatistics.dpdMeanTuPower;
float peakTu = dpdStatus.dpdStatistics.dpdPeakTuPower;
float meanTx = dpdStatus.dpdStatistics.dpdMeanTxPower;
float peakTx = dpdStatus.dpdStatistics.dpdPeakTxPower;
float meanOrx = dpdStatus.dpdStatistics.dpdMeanOrxPower;
float peakOrx = dpdStatus.dpdStatistics.dpdPeakOrxPower;

printf ("dpdModelTable		:%d\n",dpdStatus.dpdModelTable);


printf ("dpdMeanTuPower		:%f\n",20*log10(sqrt(meanTu) / 32768));
printf ("dpdPeakTuPower		:%f\n",(20*log10(sqrt(peakTu) / 32768)));
printf ("dpdMeanTxPower		:%f\n",(20*log10(sqrt(meanTx) / 32768)));
printf ("dpdPeakTxPower		:%f\n",20*log10(sqrt(peakTx) / 32768));
printf ("dpdMeanOrxPower		:%f\n",20*log10(sqrt(meanOrx) / 32768));
printf ("dpdPeakOrxPower		:%f\n",20*log10(sqrt(peakOrx) / 32768));
printf ("dpdDirectEvm		:%f\n",dpdStatus.dpdStatistics.dpdDirectEvm);
printf ("dpdIndirectEvm		:%f\n",dpdStatus.dpdStatistics.dpdIndirectEvm);
printf ("dpdSelectError		:%f\n",dpdStatus.dpdStatistics.dpdSelectError);
printf ("dpdIndirectError	:%f\n",dpdStatus.dpdStatistics.dpdIndirectError);
printf ("dpdErrorStatus0 (metrics:actions): X:X	:%d:%d\n",	dpdStatus.dpdErrorStatus0.dpdMetricsMask,
						    dpdStatus.dpdErrorStatus0.dpdActionMask);

printf ("dpdErrorStatus1 (metrics:actions)		:%d:%d\n", 	dpdStatus.dpdErrorStatus1.dpdMetricsMask,
							dpdStatus.dpdErrorStatus1.dpdActionMask);
printf ("dpdPersistentErrorStatus0 (metrics:actions)	:%d:%d\n", 	dpdStatus.dpdPersistentErrorStatus0.dpdMetricsMask,
							dpdStatus.dpdPersistentErrorStatus0.dpdActionMask);
printf ("dpdPersistentErrorStatus1 (metrics:actions)	:%d:%d\n", 	dpdStatus.dpdPersistentErrorStatus1.dpdMetricsMask,
							dpdStatus.dpdPersistentErrorStatus1.dpdActionMask);
printf ("reservedPM		:%d\n",dpdStatus.reservedPM);
printf ("reservedTP		:%d\n",dpdStatus.reservedTP);
printf ("reservedPR		:%d\n",dpdStatus.reservedPR);

16. Started monitoring CLGC status (See code snippet)

recoveryAct = adi_adrv9025_ClgcStatusGet(   adrv9025Device  ,
                                                ADI_ADRV9025_TX2,
                                                &clgc_status
                                            );

printf("******** CLGC Monitoring ****************\n")  ;
printf ("clgc_status.clgcLoopGain           : %f\n", clgc_status.clgcLoopGain) ;
printf ("clgc_status.clgcTxRmsPower           : %f\n", clgc_status.clgcTxRmsPower) ;
printf ("clgc_status.clgcOrxRmsPower           : %f\n", clgc_status.clgcOrxRmsPower) ;
printf ("clgc_status.activeTxAttenIndex           : 0x%x\n", clgc_status.activeTxAttenIndex) ;
printf ("clgc_status.activeOrxGainIndex           : 0x%x\n", clgc_status.activeOrxGainIndex) ;

---- And, here's the output of the above code: ----- 

*** Tx2 DPD Status ***
***************************************
Retrieving DPD status
dpdErrorCode :0x3405
dpdPercentComplete :0
dpdPerformanceMetric :0
dpdIterCount :18
dpdUpdateCount :0
dpdSyncStatus :4
dpdModelTable :0
dpdMeanTuPower :-14.280720
dpdPeakTuPower :-3.605944
dpdMeanTxPower :-inf
dpdPeakTxPower :-inf
dpdMeanOrxPower :-58.033522
dpdPeakOrxPower :-49.337814
dpdDirectEvm :4.338248
dpdIndirectEvm :nan
dpdSelectError :0.000000
dpdIndirectError :0.000000
dpdErrorStatus0 (metrics:actions): X:X :0:0
dpdErrorStatus1 (metrics:actions) :0:0
dpdPersistentErrorStatus0 (metrics:actions) :0:0
dpdPersistentErrorStatus1 (metrics:actions) :0:0
reservedPM :0
reservedTP :40249683
reservedPR :40249683
***************************************

*** Running Monitor CLGC tracking Calibration Status ***
******** CLGC Monitoring ****************
clgc_status.clgcLoopGain : 0.000000
clgc_status.clgcTxRmsPower : 0.000000
clgc_status.clgcOrxRmsPower : 0.000000
clgc_status.activeTxAttenIndex : 0x0
clgc_status.activeOrxGainIndex : 0x0
---------------- End of output ----------------------------
 
I am not sure what I am doing wrong here. Could it be because I have not connected a PA yet? 


One thing to add is that after asserting reset, the signal on the TX2-ORX1 path dies and never comes back up. Could it be that I am not performing reset correctly? 
[edited by: AlexAntwi at 2:44 AM (GMT -5) on 12 Nov 2021]
Parents
  • dpdErrorCode of 3405 refers to 'ORX signal being Too small' which means the ORX signal is not present/ out of threshold.

    You have mentioned ORX disabled in Step2, is it enabled while you are running DPD tracking cal?

    Also, while you are running ext. path delay cal, hope the PA is switched on.

    Have you generated the Initdata.c from the latest GUI with the required ORX selection and used in your code?  

  • Hello

    ORx is disabled while running DPD tracking Cal. Actually, it stays disabled.

    As I mentioned, I have not connected a PA between the Tx2-ORx1 path yet. That is if you mean the external PA.

    I generated the initdata.c some time back and haven't changed it since, so I am not sure if the software has been update since then. And, from the initdata.c file, I can see we are using framer[1] for ORx1_I/Q. Please see the below snippet from the framer[1] setting. 

     {  // framer[1]
                0,  // enableJesd204C
                0,  // bankId
                1,  // deviceId
                0,  // lane0Id
                2,  // jesd204M
                32,  // jesd204K
                4,  // jesd204F
                16,  // jesd204Np
                0,  // jesd204E
                1,  // scramble
                4,  // serializerLanesEnabled
                0,  // lmfcOffset
                1,  // syncbInSelect
                0,  // overSample
                1,  // syncbInLvdsMode
                0,  // syncbInLvdsPnInvert
                { // serializerLaneCrossbar
                    8,  // lane0FramerOutSel
                    8,  // lane1FramerOutSel
                    0,  // lane2FramerOutSel
                    8   // lane3FramerOutSel
                },
                { // adcCrossbar
                    ADI_ADRV9025_ADC_ORX1_I,  // conv0
                    ADI_ADRV9025_ADC_ORX1_Q,  // conv1
                    ADI_ADRV9025_ADC_DISABLE,  // conv2
                    ADI_ADRV9025_ADC_DISABLE,  // conv3
                    ADI_ADRV9025_ADC_DISABLE,  // conv4
                    ADI_ADRV9025_ADC_DISABLE,  // conv5
                    ADI_ADRV9025_ADC_DISABLE,  // conv6
                    ADI_ADRV9025_ADC_DISABLE,  // conv7
                    ADI_ADRV9025_ADC_DISABLE,  // conv8
                    ADI_ADRV9025_ADC_DISABLE,  // conv9
                    ADI_ADRV9025_ADC_DISABLE,  // conv10
                    ADI_ADRV9025_ADC_DISABLE,  // conv11
                    ADI_ADRV9025_ADC_DISABLE,  // conv12
                    ADI_ADRV9025_ADC_DISABLE,  // conv13
                    ADI_ADRV9025_ADC_DISABLE,  // conv14
                    ADI_ADRV9025_ADC_DISABLE,  // conv15
                    ADI_ADRV9025_ADC_DISABLE,  // conv16
                    ADI_ADRV9025_ADC_DISABLE,  // conv17
                    ADI_ADRV9025_ADC_DISABLE,  // conv18
                    ADI_ADRV9025_ADC_DISABLE,  // conv19
                    ADI_ADRV9025_ADC_DISABLE,  // conv20
                    ADI_ADRV9025_ADC_DISABLE,  // conv21
                    ADI_ADRV9025_ADC_DISABLE,  // conv22
                    ADI_ADRV9025_ADC_DISABLE   // conv23
                },

     I may have to edit it so it supports ORx3 (since we are using that too. But, that should not be a problem since I am using the ORx1 right? 

  • ORx is disabled while running DPD tracking Cal. Actually, it stays disabled.

    ORX path must be enabled while DPD tracking cal is running.

    As I mentioned, I have not connected a PA between the Tx2-ORx1 path yet. That is if you mean the external PA.

    Oh yes, I missed that the PA is not connected in your setup.But the ORX path must be enabled for External Path delay cal.

    Can you please generate the required configuration from the TES GUI and then use it?

  • Hello

    Thank you for your response. I am a bit confused when you say I have to enable the ORX path while DPD cal is running because I got the idea of switching it off from another Analog devices employee. Kindly check Pvalavan's post from this link: https://ez.analog.com/wide-band-rf-transceivers/design-support-adrv9026/f/q-a/544898/adrv9029-dpd-configuration. I have quoted the part where I understood as I had to turn off the ORX pasth below:

    "While testing DPD we recommend to disable the ORX Path. Before enabling DPD you can enable ORX path and measure ORXDecpower if required"

    Could you kindly clarify for me? In the mean time, I will go ahead and enable the ORX path and let you know what I get from it. 

    Also, I already generated the required configuration from the TES GUI. That's what I am using. The only thing missing is the ORX3 path which I didn't enable. I hope I can test without that path enabled for now.

  • Correction: As you are using API/ SPI mode for ORX control, the ARM takes care of enabling/ disabling the ORX while DPD cal is running. So, ORX path need not be enabled explicitly.

    Also, I already generated the required configuration from the TES GUI. That's what I am using. The only thing missing is the ORX3 path which I didn't enable. I hope I can test without that path enabled for now.

    Yes, this should not be a problem.

    This issue is something to do with ORX mapping, are you testing in FDD or TDD mode, Which use case are you using?

  • Hello 

    Thanks a lot for the clarification.

    To answer your question, I am using Use Case 50 nonLink Sharing. 

    This issue is something to do with ORX mapping

    I am beginning to think so too. The signal doesn't go off completely as in when the Tx channel is disabled. I see a low-powered single tone when my written data gets taken down. Could it be the system reverts to a different mapping during DPD reset and as it cannot detect any data, it just sends an internally generated carrier signal?

    When I call adi_adrv9025_TxToOrxMappingGet() however, it returns with 0x2 which is TX2 and that is correct. Could it be a problem in my GUI configuration?

    Kindly let me know If you would need other information about my TES GUI configuration. I can send you my files and pictures of the GUI configurations. 

  • Can you please disable CLGC tracking cal and test only with DPD tracking cal enable?

    Kindly let me know If you would need other information about my TES GUI configuration. I can send you my files and pictures of the GUI configurations. 

    Yes, please share your files, pictures of the GUI configurations.

  • Hello 

    Please check the link below for my GUI configuration images and generated files. 

    https://drive.google.com/file/d/1fa2g6JW450Zu_EiTTun6RbaSbRuG-U6e/view?usp=sharing

    About testing with only DPD cal enable, that was what I did the first time I tried running DPD. I thought I probably had to include CLGC in order for the capture timeout and ORx low power error messages to go away. The results then, and now are the same. 

  • Thanks for sharing the files. Can you please change the following and try once?

    As you are using the same frequency for LO1 (RX) and LO2 (TX), can you switch off LO1 and use same LO2 for RX as well? So LO1 will be off and LO2 is used for both RX and TX.

    Also, the ORX channel for TX2 need to be selected as ORX1 as per your Tx-ORX mapping.

Reply
  • Thanks for sharing the files. Can you please change the following and try once?

    As you are using the same frequency for LO1 (RX) and LO2 (TX), can you switch off LO1 and use same LO2 for RX as well? So LO1 will be off and LO2 is used for both RX and TX.

    Also, the ORX channel for TX2 need to be selected as ORX1 as per your Tx-ORX mapping.

Children
  • Hello

    I tried what you suggested, the situation remains the same as before :( 

    I have a few questions  though, I need to be sure about some things:

    1. Do I have to use DPD in pin mode? 
    2. You mentioned that the ARM takes care of enabling and disabling the ORX if I use the ORx in SPI enable mode. Did you mean that it switches between ORx1 and ORx2 as is done with the pin mode? How can I verify that the arm is actually doing this switching?
    3. Can my wrong setting (apart from setting the enable mode to SPI or pin control) cause the ARM to erroneously switch on an ORx I didn't intend for it to use?
    4. The sequence I used in bringing up DPD is from table 14 (DPD Tracking Calibration Bringup Sequence) of the "ADRV9029 DPD, CLGC and CFR User Guide" document. Step 4 says to turn on the PA ... I guess this is the external PA ? 

  • Have you connected the Tx2 path to ORX1 path without any switch between ORX1 and ORX2? Can you please send us the block diagram of the Physical connections including the control pins if you are using any for external ORX switch control, Selection etc.

  • What switch are you referring to? The configuration I used was the SPI mode for all channels. I enabled and disabled ORx/Tx/Rx via API. And you mentioned that the ARM CPU would do the switching (which is why I need not enable the ORx while running DPD tracking cals). This was before I switched to pin control mode (but that is still under test... I am using 2Tx/2Rx/2ORx and ORx mode is set to single-channel-2pin mode... still no luck, but I am testing) 

  • I believe you are using custom board. If so, at what stage are you enabling the carrier. Can you try 'Reset DPD' and then enable the carrier? Can you read ORX dec power ?

    Can you test it on EVB once? The ORX port naming is incorrect on the EVB(Treat ORX1 as ORX2 and vice versa). While you enable DPD tracking, make sure that the ORX capture is not being played in the GUI.

    Please refer to various use cases as mentioned in Page 114 of the user guide.

    PDF

  • Hello  

    I tried running on the EVB, following the document you uploaded. I chose Use Case 50NLS, and selected LO2 for Tx and Rx. ORx uses TXLO as usual. However, I am not able to get past step 6 (Apply model M table). Neither does step7 (Apply model C table) work I have posted the error message below:

    ===========================================================

    --- Error Message: ---

    Unable set DPD Model Config on device. API function DpdReset failed. API Exception message: Unable to reset DPD on device. API function DpdReset failed. API Exception message: CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?.

    --- Technical Details: ---

    Method name: DpdModelConfigSet
    Message Source: GUI (original Exception from: API)

    The HandledException was caught:
    at Modules.UserControls.DPD.DpdFunctions.btnApplyModelMTable_Click(Object sender, EventArgs e)
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at Adi.adrv9010.MainWindow.Program.Main()


    API Error details:
    - Message: CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?.
    - Error Number: 3
    - Function Name: adi_adrv9025_CpuCmdStatusWait
    - Recovery Action: -2
    - Source: adi_adrv9025_cpu.c, line 1160

    Adi.Trx.HandledException: Unable to reset DPD on device. API function DpdReset failed. API Exception message: CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?. ---> System.Exception: ERROR during adi_adrv9010_DpdReset : ERROR: adrv9010Device Error number 3, Recovery action -2. In file ../../../../c_src/devices/adrv9025/public/src/adi_adrv9025_cpu.c, in function adi_adrv9025_CpuCmdStatusWait, in line 1160, variable name device. Error message CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?.

    at adrv9010_dll.SubClasses.Adrv9010Dfe.DpdReset(adi_adrv9010_TxChannels_e txChannel, adi_adrv9010_DpdResetMode_e dpdResetMode)
    at Adi.adrv9010.ApiCalls.Api.DpdReset(adi_adrv9010_TxChannels_e txChannel, adi_adrv9010_DpdResetMode_e resetMode)
    --- End of inner exception stack trace ---
    at Adi.adrv9010.ApiCalls.Api.DpdReset(adi_adrv9010_TxChannels_e txChannel, adi_adrv9010_DpdResetMode_e resetMode)
    at Adi.adrv9010.ApiCalls.Api.<>c__DisplayClass115_0.<DpdModelConfigSet>b__0(adi_adrv9010_TxChannels_e channel)
    at Adi.Trx.Extensions.ForEachFlag[TEnum](UInt32 flags, Action`1 action) in Y:\Adi.Trx.Common\Helpers\Extensions.cs:line 380
    at Adi.adrv9010.ApiCalls.Api.DpdModelConfigSet(adi_adrv9010_DpdModelConfig_t dpdModelConfig, UInt32 channelMask, Boolean isMTable)

    --- Technical Details from wrapped HandledException: ---

    Method name: adi_adrv9025_CpuCmdStatusWait
    Message Source: API

    The Exception was caught:
    at Adi.adrv9010.ApiCalls.Api.<>c__DisplayClass115_0.<DpdModelConfigSet>b__0(adi_adrv9010_TxChannels_e channel)
    at Adi.Trx.Extensions.ForEachFlag[TEnum](UInt32 flags, Action`1 action)
    at Adi.adrv9010.ApiCalls.Api.DpdModelConfigSet(adi_adrv9010_DpdModelConfig_t dpdModelConfig, UInt32 channelMask, Boolean isMTable)
    at Modules.UserControls.DPD.DpdFunctions.btnApplyModelMTable_Click(Object sender, EventArgs e)
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at Adi.adrv9010.MainWindow.Program.Main()


    API Error details:
    - Message: CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?.
    - Error Number: 3
    - Function Name: adi_adrv9025_CpuCmdStatusWait
    - Recovery Action: -2
    - Source: adi_adrv9025_cpu.c, line 1160

    System.Exception: ERROR during adi_adrv9010_DpdReset : ERROR: adrv9010Device Error number 3, Recovery action -2. In file ../../../../c_src/devices/adrv9025/public/src/adi_adrv9025_cpu.c, in function adi_adrv9025_CpuCmdStatusWait, in line 1160, variable name device. Error message CpuCmdStatusWait() failed due to thrown CPU error. Is device in correct state for calling command?.

    at adrv9010_dll.SubClasses.Adrv9010Dfe.DpdReset(adi_adrv9010_TxChannels_e txChannel, adi_adrv9010_DpdResetMode_e dpdResetMode)
    at Adi.adrv9010.ApiCalls.Api.DpdReset(adi_adrv9010_TxChannels_e txChannel, adi_adrv9010_DpdResetMode_e resetMode)

    --- Versions: ---

    Adrv9029 Transceiver Evaluation Software

    GUI Version: 5.1.0.30
    DLL Version: 5.1.0.21
    Cmd Server Version: 5.1.0.21
    Fpga Version: 0xD9000007
    Arm Version: 5.1.0.9(ADI_ADRV9010_ARMBUILD_TESTOBJ)
    Stream Version: 8.1.0.1

    Analog Device Inc.
    Copyright (c) 2019

    --- Loaded Assemblies: ---

    - TrxSoln.exe, v.5.1.0.30
    - Adi.Trx.Common.GUI.dll, v.1.0.0.0
    - Adi.Trx.Common.dll, v.1.0.0.0
    - Adi.Trx.Common.GUI.Abstractions.dll, v.1.0.0.0
    - Adrv9010ProfileGen.dll, v.1.0.0.0
    - adrvtrx_dll.dll, v.5.1.0.21
    - AdiGraph.dll, v.1.0.6656.22494
    - ucAdrv9010ConfigWizard.dll, v.1.0.0.0
    - log4net.dll, v.2.0.8.0
    - Adi.ucCollapsiblePanel.dll, v.1.0.6465.15981
    - FMCEepromParser.dll, v.1.0.0.0
    - DictionaryView.dll, v.1.0.0.0
    - System.Data.SQLite.dll, v.1.0.111.0
    - Adi.Utilities.dll, v.1.0.6690.31656
    - NationalInstruments.UI.WindowsForms.dll, v.15.0.40.49153
    - NationalInstruments.UI.dll, v.15.0.40.49153
    - NationalInstruments.Common.dll, v.15.0.40.49154
    - Signal.dll, v.1.0.0.0
    - Modules.dll, v.1.0.0.0
    - StreamGen.dll, v.8.1.0.1
    - Renci.SshNet.dll, v.2016.0.0
    - Newtonsoft.Json.dll, v.11.0.2.21924
    - VectorGeneration.dll, v.1.0.7341.23392
    - NationalInstruments.Analysis.Enterprise.dll, v.15.0.40.49153

    ==============================================================

    At this point I think the problem might be with my DPD model file which I loaded from the TES installation folder), or the init cals. The use case 50nls supports dpd (the dpd blocks are enabled in the tx settings. Also, DPD is checked by default in the initcal settings) What could I be doing wrong?

    The ORX port naming is incorrect on the EVB(Treat ORX1 as ORX2 and vice versa)

    You mean physically on the trx board? Tx1 is mapped to ORx1 in the GUI (using default settings as much as possible) and connecting to any other port apart from ORx1 physically, reports low power (about -90dbFS) 

  • At this point I think the problem might be with my DPD model file which I loaded from the TES installation folder), or the init cals. The use case 50nls supports dpd (the dpd blocks are enabled in the tx settings. Also, DPD is checked by default in the initcal settings) What could I be doing wrong?

    The init cals are all ran properly without any errors? Have you connected the Tx1 to ORX1 physically? Yes, UC50 NLS supports DPD. Any model file should be fine for loading and model file may not be an issue. Can you give some RF input at ORX port and capture in the GUI and check if the signal is present and which ORX is being provided the RF input? Pls dont enable 'Play' button while DPD is on. Can you change the sequence to Reset DPD and then start Tx?

  • Hello

    I think I solved the issue with the errors in the GUI. I am not sure, but there seems to be an error with the defaultDpdModel.txt file I was using (see my initial post for the dpd model) ; 

    According to the ADRV9026/ADRV9029 System Development USer Guide (Rev. PrA), sub-topic "GMP Model and Look Up Table, page 10, each row in the LUT bank shares the same cross term (j) values. The model file I was using does not follow this rule so I edited it and loaded it up again. No more GUI errors when I apply the M and C tables.

    I used this same model for our custom board and, after loading the model in my code (before asserting ADI_ADRV9025_DPD_RESET_FULL), I asserted ADI_ADRV9025_DPD_LUT_RESTORE_C_TABLE and/or ADI_ADRV9025_DPD_LUT_RESTORE. And then finally asserted the full reset. With this sequence, the RF signal does not die off. However, this is, problem half solved.  There's still one more thing; without any PA connected, I expect to see distortion in my RF signal, however, the signal stays the same (DPD ON or DPD OFF). I will keep testing from here onwards and update this post if there is any luck. But, I would really appreciate your thoughts, I may still probably be doing something wrong (and may be wrong about half-solving the error). 

  • According to the ADRV9026/ADRV9029 System Development USer Guide (Rev. PrA), sub-topic "GMP Model and Look Up Table, page 10, each row in the LUT bank shares the same cross term (j) values. The model file I was using does not follow this rule so I edited it and loaded it up again. No more GUI errors when I apply the M and C tables.

    This is a good point. Can you please share me the model file with and without the update of the LUT? Which Software package are you using? We might have to review the model files that come along with the package in this case?

    I used this same model for our custom board and, after loading the model in my code (before asserting ADI_ADRV9025_DPD_RESET_FULL), I asserted ADI_ADRV9025_DPD_LUT_RESTORE_C_TABLE and/or ADI_ADRV9025_DPD_LUT_RESTORE. And then finally asserted the full reset. With this sequence, the RF signal does not die off. However, this is, problem half solved.  There's still one more thing; without any PA connected, I expect to see distortion in my RF signal, however, the signal stays the same (DPD ON or DPD OFF). I will keep testing from here onwards and update this post if there is any luck. But, I would really appreciate your thoughts, I may still probably be doing something wrong (and may be wrong about half-solving the error). 

    Without the PA connected, with DPD ON and OFF, you don't see any significant change in the spectrum as the TX out from the TRX is linear enough and the ORX path does not see any distortion. When there is significant error between the transmitted Tx and the received ORX, the DPD estimation will try to pre-distort the Tx. signal and you would see a corrected spectrum.

    At this point, you can probably connect a PA and check the performance.

  • Alright. Thanks a lot for the help. I have attached the model as well as a screen capture of my software info below. As you can see from the model, the j terms for luts 0 and 2 are different, when they should be the same. 

    ----------- Software Info ----------

    -------------- DPD Model File ( C:\Program Files\Analog Devices\ADRV9025 Transceiver Evaluation Software_x64_FULL\Resources\DpdModels) ---------------

    // DPD Model descriptor.
    // Each row represents one DPD "feature" with the following fields:
    //  i    i - Memory term
    //  j    j - Cross term
    //  k    k - Power term
    //  lut  LUT pointer (0-31)
    //  row  Row (which complex multiplier row)
    //  a    Complex Coefficient
    //
    // i  j  k  lut  Real(coeff)   Imag(coeff)
    // ---------------------------------------
       0  0  0   0       0            0
       0  0  1   0       0            0
       0  0  2   0       0            0
       0  0  3   0       0            0
       0  0  4   0       0            0
       0  0  5   0       0            0
       1  1  1   2       0            0
       1  1  2   2       0            0
       1  1  3   2       0            0
       1  1  4   2       0            0
       1  1  5   2       0            0
       0  1  0   8       0            0
       0  1  1   8       0            0
       0  1  2   8       0            0
       0  1  3   8       0            0
       0  1  4   8       0            0
       0  1  5   8       0            0
       2  2  1  26       0            0
       2  2  2  26       0            0
       2  2  3  26       0            0
       2  2  4  26       0            0
       2  2  5  26       0            0

  • -------------- DPD Model File ( C:\Program Files\Analog Devices\ADRV9025 Transceiver Evaluation Software_x64_FULL\Resources\DpdModels) ---------------

    Hi Alex,

    Good day,

    I have same issue on ADRV9025A, could you provide correct DPD model.

    Many thanks.