我目前正在实施符号时间恢复块。这个想法是能够选择不同的 TED(加德纳、过零、早晚、最大似然等)。在像 M&M 恢复这样的块中,环路的增益参数被明确表示(gain_omega 和 gain_mu),这可能很难正确。然而,contro_loop 类更方便(环路特性可以通过“环路带宽”和“阻尼因子”(zeta)来指定)。因此,我的第一个测试从使用控制回路重新实现 MM 时钟恢复开始。该块的工作函数如下所示(评论是我的)
clock_recovery_mm_ff_impl::general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *)input_items[0];
float *out = (float *)output_items[0];
int ii = 0; // input index
int oo = 0; // output index
int ni = ninput_items[0] - d_interp->ntaps(); // don't use more input than this
float mm_val;
while(oo < noutput_items && ii < ni ) {
// produce output sample
out[oo] = d_interp->interpolate(&in[ii], d_mu); //Interpolation
mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample; // Error calculation
d_last_sample = out[oo];
//Loop filtering
d_omega = d_omega + d_gain_omega * mm_val; //Frequency
d_omega = d_omega_mid + gr::branchless_clip(d_omega-d_omega_mid, d_omega_lim); //Bound the frequency
d_mu = d_mu + d_omega + d_gain_mu * mm_val; //Phase
ii += (int)floor(d_mu); // Basepoint index
d_mu = d_mu - floor(d_mu); // Fractional interval
oo++;
}
consume_each(ii);
return oo;
}
这是我的代码。一、控制循环初始化构造函数
loop(new gr::blocks::control_loop(0.02,(1 + d_omega_relative_limit)*omega,
(1 - d_omega_relative_limit)*omega))
首先,我想消除我对符号时序恢复中的 pll(上面的 control_loop)特别是相位和频率范围(又用于包装)的几个疑问。从科斯塔斯循环中进行类比:载波相位在 -2pi 和 +2pi 之间包裹,并且频率偏移在 -1 和 +1 之间进行跟踪。很容易看出原因。不幸的是,我无法理解符号恢复中的相位和频率跟踪。从 m&m 块中,跟踪 (1+omega_relative_limit) 和 (1 - omega_relative_limit)*omega 之间的频率,其中 omega 只是每个符号的样本数。在 0 和 omega 之间跟踪相位。我不明白为什么会这样以及为什么 m&m 块不包装它。这里的任何想法将不胜感激。这是我的工作职能
debug_time_recovery_pam_test_1_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
// Tell runtime system how many output items we produced.
const float *in = (const float *)input_items[0];
float *out = (float *)output_items[0];
int ii = 0; // input index
int oo = 0; // output index
int ni = ninput_items[0] - d_interp->ntaps(); // don't use more input than this
float mm_val;
while(oo < noutput_items && ii < ni ) {
// produce output sample
out[oo] = d_interp->interpolate(&in[ii], d_mu);
//Calculating error
mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample;
d_last_sample = out[oo];
//Loop filtering
loop->advance_loop(mm_val); // Filter the error
loop->frequency_limit(); //Stop frequency from wandering too far
//Loop phase and frequency
d_omega = loop->get_frequency();
d_mu = loop->get_phase();
//d_omega = d_omega + d_gain_omega * mm_val;
//d_omega = d_omega_mid + gr::branchless_clip(d_omega-d_omega_mid, d_omega_lim);
//d_mu = d_mu + d_omega + d_gain_mu * mm_val;
ii += (int)floor(d_mu); // Basepoint index
d_mu = d_mu - floor(d_mu);//Fractional interval
oo++;
}
consume_each(ii);
return oo;
}
我尝试在 GFSK 解调器中使用该模块,但出现此错误
python: /build/gnuradio-bJXzXK/gnuradio-3.7.9.1/gnuradio-runtime/include/gnuradio/buffer.h:177: unsigned int gr::buffer::index_add(unsigned int, unsigned int): Assertion `s < d_bufsize' failed.
关于这个错误的第一个谷歌搜索表明我以某种方式“滥用”调度程序,因为这个错误出现在 API 下方的某个地方。我认为我从控制循环中计算 d_omega 和 d_mu 有点幼稚,但不幸的是我不知道其他任何方法。另一种选择是使用模 1 计数器(递增或递减),但我想先探索这个选项。