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::sptr
    reader::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 transmitting

      n_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 sizes
      n_cwquery_s   = (T1_D+T2_D+RN16_D)/sample_d;     //RN16
      n_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 flag
      n_p_down_s     = (P_DOWN_D)/sample_d;  

      p_down.resize(n_p_down_s);        // Power down samples
      cw_query.resize(n_cwquery_s);      // Sent after query/query rep
      cw_ack.resize(n_cwack_s);          // Sent after ack

      std::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); // RTcal
      std::fill_n(trcal.begin(), trcal.size() - n_pw_s, 1); // TRcal

      // create preamble
      preamble.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 framesync
      frame_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 rep
      query_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 nak
      nak.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()
    {

    }
	void
		reader_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函数对统计结果进行输出,这一般在系统结束时才允许,不能达到实时显示读取情况,这也是该系统的一个缺陷。

   int
    reader_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 blocks
          reader_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 RN16
          memcpy(&out[written], &cw_query[0], sizeof(float) * cw_query.size() );
          written+=cw_query.size();

          // Return to IDLE
          reader_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 blocks
            reader_state->decoder_status = DECODER_DECODE_EPC;
            reader_state->gate_status    = GATE_SEEK_EPC;

            gen_ack_bits(in);
          
            // Send FrameSync
            memcpy(&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 IDLE
          break;

        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 blocks
          reader_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 IDLE
          break;
      
        case SEND_QUERY_ADJUST:
          GR_LOG_INFO(d_debug_logger, "SEND QUERY_ADJUST");
          // Controls the other two blocks
          reader_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 IDLE
          break;

        default:
          // IDLE
          break;
      }
      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的构造过程。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值