diff options
author | Tom Rondeau <tom@trondeau.com> | 2014-05-15 12:04:41 -0400 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2014-05-17 17:45:16 -0400 |
commit | 0e28a39e8e821f5bdd721b783ce939d480266c08 (patch) | |
tree | 0230cc44af74fac9e8f26e226a044a292c0c09c9 | |
parent | 2e26269d32a357688f6fea652137d9a1900c3a29 (diff) |
digital: modified tagged stream correlate access code.
Decodes the header of a packet to get the frame length (in bytes). Uses this, fec rate, and fec extra parameter to set the tag stream output size in bits (or soft decision floats)
4 files changed, 216 insertions, 58 deletions
diff --git a/gr-digital/grc/digital_correlate_access_code_xx_ts.xml b/gr-digital/grc/digital_correlate_access_code_xx_ts.xml index 5b6dda0e75..547bbb76a1 100644 --- a/gr-digital/grc/digital_correlate_access_code_xx_ts.xml +++ b/gr-digital/grc/digital_correlate_access_code_xx_ts.xml @@ -8,7 +8,8 @@ <name>Correlate Access Code - Tag Stream</name> <key>digital_correlate_access_code_xx_ts</key> <import>from gnuradio import digital</import> - <make>digital.correlate_access_code_$(type.fcn)_ts($access_code, $threshold, $tagname)</make> + <make>digital.correlate_access_code_$(type.fcn)_ts($access_code, + $threshold, $tagname, $fec_rate, $fec_extra)</make> <param> <name>IO Type</name> @@ -45,6 +46,20 @@ <type>string</type> </param> + <param> + <name>FEC Rate</name> + <key>fec_rate</key> + <value>1</value> + <type>float</type> + </param> + + <param> + <name>FEC Extras</name> + <key>fec_extra</key> + <value>0</value> + <type>int</type> + </param> + <sink> <name>in</name> <type>$type</type> diff --git a/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h b/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h index d7ba6533eb..5d05c890d0 100644 --- a/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h +++ b/gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h @@ -35,12 +35,25 @@ namespace gr { * \ingroup packet_operators_blk * * \details - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: unaltered stream of bits (plus tags) + * input: stream of floats (generally, soft decisions) + * output: unaltered stream of floats in a tagged stream * - * This block annotates the input stream with tags. The tags have - * key name [tag_name], specified in the constructor. Used for - * searching an input data stream for preambles, etc. + * This block searches for the given access code by slicing the + * soft decision symbol inputs. Once found, it expects the + * following 32 samples to contain a header that includes the + * frame length. It decodes the header to get the frame length in + * order to set up the the tagged stream key information. + * + * If the block is given a \p fec_rate and/or \p fec_extra, this + * information is used to adjust the tagged stream information + * based on the follow-on FEC decoding. The header provides + * information about the uncoded frame size (in bytes), so the + * actual frame length based on the FEC code used will be: + * + * pkt_len = fec_rate*8*frame_size + fec_extra + * + * The output of this block is appropriate for use with tagged + * stream blocks. */ class DIGITAL_API correlate_access_code_ff_ts : virtual public block { @@ -53,16 +66,27 @@ namespace gr { * e.g., "010101010111000100" * \param threshold maximum number of bits that may be wrong * \param tag_name key of the tag inserted into the tag stream + * \param fec_rate Rate of the FEC used to adjust the frame length info + * \param fec_extra Any extra samples added by the FEC + * (e.g., the 2(K-1) tail used in the terminated CC codes). */ static sptr make(const std::string &access_code, int threshold, - const std::string &tag_name); + const std::string &tag_name, + float fec_rate=1, + int fec_extra=0); /*! * \param access_code is represented with 1 byte per bit, * e.g., "010101010111000100" */ virtual bool set_access_code(const std::string &access_code) = 0; + virtual void set_fec_rate(float rate) = 0; + virtual void set_fec_extra(int extra) = 0; + + virtual unsigned long long access_code() const = 0; + virtual float fec_rate() const = 0; + virtual int fec_extra() const = 0; }; } /* namespace digital */ diff --git a/gr-digital/lib/correlate_access_code_ff_ts_impl.cc b/gr-digital/lib/correlate_access_code_ff_ts_impl.cc index e06273042c..bdba736ff9 100644 --- a/gr-digital/lib/correlate_access_code_ff_ts_impl.cc +++ b/gr-digital/lib/correlate_access_code_ff_ts_impl.cc @@ -39,17 +39,20 @@ namespace gr { correlate_access_code_ff_ts::sptr correlate_access_code_ff_ts::make(const std::string &access_code, - int threshold, - const std::string &tag_name) + int threshold, + const std::string &tag_name, + float fec_rate, int fec_extra) { return gnuradio::get_initial_sptr (new correlate_access_code_ff_ts_impl(access_code, - threshold, tag_name)); + threshold, tag_name, + fec_rate, fec_extra)); } correlate_access_code_ff_ts_impl::correlate_access_code_ff_ts_impl( - const std::string &access_code, int threshold, const std::string &tag_name) + const std::string &access_code, int threshold, const std::string &tag_name, + float fec_rate, int fec_extra) : block("correlate_access_code_ff_ts", io_signature::make(1, 1, sizeof(float)), io_signature::make(1, 1, sizeof(float))), @@ -67,10 +70,14 @@ namespace gr { d_me = pmt::string_to_symbol(str.str()); d_key = pmt::string_to_symbol(tag_name); - // READ IN AS ARGS; MAKE SETTERS/GETTERS - d_pkt_key = pmt::string_to_symbol("pkt_len"); - d_pkt_len = 2*120*8 + 12 + 0; + d_state = STATE_SYNC_SEARCH; + d_pkt_len = 0; d_pkt_count = 0; + d_hdr_reg = 0; + d_hdr_count = 0; + + set_fec_rate(fec_rate); + set_fec_extra(fec_extra); } correlate_access_code_ff_ts_impl::~correlate_access_code_ff_ts_impl() @@ -78,8 +85,7 @@ namespace gr { } bool - correlate_access_code_ff_ts_impl::set_access_code( - const std::string &access_code) + correlate_access_code_ff_ts_impl::set_access_code(const std::string &access_code) { d_len = access_code.length(); // # of bytes in string if(d_len > 64) @@ -100,6 +106,77 @@ namespace gr { return true; } + void + correlate_access_code_ff_ts_impl::set_fec_rate(float rate) + { + if(rate <= 0) { + throw std::runtime_error("correlate_access_code_ff_ts: FEC rate must be > 0"); + } + d_fec_rate = rate; + } + + void + correlate_access_code_ff_ts_impl::set_fec_extra(int extra) + { + if(extra < 0) { + throw std::runtime_error("correlate_access_code_ff_ts: FEC extra bits must be >= 0"); + } + d_fec_extra = extra; + } + + unsigned long long + correlate_access_code_ff_ts_impl::access_code() const + { + return d_access_code; + } + + float + correlate_access_code_ff_ts_impl::fec_rate() const + { + return d_fec_rate; + } + + int + correlate_access_code_ff_ts_impl::fec_extra() const + { + return d_fec_extra; + } + + inline void + correlate_access_code_ff_ts_impl::enter_search() + { + d_state = STATE_SYNC_SEARCH; + } + + inline void + correlate_access_code_ff_ts_impl::enter_have_sync() + { + d_state = STATE_HAVE_SYNC; + d_hdr_reg = 0; + d_hdr_count = 0; + } + + inline void + correlate_access_code_ff_ts_impl::enter_have_header(int payload_len) + { + d_state = STATE_HAVE_HEADER; + d_pkt_len = d_fec_rate*8*payload_len + d_fec_extra; + d_pkt_count = 0; + } + + bool + correlate_access_code_ff_ts_impl::header_ok() + { + // confirm that two copies of header info are identical + return ((d_hdr_reg >> 16) ^ (d_hdr_reg & 0xffff)) == 0; + } + + int + correlate_access_code_ff_ts_impl::header_payload() + { + return (d_hdr_reg >> 16) & 0x0fff; + } + int correlate_access_code_ff_ts_impl::general_work(int noutput_items, gr_vector_int &ninput_items, @@ -113,57 +190,75 @@ namespace gr { int nprod = 0; - for(int i = 0; i < noutput_items; i++) { - if(d_pkt_count == 0) { - // compute hamming distance between desired access code and current data - uint64_t wrong_bits = 0; - uint64_t nwrong = d_threshold+1; - - wrong_bits = (d_data_reg ^ d_access_code) & d_mask; - volk_64u_popcnt(&nwrong, wrong_bits); - - // shift in new data - d_data_reg = (d_data_reg << 1) | (gr::branchless_binary_slicer(in[i]) & 0x1); - if(nwrong <= d_threshold) { - if(VERBOSE) - std::cerr << "writing tag at sample " << abs_out_sample_cnt + i << std::endl; - add_item_tag(0, // stream ID - abs_out_sample_cnt + nprod, // sample - d_key, // frame info - pmt::from_long(nwrong), // data (number wrong) - d_me); // block src id + int count = 0; + while(count < noutput_items) { + switch(d_state) { + case STATE_SYNC_SEARCH: // Look for the access code correlation - // MAKE A TAG OUT OF THIS AND UPDATE OFFSET - add_item_tag(0, // stream ID - abs_out_sample_cnt + nprod, // sample - d_pkt_key, // length key - pmt::from_long(d_pkt_len), // length data - d_me); // block src id - d_pkt_count = d_pkt_len; - d_data_reg = 0; + while(count < noutput_items) { + // shift in new data + d_data_reg = (d_data_reg << 1) | (gr::branchless_binary_slicer(in[count++]) & 0x1); + + // compute hamming distance between desired access code and current data + uint64_t wrong_bits = 0; + uint64_t nwrong = d_threshold+1; + + wrong_bits = (d_data_reg ^ d_access_code) & d_mask; + volk_64u_popcnt(&nwrong, wrong_bits); + + if(nwrong <= d_threshold) { + enter_have_sync(); + break; + } } - } + break; + + case STATE_HAVE_SYNC: + while(count < noutput_items) { // Shift bits one at a time into header + d_hdr_reg = (d_hdr_reg << 1) | (gr::branchless_binary_slicer(in[count++]) & 0x1); + d_hdr_count++; - if(d_pkt_count > 0) { - out[nprod] = in[i]; - d_pkt_count--; - nprod++; + if(d_hdr_count == 32) { + // we have a full header, check to see if it has been received properly + if(header_ok()) { + int payload_len = header_payload(); + enter_have_header(payload_len); + } + else { + enter_search(); // bad header + } + break; + } + } + break; + case STATE_HAVE_HEADER: if(d_pkt_count == 0) { - add_item_tag(0, - abs_out_sample_cnt + i, - pmt::intern("STOP"), - pmt::from_long(abs_out_sample_cnt + nprod), - d_me); + // MAKE A TAG OUT OF THIS AND UPDATE OFFSET + add_item_tag(0, // stream ID + abs_out_sample_cnt + nprod, // sample + d_key, // length key + pmt::from_long(d_pkt_len), // length data + d_me); // block src id } + + while(count < noutput_items) { + if(d_pkt_count < d_pkt_len) { + out[nprod++] = in[count++]; + d_pkt_count++; + } + else { + enter_search(); + break; + } + } + break; } } - //std::cerr << "Producing data: " << nprod << std::endl; consume_each(noutput_items); return nprod; } } /* namespace digital */ } /* namespace gr */ - diff --git a/gr-digital/lib/correlate_access_code_ff_ts_impl.h b/gr-digital/lib/correlate_access_code_ff_ts_impl.h index 861ade8f72..e96ab7fbe9 100644 --- a/gr-digital/lib/correlate_access_code_ff_ts_impl.h +++ b/gr-digital/lib/correlate_access_code_ff_ts_impl.h @@ -32,6 +32,10 @@ namespace gr { public correlate_access_code_ff_ts { private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + state_t d_state; + unsigned long long d_access_code; // access code to locate start of packet // access code is left justified in the word unsigned long long d_data_reg; // used to look for access_code @@ -40,14 +44,28 @@ namespace gr { unsigned int d_threshold; // how many bits may be wrong in sync vector unsigned int d_len; // the length of the access code - pmt::pmt_t d_key, d_me; //d_key is the tag name, d_me is the block name + unique ID - pmt::pmt_t d_pkt_key; + unsigned long long d_hdr_reg; // used to look for header + int d_hdr_count; + + pmt::pmt_t d_key, d_me; // d_key is the tag name, d_me is the block name + unique ID int d_pkt_len, d_pkt_count; + float d_fec_rate; + int d_fec_extra; + + void enter_search(); + void enter_have_sync(); + void enter_have_header(int payload_len); + + bool header_ok(); + int header_payload(); + public: correlate_access_code_ff_ts_impl(const std::string &access_code, int threshold, - const std::string &tag_name); + const std::string &tag_name, + float fec_rate=1, + int fec_extra=0); ~correlate_access_code_ff_ts_impl(); int general_work(int noutput_items, @@ -56,6 +74,12 @@ namespace gr { gr_vector_void_star &output_items); bool set_access_code(const std::string &access_code); + void set_fec_rate(float rate); + void set_fec_extra(int extra); + + unsigned long long access_code() const; + float fec_rate() const; + int fec_extra() const; }; } /* namespace digital */ |