gr_mpsk_receiver()


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

まずはworkの部分
int
gr_mpsk_receiver_cc::general_work (int noutput_items, 
				   gr_vector_int &ninput_items,
				   gr_vector_const_void_star &input_items,
				   gr_vector_void_star &output_items)
{
  const gr_complex *in = (const gr_complex *) input_items[0];
  gr_complex *out = (gr_complex *) output_items[0];

  int i=0, o=0;

  while((o < noutput_items) && (i < ninput_items[0])) {
    while((d_mu > 1) && (i < ninput_items[0]))  {
      mm_sampler(in[i]);   // puts symbols into a buffer and adjusts d_mu
      i++;
    }
    
    if(i < ninput_items[0]) {
      gr_complex interp_sample = d_interp->interpolate(&d_dl[d_dl_idx], d_mu);
       
      mm_error_tracking(interp_sample);     // corrects M&M sample time
      phase_error_tracking(interp_sample);  // corrects phase and frequency offsets 

      out[o++] = interp_sample;
    }
  }

  #if 0
  printf("ninput_items: %d   noutput_items: %d   consuming: %d   returning: %d\n", 
	 ninput_items[0], noutput_items, i, o);
  #endif

  consume_each(i);
  return o;
}

//コンストラクタ
/*!
  * \brief Constructor to synchronize incoming M-PSK symbols
  *
  * \param M	        modulation order of the M-PSK modulation
  * \param theta	any constant phase rotation from the real axis of the constellation
  * \param alpha	gain parameter to adjust the phase in the Costas loop (~0.01)
  * \param beta        gain parameter to adjust the frequency in the Costas loop (~alpha^2/4)	
  * \param fmin        minimum normalized frequency value the loop can achieve
  * \param fmax        maximum normalized frequency value the loop can achieve
  * \param mu          initial parameter for the interpolator [0,1]
  * \param gain_mu     gain parameter of the M&M error signal to adjust mu (~0.05)
  * \param omega       initial value for the number of symbols between samples (~number of samples/symbol)
  * \param gain_omega  gain parameter to adjust omega based on the error (~omega^2/4)
  * \param omega_rel   sets the maximum (omega*(1+omega_rel)) and minimum (omega*(1+omega_rel)) omega (~0.005)
  *
  * The constructor also chooses which phase detector and decision maker to use in the work loop based on the
  * value of M.
*/

gr_mpsk_receiver_cc::gr_mpsk_receiver_cc (unsigned int M, float theta,  
					  float alpha, float beta,
					  float fmin, float fmax,
					  float mu, float gain_mu, 
					  float omega, float gain_omega, float omega_rel)
  : gr_block ("mpsk_receiver_cc",
	      gr_make_io_signature (1, 1, sizeof (gr_complex)),
	      gr_make_io_signature (1, 1, sizeof (gr_complex))),
    d_M(M), d_theta(theta), 
    d_alpha(alpha), d_beta(beta), d_freq(0), d_max_freq(fmax), d_min_freq(fmin), d_phase(0),
    d_current_const_point(0),
    d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega), 
    d_omega_rel(omega_rel), d_max_omega(0), d_min_omega(0),
    d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0)
{
  //補間サンプルを計算
  d_interp = new gri_mmse_fir_interpolator_cc();//Compute intermediate samples between signal samples x(k*Ts)
  d_dl_idx = 0;
  //omega(interpolation.クロックレート.サンプル間にいくつのシンボルが入っているかを示す.最大値はsamples/symbol)をセットする.
  set_omega(omega); // \param omega\ initial value for the number of symbols between samples (~number of samples/symbol)
  if (omega <= 0.0) //omegaは0より大きくないとだめ
    throw std::out_of_range ("clock rate must be > 0");
  if (gain_mu <  0  || gain_omega < 0) 
    throw std::out_of_range ("Gains must be non-negative");
  
  assert(d_interp->ntaps() <= DLLEN); //DLLEN(=8)はdelay line lengthらしい。。
  
  // zero double length delay line.
  for (unsigned int i = 0; i < 2 * DLLEN; i++)
    d_dl[i] = gr_complex(0.0,0.0); //d_dlはDDLENの二倍確保

  // build the constellation vector from M
  make_constellation();
  
  // Select a phase detector and a decision maker for the modulation order
  switch(d_M) {
  case 2:  // optimized algorithms for BPSK
   /*!
   * \brief Phase error detector for BPSK modulation.
   * \param sample   the I&Q sample from which to determine the phase error
   * This function determines the phase error using a simple BPSK phase error detector by multiplying the real
   * and imaginary (the error signal) components together. As the imaginary part goes to 0, so does this error.
   * \returns the approximated phase error.
  */
    //float phase_error_detector_bpsk(gr_complex sample) const;位相誤り検波
    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_bpsk; 
    d_decision = &gr_mpsk_receiver_cc::decision_bpsk; //bpsk用のスライサー(0以上or0以下).エラーを最小化するコンスタレーションを返す。
    break; 

  case 4: // optimized algorithms for QPSK
    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_qpsk; //qpsk;
    d_decision = &gr_mpsk_receiver_cc::decision_qpsk;
    break;

  default: // generic algorithms for any M (power of 2?) but not pretty
    d_phase_error_detector = &gr_mpsk_receiver_cc::phase_error_detector_generic;
    d_decision = &gr_mpsk_receiver_cc::decision_generic;
    break;
  }
}

//シンボル一つずつをバッファーに入れてd_muを調節する。muは少数部分遅延
void
gr_mpsk_receiver_cc::mm_sampler(const gr_complex symbol)
{
  gr_complex sample, nco;

  d_mu--;             // skip a number of symbols between sampling
  d_phase += d_freq;  // increment the phase based on the frequency of the rotation

  // Keep phase clamped and not walk to infinity
  while(d_phase > M_TWOPI)
    d_phase -= M_TWOPI;
  while(d_phase < -M_TWOPI)
    d_phase += M_TWOPI;
  
  nco = gr_expj(d_phase+d_theta);   // get the NCO value for derotating the current sample
  sample = nco*symbol;      // get the downconverted symbol
  
  // Fill up the delay line for the interpolator
  //バッファにダウンコーバートしたシンボルを入れる
  d_dl[d_dl_idx] = sample;
  //オーバーフロウのためバッファの後半部にこいつを入れる。
  d_dl[(d_dl_idx + DLLEN)] = sample;  // put this in the second half of the buffer for overflows
  //境界で遅延ラインインデックスをキープする
  d_dl_idx = (d_dl_idx+1) % DLLEN;    // Keep the delay line index in bounds
}