summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <tom@trondeau.com>2014-05-15 12:04:41 -0400
committerTom Rondeau <tom@trondeau.com>2014-05-17 17:45:16 -0400
commit0e28a39e8e821f5bdd721b783ce939d480266c08 (patch)
tree0230cc44af74fac9e8f26e226a044a292c0c09c9
parent2e26269d32a357688f6fea652137d9a1900c3a29 (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)
-rw-r--r--gr-digital/grc/digital_correlate_access_code_xx_ts.xml17
-rw-r--r--gr-digital/include/gnuradio/digital/correlate_access_code_ff_ts.h36
-rw-r--r--gr-digital/lib/correlate_access_code_ff_ts_impl.cc191
-rw-r--r--gr-digital/lib/correlate_access_code_ff_ts_impl.h30
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 */