本篇博客用于记录学习和使用github程序包Gen2-UHF-RFID-Reader的过程。出错的地方还望大家指正。
使用平台:ubuntu16.04      UHD3.14.0.HEAD-0-g6875d061     gnuradio3.7.10.1      USRP N210(SBX子板)
本篇详细分析reader_impl.cc文件。
reader模块功能:判断系统所处盘存阶段,生成对应命令或信号,并对基带信号进行PIE编码输出。

    reader::sptrreader::make(int sample_rate, int dac_rate){return gnuradio::get_initial_sptr(new reader_impl(sample_rate,dac_rate));}

reader模块的重要参数为sample_rate,dac_rate。

    reader_impl::reader_impl(int sample_rate, int dac_rate): gr::block("reader",gr::io_signature::make( 1, 1, sizeof(float)),gr::io_signature::make( 1, 1, sizeof(float))){GR_LOG_INFO(d_logger, "Block initialized");sample_d = 1.0/dac_rate * pow(10,6);// Number of samples for transmittingn_data0_s = 2 * PW_D / sample_d;n_data1_s = 4 * PW_D / sample_d;n_pw_s    = PW_D    / sample_d;n_cw_s    = CW_D    / sample_d;n_delim_s = DELIM_D / sample_d;n_trcal_s = TRCAL_D / sample_d;GR_LOG_INFO(d_logger, "Number of samples data 0 : " << n_data0_s);GR_LOG_INFO(d_logger, "Number of samples data 1 : " << n_data1_s);GR_LOG_INFO(d_logger, "Number of samples cw : "     << n_cw_s);GR_LOG_INFO(d_logger, "Number of samples delim : "  << n_delim_s);GR_LOG_INFO(d_logger, "Number of slots : "          << std::pow(2,FIXED_Q));// CW waveforms of different sizesn_cwquery_s   = (T1_D+T2_D+RN16_D)/sample_d;     //RN16n_cwack_s     = (3*T1_D+T2_D+EPC_D)/sample_d;    //EPC   if it is longer than nominal it wont cause tags to change inventoried flagn_p_down_s     = (P_DOWN_D)/sample_d;  p_down.resize(n_p_down_s);        // Power down samplescw_query.resize(n_cwquery_s);      // Sent after query/query repcw_ack.resize(n_cwack_s);          // Sent after ackstd::fill_n(cw_query.begin(), cw_query.size(), 1);std::fill_n(cw_ack.begin(), cw_ack.size(), 1);GR_LOG_INFO(d_logger, "Carrier wave after a query transmission in samples : "     << n_cwquery_s);GR_LOG_INFO(d_logger, "Carrier wave after ACK transmission in samples : "        << n_cwack_s);// Construct vectors (resize() default initialization is zero)data_0.resize(n_data0_s);data_1.resize(n_data1_s);cw.resize(n_cw_s);delim.resize(n_delim_s);rtcal.resize(n_data0_s + n_data1_s);trcal.resize(n_trcal_s);// Fill vectors with data,利用PIE编码进行编码填充std::fill_n(data_0.begin(), data_0.size()/2, 1);std::fill_n(data_1.begin(), 3*data_1.size()/4, 1);std::fill_n(cw.begin(), cw.size(), 1);std::fill_n(rtcal.begin(), rtcal.size() - n_pw_s, 1); // RTcalstd::fill_n(trcal.begin(), trcal.size() - n_pw_s, 1); // TRcal// create preamblepreamble.insert( preamble.end(), delim.begin(), delim.end() );preamble.insert( preamble.end(), data_0.begin(), data_0.end() );preamble.insert( preamble.end(), rtcal.begin(), rtcal.end() );preamble.insert( preamble.end(), trcal.begin(), trcal.end() );// create framesyncframe_sync.insert( frame_sync.end(), delim.begin() , delim.end() );frame_sync.insert( frame_sync.end(), data_0.begin(), data_0.end() );frame_sync.insert( frame_sync.end(), rtcal.begin() , rtcal.end() );// create query repquery_rep.insert( query_rep.end(), frame_sync.begin(), frame_sync.end());query_rep.insert( query_rep.end(), data_0.begin(), data_0.end() );query_rep.insert( query_rep.end(), data_0.begin(), data_0.end() );query_rep.insert( query_rep.end(), data_0.begin(), data_0.end() );query_rep.insert( query_rep.end(), data_0.begin(), data_0.end() );// create naknak.insert( nak.end(), frame_sync.begin(), frame_sync.end());nak.insert( nak.end(), data_1.begin(), data_1.end() );nak.insert( nak.end(), data_1.begin(), data_1.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );nak.insert( nak.end(), data_0.begin(), data_0.end() );gen_query_bits();gen_query_adjust_bits();}

reader模块有一个输入端口,一个输出端口。构造函数中计算了数字“0”、数字“1”、半个Tari、连续波CW、前导码、TRcal、标签响应RN16、标签响应EPC、掉电时的采样点数,利用PIE编码对“0”、“1”、CW、RTcal、TRcal进行编码,并对前导码、帧同步码、query_rep、nak命令进行构造,以便后续使用。

   void reader_impl::gen_query_bits(){int num_ones = 0, num_zeros = 0;query_bits.resize(0);query_bits.insert(query_bits.end(), &QUERY_CODE[0], &QUERY_CODE[4]);query_bits.push_back(DR);query_bits.insert(query_bits.end(), &M[0], &M[2]);query_bits.push_back(TREXT);query_bits.insert(query_bits.end(), &SEL[0], &SEL[2]);query_bits.insert(query_bits.end(), &SESSION[0], &SESSION[2]);query_bits.push_back(TARGET);query_bits.insert(query_bits.end(), &Q_VALUE[FIXED_Q][0], &Q_VALUE[FIXED_Q][4]);crc_append(query_bits);}

gen_query_bits函数对query字段进行构造填充,关于query字段的解释详见Gen2-UHF-RFID-Reader学习(二)。

    void reader_impl::gen_ack_bits(const float * in){ack_bits.resize(0);ack_bits.insert(ack_bits.end(), &ACK_CODE[0], &ACK_CODE[2]);ack_bits.insert(ack_bits.end(), &in[0], &in[16]);}void reader_impl::gen_query_adjust_bits(){query_adjust_bits.resize(0);query_adjust_bits.insert(query_adjust_bits.end(), &QADJ_CODE[0], &QADJ_CODE[4]);query_adjust_bits.insert(query_adjust_bits.end(), &SESSION[0], &SESSION[2]);query_adjust_bits.insert(query_adjust_bits.end(), &Q_UPDN[1][0], &Q_UPDN[1][3]);}

gen_ack_bits函数对ack命令字段进行构造填充。gen_query_adjust_bits函数对query_adjust命令字段进行构造填充。

    reader_impl::~reader_impl(){}voidreader_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required){ninput_items_required[0] = 0;}

析构函数没有内容。forecast函数为自带函数,无需变更。

    int reader_impl::print_results(){//std::cout << "count: " << get_count() << std::endl;std::cout << "\n --------------------------" << std::endl;std::cout << "| Number of queries/queryreps sent : " << reader_state->reader_stats.n_queries_sent - 1 << std::endl;std::cout << "| Current Inventory round : "          << reader_state->reader_stats.cur_inventory_round << std::endl;std::cout << " --------------------------"            << std::endl;std::cout << "| Correctly decoded EPC : "  <<  reader_state->reader_stats.n_epc_correct     << std::endl;std::cout << "| Number of unique tags : "  <<  reader_state->reader_stats.tag_reads.size() << std::endl;std::map<std::string,int>::iterator it;for(it = reader_state->reader_stats.tag_reads.begin(); it != reader_state->reader_stats.tag_reads.end(); it++) {std::cout <<  "| Tag ID : ";for(int i = 0; i < it->first.size(); ++i){std::cout << it->first[i];if(i%4 == 3 && i != it->first.size()-1)std::cout << "-";} std::cout << std::endl;std::cout << "Num of reads : " << std::dec << it->second << std::endl;}std::cout << " --------------------------" << std::endl;std::cout << reader_state->reader_stats.n_queries_sent << std::endl;return 1;}

print_results函数对统计结果进行输出,这一般在系统结束时才允许,不能达到实时显示读取情况,这也是该系统的一个缺陷。

   intreader_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];std::vector<float> out_message; int n_output;int consumed = 0;int written = 0;consumed = ninput_items[0];switch (reader_state->gen2_logic_status){case START:GR_LOG_INFO(d_debug_logger, "START");memcpy(&out[written], &cw_ack[0], sizeof(float) * cw_ack.size() );written += cw_ack.size();reader_state->gen2_logic_status = SEND_QUERY;    break;case POWER_DOWN:GR_LOG_INFO(d_debug_logger, "POWER DOWN");memcpy(&out[written], &p_down[0], sizeof(float) * p_down.size() );written += p_down.size();reader_state->gen2_logic_status = START;    break;case SEND_NAK_QR:GR_LOG_INFO(d_debug_logger, "SEND NAK");memcpy(&out[written], &nak[0], sizeof(float) * nak.size() );written += nak.size();memcpy(&out[written], &cw[0], sizeof(float) * cw.size() );written+=cw.size();reader_state->gen2_logic_status = SEND_QUERY_REP;    break;case SEND_NAK_Q:GR_LOG_INFO(d_debug_logger, "SEND NAK");memcpy(&out[written], &nak[0], sizeof(float) * nak.size() );written += nak.size();memcpy(&out[written], &cw[0], sizeof(float) * cw.size() );written+=cw.size();reader_state->gen2_logic_status = SEND_QUERY;    break;case SEND_QUERY:/*if (reader_state->reader_stats.n_queries_sent % 10 == 0){std::cout << "Running " << std::endl;}*///std::cout << "count:" << get_count() << std::endl; GR_LOG_INFO(d_debug_logger, "QUERY");GR_LOG_INFO(d_debug_logger, "INVENTORY ROUND : " << reader_state->reader_stats.cur_inventory_round << " SLOT NUMBER : " << reader_state->reader_stats.cur_slot_number);reader_state->reader_stats.n_queries_sent +=1; // Controls the other two blocksreader_state->decoder_status = DECODER_DECODE_RN16;reader_state->gate_status    = GATE_SEEK_RN16;memcpy(&out[written], &preamble[0], sizeof(float) * preamble.size() );written+=preamble.size();for(int i = 0; i < query_bits.size(); i++){if(query_bits[i] == 1){memcpy(&out[written], &data_1[0], sizeof(float) * data_1.size() );written+=data_1.size();}else{memcpy(&out[written], &data_0[0], sizeof(float) * data_0.size() );written+=data_0.size();}}// Send CW for RN16memcpy(&out[written], &cw_query[0], sizeof(float) * cw_query.size() );written+=cw_query.size();// Return to IDLEreader_state->gen2_logic_status = IDLE;      break;case SEND_ACK:GR_LOG_INFO(d_debug_logger, "SEND ACK");if (ninput_items[0] == RN16_BITS - 1){// Controls the other two blocksreader_state->decoder_status = DECODER_DECODE_EPC;reader_state->gate_status    = GATE_SEEK_EPC;gen_ack_bits(in);// Send FrameSyncmemcpy(&out[written], &frame_sync[0], sizeof(float) * frame_sync.size() );written += frame_sync.size();for(int i = 0; i < ack_bits.size(); i++){if(ack_bits[i] == 1){memcpy(&out[written], &data_1[0], sizeof(float) * data_1.size() );written += data_1.size();}else  {memcpy(&out[written], &data_0[0], sizeof(float) * data_0.size() );written += data_0.size();}}consumed = ninput_items[0];reader_state->gen2_logic_status = SEND_CW; }break;case SEND_CW:GR_LOG_INFO(d_debug_logger, "SEND CW");memcpy(&out[written], &cw_ack[0], sizeof(float) * cw_ack.size() );written += cw_ack.size();reader_state->gen2_logic_status = IDLE;      // Return to IDLEbreak;case SEND_QUERY_REP:GR_LOG_INFO(d_debug_logger, "SEND QUERY_REP");GR_LOG_INFO(d_debug_logger, "INVENTORY ROUND : " << reader_state->reader_stats.cur_inventory_round << " SLOT NUMBER : " << reader_state->reader_stats.cur_slot_number);// Controls the other two blocksreader_state->decoder_status = DECODER_DECODE_RN16;reader_state->gate_status    = GATE_SEEK_RN16;reader_state->reader_stats.n_queries_sent +=1;  memcpy(&out[written], &query_rep[0], sizeof(float) * query_rep.size() );written += query_rep.size();memcpy(&out[written], &cw_query[0], sizeof(float) * cw_query.size());written+=cw_query.size();reader_state->gen2_logic_status = IDLE;    // Return to IDLEbreak;case SEND_QUERY_ADJUST:GR_LOG_INFO(d_debug_logger, "SEND QUERY_ADJUST");// Controls the other two blocksreader_state->decoder_status = DECODER_DECODE_RN16;reader_state->gate_status    = GATE_SEEK_RN16;reader_state->reader_stats.n_queries_sent +=1;  memcpy(&out[written], &frame_sync[0], sizeof(float) * frame_sync.size() );written += frame_sync.size();for(int i = 0; i < query_adjust_bits.size(); i++){if(query_adjust_bits[i] == 1){memcpy(&out[written], &data_1[0], sizeof(float) * data_1.size() );written+=data_1.size();}else{memcpy(&out[written], &data_0[0], sizeof(float) * data_0.size() );written+=data_0.size();}}memcpy(&out[written], &cw_query[0], sizeof(float) * cw_query.size());written+=cw_query.size();reader_state->gen2_logic_status = IDLE;    // Return to IDLEbreak;default:// IDLEbreak;}consume_each (consumed);return  written;}

模块的核心工作,其逻辑可用下述流程图表示:

    /* Function adapted from https://www.cgran.org/wiki/Gen2 */void reader_impl::crc_append(std::vector<float> & q){int crc[] = {1,0,0,1,0};for(int i = 0; i < 17; i++){int tmp[] = {0,0,0,0,0};tmp[4] = crc[3];if(crc[4] == 1){if (q[i] == 1){tmp[0] = 0;tmp[1] = crc[0];tmp[2] = crc[1];tmp[3] = crc[2];}else{tmp[0] = 1;tmp[1] = crc[0];tmp[2] = crc[1];if(crc[2] == 1){tmp[3] = 0;}else{tmp[3] = 1;}}}else{if (q[i] == 1){tmp[0] = 1;tmp[1] = crc[0];tmp[2] = crc[1];if(crc[2] == 1){tmp[3] = 0;}else{tmp[3] = 1;}}else{tmp[0] = 0;tmp[1] = crc[0];tmp[2] = crc[1];tmp[3] = crc[2];}}memcpy(crc, tmp, 5*sizeof(float));}for (int i = 4; i >= 0; i--)q.push_back(crc[i]);}

crc_append函数为CRC-16的构造过程。

Gen2-UHF-RFID-Reader学习(六)reader相关推荐

  1. The RF in RFID(chapter 3, Radio Basics for UHF RFID)

    Radio Basics for UHF RFID 电磁波 信号电压和信号能量 信息,调制和多路复用 后向散射无线电链路 链路预算 阅读器发射能量 路径损失 标签启动能量 标签反射功率和距离的关系 天 ...

  2. EXTRONICS推出IRFID500便携式UHF RFID读写器

    采矿.石油和天然气.化工.制药.石化等行业防爆无线技术制造商Extronics推出iRFID500便携式蓝牙无源UHF RFID读取器.该设备可简化资产跟踪,维修任务监控及计划的业务流程并确保危险环境 ...

  3. 超高频UHF RFID读写模块R200开发测试

    超高频UHF RFID读写模块R200开发测试 概述 一.使用模块 二.UHF-R200 模块简述 2.1 模块参数 2.2 模块引脚 三.R200-C50 开发板 四.RFID电子标签 4.1 PV ...

  4. Apollo代码学习(六)—模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

    Apollo代码学习(六)-模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码

  5. 艾伟:C#多线程学习(六) 互斥对象

    本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...

  6. C#多线程学习(六) 互斥对象

    C#多线程学习(六) 互斥对象 原文链接:http://kb.cnblogs.com/page/42533/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个 ...

  7. OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽

    OpenCV与图像处理学习六--图像形态学操作:腐蚀.膨胀.开.闭运算.形态学梯度.顶帽和黑帽 四.图像形态学操作 4.1 腐蚀和膨胀 4.1.1 图像腐蚀 4.1.2 图像膨胀 4.2 开运算与闭运 ...

  8. PyTorch框架学习六——图像预处理transforms(二)

    PyTorch框架学习六--图像预处理transforms(二) (续)二.transforms的具体方法 4.图像变换 (1)尺寸变换:transforms.Resize() (2)标准化:tran ...

  9. JMS学习六(ActiveMQ消息传送模型)

    JMS学习六(ActiveMQ消息传送模型) ActiveMQ 支持两种截然不同的消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布 /订阅模型),分别称作:PTP Domain 和Pub/ ...

  10. Docker学习六:综合实践

    前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...

最新文章

  1. pyhton列表习题
  2. python 异常和弹出框
  3. HttpServlet类简介和简单用法
  4. 为什么发了个博客分分钟被各种网站花式转载=。=而不通知我
  5. 常用Java面试题 List集合
  6. 前端:JS实现数组去重常用的六种方法介绍
  7. Linux系统(五)负载均衡LVS集群之DR模式
  8. OS --written test1
  9. 基于Monte Carlo方法的2048 A.I.
  10. android电源管理
  11. yii2 关系...
  12. 黑白翻转棋算法java实现_黑白翻转棋算法java实现
  13. Ubuntu安装完驱动后进不去界面
  14. 【数据结构】栈的基本操作
  15. 单元格里的字怎样居中_word表格中文字如何设置左右和上下居中(水平和垂直居中)...
  16. json 日期格式化
  17. 互联网晚报 | 1月3日 星期一 | 春运首日火车票今日开售;中兴终端2021年出货量超1亿部;抖音上线“学习”频道...
  18. DNX/ASP.NET 5的xUnit入门向导
  19. rxjs ajax query,rxjs入门之ajax封装
  20. 【媒体】黑灰产横行,金融行业如何“数智化”反欺诈?

热门文章

  1. 建筑八大员培训湖北质量员培训古建筑施工中的质量控制要点
  2. MySQL数据迁移工具
  3. java的dbcp使用方法_Java dbcp连接池的使用方法
  4. 小白如何学习GNSS(一)
  5. 批量解压子目录下包含密码的压缩包
  6. java并发编程——九 AbstractQueuedSynchronizer AQS详解
  7. 输入地址,获取邮编的工具类
  8. Word初学者编辑文字时注意改写和插入两种状态
  9. 常用的继电器触点保护电路
  10. DNF登陆的时候说连接服务器失败,请检查您的网络。是否启用修复程序进行修复?,地下城和勇士常见问题修复方法.doc...