まずは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
}
最終更新:2011年07月30日 22:22