本篇博客用于记录学习和使用github程序包Gen2-UHF-RFID-Reader的过程。出错的地方还望大家指正。
使用平台:ubuntu16.04 UHD3.14.0.HEAD-0-g6875d061 gnuradio3.7.10.1 USRP N210(SBX子板)
本篇分析gate_impl.cc文件。
Gate模块的作用:检测reader发出的命令,消除原始数据中的直流分量,并将结果输出到decoder模块中。
消除直流分量的原因:系统中信号的直流分量是由硬件等其他因素引起的,不携带我们所需要的信息,消除直流分量可在保证信息准确性的前提下减少系统处理数据的负担。
gate::sptr
gate::make(int sample_rate)
{
return gnuradio::get_initial_sptr
(new gate_impl(sample_rate));
}
gate模块需通过采样率sample_rate进行初始化。
/*
* The private constructor
*/
gate_impl::gate_impl(int sample_rate)
: gr::block("gate",
gr::io_signature::make(1, 1, sizeof(gr_complex)), //输入端口
gr::io_signature::make(1, 1, sizeof(gr_complex))), //输出端口
n_samples(0), win_index(0), dc_index(0), num_pulses(0), signal_state(NEG_EDGE), avg_ampl(0), dc_est(0,0) //默认参数,用于计数或变换
{
n_samples_T1 = T1_D * (sample_rate / pow(10,6)); //T1时间内的采样点数
n_samples_PW = PW_D * (sample_rate / pow(10,6)); //Tari/2时间内的采样点数
n_samples_TAG_BIT = TAG_BIT_D * (sample_rate / pow(10,6)); //1bit数据的采样点数
win_length = WIN_SIZE_D * (sample_rate/ pow(10,6)); //win窗口下采样点数
dc_length = DC_SIZE_D * (sample_rate / pow(10,6)); //直流分量的采样点数
win_samples.resize(win_length); //按照长度分配内存
dc_samples.resize(dc_length);
GR_LOG_INFO(d_logger, "T1 samples : " << n_samples_T1);
GR_LOG_INFO(d_logger, "PW samples : " << n_samples_PW);
GR_LOG_INFO(d_logger, "Samples of Tag bit : "<< n_samples_TAG_BIT);
GR_LOG_INFO(d_logger, "Size of window : " << win_length);
GR_LOG_INFO(d_logger, "Size of window for dc offset estimation : " << dc_length);
GR_LOG_INFO(d_logger, "Duration of window for dc offset estimation : " << DC_SIZE_D << " us");
// First block to be scheduled
GR_LOG_INFO(d_logger, "Initializing reader state...");
initialize_reader_state(); //实例化模块时先进行reader初始化
}
构造函数:一个complex输入端口,一个complex输出端口;进行采样点数量的计算,方便后续程序使用。
/*
* Our virtual destructor.
*/
gate_impl::~gate_impl()
{
}
void
gate_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
}
析构函数没有内容。forecast函数为自带函数,无需变更。
int
gate_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 gr_complex *in = (const gr_complex *) input_items[0]; //输入
gr_complex *out = (gr_complex *) output_items[0]; //输出
int n_items = ninput_items[0];
int number_samples_consumed = n_items; //使用过的采样点数量
float sample_ampl = 0; //采样点幅值
int written = 0; //下标,用于输出数据流的写入
if( (reader_state-> reader_stats.n_queries_sent > MAX_NUM_QUERIES ||
reader_state-> reader_stats.tag_reads.size() > NUMBER_UNIQUE_TAGS) &&
reader_state-> status != TERMINATED) //达到终止条件
{
reader_state-> status = TERMINATED; //系统中止
gettimeofday (&reader_state-> reader_stats.end, NULL); //计时结束
std::cout << "| Execution time : " << reader_state-> reader_stats.end.tv_sec - reader_state-> reader_stats.start.tv_sec << " seconds" << std::endl;
GR_LOG_INFO(d_logger, "Termination");
}
// Gate block is controlled by the Gen2 Logic block
if(reader_state->gate_status == GATE_SEEK_EPC) //gate状态为seek_epc
{
reader_state->gate_status = GATE_CLOSED; //更改状态
reader_state->n_samples_to_ungate = (EPC_BITS + TAG_PREAMBLE_BITS) * n_samples_TAG_BIT + 2*n_samples_TAG_BIT; //需要解码的数据量为(EPC_BITS + TAG_PREAMBLE_BITS+2)位
n_samples = 0; //采样点数归0
}
else if (reader_state->gate_status == GATE_SEEK_RN16)
{
reader_state->gate_status = GATE_CLOSED; //更改状态
reader_state->n_samples_to_ungate = (RN16_BITS + TAG_PREAMBLE_BITS) * n_samples_TAG_BIT + 2*n_samples_TAG_BIT; //需要解码的数据量为(RN16_BITS + TAG_PREAMBLE_BITS+2)位
n_samples = 0; //采样点数归0
}
if (reader_state->status == RUNNING)
{
for(int i = 0; i < n_items; i++)
{
// Tracking average amplitude
//追踪窗口内的平均幅值
sample_ampl = std::abs(in[i]);
avg_ampl = avg_ampl + (sample_ampl - win_samples[win_index])/win_length;
win_samples[win_index] = sample_ampl;
win_index = (win_index + 1) % win_length;
//Threshold for detecting negative/positive edges
sample_thresh = avg_ampl * THRESH_FRACTION; //判别上升沿或下降沿的阈值
if( !(reader_state->gate_status == GATE_OPEN) )
{
//Tracking DC offset (only during T1)
//预测直流分量幅值
dc_est = dc_est + (in[i] - dc_samples[dc_index])/std::complex<float>(dc_length,0);
dc_samples[dc_index] = in[i];
dc_index = (dc_index + 1) % dc_length;
n_samples++;
// Potitive edge -> Negative edge,采样点数归0
if( sample_ampl < sample_thresh && signal_state == POS_EDGE)
{
n_samples = 0;
signal_state = NEG_EDGE;
}
// Negative edge -> Positive edge
else if (sample_ampl > sample_thresh && signal_state == NEG_EDGE)
{
signal_state = POS_EDGE;
if (n_samples > n_samples_PW/2) //脉冲数+1,用于判断是否达到检测命令的脉冲
num_pulses++;
else
num_pulses = 0;
n_samples = 0;
}
if(n_samples > n_samples_T1 && signal_state == POS_EDGE && num_pulses > NUM_PULSES_COMMAND) //开始检测命令
{
GR_LOG_INFO(d_debug_logger, "READER COMMAND DETECTED");
reader_state->gate_status = GATE_OPEN;
reader_state->magn_squared_samples.resize(0);
reader_state->magn_squared_samples.push_back(std::norm(in[i] - dc_est));
out[written] = in[i] - dc_est; //输出=输入减去直流分量
written++;
num_pulses = 0;
n_samples = 1; // Count number of samples passed to the next block
}
}
else
{
n_samples++;
reader_state->magn_squared_samples.push_back(std::norm(in[i] - dc_est));
out[written] = in[i] - dc_est; // Remove offset from complex samples
written++;
if (n_samples >= reader_state->n_samples_to_ungate)
{
reader_state->gate_status = GATE_CLOSED;
number_samples_consumed = i+1;
break;
}
}
}
}
consume_each (number_samples_consumed);
return written;
}
模块的核心工作,其逻辑可用下述流程图表示
!这部分代码只看懂了大致意思,为什么这么写还没有完全明白,等清楚之后再来更新。