Gen2-UHF-RFID-Reader学习(六)reader
本篇博客用于记录学习和使用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相关推荐
- The RF in RFID(chapter 3, Radio Basics for UHF RFID)
Radio Basics for UHF RFID 电磁波 信号电压和信号能量 信息,调制和多路复用 后向散射无线电链路 链路预算 阅读器发射能量 路径损失 标签启动能量 标签反射功率和距离的关系 天 ...
- EXTRONICS推出IRFID500便携式UHF RFID读写器
采矿.石油和天然气.化工.制药.石化等行业防爆无线技术制造商Extronics推出iRFID500便携式蓝牙无源UHF RFID读取器.该设备可简化资产跟踪,维修任务监控及计划的业务流程并确保危险环境 ...
- 超高频UHF RFID读写模块R200开发测试
超高频UHF RFID读写模块R200开发测试 概述 一.使用模块 二.UHF-R200 模块简述 2.1 模块参数 2.2 模块引脚 三.R200-C50 开发板 四.RFID电子标签 4.1 PV ...
- Apollo代码学习(六)—模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码
Apollo代码学习(六)-模型预测控制(MPC)_follow轻尘的博客-CSDN博客_mpc代码
- 艾伟:C#多线程学习(六) 互斥对象
本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...
- C#多线程学习(六) 互斥对象
C#多线程学习(六) 互斥对象 原文链接:http://kb.cnblogs.com/page/42533/ 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个 ...
- OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽
OpenCV与图像处理学习六--图像形态学操作:腐蚀.膨胀.开.闭运算.形态学梯度.顶帽和黑帽 四.图像形态学操作 4.1 腐蚀和膨胀 4.1.1 图像腐蚀 4.1.2 图像膨胀 4.2 开运算与闭运 ...
- PyTorch框架学习六——图像预处理transforms(二)
PyTorch框架学习六--图像预处理transforms(二) (续)二.transforms的具体方法 4.图像变换 (1)尺寸变换:transforms.Resize() (2)标准化:tran ...
- JMS学习六(ActiveMQ消息传送模型)
JMS学习六(ActiveMQ消息传送模型) ActiveMQ 支持两种截然不同的消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布 /订阅模型),分别称作:PTP Domain 和Pub/ ...
- Docker学习六:综合实践
前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...
最新文章
- pyhton列表习题
- python 异常和弹出框
- HttpServlet类简介和简单用法
- 为什么发了个博客分分钟被各种网站花式转载=。=而不通知我
- 常用Java面试题 List集合
- 前端:JS实现数组去重常用的六种方法介绍
- Linux系统(五)负载均衡LVS集群之DR模式
- OS --written test1
- 基于Monte Carlo方法的2048 A.I.
- android电源管理
- yii2 关系...
- 黑白翻转棋算法java实现_黑白翻转棋算法java实现
- Ubuntu安装完驱动后进不去界面
- 【数据结构】栈的基本操作
- 单元格里的字怎样居中_word表格中文字如何设置左右和上下居中(水平和垂直居中)...
- json 日期格式化
- 互联网晚报 | 1月3日 星期一 | 春运首日火车票今日开售;中兴终端2021年出货量超1亿部;抖音上线“学习”频道...
- DNX/ASP.NET 5的xUnit入门向导
- rxjs ajax query,rxjs入门之ajax封装
- 【媒体】黑灰产横行,金融行业如何“数智化”反欺诈?
热门文章
- 建筑八大员培训湖北质量员培训古建筑施工中的质量控制要点
- MySQL数据迁移工具
- java的dbcp使用方法_Java dbcp连接池的使用方法
- 小白如何学习GNSS(一)
- 批量解压子目录下包含密码的压缩包
- java并发编程——九 AbstractQueuedSynchronizer AQS详解
- 输入地址,获取邮编的工具类
- Word初学者编辑文字时注意改写和插入两种状态
- 常用的继电器触点保护电路
- DNF登陆的时候说连接服务器失败,请检查您的网络。是否启用修复程序进行修复?,地下城和勇士常见问题修复方法.doc...