AnsweredAssumed Answered

Send QPSK data via DMA on the platform ZedBoard +AD-FMCOMMS2-EBZ?

Question asked by ADI_Wei on May 28, 2015
Latest reply on Jun 4, 2015 by DragosB

Hello,

I have verified the dac_init(ad9361_phy, DATA_SEL_DMA) when use the data in the sine_lut[32] as the example code provided by No-OS reference design. Now I want to implement the QPSK modulation on the ZYNQ7 ARM, and send the modulated data to the AD9361 DAC via the DMA. QPSK modulation procedure are that:  Symbol(1,-1)--->Interpolation--->FIR filter--->Gain. The coding are shown as below,

 

// Modulation

#define sigPts 32                                //The number of the points of the signal
#define INTERP 1                                 //Interpolation
uint16_t Modulation_I[INTERP*sigPts];            //QPSK modulation data
uint16_t Modulation_Q[INTERP*sigPts];

int I_sig[sigPts] = {1, -1, 1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1, -1, 1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1 };
int Q_sig[sigPts] = {1, -1, 1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1, -1, 1,-1,1,-1,1,-1,1,-1,1,-1,1,-1,1,-1 };

#define numTaps 129
double FiltCo[numTaps]= {-0.00178639762948631, -0.00155870891521665, -0.000922036038762769, 0.00000662031, 0.00103044085161447, 0.00191388559033746, 0.00243598493785789, 0.00244400398906142, 0.00189476081655801, 0.000872921089200887,
-0.000419709629504921,-0.00170344065767972,-0.00268126358080306,-0.00310793749585022, -0.00285184386126175, -0.00193439405747001, -0.000535919288845883, 0.00103596532019569, 0.00241097910976235, 0.00324106979302367,
0.00328702940012335, 0.00248629239803016, 0.000984025097746820, -0.000883327845517629, -0.00265266514318121, -0.00383636150297830, -0.00404139377562236, -0.00307889018257000, -0.00103701475424289, 0.00170425033241046,
0.00452673801836021, 0.00669183962077948, 0.00750287004384248, 0.00648014375734146, 0.00351020737564072, -0.00106815027261384, -0.00646896467885034, -0.0115664335073279, -0.0150947784610852, -0.0159096812526340,
-0.0132633257159061, -0.00703622071963034, 0.00212907248421584, 0.0128337651111222, 0.0230863934085282, 0.0306128663043164, 0.0332715117147205, 0.0295063781830588, 0.0187571751096062, 0.00174348919144343,
-0.0194443899631484, -0.0414871059817277, -0.0602111843354427, -0.0711566623812208, -0.0702593919791229, -0.0545437726214533, -0.0227119727991704, 0.0244748089735988, 0.0840994799974748, 0.151310515791484,
0.219845441524588, 0.282790431364563, 0.333469700685869, 0.366334267559297, 0.377716366526600, 0.366334267559297, 0.333469700685869, 0.282790431364563, 0.219845441524588, 0.151310515791484,
0.0840994799974748, 0.0244748089735988, -0.0227119727991704, -0.0545437726214533, -0.0702593919791229, -0.0711566623812208, -0.0602111843354427, -0.0414871059817277, -0.0194443899631484, 0.00174348919144343,
0.0187571751096062, 0.0295063781830588, 0.0332715117147205, 0.0306128663043164, 0.0230863934085282, 0.0128337651111222, 0.00212907248421584, -0.00703622071963034, -0.0132633257159061, -0.0159096812526340,
-0.0150947784610852, -0.0115664335073279, -0.00646896467885034, -0.00106815027261384, 0.00351020737564072, 0.00648014375734146, 0.00750287004384248, 0.00669183962077948, 0.00452673801836021, 0.00170425033241046,
-0.00103701475424289, -0.00307889018257000, -0.00404139377562236, -0.00383636150297830, -0.00265266514318121, -0.000883327845517629, 0.000984025097746820, 0.00248629239803016, 0.00328702940012335, 0.00324106979302367,
0.00241097910976235, 0.00103596532019569, -0.000535919288845883, -0.00193439405747001, -0.00285184386126175, -0.00310793749585022, -0.00268126358080306, -0.00170344065767972, -0.000419709629504921, 0.000872921089200887,
0.00189476081655801, 0.00244400398906142, 0.00243598493785789, 0.00191388559033746, 0.00103044085161447, 0.0000066203105226536, -0.000922036038762769, -0.00155870891521665, -0.00178639762948631};

 

void UpSample_INTERP(int *Signal,int NumSigPts,double *signal_interpolated)
{
int i,j;
double delta;
for(i=0; i<NumSigPts-1;i++)
{
  delta=(Signal[i+1]-Signal[i])/INTERP;
  for(j=0;j<INTERP;j++)
  {
   signal_interpolated[INTERP*i+j]=Signal[i]+j*delta;
  }

}
signal_interpolated[INTERP*NumSigPts]=Signal[NumSigPts];
for(j=0;j<INTERP;j++)
   {
   signal_interpolated[INTERP*NumSigPts+j]=0;
   }
}


void RunFIRFilter(double *FiltCoeff, int NumTaps, double *Signal, double *FilteredSignal, int NumSigPts)
{
int j, k;
double y, Reg[256];  // This assumes <= 256 taps.

for(j=0; j<NumTaps; j++)Reg[j]=0.0; // Init the delay registers.

for(j=0; j<NumSigPts; j++)
{
  // Shift the register values down and set Reg[0].
  for(k=NumTaps; k>1; k--)Reg[k-1] = Reg[k-2];
  Reg[0] = Signal[j];

  y=0.0;
  for(k=0; k<NumTaps; k++) y+= FiltCoeff[k]*Reg[k];
  FilteredSignal[j]=y;
}

}

void Gain(double *filteredSignal, uint16_t *ScaledSignal,int NumSigPts)
{

int i,j;
double abs_MAXvalue, temp;
abs_MAXvalue=0.0;
for(i=0;i<NumSigPts;i++)
    {
if (filteredSignal[i]<0)
  {temp=-1*filteredSignal[i];}
else
  temp=filteredSignal[i];
if(temp>abs_MAXvalue)
  {abs_MAXvalue=temp;} //find the abs max value of the filtered signal.
    }

for(j=0;j<NumSigPts;j++)
    {
ScaledSignal[j]=filteredSignal[j]*2047/abs_MAXvalue;
    }
}

 

void GenerateModulationdata(uint16_t *Modulation_I,uint16_t *Modulation_Q,int *I_sig, int *Q_sig)
{

double I_Signal_interpolated[INTERP*sigPts];          //interpolation ratio is INTERP;
double Q_Signal_interpolated[INTERP*sigPts];
double I_data_fir[INTERP*sigPts];          //save the filtered data
double Q_data_fir[INTERP*sigPts];

UpSample_INTERP(I_sig,sigPts,I_Signal_interpolated);
UpSample_INTERP(Q_sig,sigPts,Q_Signal_interpolated);

RunFIRFilter(FiltCo,numTaps,I_Signal_interpolated,I_data_fir,INTERP*sigPts);
RunFIRFilter(FiltCo,numTaps,I_Signal_interpolated,Q_data_fir,INTERP*sigPts);

Gain(I_data_fir,Modulation_I,INTERP*sigPts);
Gain(Q_data_fir,Modulation_Q,INTERP*sigPts);

}

 

//DAC ini DMA

case DATA_SEL_DMA:

    GenerateModulationdata(Modulation_I,Modulation_Q,I_sig,Q_sig);                    
    tx_count =sizeof(Modulation_I) / sizeof(uint16_t);
    if (dds_st[phy->id_no].rx2tx2) {
     for (index = 0; index < (tx_count * 2); index +=2) {
      data_i1 = (Modulation_I[index/2] << 20);
      data_q1 = (Modulation_Q[index/2] << 4);
      Xil_Out32(DAC_DDR_BASEADDR + index * 4, data_i1 | data_q1);

      data_i2 = (Modulation_I[index/2] << 20);
      data_q2 = (Modulation_Q[index/2] << 4);
      Xil_Out32(DAC_DDR_BASEADDR + (index + 1) * 4, data_i2 | data_q2);
     }
    }
    else {
     for (index = 0; index < (tx_count * 2); index +=2) {
      data_i1 = (Modulation_I[index/2] << 20);
      data_q1 = (Modulation_Q[index/2] << 4);
      Xil_Out32(DAC_DDR_BASEADDR + index * 4, data_i1 | data_q1);
     }
    }

 

//main

ad9361_phy = ad9361_init(&default_init_param);

ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config);
ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config);

xil_printf("Before DAC_DMA\n");

dac_init(ad9361_phy, DATA_SEL_DMA);

xil_printf("After DAC_DMA\n");

 

But after click 'run as configuration', the code will running the initial code repeatedly and continuously. In the console window, I can find below information, which prove that the code will suspend and the ad9361_reset will be issued when the code runing to the dac_init(ad9361_phy, DATA_SEL_DMA). Could you please help to give some sugestion? Now I am doubt whether the modulation can be implemented on the ZYNQ ARM core.

ad9361_auxadc_setup

ad9361_init : AD9361 Rev 2 successfully initialized

ad9361_load_fir_filter_coef: TAPS 128, gain -6, dest 3

ad9361_load_fir_filter_coef: TAPS 128, gain 0, dest 131

Before DAC_DMA

ad9361_reset: by GPIO

Outcomes