summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnathan Corgan <johnathan@corganlabs.com>2013-03-15 09:57:31 -0700
committerJohnathan Corgan <johnathan@corganlabs.com>2013-03-15 09:57:31 -0700
commite965a5bb209ad46a509ccd21f393667fd69d95f9 (patch)
tree40d683ef8f80980f12eac6cfe7f3423c49b45f87
parent2bf9c4cb4b0b426690f353fc1662a13e70c0d5e0 (diff)
parent27990ca9e236931e39a830e48f0a1efe13ec085f (diff)
Merge branch 'ofdm-master' into ofdm-next
Added fixups for next branch changes Conflicts: CMakeLists.txt gnuradio-core/src/lib/io/gr_message_sink.cc gnuradio-core/src/lib/io/gr_message_sink.h gnuradio-core/src/lib/io/gr_message_sink.i gnuradio-core/src/lib/io/gr_message_source.cc gnuradio-core/src/lib/io/gr_message_source.h gnuradio-core/src/lib/io/gr_message_source.i gr-blocks/CMakeLists.txt gr-digital/CMakeLists.txt gr-digital/grc/digital_block_tree.xml gr-digital/include/digital/CMakeLists.txt gr-digital/include/digital_ofdm_cyclic_prefixer.h gr-digital/lib/CMakeLists.txt gr-digital/lib/digital_ofdm_cyclic_prefixer.cc gr-digital/lib/ofdm_cyclic_prefixer_impl.h gr-digital/python/CMakeLists.txt gr-digital/swig/CMakeLists.txt gr-digital/swig/digital_swig.i
-rw-r--r--CMakeLists.txt1
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t11
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t2
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t1
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t67
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t11
-rw-r--r--gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t6
-rw-r--r--gnuradio-core/src/lib/runtime/CMakeLists.txt3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tagged_stream_block.cc144
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tagged_stream_block.h138
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tagged_stream_block.i30
-rw-r--r--gnuradio-core/src/lib/runtime/runtime.i2
-rw-r--r--gnuradio-core/src/lib/swig/gnuradio.i5
-rw-r--r--gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h1
-rw-r--r--gr-analog/grc/analog_block_tree.xml1
-rw-r--r--gr-analog/grc/analog_plateau_detector_fb.xml26
-rw-r--r--gr-analog/include/analog/CMakeLists.txt3
-rw-r--r--gr-analog/include/analog/plateau_detector_fb.h71
-rw-r--r--gr-analog/lib/CMakeLists.txt1
-rw-r--r--gr-analog/lib/plateau_detector_fb_impl.cc82
-rw-r--r--gr-analog/lib/plateau_detector_fb_impl.h50
-rw-r--r--gr-analog/python/CMakeLists.txt1
-rwxr-xr-xgr-analog/python/qa_plateau_detector_fb.py46
-rw-r--r--gr-analog/swig/analog_swig.i3
-rw-r--r--gr-blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml1
-rw-r--r--gr-blocks/grc/blocks_repack_bits_bb.xml46
-rw-r--r--gr-blocks/grc/blocks_tagged_stream_mux.xml65
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt6
-rw-r--r--gr-blocks/include/blocks/message_sink.h5
-rw-r--r--gr-blocks/include/blocks/message_source.h2
-rw-r--r--gr-blocks/include/blocks/repack_bits_bb.h65
-rw-r--r--gr-blocks/include/blocks/tagged_stream_mux.h61
-rw-r--r--gr-blocks/lib/CMakeLists.txt6
-rw-r--r--gr-blocks/lib/message_sink_impl.cc79
-rw-r--r--gr-blocks/lib/message_sink_impl.h6
-rw-r--r--gr-blocks/lib/message_source_impl.cc100
-rw-r--r--gr-blocks/lib/message_source_impl.h6
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.cc123
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.h58
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.cc93
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.h54
-rw-r--r--gr-blocks/python/qa_message_tags.py27
-rwxr-xr-xgr-blocks/python/qa_repack_bits_bb.py127
-rwxr-xr-xgr-blocks/python/qa_tagged_stream_mux.py111
-rw-r--r--gr-blocks/swig/blocks_swig.i12
-rw-r--r--gr-digital/CMakeLists.txt3
-rw-r--r--gr-digital/examples/ofdm/ofdm_bugsquatch.py22
-rw-r--r--gr-digital/examples/ofdm/rx_ofdm.grc1092
-rw-r--r--gr-digital/examples/ofdm/tx_ofdm.grc1143
-rw-r--r--gr-digital/grc/CMakeLists.txt4
-rw-r--r--gr-digital/grc/digital_block_tree.xml40
-rw-r--r--gr-digital/grc/digital_crc32_bb.xml33
-rw-r--r--gr-digital/grc/digital_header_payload_demux.xml94
-rw-r--r--gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml45
-rw-r--r--gr-digital/grc/digital_ofdm_chanest_vcvc.xml61
-rw-r--r--gr-digital/grc/digital_ofdm_cyclic_prefixer.xml20
-rw-r--r--gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml45
-rw-r--r--gr-digital/grc/digital_ofdm_mod2.xml65
-rw-r--r--gr-digital/grc/digital_ofdm_serializer_vcc.xml50
-rw-r--r--gr-digital/grc/digital_ofdm_sync_sc_cfb.xml29
-rw-r--r--gr-digital/grc/digital_packet_headergenerator_bb.xml19
-rw-r--r--gr-digital/grc/digital_packet_headergenerator_bb_default.xml26
-rw-r--r--gr-digital/grc/digital_packet_headerparser_b.xml19
-rw-r--r--gr-digital/grc/digital_packet_headerparser_b_default.xml26
-rw-r--r--gr-digital/grc/digital_scale_tags.xml31
-rw-r--r--gr-digital/include/CMakeLists.txt34
-rw-r--r--gr-digital/include/digital/CMakeLists.txt33
-rw-r--r--gr-digital/include/digital/constellation.h2
-rw-r--r--gr-digital/include/digital/header_payload_demux.h90
-rw-r--r--gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h63
-rw-r--r--gr-digital/include/digital/ofdm_serializer_vcc.h91
-rw-r--r--gr-digital/include/digital/packet_header_default.h101
-rw-r--r--gr-digital/include/digital/packet_header_ofdm.h83
-rw-r--r--gr-digital/include/digital/packet_headergenerator_bb.h57
-rw-r--r--gr-digital/include/digital/packet_headerparser_b.h65
-rw-r--r--gr-digital/include/digital/scale_tags.h58
-rw-r--r--gr-digital/include/digital/tagged_stream_check.h55
-rw-r--r--gr-digital/include/digital/ts_insert_zeros_cc.h55
-rw-r--r--gr-digital/include/digital_crc32_bb.h67
-rw-r--r--gr-digital/include/digital_ofdm_carrier_allocator_cvc.h116
-rw-r--r--gr-digital/include/digital_ofdm_chanest_vcvc.h133
-rw-r--r--gr-digital/include/digital_ofdm_cyclic_prefixer.h95
-rw-r--r--gr-digital/include/digital_ofdm_equalizer_base.h102
-rw-r--r--gr-digital/include/digital_ofdm_equalizer_simpledfe.h126
-rw-r--r--gr-digital/include/digital_ofdm_equalizer_static.h97
-rw-r--r--gr-digital/include/digital_ofdm_sync_sc_cfb.h79
-rw-r--r--gr-digital/lib/CMakeLists.txt44
-rw-r--r--gr-digital/lib/digital_crc32_bb.cc102
-rw-r--r--gr-digital/lib/digital_ofdm_carrier_allocator_cvc.cc156
-rw-r--r--gr-digital/lib/digital_ofdm_chanest_vcvc.cc281
-rw-r--r--gr-digital/lib/digital_ofdm_cyclic_prefixer.cc162
-rw-r--r--gr-digital/lib/digital_ofdm_equalizer_base.cc116
-rw-r--r--gr-digital/lib/digital_ofdm_equalizer_simpledfe.cc101
-rw-r--r--gr-digital/lib/digital_ofdm_equalizer_static.cc90
-rw-r--r--gr-digital/lib/digital_ofdm_sync_sc_cfb.cc109
-rw-r--r--gr-digital/lib/header_payload_demux_impl.cc292
-rw-r--r--gr-digital/lib/header_payload_demux_impl.h85
-rw-r--r--gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc89
-rw-r--r--gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h57
-rw-r--r--gr-digital/lib/ofdm_serializer_vcc_impl.cc205
-rw-r--r--gr-digital/lib/ofdm_serializer_vcc_impl.h69
-rw-r--r--gr-digital/lib/packet_header_default.cc128
-rw-r--r--gr-digital/lib/packet_header_ofdm.cc115
-rw-r--r--gr-digital/lib/packet_headergenerator_bb_impl.cc90
-rw-r--r--gr-digital/lib/packet_headergenerator_bb_impl.h55
-rw-r--r--gr-digital/lib/packet_headerparser_b_impl.cc90
-rw-r--r--gr-digital/lib/packet_headerparser_b_impl.h48
-rw-r--r--gr-digital/lib/scale_tags_impl.cc84
-rw-r--r--gr-digital/lib/scale_tags_impl.h51
-rw-r--r--gr-digital/lib/tagged_stream_check_impl.cc112
-rw-r--r--gr-digital/lib/tagged_stream_check_impl.h53
-rw-r--r--gr-digital/lib/ts_insert_zeros_cc_impl.cc130
-rw-r--r--gr-digital/lib/ts_insert_zeros_cc_impl.h54
-rw-r--r--gr-digital/python/CMakeLists.txt7
-rw-r--r--gr-digital/python/__init__.py2
-rw-r--r--gr-digital/python/fftshift.py31
-rw-r--r--gr-digital/python/ofdm_txrx.py268
-rwxr-xr-xgr-digital/python/qa_crc32_bb.py150
-rwxr-xr-xgr-digital/python/qa_header_payload_demux.py78
-rwxr-xr-xgr-digital/python/qa_ofdm_carrier_allocator_cvc.py154
-rwxr-xr-xgr-digital/python/qa_ofdm_chanest_vcvc.py284
-rwxr-xr-xgr-digital/python/qa_ofdm_cyclic_prefixer.py95
-rwxr-xr-xgr-digital/python/qa_ofdm_frame_equalizer_vcvc.py161
-rwxr-xr-xgr-digital/python/qa_ofdm_serializer_vcc.py214
-rwxr-xr-xgr-digital/python/qa_ofdm_sync_sc_cfb.py203
-rwxr-xr-xgr-digital/python/qa_ofdm_txrx.py58
-rwxr-xr-xgr-digital/python/qa_packet_headergenerator_bb.py157
-rwxr-xr-xgr-digital/python/qa_packet_headerparser_b.py72
-rwxr-xr-xgr-digital/python/qa_scale_tags.py57
-rw-r--r--gr-digital/python/qa_ts_insert_zeros.py78
-rw-r--r--gr-digital/python/utils/tagged_streams.py112
-rw-r--r--gr-digital/swig/CMakeLists.txt9
-rw-r--r--gr-digital/swig/digital_crc32_bb.i32
-rw-r--r--gr-digital/swig/digital_ofdm_carrier_allocator_cvc.i37
-rw-r--r--gr-digital/swig/digital_ofdm_chanest_vcvc.i40
-rw-r--r--gr-digital/swig/digital_ofdm_cyclic_prefixer.i35
-rw-r--r--gr-digital/swig/digital_ofdm_equalizer_base.i64
-rw-r--r--gr-digital/swig/digital_ofdm_equalizer_simpledfe.i58
-rw-r--r--gr-digital/swig/digital_ofdm_equalizer_static.i55
-rw-r--r--gr-digital/swig/digital_ofdm_sync_sc_cfb.i33
-rw-r--r--gr-digital/swig/digital_swig.i105
-rw-r--r--gr-digital/swig/packet_header.i34
-rw-r--r--grc/blocks/gr_vector_source_x.xml11
144 files changed, 11746 insertions, 145 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64d9d0fb4d..9caa87f2f9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -275,7 +275,6 @@ add_subdirectory(grc)
add_subdirectory(gr-fec)
add_subdirectory(gr-fft)
add_subdirectory(gr-filter)
-#add_subdirectory(gr-ctrlport)
add_subdirectory(gr-analog)
add_subdirectory(gr-digital)
add_subdirectory(gr-atsc)
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t
index a9e3a0a3ea..2b8207c027 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t
@@ -28,6 +28,7 @@
#include <@NAME@.h>
#include <algorithm>
#include <gr_io_signature.h>
+#include <iostream>
@NAME@::@NAME@ (int vlen)
@@ -46,7 +47,9 @@ int
@TYPE@ *iptr = (@TYPE@ *) input_items[0];
for (int i = 0; i < noutput_items * d_vlen; i++)
d_data.push_back (iptr[i]);
-
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items);
+ d_tags.insert(d_tags.end(), tags.begin(), tags.end());
return noutput_items;
}
@@ -62,3 +65,9 @@ std::vector<@TYPE@>
{
return d_data;
}
+
+std::vector<gr_tag_t>
+@NAME@::tags () const
+{
+ return d_tags;
+}
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t
index b9126dc7b2..b7de1d101c 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t
@@ -43,6 +43,7 @@ gr_make_@BASE_NAME@ (int vlen = 1);
class GR_CORE_API @NAME@ : public gr_sync_block {
friend GR_CORE_API @NAME@_sptr gr_make_@BASE_NAME@ (int vlen);
std::vector<@TYPE@> d_data;
+ std::vector<gr_tag_t> d_tags;
int d_vlen;
@NAME@ (int vlen);
@@ -54,6 +55,7 @@ class GR_CORE_API @NAME@ : public gr_sync_block {
void reset() {d_data.clear();}
void clear() {reset(); } // deprecated
std::vector<@TYPE@> data () const;
+ std::vector<gr_tag_t> tags () const;
};
#endif
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t
index d4a9409114..ee0ebf378b 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t
@@ -35,5 +35,6 @@ class @NAME@ : public gr_sync_block {
void clear(); // deprecated
void reset();
std::vector<@TYPE@> data () const;
+ std::vector<gr_tag_t> tags () const;
};
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t
index 9f68f9cf14..19272ee24b 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t
@@ -30,20 +30,39 @@
#include <gr_io_signature.h>
#include <stdexcept>
-
-@NAME@::@NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen)
+@NAME@::@NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen, const std::vector<gr_tag_t> &tags)
: gr_sync_block ("@BASE_NAME@",
gr_make_io_signature (0, 0, 0),
gr_make_io_signature (1, 1, sizeof (@TYPE@) * vlen)),
d_data (data),
d_repeat (repeat),
d_offset (0),
- d_vlen (vlen)
+ d_vlen (vlen),
+ d_tags (tags),
+ d_tagpos (0)
{
+ if (tags.size() == 0) {
+ d_settags = 0;
+ } else {
+ d_settags = 1;
+ set_output_multiple(data.size() / vlen);
+ }
if ((data.size() % vlen) != 0)
throw std::invalid_argument("data length must be a multiple of vlen");
}
+void
+@NAME@::set_data (const std::vector<@TYPE@> &data, const std::vector<gr_tag_t> &tags){
+ d_data = data;
+ d_tags = tags;
+ rewind();
+ if (tags.size() == 0) {
+ d_settags = false;
+ } else {
+ d_settags = true;
+ }
+}
+
int
@NAME@::work (int noutput_items,
gr_vector_const_void_star &input_items,
@@ -54,36 +73,52 @@ int
if (d_repeat){
unsigned int size = d_data.size ();
unsigned int offset = d_offset;
-
if (size == 0)
return -1;
- for (int i = 0; i < noutput_items*d_vlen; i++){
- optr[i] = d_data[offset++];
- if (offset >= size)
- offset = 0;
+ if (d_settags) {
+ int n_outputitems_per_vector = d_data.size() / d_vlen;
+ for (int i = 0; i < noutput_items; i += n_outputitems_per_vector) {
+ // FIXME do proper vector copy
+ memcpy((void *) optr, (const void *) &d_data[0], size * sizeof (@TYPE@));
+ optr += size;
+ for (unsigned t = 0; t < d_tags.size(); t++) {
+ add_item_tag(0, nitems_written(0)+i+d_tags[t].offset, d_tags[t].key, d_tags[t].value);
+ }
+ }
+ } else {
+ for (int i = 0; i < noutput_items*d_vlen; i++){
+ optr[i] = d_data[offset++];
+ if (offset >= size) {
+ offset = 0;
+ }
+ }
}
+
+
d_offset = offset;
return noutput_items;
- }
-
- else {
+ } else {
if (d_offset >= d_data.size ())
return -1; // Done!
unsigned n = std::min ((unsigned) d_data.size () - d_offset,
- (unsigned) noutput_items*d_vlen);
- for (unsigned i = 0; i < n; i++)
+ (unsigned) noutput_items*d_vlen);
+ for (unsigned i = 0; i < n; i++) {
optr[i] = d_data[d_offset + i];
-
+ }
+ for (unsigned t = 0; t < d_tags.size(); t++) {
+ if ((d_tags[t].offset >= d_offset) && (d_tags[t].offset < d_offset+n))
+ add_item_tag(0, d_tags[t].offset, d_tags[t].key, d_tags[t].value);
+ }
d_offset += n;
return n/d_vlen;
}
}
@NAME@_sptr
-gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen)
+gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen, const std::vector<gr_tag_t> &tags)
{
- return gnuradio::get_initial_sptr(new @NAME@ (data, repeat, vlen));
+ return gnuradio::get_initial_sptr(new @NAME@ (data, repeat, vlen, tags));
}
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t
index fe02c1346f..592467778a 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t
@@ -38,24 +38,27 @@ typedef boost::shared_ptr<@NAME@> @NAME@_sptr;
class @NAME@ : public gr_sync_block {
friend GR_CORE_API @NAME@_sptr
- gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen);
+ gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen, const std::vector<gr_tag_t> &tags);
std::vector<@TYPE@> d_data;
bool d_repeat;
unsigned int d_offset;
int d_vlen;
+ bool d_settags;
+ std::vector<gr_tag_t> d_tags;
+ unsigned int d_tagpos;
- @NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen);
+ @NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen, const std::vector<gr_tag_t> &tags);
public:
void rewind() {d_offset=0;}
virtual int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
- void set_data(const std::vector<@TYPE@> &data){ d_data = data; rewind(); }
+ void set_data(const std::vector<@TYPE@> &data, const std::vector<gr_tag_t> &tags);
};
GR_CORE_API @NAME@_sptr
-gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1);
+gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1, const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>());
#endif
diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t
index 4986c68a35..c661ca6d3f 100644
--- a/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t
+++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t
@@ -25,13 +25,13 @@
GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@);
@NAME@_sptr
-gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1)
+gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1, const std::vector<gr_tag_t> &tags=std::vector<gr_tag_t>())
throw(std::invalid_argument);
class @NAME@ : public gr_sync_block {
public:
void rewind();
- void set_data(const std::vector<@TYPE@> &data);
+ void set_data(const std::vector<@TYPE@> &data, const std::vector<gr_tag_t> &tags);
private:
- @NAME@ (const std::vector<@TYPE@> &data, int vlen);
+ @NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen, const std::vector<gr_tag_t> &tags);
};
diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt
index f6fce8fb16..a322d1b998 100644
--- a/gnuradio-core/src/lib/runtime/CMakeLists.txt
+++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt
@@ -79,6 +79,7 @@ list(APPEND gnuradio_core_sources
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_sys_paths.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_tagged_stream_block.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.cc
${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.cc
@@ -160,6 +161,7 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_tagged_stream_block.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.h
${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.h
@@ -218,6 +220,7 @@ install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.i
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.i
${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.i
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr_tagged_stream_block.i
${CMAKE_CURRENT_SOURCE_DIR}/gr_tags.i
${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.i
${CMAKE_CURRENT_SOURCE_DIR}/runtime.i
diff --git a/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.cc b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.cc
new file mode 100644
index 0000000000..32b6a09033
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.cc
@@ -0,0 +1,144 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_tagged_stream_block.h>
+
+gr_tagged_stream_block::gr_tagged_stream_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ const std::string &length_tag_key)
+ : gr_block(name, input_signature, output_signature),
+ d_length_tag_key(pmt::string_to_symbol(length_tag_key)),
+ d_n_input_items_reqd(input_signature->min_streams(), 0),
+ d_length_tag_key_str(length_tag_key)
+{
+}
+
+
+// This is evil hackery: We trick the scheduler into creating the right number of input items
+void
+gr_tagged_stream_block::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned i = 0; i < ninputs; i++) {
+ if (i < d_n_input_items_reqd.size() && d_n_input_items_reqd[i] != 0) {
+ ninput_items_required[i] = d_n_input_items_reqd[i];
+ } else {
+ // If there's no item, there's no tag--so there must at least be one!
+ ninput_items_required[i] = std::max(1, (int) std::floor((double) noutput_items / relative_rate() + 0.5));
+ }
+ }
+}
+
+
+void
+gr_tagged_stream_block::parse_length_tags(
+ const std::vector<std::vector<gr_tag_t> > &tags,
+ gr_vector_int &n_input_items_reqd
+){
+ for (unsigned i = 0; i < tags.size(); i++) {
+ for (unsigned k = 0; k < tags[i].size(); k++) {
+ if (tags[i][k].key == d_length_tag_key) {
+ n_input_items_reqd[i] = pmt::to_long(tags[i][k].value);
+ remove_item_tag(i, tags[i][k]);
+ }
+ }
+ }
+}
+
+
+int
+gr_tagged_stream_block::calculate_output_stream_length(const gr_vector_int &ninput_items)
+{
+ int noutput_items = *std::max_element(ninput_items.begin(), ninput_items.end());
+ return (int) std::floor(relative_rate() * noutput_items + 0.5);
+}
+
+
+void
+gr_tagged_stream_block::update_length_tags(int n_produced, int n_ports)
+{
+ for (int i = 0; i < n_ports; i++) {
+ add_item_tag(i, nitems_written(i),
+ d_length_tag_key,
+ pmt::from_long(n_produced)
+ );
+ }
+ return;
+}
+
+
+int
+gr_tagged_stream_block::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ if (d_length_tag_key_str.empty()) {
+ return work(noutput_items, ninput_items, input_items, output_items);
+ }
+
+ if (d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call
+ std::vector<std::vector<gr_tag_t> > tags(input_items.size(), std::vector<gr_tag_t>());
+ for (unsigned i = 0; i < input_items.size(); i++) {
+ get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1);
+ }
+ d_n_input_items_reqd.assign(input_items.size(), -1);
+ parse_length_tags(tags, d_n_input_items_reqd);
+ }
+ for (unsigned i = 0; i < input_items.size(); i++) {
+ if (d_n_input_items_reqd[i] == -1) {
+ throw std::runtime_error("Missing length tag.");
+ }
+ if (d_n_input_items_reqd[i] > ninput_items[i]) {
+ return 0;
+ }
+ }
+
+ int min_output_size = calculate_output_stream_length(d_n_input_items_reqd);
+ if (noutput_items < min_output_size) {
+ set_min_noutput_items(min_output_size);
+ return 0;
+ }
+ set_min_noutput_items(1);
+
+ // WORK CALLED HERE //
+ int n_produced = work(noutput_items, d_n_input_items_reqd, input_items, output_items);
+ //////////////////////
+
+ if (n_produced == WORK_DONE) {
+ return n_produced;
+ }
+ for (int i = 0; i < (int) d_n_input_items_reqd.size(); i++) {
+ consume(i, d_n_input_items_reqd[i]);
+ }
+ update_length_tags(n_produced, output_items.size());
+
+ d_n_input_items_reqd.assign(input_items.size(), 0);
+
+ return n_produced;
+}
+
diff --git a/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.h b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.h
new file mode 100644
index 0000000000..a9d396c06f
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.h
@@ -0,0 +1,138 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_TAGGED_STREAM_BLOCK_H
+#define INCLUDED_GR_TAGGED_STREAM_BLOCK_H
+
+#include <gr_core_api.h>
+#include <gr_block.h>
+
+/*!
+ * \brief Block that operates on PDUs in form of tagged streams
+ * \ingroup base_blk
+ *
+ * Override work to provide the signal processing implementation.
+ */
+class GR_CORE_API gr_tagged_stream_block : public gr_block
+{
+ private:
+ pmt::pmt_t d_length_tag_key; //! This is the key for the tag that stores the PDU length
+ gr_vector_int d_n_input_items_reqd; //! How many input items do I need to process the next PDU?
+
+ protected:
+ std::string d_length_tag_key_str;
+ gr_tagged_stream_block (void){} //allows pure virtual interface sub-classes
+ gr_tagged_stream_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ const std::string &length_tag_key);
+
+ /* \brief Parse all tags on the first sample of a PDU, return the number of items per input
+ * and prune the length tags.
+ *
+ * In most cases, you don't need to override this, unless the number of items read
+ * is not directly coded in one single tag.
+ *
+ * Default behaviour:
+ * - Go through all input ports
+ * - On every input port, search for the tag with the key specified in \p length_tag_key
+ * - Copy that value as an int to the corresponding position in \p n_input_items_reqd
+ * - Remove the length tag.
+ *
+ * \param[in] tags All the tags found on the first item of every input port.
+ * \param[out] n_input_items_reqd Number of items which will be read from every input
+ */
+ virtual void parse_length_tags(
+ const std::vector<std::vector<gr_tag_t> > &tags,
+ gr_vector_int &n_input_items_reqd
+ );
+
+ /* \brief Calculate the number of output items.
+ *
+ * This is basically the inverse function to forecast(): Given a number of input
+ * items, it returns the maximum number of output items.
+ *
+ * You most likely need to override this function, unless your block is a sync
+ * block or integer interpolator/decimator.
+ *
+ */
+ virtual int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ /* \brief Set the new length tags on the output stream
+ *
+ * Default behaviour: Set a tag with key \p length_tag_key and
+ * the number of produced items on every output port.
+ *
+ * For anything else, override this.
+ *
+ * \param n_produced Length of the new PDU
+ * \param n_ports Number of output ports
+ */
+ virtual void update_length_tags(int n_produced, int n_ports);
+
+ public:
+
+ /* \brief Don't override this.
+ */
+ void /* final */ forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ /* - Reads the number of input items from the tags using parse_length_tags()
+ * - Checks there's enough data on the input and output buffers
+ * - If not, inform the scheduler and do nothing
+ * - Calls work() with the exact number of items per PDU
+ * - Updates the tags using update_length_tags()
+ */
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ /*!
+ * \brief Just like gr_block::general_work, but makes sure the input is valid
+ *
+ * The user must override work to define the signal processing code.
+ * Check the documentation for general_work() to see what happens here.
+ *
+ * Like gr_sync_block, this calls consume() for you (it consumes ninput_items[i]
+ * items from the i-th port).
+ *
+ * A note on tag propagation: The PDU length tags are handled by other functions,
+ * but all other tags are handled just as in any other \p gr_block. So, most likely,
+ * you either set the tag propagation policy to TPP_DONT and handle the tag
+ * propagation manually, or you propagate tags through the scheduler and don't
+ * do anything here.
+ *
+ * \param noutput_items The size of the writable output buffer
+ * \param ninput_items The exact size of the items on every input for this particular PDU.
+ * These will be consumed if a length tag key is provided!
+ * \param input_items See gr_block
+ * \param output_items See gr_block
+ */
+ virtual int work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items) = 0;
+
+};
+
+#endif /* INCLUDED_GR_TAGGED_STREAM_BLOCK_H */
+
diff --git a/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.i b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.i
new file mode 100644
index 0000000000..9fc803dca1
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tagged_stream_block.i
@@ -0,0 +1,30 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+class gr_tagged_stream_block : public gr_block
+{
+ protected:
+ gr_tagged_stream_block (const std::string &name,
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature,
+ const std::string &length_tag_key);
+};
+
diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i
index 73a816a14c..ac0092f917 100644
--- a/gnuradio-core/src/lib/runtime/runtime.i
+++ b/gnuradio-core/src/lib/runtime/runtime.i
@@ -39,6 +39,7 @@
#include <gr_sync_block.h>
#include <gr_sync_decimator.h>
#include <gr_sync_interpolator.h>
+#include <gr_tagged_stream_block.h>
#include <gr_top_block.h>
#include <gr_logger.h>
%}
@@ -67,6 +68,7 @@
%include <gr_sync_block.i>
%include <gr_sync_decimator.i>
%include <gr_sync_interpolator.i>
+%include <gr_tagged_stream_block.i>
%include <gr_top_block.i>
%include <gr_logger.i>
diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i
index 3a421ad5d6..4378e6aad2 100644
--- a/gnuradio-core/src/lib/swig/gnuradio.i
+++ b/gnuradio-core/src/lib/swig/gnuradio.i
@@ -38,6 +38,7 @@
#include <gr_types.h>
#include <stddef.h> // size_t
#include <complex>
+#include <string.h>
%}
%feature("autodoc","1");
@@ -48,6 +49,7 @@
%include <std_vector.i>
%include <stl.i>
%include <std_except.i>
+%include <std_string.i>
typedef std::complex<float> gr_complex;
typedef std::complex<double> gr_complexd;
@@ -64,7 +66,8 @@ namespace std {
%template() vector<int>;
%template() vector<float>;
%template() vector<double>;
- // %template() std::complex<float>;
+ %template() vector<std::string>;
+ %template() vector<gr_tag_t>;
%template() vector< std::complex<float> >;
%template() vector< std::vector< unsigned char > >;
diff --git a/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h b/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h
index 1994f06609..bbbabaf07b 100644
--- a/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h
+++ b/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h
@@ -40,6 +40,7 @@ class gr_msg_queue;
class gr_sync_block;
class gr_sync_decimator;
class gr_sync_interpolator;
+class gr_tagged_stream_block;
class gr_top_block;
#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */
diff --git a/gr-analog/grc/analog_block_tree.xml b/gr-analog/grc/analog_block_tree.xml
index 5d2ab6512b..1c4e46c914 100644
--- a/gr-analog/grc/analog_block_tree.xml
+++ b/gr-analog/grc/analog_block_tree.xml
@@ -58,6 +58,7 @@
<block>analog_pll_carriertracking_cc</block>
<block>analog_pll_freqdet_cf</block>
<block>analog_pll_refout_cc</block>
+ <block>analog_plateau_detector_fb</block>
</cat>
<cat>
<name>Probes</name>
diff --git a/gr-analog/grc/analog_plateau_detector_fb.xml b/gr-analog/grc/analog_plateau_detector_fb.xml
new file mode 100644
index 0000000000..f14efc97f4
--- /dev/null
+++ b/gr-analog/grc/analog_plateau_detector_fb.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<block>
+ <name>Plateau Detector</name>
+ <key>analog_plateau_detector_fb</key>
+ <import>from gnuradio import analog</import>
+ <make>analog.plateau_detector_fb($max_len, $threshold)</make>
+ <param>
+ <name>Max. plateau length</name>
+ <key>max_len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Threshold</name>
+ <key>threshold</key>
+ <value>0.9</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>real</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-analog/include/analog/CMakeLists.txt b/gr-analog/include/analog/CMakeLists.txt
index 3c18c949ab..1cbbf988f3 100644
--- a/gr-analog/include/analog/CMakeLists.txt
+++ b/gr-analog/include/analog/CMakeLists.txt
@@ -95,6 +95,7 @@ install(FILES
fmdet_cf.h
frequency_modulator_fc.h
phase_modulator_fc.h
+ plateau_detector_fb.h
pll_carriertracking_cc.h
pll_freqdet_cf.h
pll_refout_cc.h
@@ -106,7 +107,7 @@ install(FILES
quadrature_demod_cf.h
rail_ff.h
sig_source_waveform.h
- simple_squelch_cc.h
+ simple_squelch_cc.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/analog
COMPONENT "analog_devel"
)
diff --git a/gr-analog/include/analog/plateau_detector_fb.h b/gr-analog/include/analog/plateau_detector_fb.h
new file mode 100644
index 0000000000..33629bd18b
--- /dev/null
+++ b/gr-analog/include/analog/plateau_detector_fb.h
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_H
+#define INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_H
+
+#include <analog/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace analog {
+
+ /*!
+ * \brief Detects a plateau and marks the middle.
+ *
+ * Detect a plateau of a-priori known height. Input is a stream of floats,
+ * the output is a stream of bytes. Whenever a plateau is detected, the
+ * middle of that plateau is marked with a '1' on the output stream (all
+ * other samples are left at zero).
+ *
+ * You can use this in a Schmidl & Cox synchronisation algorithm to interpret
+ * the output of the normalized correlator. Just pass the length of the cyclic
+ * prefix (in samples) as the max_len parameter).
+ *
+ * Unlike the peak detectors, you must the now the absolute height of the plateau.
+ * Whenever the amplitude exceeds the given threshold, it starts assuming the
+ * presence of a plateau.
+ *
+ * An implicit hysteresis is provided by the fact that after detecting one plateau,
+ * it waits at least max_len samples before the next plateau can be detected.
+ *
+ * \ingroup analog
+ *
+ */
+ class ANALOG_API plateau_detector_fb : virtual public gr_sync_block
+ {
+ public:
+ typedef boost::shared_ptr<plateau_detector_fb> sptr;
+
+ /*!
+ * \param max_len Maximum length of the plateau
+ * \param threshold Anything above this value is considered a plateau
+ */
+ static sptr make(int max_len, float threshold=0.9);
+ };
+
+ } // namespace analog
+} // namespace gr
+
+#endif /* INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_H */
+
diff --git a/gr-analog/lib/CMakeLists.txt b/gr-analog/lib/CMakeLists.txt
index a85c90851f..53cbb00a51 100644
--- a/gr-analog/lib/CMakeLists.txt
+++ b/gr-analog/lib/CMakeLists.txt
@@ -128,6 +128,7 @@ list(APPEND analog_sources
fmdet_cf_impl.cc
frequency_modulator_fc_impl.cc
phase_modulator_fc_impl.cc
+ plateau_detector_fb_impl.cc
pll_carriertracking_cc_impl.cc
pll_freqdet_cf_impl.cc
pll_refout_cc_impl.cc
diff --git a/gr-analog/lib/plateau_detector_fb_impl.cc b/gr-analog/lib/plateau_detector_fb_impl.cc
new file mode 100644
index 0000000000..0d2890bc55
--- /dev/null
+++ b/gr-analog/lib/plateau_detector_fb_impl.cc
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "plateau_detector_fb_impl.h"
+
+namespace gr {
+ namespace analog {
+
+plateau_detector_fb::sptr
+plateau_detector_fb::make(int max_len, float threshold)
+{
+ return gnuradio::get_initial_sptr (new plateau_detector_fb_impl(max_len, threshold));
+}
+
+plateau_detector_fb_impl::plateau_detector_fb_impl(int max_len, float threshold)
+ : gr_sync_block("plateau_detector_fb",
+ gr_make_io_signature(1, 1, sizeof (float)),
+ gr_make_io_signature(1, 1, sizeof (char))),
+ d_max_len(max_len),
+ d_threshold(threshold)
+{}
+
+plateau_detector_fb_impl::~plateau_detector_fb_impl()
+{
+}
+
+int
+plateau_detector_fb_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const float *in = (const float *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+ int flank_start;
+
+ memset((void *) out, 0x00, noutput_items);
+ int i;
+ for (i = 0; i < noutput_items; i++) {
+ if (in[i] >= d_threshold) {
+ if (noutput_items-i < 2*d_max_len) { // If we can't finish, come back later
+ break;
+ }
+ flank_start = i;
+ while (i < noutput_items && in[i] >= d_threshold)
+ i++;
+ if ((i - flank_start) > 1) { // 1 Sample is not a plateau
+ out[flank_start + (i-flank_start)/2] = 1;
+ i = std::min(i+d_max_len, noutput_items-1);
+ }
+ }
+ }
+
+ return i;
+}
+
+ } /* namespace analog */
+} /* namespace gr */
+
diff --git a/gr-analog/lib/plateau_detector_fb_impl.h b/gr-analog/lib/plateau_detector_fb_impl.h
new file mode 100644
index 0000000000..daf1dd56d9
--- /dev/null
+++ b/gr-analog/lib/plateau_detector_fb_impl.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_IMPL_H
+#define INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_IMPL_H
+
+#include <analog/plateau_detector_fb.h>
+
+namespace gr {
+ namespace analog {
+
+class plateau_detector_fb_impl : public plateau_detector_fb
+{
+ private:
+ int d_max_len;
+ float d_threshold;
+
+ public:
+ plateau_detector_fb_impl(int max_len, float threshold);
+ ~plateau_detector_fb_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+ } // namespace analog
+} // namespace gr
+
+#endif /* INCLUDED_ANALOG_PLATEAU_DETECTOR_FB_IMPL_H */
+
diff --git a/gr-analog/python/CMakeLists.txt b/gr-analog/python/CMakeLists.txt
index a3f789ddfa..44e38621a2 100644
--- a/gr-analog/python/CMakeLists.txt
+++ b/gr-analog/python/CMakeLists.txt
@@ -59,3 +59,4 @@ foreach(py_qa_test_file ${py_qa_test_files})
GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
+
diff --git a/gr-analog/python/qa_plateau_detector_fb.py b/gr-analog/python/qa_plateau_detector_fb.py
new file mode 100755
index 0000000000..5f8abc74ec
--- /dev/null
+++ b/gr-analog/python/qa_plateau_detector_fb.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import analog_swig as analog
+
+class qa_plateau_detector_fb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_t (self):
+ # | Spur spike 1 | Plateau | Spur spike 2
+ test_signal = (0, 1, .2, .4, .6, .8, 1, 1, 1, 1, 1, .8, .6, .4, 1, 0)
+ expected_sig = (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0)
+ # | Center of Plateau
+ sink = gr.vector_sink_b()
+ self.tb.connect(gr.vector_source_f(test_signal), analog.plateau_detector_fb(5), sink)
+ self.tb.run ()
+ self.assertEqual(expected_sig, sink.data())
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_plateau_detector_fb, "qa_plateau_detector_fb.xml")
diff --git a/gr-analog/swig/analog_swig.i b/gr-analog/swig/analog_swig.i
index ab7beb3c0f..2c6f5a66cb 100644
--- a/gr-analog/swig/analog_swig.i
+++ b/gr-analog/swig/analog_swig.i
@@ -49,6 +49,7 @@
#include "analog/noise_source_f.h"
#include "analog/noise_source_c.h"
#include "analog/phase_modulator_fc.h"
+#include "analog/plateau_detector_fb.h"
#include "analog/pll_carriertracking_cc.h"
#include "analog/pll_freqdet_cf.h"
#include "analog/pll_refout_cc.h"
@@ -91,6 +92,7 @@
%include "analog/noise_source_f.h"
%include "analog/noise_source_c.h"
%include "analog/phase_modulator_fc.h"
+%include "analog/plateau_detector_fb.h"
%include "analog/pll_carriertracking_cc.h"
%include "analog/pll_freqdet_cf.h"
%include "analog/pll_refout_cc.h"
@@ -130,6 +132,7 @@ GR_SWIG_BLOCK_MAGIC2(analog, noise_source_i);
GR_SWIG_BLOCK_MAGIC2(analog, noise_source_f);
GR_SWIG_BLOCK_MAGIC2(analog, noise_source_c);
GR_SWIG_BLOCK_MAGIC2(analog, phase_modulator_fc);
+GR_SWIG_BLOCK_MAGIC2(analog, plateau_detector_fb);
GR_SWIG_BLOCK_MAGIC2(analog, pll_carriertracking_cc);
GR_SWIG_BLOCK_MAGIC2(analog, pll_freqdet_cf);
GR_SWIG_BLOCK_MAGIC2(analog, pll_refout_cc);
diff --git a/gr-blocks/CMakeLists.txt b/gr-blocks/CMakeLists.txt
index 9772803705..98f73d2177 100644
--- a/gr-blocks/CMakeLists.txt
+++ b/gr-blocks/CMakeLists.txt
@@ -34,6 +34,7 @@ GR_REGISTER_COMPONENT("gr-blocks" ENABLE_GR_BLOCKS
GR_SET_GLOBAL(GR_BLOCKS_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_BINARY_DIR}/lib
${CMAKE_CURRENT_BINARY_DIR}/include
)
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index 42adc804a8..90d94bdb29 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -97,6 +97,7 @@
<block>blocks_int_to_float</block>
<block>blocks_interleaved_short_to_complex</block>
<block>blocks_short_to_char</block>
+ <block>blocks_repack_bits_bb</block>
<block>blocks_short_to_float</block>
<block>blocks_uchar_to_float</block>
</cat>
diff --git a/gr-blocks/grc/blocks_repack_bits_bb.xml b/gr-blocks/grc/blocks_repack_bits_bb.xml
new file mode 100644
index 0000000000..4ad5ec631b
--- /dev/null
+++ b/gr-blocks/grc/blocks_repack_bits_bb.xml
@@ -0,0 +1,46 @@
+<block>
+ <name>Repack Bits</name>
+ <key>blocks_repack_bits_bb</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.repack_bits_bb($k, $l, $len_tag_key, $align_output)</make>
+ <param>
+ <name>Bits per input byte</name>
+ <key>k</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bits per output byte</name>
+ <key>l</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Key</name>
+ <key>len_tag_key</key>
+ <value>""</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Packet Alignment</name>
+ <key>align_output</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>Output</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Input</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-blocks/grc/blocks_tagged_stream_mux.xml b/gr-blocks/grc/blocks_tagged_stream_mux.xml
new file mode 100644
index 0000000000..40d98a3346
--- /dev/null
+++ b/gr-blocks/grc/blocks_tagged_stream_mux.xml
@@ -0,0 +1,65 @@
+<block>
+ <name>Tagged Stream Mux</name>
+ <key>blocks_tagged_stream_mux</key>
+ <category>Stream Operations</category>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.tagged_stream_mux($type.size*$vlen, $lengthtagname)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Number of inputs</name>
+ <key>ninputs</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length tag names</name>
+ <key>lengthtagname</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Vector Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ <nports>$ninputs</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
+
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index 82d4179c72..0f158ff473 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -65,8 +65,8 @@ endmacro(expand_h)
# Invoke macro to generate various sources
########################################################################
expand_h(add_XX ss ii cc)
-expand_h(add_const_XX ss ii ff cc)
-expand_h(add_const_vXX ss ii ff cc)
+expand_h(add_const_XX bb ss ii ff cc)
+expand_h(add_const_vXX bb ss ii ff cc)
expand_h(and_XX bb ss ii)
expand_h(and_const_XX bb ss ii)
expand_h(argmax_XX fs is ss)
@@ -156,6 +156,7 @@ install(FILES
random_pdu.h
probe_rate.h
regenerate_bb.h
+ repack_bits_bb.h
repeat.h
rms_cf.h
rms_ff.h
@@ -175,6 +176,7 @@ install(FILES
throttle.h
transcendental.h
tuntap_pdu.h
+ tagged_stream_mux.h
uchar_to_float.h
udp_sink.h
udp_source.h
diff --git a/gr-blocks/include/blocks/message_sink.h b/gr-blocks/include/blocks/message_sink.h
index 5d14836dd4..5d3084d02d 100644
--- a/gr-blocks/include/blocks/message_sink.h
+++ b/gr-blocks/include/blocks/message_sink.h
@@ -40,7 +40,10 @@ namespace gr {
// gr::blocks::message_sink::sptr
typedef boost::shared_ptr<message_sink> sptr;
- static sptr make (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block);
+ static sptr make(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block);
+ static sptr make(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname);
+
};
} /* namespace blocks */
diff --git a/gr-blocks/include/blocks/message_source.h b/gr-blocks/include/blocks/message_source.h
index 5b55191880..cf4bafc22b 100644
--- a/gr-blocks/include/blocks/message_source.h
+++ b/gr-blocks/include/blocks/message_source.h
@@ -42,6 +42,8 @@ namespace gr {
static sptr make(size_t itemsize, int msgq_limit=0);
static sptr make(size_t itemsize, gr_msg_queue_sptr msgq);
+ static sptr make(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname);
virtual gr_msg_queue_sptr msgq() const = 0;
};
diff --git a/gr-blocks/include/blocks/repack_bits_bb.h b/gr-blocks/include/blocks/repack_bits_bb.h
new file mode 100644
index 0000000000..9ade0a4353
--- /dev/null
+++ b/gr-blocks/include/blocks/repack_bits_bb.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_BLOCKS_REPACK_BITS_BB_H
+#define INCLUDED_BLOCKS_REPACK_BITS_BB_H
+
+#include <blocks/api.h>
+#include <gr_tagged_stream_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Pack \p k bits from the input stream onto \p k bits of the output stream.
+ * \ingroup blocks
+ *
+ * No bits are lost here; any value for k and l (within [1, 8]) is allowed.
+ * On every fresh input byte, it starts reading on the LSB, and starts copying
+ * to the LSB as well.
+ *
+ * If a packet length tag is given, this block assumes a tagged stream.
+ * In this case, the tag with the packet length is updated accordingly.
+ * Also, the number of input bits is padded with zeros if the number of input
+ * bits is not an integer multiple of \p l, or bits are truncated from the input
+ * if \p align_output is set to true.
+ */
+ class BLOCKS_API repack_bits_bb : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<repack_bits_bb> sptr;
+
+ /*!
+ * \param k Number of relevant bits on the input stream
+ * \param l Number of relevant bits on the output stream
+ * \param len_tag_key If not empty, this is the key for the length tag.
+ * \param align_output If len_tag_key is given, this controls if the input
+ * or the output is aligned.
+ */
+ static sptr make(int k, int l=8, const std::string &len_tag_key="", bool align_output=false);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_H */
+
diff --git a/gr-blocks/include/blocks/tagged_stream_mux.h b/gr-blocks/include/blocks/tagged_stream_mux.h
new file mode 100644
index 0000000000..23e8a94403
--- /dev/null
+++ b/gr-blocks/include/blocks/tagged_stream_mux.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_TAGGED_STREAM_MUX_H
+#define INCLUDED_TAGGED_STREAM_MUX_H
+
+#include <blocks/api.h>
+#include <gr_tagged_stream_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Combines tagged streams.
+ *
+ * \description
+ * Takes N streams as input. Each stream is tagged with packet lengths.
+ * Packets are output sequentially from each input stream.
+ *
+ * The output signal has a new length tag, which is the sum of all
+ * individual length tags.
+ *
+ * All other tags are propagated as expected, i.e. they stay associated
+ * with the same input item.
+ *
+ * \ingroup blocks
+ */
+ class BLOCKS_API tagged_stream_mux : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<tagged_stream_mux> sptr;
+
+ /* \param itemsize Items size (number of bytes per item)
+ * \param lengthtagname Length tag key
+ */
+ static sptr make(size_t itemsize, const std::string &lengthtagname);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_TAGGED_STREAM_MUX_H */
+
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index c7a7b6362f..b6ad772d29 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -91,8 +91,8 @@ endmacro(expand_cc_h_impl)
# Invoke macro to generate various sources
########################################################################
expand_cc_h_impl(add_XX ss ii cc)
-expand_cc_h_impl(add_const_XX ss ii ff cc)
-expand_cc_h_impl(add_const_vXX ss ii ff cc)
+expand_cc_h_impl(add_const_XX bb ss ii ff cc)
+expand_cc_h_impl(add_const_vXX bb ss ii ff cc)
expand_cc_h_impl(and_XX bb ss ii)
expand_cc_h_impl(and_const_XX bb ss ii)
expand_cc_h_impl(argmax_XX fs is ss)
@@ -200,6 +200,7 @@ list(APPEND gr_blocks_sources
random_pdu_impl.cc
probe_rate_impl.cc
regenerate_bb_impl.cc
+ repack_bits_bb_impl.cc
repeat_impl.cc
rms_cf_impl.cc
rms_ff_impl.cc
@@ -220,6 +221,7 @@ list(APPEND gr_blocks_sources
transcendental_impl.cc
tcp_connection.cc
tuntap_pdu_impl.cc
+ tagged_stream_mux_impl.cc
uchar_array_to_float.cc
uchar_to_float_impl.cc
udp_sink_impl.cc
diff --git a/gr-blocks/lib/message_sink_impl.cc b/gr-blocks/lib/message_sink_impl.cc
index a8dbfb4c71..fbc7b27d58 100644
--- a/gr-blocks/lib/message_sink_impl.cc
+++ b/gr-blocks/lib/message_sink_impl.cc
@@ -44,11 +44,30 @@ namespace gr {
(new message_sink_impl(itemsize, msgq, dont_block));
}
+ message_sink::sptr
+ message_sink::make(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname)
+ {
+ return gnuradio::get_initial_sptr
+ (new message_sink_impl(itemsize, msgq, dont_block, lengthtagname));
+ }
+
message_sink_impl::message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block)
: gr_sync_block("message_sink",
gr_make_io_signature(1, 1, itemsize),
gr_make_io_signature(0, 0, 0)),
- d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block)
+ d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block),
+ d_tags(false), d_items_read(0)
+ {
+ }
+
+ message_sink_impl::message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname)
+ : gr_sync_block("message_sink",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(0, 0, 0)),
+ d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block),
+ d_tags(true), d_lengthtagname(lengthtagname), d_items_read(0)
{
}
@@ -61,23 +80,53 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- const char *in = (const char*)input_items[0];
-
- // if we'd block, drop the data on the floor and say everything is OK
- if(d_dont_block && d_msgq->full_p())
- return noutput_items;
-
- // build a message to hold whatever we've got
- gr_message_sptr msg = gr_make_message(0, // msg type
- d_itemsize, // arg1 for other end
- noutput_items, // arg2 for other end (redundant)
- noutput_items * d_itemsize); // len of msg
- memcpy(msg->msg(), in, noutput_items * d_itemsize);
+ const char *in = (const char *) input_items[0];
- d_msgq->handle(msg); // send it
+ if (d_tags) {
+ long packet_length = 0;
+ std::vector<gr_tag_t> tags;
+ this->get_tags_in_range(tags, 0, d_items_read, d_items_read+1);
+ //const size_t ninput_items = noutput_items; //assumption for sync block, this can change
+ for (unsigned int i = 0; i < tags.size(); i++) {
+ if (pmt::symbol_to_string(tags[i].key) == d_lengthtagname) {
+ packet_length = pmt::to_long(tags[i].value);
+ }
+ }
+ assert(packet_length != 0);
+
+ // FIXME run this multiple times if input_items >= N * packet_length
+ if (noutput_items >= packet_length ) {
+ // If the message queue is full we drop the packet.
+ if (!d_msgq->full_p()) {
+ gr_message_sptr msg = gr_make_message(0, // msg type
+ d_itemsize, // arg1 for other end
+ packet_length, // arg2 for other end (redundant)
+ packet_length * d_itemsize); // len of msg
+ memcpy(msg->msg(), in, packet_length * d_itemsize);
+ d_msgq->handle(msg); // send it
+ }
+ d_items_read += packet_length;
+ return packet_length;
+ } else {
+ return 0;
+ }
+ } else {
+ // If the queue if full we drop all the data we got.
+ if (!d_msgq->full_p()) {
+ // build a message to hold whatever we've got
+ gr_message_sptr msg = gr_make_message(0, // msg type
+ d_itemsize, // arg1 for other end
+ noutput_items, // arg2 for other end (redundant)
+ noutput_items * d_itemsize); // len of msg
+ memcpy(msg->msg(), in, noutput_items * d_itemsize);
+
+ d_msgq->handle(msg); // send it
+ }
- return noutput_items;
+ return noutput_items;
+ }
}
} /* namespace blocks */
} /* namespace gr */
+
diff --git a/gr-blocks/lib/message_sink_impl.h b/gr-blocks/lib/message_sink_impl.h
index a3106bc058..280a46765e 100644
--- a/gr-blocks/lib/message_sink_impl.h
+++ b/gr-blocks/lib/message_sink_impl.h
@@ -34,9 +34,15 @@ namespace gr {
size_t d_itemsize;
gr_msg_queue_sptr d_msgq;
bool d_dont_block;
+ bool d_tags;
+ std::string d_lengthtagname;
+ uint64_t d_items_read;
public:
message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block);
+ message_sink_impl(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block,
+ const std::string& lengthtagname);
+
~message_sink_impl();
int work(int noutput_items,
diff --git a/gr-blocks/lib/message_source_impl.cc b/gr-blocks/lib/message_source_impl.cc
index cda4fc16c0..818cd336f1 100644
--- a/gr-blocks/lib/message_source_impl.cc
+++ b/gr-blocks/lib/message_source_impl.cc
@@ -51,12 +51,20 @@ namespace gr {
(new message_source_impl(itemsize, msgq));
}
+ message_source::sptr
+ message_source::make(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname)
+ {
+ return gnuradio::get_initial_sptr
+ (new message_source_impl(itemsize, msgq, lengthtagname));
+ }
+
message_source_impl::message_source_impl(size_t itemsize, int msgq_limit)
: gr_sync_block("message_source",
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, itemsize)),
d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)),
- d_msg_offset(0), d_eof(false)
+ d_msg_offset(0), d_eof(false), d_tags(false)
{
}
@@ -65,7 +73,17 @@ namespace gr {
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, itemsize)),
d_itemsize(itemsize), d_msgq(msgq),
- d_msg_offset(0), d_eof(false)
+ d_msg_offset(0), d_eof(false), d_tags(false)
+ {
+ }
+
+ message_source_impl::message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname)
+ : gr_sync_block("message_source",
+ gr_make_io_signature(0, 0, 0),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false),
+ d_tags(true), d_lengthtagname(lengthtagname)
{
}
@@ -82,42 +100,48 @@ namespace gr {
int nn = 0;
while(nn < noutput_items) {
- if(d_msg) {
- //
- // Consume whatever we can from the current message
- //
- int mm = std::min(noutput_items - nn,
- (int)((d_msg->length() - d_msg_offset) / d_itemsize));
- memcpy(out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize);
-
- nn += mm;
- out += mm * d_itemsize;
- d_msg_offset += mm * d_itemsize;
- assert(d_msg_offset <= d_msg->length());
-
- if(d_msg_offset == d_msg->length()) {
- if(d_msg->type() == 1) // type == 1 sets EOF
- d_eof = true;
- d_msg.reset();
- }
- }
- else {
- //
- // No current message
- //
- if(d_msgq->empty_p() && nn > 0) { // no more messages in the queue, return what we've got
- break;
- }
-
- if(d_eof)
- return -1;
-
- d_msg = d_msgq->delete_head(); // block, waiting for a message
- d_msg_offset = 0;
-
- if((d_msg->length() % d_itemsize) != 0)
- throw std::runtime_error("msg length is not a multiple of d_itemsize");
- }
+ if (d_msg){
+ //
+ // Consume whatever we can from the current message
+ //
+ int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize));
+ memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize);
+
+ if (d_tags && (d_msg_offset == 0)) {
+ const uint64_t offset = this->nitems_written(0) + nn;
+ pmt::pmt_t key = pmt::string_to_symbol(d_lengthtagname);
+ pmt::pmt_t value = pmt::from_long(d_msg->length());
+ this->add_item_tag(0, offset, key, value);
+ }
+ nn += mm;
+ out += mm * d_itemsize;
+ d_msg_offset += mm * d_itemsize;
+ assert(d_msg_offset <= d_msg->length());
+
+ if (d_msg_offset == d_msg->length()){
+ if (d_msg->type() == 1) // type == 1 sets EOF
+ d_eof = true;
+ d_msg.reset();
+ }
+ }
+ else {
+ //
+ // No current message
+ //
+ if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got
+ break;
+ }
+
+ if (d_eof)
+ return -1;
+
+ d_msg = d_msgq->delete_head(); // block, waiting for a message
+ d_msg_offset = 0;
+
+ if ((d_msg->length() % d_itemsize) != 0)
+ throw std::runtime_error("msg length is not a multiple of d_itemsize");
+ }
+
}
return nn;
diff --git a/gr-blocks/lib/message_source_impl.h b/gr-blocks/lib/message_source_impl.h
index c420704478..8fbd209e0a 100644
--- a/gr-blocks/lib/message_source_impl.h
+++ b/gr-blocks/lib/message_source_impl.h
@@ -37,10 +37,16 @@ namespace gr {
gr_message_sptr d_msg;
unsigned d_msg_offset;
bool d_eof;
+ bool d_tags;
+ // FIXME: Is this adequate tagname length.
+ std::string d_lengthtagname;
public:
message_source_impl(size_t itemsize, int msgq_limit);
message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq);
+ message_source_impl(size_t itemsize, gr_msg_queue_sptr msgq,
+ const std::string& lengthtagname);
+
~message_source_impl();
gr_msg_queue_sptr msgq() const { return d_msgq; }
diff --git a/gr-blocks/lib/repack_bits_bb_impl.cc b/gr-blocks/lib/repack_bits_bb_impl.cc
new file mode 100644
index 0000000000..c7ed054c8a
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.cc
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "repack_bits_bb_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ repack_bits_bb::sptr
+ repack_bits_bb::make(int k, int l, const std::string &len_tag_key, bool align_output)
+ {
+ return gnuradio::get_initial_sptr (new repack_bits_bb_impl(k, l, len_tag_key, align_output));
+ }
+
+ repack_bits_bb_impl::repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output)
+ : gr_tagged_stream_block("repack_bits_bb",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ len_tag_key),
+ d_k(k), d_l(l),
+ d_packet_mode(!len_tag_key.empty()),
+ d_in_index(0), d_out_index(0),
+ d_align_output(align_output)
+ {
+ if (d_k > 8 || d_k < 1 || d_l > 8 || d_l < 1) {
+ throw std::invalid_argument("k and l must be in [1, 8]");
+ }
+
+ set_relative_rate((double) d_k / d_l);
+ }
+
+ repack_bits_bb_impl::~repack_bits_bb_impl()
+ {
+ }
+
+ int
+ repack_bits_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int n_out_bytes_required = (ninput_items[0] * d_k) / d_l;
+ if ((ninput_items[0] * d_k) % d_l && (!d_packet_mode || (d_packet_mode && !d_align_output))) {
+ n_out_bytes_required++;
+ }
+
+ return n_out_bytes_required;
+ }
+
+ int
+ repack_bits_bb_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+ int bytes_to_write = noutput_items;
+
+ if (d_packet_mode) { // noutput_items could be larger than necessary
+ int bytes_to_read = ninput_items[0];
+ bytes_to_write = bytes_to_read * d_k / d_l;
+ if (!d_align_output && (((bytes_to_read * d_k) % d_l) != 0)) {
+ bytes_to_write++;
+ }
+ }
+
+ int n_read = 0;
+ int n_written = 0;
+ while(n_written < bytes_to_write && n_read < ninput_items[0]) {
+ if (d_out_index == 0) { // Starting a fresh byte
+ out[n_written] = 0;
+ }
+ out[n_written] |= ((in[n_read] >> d_in_index) & 0x01) << d_out_index;
+
+ d_in_index = (d_in_index + 1) % d_k;
+ d_out_index = (d_out_index + 1) % d_l;
+ if (d_in_index == 0) {
+ n_read++;
+ d_in_index = 0;
+ }
+ if (d_out_index == 0) {
+ n_written++;
+ d_out_index = 0;
+ }
+ }
+
+ if (d_packet_mode) {
+ if (d_out_index) {
+ n_written++;
+ d_out_index = 0;
+ }
+ } else {
+ consume_each(n_read);
+ }
+
+ return n_written;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/repack_bits_bb_impl.h b/gr-blocks/lib/repack_bits_bb_impl.h
new file mode 100644
index 0000000000..bf39f8cb0f
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H
+#define INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H
+
+#include <blocks/repack_bits_bb.h>
+
+namespace gr {
+ namespace blocks {
+
+ class repack_bits_bb_impl : public repack_bits_bb
+ {
+ private:
+ const int d_k; //! Bits on input stream
+ const int d_l; //! Bits on output stream
+ const bool d_packet_mode;
+ int d_in_index; // Current bit of input byte
+ int d_out_index; // Current bit of output byte
+ bool d_align_output; //! true if the output shall be aligned, false if the input shall be aligned
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output);
+ ~repack_bits_bb_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.cc b/gr-blocks/lib/tagged_stream_mux_impl.cc
new file mode 100644
index 0000000000..59e36fa07e
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.cc
@@ -0,0 +1,93 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "tagged_stream_mux_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ tagged_stream_mux::sptr
+ tagged_stream_mux::make(size_t itemsize, const std::string &lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new tagged_stream_mux_impl(itemsize, lengthtagname));
+ }
+
+ tagged_stream_mux_impl::tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname)
+ : gr_tagged_stream_block("tagged_stream_mux",
+ gr_make_io_signature(1, -1, itemsize),
+ gr_make_io_signature(1, 1, itemsize),
+ lengthtagname),
+ d_itemsize(itemsize)
+ {
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ tagged_stream_mux_impl::~tagged_stream_mux_impl()
+ {
+ }
+
+ int
+ tagged_stream_mux_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int nout = 0;
+ for (unsigned i = 0; i < ninput_items.size(); i++) {
+ nout += ninput_items[i];
+ }
+ return nout;
+ }
+
+ int
+ tagged_stream_mux_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ unsigned char *out = (unsigned char *) output_items[0];
+ int n_produced = 0;
+
+ set_relative_rate(ninput_items.size());
+
+ for (unsigned int i = 0; i < input_items.size(); i++) {
+ const unsigned char *in = (const unsigned char *) input_items[i];
+
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, i, nitems_read(i), nitems_read(i)+ninput_items[i]);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ const uint64_t offset = tags[j].offset - nitems_read(i) + nitems_written(0) + n_produced;
+ add_item_tag(0, offset, tags[j].key, tags[j].value);
+ }
+ memcpy((void *) out, (const void *) in, ninput_items[i] * d_itemsize);
+ out += ninput_items[i] * d_itemsize;
+ n_produced += ninput_items[i];
+ }
+
+ return n_produced;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.h b/gr-blocks/lib/tagged_stream_mux_impl.h
new file mode 100644
index 0000000000..19862e6868
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_TAGGED_STREAM_MUX_IMPL_H
+#define INCLUDED_TAGGED_STREAM_MUX_IMPL_H
+
+#include <vector>
+#include <blocks/tagged_stream_mux.h>
+
+namespace gr {
+ namespace blocks {
+
+ class tagged_stream_mux_impl : public tagged_stream_mux
+ {
+ private:
+ size_t d_itemsize;
+
+ protected:
+ int calculate_output_stream_length(const std::vector<int> &ninput_items);
+
+ public:
+ tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname);
+ ~tagged_stream_mux_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif
+
diff --git a/gr-blocks/python/qa_message_tags.py b/gr-blocks/python/qa_message_tags.py
new file mode 100644
index 0000000000..0ab857b1aa
--- /dev/null
+++ b/gr-blocks/python/qa_message_tags.py
@@ -0,0 +1,27 @@
+import time
+
+from gnuradio import gr, gr_unittest
+import blocks_swig as blocks
+
+class test_message_tags (gr_unittest.TestCase):
+
+ def test_1 (self):
+ data = ('hello', 'you', 'there')
+ tx_msgq = gr.msg_queue ()
+ rx_msgq = gr.msg_queue ()
+ for d in data:
+ tx_msgq.insert_tail(gr.message_from_string(d))
+ tb = gr.top_block()
+ src = blocks.message_source(gr.sizeof_char, tx_msgq, "packet_length")
+ snk = blocks.message_sink(gr.sizeof_char, rx_msgq, False, "packet_length")
+ tb.connect(src, snk)
+ tb.start()
+ time.sleep(1)
+ tb.stop()
+ for d in data:
+ msg = rx_msgq.delete_head()
+ contents = msg.to_string()
+ self.assertEqual(d, contents)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_message_tags, "test_message_tags.xml")
diff --git a/gr-blocks/python/qa_repack_bits_bb.py b/gr-blocks/python/qa_repack_bits_bb.py
new file mode 100755
index 0000000000..3f88df4a68
--- /dev/null
+++ b/gr-blocks/python/qa_repack_bits_bb.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import random
+from gnuradio import gr, gr_unittest
+import pmt
+import blocks_swig as blocks
+
+class qa_repack_bits_bb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_simple (self):
+ """ Very simple test, 2 bits -> 1 """
+ src_data = (0b11, 0b01, 0b10)
+ expected_data = (0b1, 0b1, 0b1, 0b0, 0b0, 0b1)
+ k = 2
+ l = 1
+ src = gr.vector_source_b(src_data, False, 1)
+ repack = blocks.repack_bits_bb(k, l)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+
+ def test_002_three (self):
+ """ 8 -> 3 """
+ src_data = (0b11111101, 0b11111111, 0b11111111)
+ expected_data = (0b101,) + (0b111,) * 7
+ k = 8
+ l = 3
+ src = gr.vector_source_b(src_data, False, 1)
+ repack = blocks.repack_bits_bb(k, l)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+
+ def test_003_lots_of_bytes (self):
+ """ Lots and lots of bytes, multiple packer stages """
+ src_data = tuple([random.randint(0, 255) for x in range(3*5*7*8 * 10)])
+ src = gr.vector_source_b(src_data, False, 1)
+ repack1 = blocks.repack_bits_bb(8, 3)
+ repack2 = blocks.repack_bits_bb(3, 5)
+ repack3 = blocks.repack_bits_bb(5, 7)
+ repack4 = blocks.repack_bits_bb(7, 8)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack1, repack2, repack3, repack4, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), src_data)
+
+ def test_004_three_with_tags (self):
+ """ 8 -> 3 """
+ src_data = (0b11111101, 0b11111111)
+ expected_data = (0b101,) + (0b111,) * 4 + (0b001,)
+ k = 8
+ l = 3
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(src_data))
+ src = gr.vector_source_b(src_data, False, 1, (tag,))
+ repack = blocks.repack_bits_bb(k, l, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+ try:
+ out_tag = sink.tags()[0]
+ except:
+ self.assertFail()
+ self.assertEqual(out_tag.offset, 0)
+ self.assertEqual(pmt.symbol_to_string(out_tag.key), tag_name)
+ self.assertEqual(pmt.to_long(out_tag.value), len(expected_data))
+
+ def test_005_three_with_tags_trailing (self):
+ """ 3 -> 8, trailing bits """
+ src_data = (0b101,) + (0b111,) * 4 + (0b001,)
+ expected_data = (0b11111101, 0b11111111)
+ k = 3
+ l = 8
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(src_data))
+ src = gr.vector_source_b(src_data, False, 1, (tag,))
+ repack = blocks.repack_bits_bb(k, l, tag_name, True)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+ try:
+ out_tag = sink.tags()[0]
+ except:
+ self.assertFail()
+ self.assertEqual(out_tag.offset, 0)
+ self.assertEqual(pmt.symbol_to_string(out_tag.key), tag_name)
+ self.assertEqual(pmt.to_long(out_tag.value), len(expected_data))
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_repack_bits_bb, "qa_repack_bits_bb.xml")
+
diff --git a/gr-blocks/python/qa_tagged_stream_mux.py b/gr-blocks/python/qa_tagged_stream_mux.py
new file mode 100755
index 0000000000..e39f8cac29
--- /dev/null
+++ b/gr-blocks/python/qa_tagged_stream_mux.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import pmt
+import blocks_swig as blocks
+import numpy
+
+def make_len_tags(tupl, key):
+ tags = []
+ tag = gr.gr_tag_t()
+ tag.key = pmt.string_to_symbol(key)
+ n_read = 0
+ for element in tupl:
+ tag.offset = n_read
+ n_read += len(element)
+ tag.value = pmt.to_pmt(len(element))
+ tags.append(tag)
+ return tags
+
+def make_len_tag(offset, key, value):
+ tag = gr.gr_tag_t()
+ tag.offset = offset
+ tag.key = pmt.string_to_symbol(key)
+ tag.value = pmt.to_pmt(value)
+ return tag
+
+
+class qa_tagged_stream_mux (gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_1(self):
+ datas = (
+ 0, 1, 2, 5, 6, 10, 14, 15, 16,
+ 3, 4, 7, 8, 9, 11, 12, 13, 17
+ )
+ expected = tuple(range(18))
+
+ tagname = "packet_length"
+ len_tags_0 = (
+ make_len_tag(0, tagname, 3),
+ make_len_tag(3, tagname, 2),
+ make_len_tag(5, tagname, 1),
+ make_len_tag(6, tagname, 3)
+ )
+ len_tags_1 = (
+ make_len_tag(0, tagname, 2),
+ make_len_tag(2, tagname, 3),
+ make_len_tag(5, tagname, 3),
+ make_len_tag(8, tagname, 1)
+ )
+ test_tag_0 = gr.gr_tag_t()
+ test_tag_0.key = pmt.string_to_symbol('spam')
+ test_tag_0.offset = 4 # On the second '1'
+ test_tag_0.value = pmt.to_pmt(42)
+ test_tag_1 = gr.gr_tag_t()
+ test_tag_1.key = pmt.string_to_symbol('eggs')
+ test_tag_1.offset = 3 # On the first '3' of the 2nd stream
+ test_tag_1.value = pmt.to_pmt(23)
+
+ src0 = gr.vector_source_b(datas[0:9], False, 1, len_tags_0 + (test_tag_0,))
+ src1 = gr.vector_source_b(datas[9:], False, 1, len_tags_1 + (test_tag_1,))
+ tagged_stream_mux = blocks.tagged_stream_mux(gr.sizeof_char, tagname)
+ snk = gr.vector_sink_b()
+ self.tb.connect(src0, (tagged_stream_mux, 0))
+ self.tb.connect(src1, (tagged_stream_mux, 1))
+ self.tb.connect(tagged_stream_mux, snk)
+ self.tb.run()
+
+ self.assertEqual(expected, snk.data())
+
+ tags = [gr.tag_to_python(x) for x in snk.tags()]
+ tags = sorted([(x.offset, x.key, x.value) for x in tags])
+ tags_expected = [
+ (0, 'packet_length', 5),
+ (5, 'packet_length', 5),
+ (6, 'spam', 42),
+ (8, 'eggs', 23),
+ (10, 'packet_length', 4),
+ (14, 'packet_length', 4)
+ ]
+ self.assertEqual(tags, tags_expected)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_tagged_stream_mux, "qa_tagged_stream_mux.xml")
+
diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i
index b12f26bad9..5245721b68 100644
--- a/gr-blocks/swig/blocks_swig.i
+++ b/gr-blocks/swig/blocks_swig.i
@@ -36,10 +36,12 @@
#include "blocks/add_ii.h"
#include "blocks/add_cc.h"
#include "blocks/add_const_ff.h"
+#include "blocks/add_const_bb.h"
#include "blocks/add_const_ss.h"
#include "blocks/add_const_ii.h"
#include "blocks/add_const_cc.h"
#include "blocks/add_const_vff.h"
+#include "blocks/add_const_vbb.h"
#include "blocks/add_const_vss.h"
#include "blocks/add_const_vii.h"
#include "blocks/add_const_vcc.h"
@@ -151,6 +153,7 @@
#include "blocks/or_ii.h"
#include "blocks/random_pdu.h"
#include "blocks/regenerate_bb.h"
+#include "blocks/repack_bits_bb.h"
#include "blocks/repeat.h"
#include "blocks/rms_cf.h"
#include "blocks/rms_ff.h"
@@ -173,6 +176,7 @@
#include "blocks/sub_cc.h"
#include "blocks/tag_debug.h"
#include "blocks/tagged_file_sink.h"
+#include "blocks/tagged_stream_mux.h"
#include "blocks/tagged_stream_to_pdu.h"
#include "blocks/threshold_ff.h"
#include "blocks/throttle.h"
@@ -200,10 +204,12 @@
%include "blocks/add_ii.h"
%include "blocks/add_cc.h"
%include "blocks/add_const_ff.h"
+%include "blocks/add_const_bb.h"
%include "blocks/add_const_ss.h"
%include "blocks/add_const_ii.h"
%include "blocks/add_const_cc.h"
%include "blocks/add_const_vff.h"
+%include "blocks/add_const_vbb.h"
%include "blocks/add_const_vss.h"
%include "blocks/add_const_vii.h"
%include "blocks/add_const_vcc.h"
@@ -316,6 +322,7 @@
%include "blocks/random_pdu.h"
%include "blocks/probe_rate.h"
%include "blocks/regenerate_bb.h"
+%include "blocks/repack_bits_bb.h"
%include "blocks/repeat.h"
%include "blocks/rms_cf.h"
%include "blocks/rms_ff.h"
@@ -337,6 +344,7 @@
%include "blocks/sub_ii.h"
%include "blocks/sub_cc.h"
%include "blocks/tagged_file_sink.h"
+%include "blocks/tagged_stream_mux.h"
%include "blocks/tagged_stream_to_pdu.h"
%include "blocks/threshold_ff.h"
%include "blocks/throttle.h"
@@ -363,10 +371,12 @@ GR_SWIG_BLOCK_MAGIC2(blocks, add_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, add_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, add_cc);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_ff);
+GR_SWIG_BLOCK_MAGIC2(blocks, add_const_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_ss);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_cc);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_vff);
+GR_SWIG_BLOCK_MAGIC2(blocks, add_const_vbb);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_vss);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_vii);
GR_SWIG_BLOCK_MAGIC2(blocks, add_const_vcc);
@@ -476,6 +486,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vi);
GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vf);
GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vc);
GR_SWIG_BLOCK_MAGIC2(blocks, regenerate_bb);
+GR_SWIG_BLOCK_MAGIC2(blocks, repack_bits_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, repeat);
GR_SWIG_BLOCK_MAGIC2(blocks, rms_cf);
GR_SWIG_BLOCK_MAGIC2(blocks, rms_ff);
@@ -498,6 +509,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, sub_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, sub_cc);
GR_SWIG_BLOCK_MAGIC2(blocks, tag_debug);
GR_SWIG_BLOCK_MAGIC2(blocks, tagged_file_sink);
+GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_mux);
GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_to_pdu);
GR_SWIG_BLOCK_MAGIC2(blocks, threshold_ff);
GR_SWIG_BLOCK_MAGIC2(blocks, throttle);
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt
index ac0dbb737d..7d3046dc50 100644
--- a/gr-digital/CMakeLists.txt
+++ b/gr-digital/CMakeLists.txt
@@ -34,6 +34,8 @@ GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL
ENABLE_GR_FILTER
ENABLE_GR_BLOCKS
ENABLE_GR_ANALOG
+ ENABLE_GR_BLOCKS
+ ENABLE_GR_FILTER
)
GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS
@@ -89,6 +91,7 @@ CPACK_COMPONENT("digital_swig"
########################################################################
# Add subdirectories
########################################################################
+add_subdirectory(include)
add_subdirectory(include/digital)
add_subdirectory(lib)
add_subdirectory(doc)
diff --git a/gr-digital/examples/ofdm/ofdm_bugsquatch.py b/gr-digital/examples/ofdm/ofdm_bugsquatch.py
new file mode 100644
index 0000000000..3b900fb46b
--- /dev/null
+++ b/gr-digital/examples/ofdm/ofdm_bugsquatch.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, digital
+from gnuradio.digital.utils import tagged_streams
+import random
+
+if __name__ == '__main__':
+ tb = gr.top_block()
+ fft_len = 64
+ cp_len = 16
+ length_tag_name = "length"
+ src = gr.vector_source_c(
+ [random.randint(0, 1)*2-1 for i in range(10*fft_len)], True, fft_len,
+ tagged_streams.make_lengthtags((10,), (0,), length_tag_name))
+ cyclic_prefixer = digital.ofdm_cyclic_prefixer(
+ fft_len, fft_len+cp_len, 0, length_tag_name)
+ sink = gr.null_sink(gr.sizeof_gr_complex)
+ checker = digital.tagged_stream_check(gr.sizeof_gr_complex*fft_len, length_tag_name)
+ checker2 = digital.tagged_stream_check(gr.sizeof_gr_complex*fft_len, length_tag_name)
+ tb.connect(src, checker, cyclic_prefixer, sink)
+ tb.run()
+
diff --git a/gr-digital/examples/ofdm/rx_ofdm.grc b/gr-digital/examples/ofdm/rx_ofdm.grc
new file mode 100644
index 0000000000..1541e8dedf
--- /dev/null
+++ b/gr-digital/examples/ofdm/rx_ofdm.grc
@@ -0,0 +1,1092 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Thu Feb 14 15:49:35 2013</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>rx_ofdm</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>OFDM Rx</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>Example of an OFDM receiver</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_symbols_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((100,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(762, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_carriers</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((0,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(557, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>header_formatter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_name)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(876, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_symbols</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((100,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(659, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>occupied_carriers</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(404, 64)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_noise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_noise_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 185)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_sync_sc_cfb</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_sync_sc_cfb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>cp_len</key>
+ <value>fft_len/4</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 178)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_frequency_modulator_fc</key>
+ <param>
+ <key>id</key>
+ <value>analog_frequency_modulator_fc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>sensitivity</key>
+ <value>-2.0/fft_len</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(692, 175)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_multiply_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_multiply_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(885, 223)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_delay</key>
+ <param>
+ <key>id</key>
+ <value>blocks_delay_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>delay</key>
+ <value>fft_len+fft_len/4</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 253)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>3200000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, 91)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>from gnuradio.digital.utils import tagged_streams</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(163, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sync_word</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(165, 46)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>header_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.constellation_bpsk()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(655, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>payload_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.constellation_qpsk()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(813, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>n_sync_symbols</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(168, 108)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(181, 200)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_constellation_decoder_cb</key>
+ <param>
+ <key>id</key>
+ <value>digital_constellation_decoder_cb_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>header_mod.base()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(854, 343)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_frame_equalizer_vcvc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_frame_equalizer_vcvc_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>equalizer</key>
+ <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols).base()</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>propagate_channel_state</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(421, 320)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_packet_headerparser_b</key>
+ <param>
+ <key>id</key>
+ <value>digital_packet_headerparser_b_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>header_formatter</key>
+ <value>header_formatter.formatter()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(651, 466)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
+ <param>
+ <key>id</key>
+ <value>fft_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value></value>
+ </param>
+ <param>
+ <key>shift</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(53, 429)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>64</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(301, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>"frame_len"</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(367, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_constellation_decoder_cb</key>
+ <param>
+ <key>id</key>
+ <value>digital_constellation_decoder_cb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>payload_mod.base()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(718, 635)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_null_sink</key>
+ <param>
+ <key>id</key>
+ <value>gr_null_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(938, 638)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_frame_equalizer_vcvc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_frame_equalizer_vcvc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>equalizer</key>
+ <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols, n_sync_symbols).base()</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
+ </param>
+ <param>
+ <key>propagate_channel_state</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(265, 612)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
+ <param>
+ <key>id</key>
+ <value>fft_vxx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value></value>
+ </param>
+ <param>
+ <key>shift</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(57, 605)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_serializer_vcc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_serializer_vcc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>occupied_carriers</key>
+ <value>occupied_carriers</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>packet_len_tag_key</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>symbols_skipped</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>input_is_shifted</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(649, 305)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_serializer_vcc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_serializer_vcc_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>occupied_carriers</key>
+ <value>occupied_carriers</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_key</value>
+ </param>
+ <param>
+ <key>packet_len_tag_key</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>symbols_skipped</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>input_is_shifted</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(496, 597)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_chanest_vcvc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_chanest_vcvc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>sync_symbol1</key>
+ <value>sync_word</value>
+ </param>
+ <param>
+ <key>sync_symbol2</key>
+ <value>()</value>
+ </param>
+ <param>
+ <key>n_data_symbols</key>
+ <value>n_sync_symbols</value>
+ </param>
+ <param>
+ <key>eq_noise_red_len</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max_carr_offset</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>force_one_symbol</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(52, 305)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_header_payload_demux</key>
+ <param>
+ <key>id</key>
+ <value>digital_header_payload_demux_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>header_len</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>items_per_symbol</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>guard_interval</key>
+ <value>fft_len/4</value>
+ </param>
+ <param>
+ <key>length_tag_key</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>trigger_tag_key</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>output_symbols</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(340, 461)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>fft_vxx_0</source_block_id>
+ <sink_block_id>digital_ofdm_chanest_vcvc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_frequency_modulator_fc_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id>
+ <sink_block_id>analog_frequency_modulator_fc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_noise_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>digital_ofdm_sync_sc_cfb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_delay_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_delay_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_constellation_decoder_cb_0_0</source_block_id>
+ <sink_block_id>digital_packet_headerparser_b_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_serializer_vcc_0</source_block_id>
+ <sink_block_id>digital_constellation_decoder_cb_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id>
+ <sink_block_id>digital_header_payload_demux_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_chanest_vcvc_0</source_block_id>
+ <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</source_block_id>
+ <sink_block_id>digital_ofdm_serializer_vcc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_packet_headerparser_b_0</source_block_id>
+ <sink_block_id>digital_header_payload_demux_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_header_payload_demux_0</source_block_id>
+ <sink_block_id>fft_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_header_payload_demux_0</source_block_id>
+ <sink_block_id>fft_vxx_0_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_multiply_xx_0</source_block_id>
+ <sink_block_id>digital_header_payload_demux_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_constellation_decoder_cb_0</source_block_id>
+ <sink_block_id>gr_null_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_frame_equalizer_vcvc_0</source_block_id>
+ <sink_block_id>digital_ofdm_serializer_vcc_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_serializer_vcc_1</source_block_id>
+ <sink_block_id>digital_constellation_decoder_cb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_vxx_0_0</source_block_id>
+ <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-digital/examples/ofdm/tx_ofdm.grc b/gr-digital/examples/ofdm/tx_ofdm.grc
new file mode 100644
index 0000000000..6c4f9797d1
--- /dev/null
+++ b/gr-digital/examples/ofdm/tx_ofdm.grc
@@ -0,0 +1,1143 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Tue Feb 5 14:47:32 2013</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>tx_ofdm</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>OFDM Tx</value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value>Example of an OFDM Transmitter</value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>no_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>run</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(0, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>from gnuradio.digital.utils import tagged_streams</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(164, 45)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>"packet_len"</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(399, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_symbols_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((100,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(735, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>occupied_carriers</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(377, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_symbols</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((100,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(632, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>pilot_carriers</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>((0,),)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(530, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>64</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(311, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>header_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.constellation_bpsk()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(620, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>payload_mod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.constellation_qpsk()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(783, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>bit_rate/8</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(234, 167)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import numpy</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(164, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import random</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 90)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sync_word</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0]</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(95, 90)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>rolloff</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(234, 91)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>header_formatter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_name)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(849, 63)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_vector_source_x</key>
+ <param>
+ <key>id</key>
+ <value>gr_vector_source_x_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>vector</key>
+ <value>range(packet_len)</value>
+ </param>
+ <param>
+ <key>tags</key>
+ <value>tagged_streams.make_lengthtags((packet_len,), (0,), length_tag_name)</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(-1, 152)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>packet_len</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>96</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(528, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_packet_headergenerator_bb</key>
+ <param>
+ <key>id</key>
+ <value>digital_packet_headergenerator_bb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>header_formatter</key>
+ <value>header_formatter.formatter()</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(761, 167)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>bit_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>3200000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(311, 0)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_repack_bits_bb</key>
+ <param>
+ <key>id</key>
+ <value>blocks_repack_bits_bb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>l</key>
+ <value>payload_mod.bits_per_symbol()</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>align_output</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(516, 228)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_chunks_to_symbols_xx</key>
+ <param>
+ <key>id</key>
+ <value>digital_chunks_to_symbols_xx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>in_type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>out_type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>symbol_table</key>
+ <value>payload_mod.points()</value>
+ </param>
+ <param>
+ <key>dimension</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(279, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_chunks_to_symbols_xx</key>
+ <param>
+ <key>id</key>
+ <value>digital_chunks_to_symbols_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>in_type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>out_type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>symbol_table</key>
+ <value>header_mod.points()</value>
+ </param>
+ <param>
+ <key>dimension</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(319, 305)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tagged_stream_mux</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tagged_stream_mux_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>ninputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>lengthtagname</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(44, 254)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_carrier_allocator_cvc</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_carrier_allocator_cvc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>occupied_carriers</key>
+ <value>occupied_carriers</value>
+ </param>
+ <param>
+ <key>pilot_carriers</key>
+ <value>pilot_carriers</value>
+ </param>
+ <param>
+ <key>pilot_symbols</key>
+ <value>pilot_symbols</value>
+ </param>
+ <param>
+ <key>len_tag_key</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(56, 453)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_vector_source_x</key>
+ <param>
+ <key>id</key>
+ <value>sync_word_source</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vector</key>
+ <value>numpy.array(sync_word) * numpy.sqrt(2)</value>
+ </param>
+ <param>
+ <key>tags</key>
+ <value>tagged_streams.make_lengthtags((len(sync_word)/fft_len,), (0,), length_tag_name)</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(56, 356)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tagged_stream_mux</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tagged_stream_mux_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>ninputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>lengthtagname</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(374, 382)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
+ <param>
+ <key>id</key>
+ <value>fft_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value></value>
+ </param>
+ <param>
+ <key>shift</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(765, 498)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_cyclic_prefixer</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_cyclic_prefixer_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>input_size</key>
+ <value>fft_len</value>
+ </param>
+ <param>
+ <key>output_size</key>
+ <value>fft_len+fft_len/4</value>
+ </param>
+ <param>
+ <key>rolloff</key>
+ <value>rolloff</value>
+ </param>
+ <param>
+ <key>tagname</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(488, 505)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(291, 460)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>gr_null_sink</key>
+ <param>
+ <key>id</key>
+ <value>gr_null_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(438, 633)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_crc32_bb</key>
+ <param>
+ <key>id</key>
+ <value>digital_crc32_bb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>check</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lengthtagname</key>
+ <value>length_tag_name</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(472, 159)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tag_debug</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tag_debug_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>tdb</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>display</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(819, 232)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>gr_vector_source_x_1</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>digital_crc32_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_crc32_bb_0</source_block_id>
+ <sink_block_id>digital_packet_headergenerator_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_tagged_stream_mux_0</source_block_id>
+ <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_mux_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>sync_word_source</source_block_id>
+ <sink_block_id>blocks_tagged_stream_mux_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_packet_headergenerator_bb_0</source_block_id>
+ <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_repack_bits_bb_0</source_block_id>
+ <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_crc32_bb_0</source_block_id>
+ <sink_block_id>blocks_repack_bits_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_tagged_stream_mux_1</source_block_id>
+ <sink_block_id>fft_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_vxx_0</source_block_id>
+ <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
+ <sink_block_id>gr_null_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_crc32_bb_0</source_block_id>
+ <sink_block_id>blocks_tag_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-digital/grc/CMakeLists.txt b/gr-digital/grc/CMakeLists.txt
index bace20847f..9888247ca2 100644
--- a/gr-digital/grc/CMakeLists.txt
+++ b/gr-digital/grc/CMakeLists.txt
@@ -18,4 +18,6 @@
# Boston, MA 02110-1301, USA.
file(GLOB xml_files "*.xml")
-install(FILES ${xml_files} DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "digital_python")
+install(FILES ${xml_files}
+ DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "digital_python"
+)
diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml
index 04c679d355..762ac66538 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -1,7 +1,6 @@
<?xml version="1.0"?>
-
<!--
- Copyright 2011 Free Software Foundation, Inc.
+ Copyright 2011,2012 Free Software Foundation, Inc.
This file is part of GNU Radio
@@ -31,8 +30,35 @@
<cat>
<name>Coding</name>
<block>digital_additive_scrambler_bb</block>
- <block>digital_descrambler_bb</block>
<block>digital_scrambler_bb</block>
+ <block>digital_descrambler_bb</block>
+ <block>digital_binary_slicer_fb</block>
+ <block>digital_bytes_to_syms</block>
+ <block>digital_chunks_to_symbols_xx</block>
+ <block>digital_clock_recovery_mm_xx</block>
+ <block>digital_cma_equalizer_cc</block>
+ <block>digital_constellation_decoder_cb</block>
+ <block>digital_constellation_receiver_cb</block>
+ <block>digital_correlate_access_code_bb</block>
+ <block>digital_costas_loop_cc</block>
+ <block>digital_crc32_bb</block>
+ <block>digital_descrambler_bb</block>
+ <block>digital_fll_band_edge_cc</block>
+ <block>digital_glfsr_source_x</block>
+ <block>digital_header_payload_demux</block>
+ <block>digital_kurtotic_equalizer_cc</block>
+ <block>digital_lms_dd_equalizer_cc</block>
+ <block>digital_map_bb</block>
+ <block>digital_mpsk_receiver_cc</block>
+ <block>digital_mpsk_snr_est_cc</block>
+ <block>digital_packet_headergenerator_bb</block>
+ <block>digital_packet_headergenerator_bb_default</block>
+ <block>digital_packet_headerparser_b</block>
+ <block>digital_packet_headerparser_b_default</block>
+ <block>digital_pfb_clock_sync_xxx</block>
+ <block>digital_pn_correlator_cc</block>
+ <block>digital_probe_density_b</block>
+ <block>digital_probe_mpsk_snr_est_c</block>
</cat>
<cat>
<name>Converters</name>
@@ -92,14 +118,20 @@
<block>digital_gmsk_demod</block>
</cat>
<cat>
- <name>OFDM</name>
+ <name>OFDM</name>
<block>digital_ofdm_mod</block>
+ <block>digital_ofdm_mod2</block>
<block>digital_ofdm_demod</block>
+ <block>digital_ofdm_carrier_allocator_cvc</block>
+ <block>digital_ofdm_chanest_vcvc</block>
<block>digital_ofdm_cyclic_prefixer</block>
<block>digital_ofdm_frame_acquisition</block>
<block>digital_ofdm_frame_sink</block>
+ <block>digital_ofdm_frame_equalizer_vcvc</block>
<block>digital_ofdm_insert_preamble</block>
<block>digital_ofdm_sampler</block>
+ <block>digital_ofdm_serializer_vcc</block>
<block>digital_ofdm_sync_pn</block>
+ <block>digital_ofdm_sync_sc_cfb</block>
</cat>
</cat>
diff --git a/gr-digital/grc/digital_crc32_bb.xml b/gr-digital/grc/digital_crc32_bb.xml
new file mode 100644
index 0000000000..d60f08f814
--- /dev/null
+++ b/gr-digital/grc/digital_crc32_bb.xml
@@ -0,0 +1,33 @@
+<block>
+ <name>Stream CRC32</name>
+ <key>digital_crc32_bb</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.crc32_bb($check, $lengthtagname)</make>
+ <param>
+ <name>Mode</name>
+ <key>check</key>
+ <type>enum</type>
+ <option>
+ <name>Generate CRC</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>Check CRC</name>
+ <key>True</key>
+ </option>
+ </param>
+ <param>
+ <name>Length tag name</name>
+ <key>lengthtagname</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_header_payload_demux.xml b/gr-digital/grc/digital_header_payload_demux.xml
new file mode 100644
index 0000000000..b29d86435b
--- /dev/null
+++ b/gr-digital/grc/digital_header_payload_demux.xml
@@ -0,0 +1,94 @@
+<block>
+ <name>Header payload demux</name>
+ <key>digital_header_payload_demux</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.header_payload_demux($header_len, $items_per_symbol, $guard_interval, $length_tag_key, $trigger_tag_key, $output_symbols, $(type.itemsize))</make>
+ <param>
+ <name>Header Length (Symbols)</name>
+ <key>header_len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Items per symbol</name>
+ <key>items_per_symbol</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Guard Interval (items)</name>
+ <key>guard_interval</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length tag key</name>
+ <key>length_tag_key</key>
+ <value>"frame_len"</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Trigger tag key</name>
+ <key>trigger_tag_key</key>
+ <value>""</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Output Format</name>
+ <key>output_symbols</key>
+ <type>enum</type>
+ <option>
+ <name>Items</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>Symbols</name>
+ <key>True</key>
+ </option>
+ </param>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>itemsize:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>itemsize:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>itemsize:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>itemsize:gr.sizeof_short</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <sink>
+ <name>trigger</name>
+ <type>byte</type>
+ </sink>
+ <sink>
+ <name>header_data</name>
+ <type>message</type>
+ </sink>
+ <source>
+ <name>out_hdr</name>
+ <type>$type</type>
+ <vlen>{True: $items_per_symbol, False: 1}[$output_symbols]</vlen>
+ </source>
+ <source>
+ <name>out_payload</name>
+ <type>$type</type>
+ <vlen>{True: $items_per_symbol, False: 1}[$output_symbols]</vlen>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml
new file mode 100644
index 0000000000..826778ff37
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<block>
+ <name>OFDM Carrier Allocator</name>
+ <key>digital_ofdm_carrier_allocator_cvc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_carrier_allocator_cvc($fft_len, $occupied_carriers, $pilot_carriers, $pilot_symbols, $len_tag_key)</make>
+ <param>
+ <name>FFT length</name>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Occupied Carriers</name>
+ <key>occupied_carriers</key>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Pilot Carriers</name>
+ <key>pilot_carriers</key>
+ <value>()</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Pilot Symbols</name>
+ <key>pilot_symbols</key>
+ <value>()</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Length tag key</name>
+ <key>len_tag_key</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$fft_len</vlen>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_chanest_vcvc.xml b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml
new file mode 100644
index 0000000000..e8b1571eb6
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<block>
+ <name>OFDM channel &amp; coarse frequency offset estimation</name>
+ <key>digital_ofdm_chanest_vcvc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_chanest_vcvc($sync_symbol1, $sync_symbol2, $n_data_symbols, $eq_noise_red_len, $max_carr_offset, $force_one_symbol)</make>
+ <param>
+ <name>Synchronisation preamble symbol 1</name>
+ <key>sync_symbol1</key>
+ <type>complex_vector</type>
+ </param>
+ <param>
+ <name>Synchronisation preamble symbol 2</name>
+ <key>sync_symbol2</key>
+ <value>()</value>
+ <type>complex_vector</type>
+ </param>
+ <param>
+ <name>Number of data symbols</name>
+ <key>n_data_symbols</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Channel taps noise reduction length</name>
+ <key>eq_noise_red_len</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Maximum carrier offset</name>
+ <key>max_carr_offset</key>
+ <value>-1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Force One Synchronisation Symbol</name>
+ <key>force_one_symbol</key>
+ <type>enum</type>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ </param>
+ <check>len($sync_symbol1)</check>
+ <check>len($sync_symbol2) == 0 or len($sync_symbol2) == len($sync_symbol1)</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>len($sync_symbol1)</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>len($sync_symbol1)</vlen>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml b/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml
index d5e5d38940..80bf339cbe 100644
--- a/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml
+++ b/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml
@@ -29,17 +29,31 @@
<name>OFDM Cyclic Prefixer</name>
<key>digital_ofdm_cyclic_prefixer</key>
<import>from gnuradio import digital</import>
- <make>digital.ofdm_cyclic_prefixer($input_size, $output_size)</make>
+ <make>digital.ofdm_cyclic_prefixer($input_size, $output_size, $rolloff, $tagname)</make>
<param>
- <name>Input Size</name>
+ <name>FFT Length</name>
<key>input_size</key>
+ <value>fft_len</value>
<type>int</type>
</param>
<param>
- <name>Output Size</name>
+ <name>Output Size (FFT length + CP length)</name>
<key>output_size</key>
+ <value>fft_len+fft_len/4</value>
<type>int</type>
</param>
+ <param>
+ <name>Rolloff</name>
+ <key>rolloff</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Key</name>
+ <key>tagname</key>
+ <value>"frame_len"</value>
+ <type>string</type>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
diff --git a/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml
new file mode 100644
index 0000000000..330b29a2fb
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml
@@ -0,0 +1,45 @@
+<block>
+ <name>OFDM Frame Equalizer</name>
+ <key>digital_ofdm_frame_equalizer_vcvc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_frame_equalizer_vcvc($equalizer, $len_tag_key, $propagate_channel_state)</make>
+ <param>
+ <name>FFT length</name>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Equalizer</name>
+ <key>equalizer</key>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Length Tag Key</name>
+ <key>len_tag_key</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Propagate Channel State</name>
+ <key>propagate_channel_state</key>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$fft_len</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$fft_len</vlen>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_mod2.xml b/gr-digital/grc/digital_ofdm_mod2.xml
new file mode 100644
index 0000000000..7de9ff7865
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_mod2.xml
@@ -0,0 +1,65 @@
+<block>
+ <name>OFDM Mod 2</name>
+ <key>digital_ofdm_mod2</key>
+ <category>OFDM</category>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_mod2(fft_len=$fft_len,
+ cp_len=$cp_len,
+ length_tag_name=$length_tag_name,
+ occupied_carriers=$occupied_carriers,
+ pilot_carriers=$pilot_carriers,
+ pilot_symbols=$pilot_symbols,
+ sync_sequence=$sync_sequence,
+ )
+ </make>
+ <param>
+ <name>Cyclic Prefix Length</name>
+ <key>cp_len</key>
+ <value>16</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>FFT Length</name>
+ <key>fft_len</key>
+ <value>64</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Name</name>
+ <key>length_tag_name</key>
+ <value>length</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Occupied Carriers</name>
+ <key>occupied_carriers</key>
+ <value>(range(1, 27) + range(38, 64),)</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Pilot Carriers</name>
+ <key>pilot_carriers</key>
+ <value>((0,),)</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Pilot Symbols</name>
+ <key>pilot_symbols</key>
+ <value>((100,),)</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Synchronization Sequence</name>
+ <key>sync_sequence</key>
+ <value>None</value>
+ <type>raw</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_serializer_vcc.xml b/gr-digital/grc/digital_ofdm_serializer_vcc.xml
new file mode 100644
index 0000000000..c7596bbb0d
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_serializer_vcc.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<block>
+ <name>OFDM Serializer</name>
+ <key>digital_ofdm_serializer_vcc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_serializer_vcc($fft_len, $occupied_carriers, $len_tag_key, $packet_len_tag_key, $symbols_skipped, $input_is_shifted)</make>
+ <param>
+ <name>FFT length</name>
+ <key>fft_len</key>
+ <value>fft_len</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Occupied Carriers</name>
+ <key>occupied_carriers</key>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Length Tag Key</name>
+ <key>len_tag_key</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Packet Length Tag Key</name>
+ <key>packet_len_tag_key</key>
+ <value>""</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Symbols skipped</name>
+ <key>symbols_skipped</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Input is shifted</name>
+ <key>input_is_shifted</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$fft_len</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml b/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml
new file mode 100644
index 0000000000..7865d248d5
--- /dev/null
+++ b/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<block>
+ <name>Schmidl &amp; Cox OFDM synchronisation</name>
+ <key>digital_ofdm_sync_sc_cfb</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.ofdm_sync_sc_cfb($fft_len, $cp_len)</make>
+ <param>
+ <name>FFT length</name>
+ <key>fft_len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Cyclic Prefix length</name>
+ <key>cp_len</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>freq_offset</name>
+ <type>float</type>
+ </source>
+ <source>
+ <name>detect</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_packet_headergenerator_bb.xml b/gr-digital/grc/digital_packet_headergenerator_bb.xml
new file mode 100644
index 0000000000..a0ec14ae80
--- /dev/null
+++ b/gr-digital/grc/digital_packet_headergenerator_bb.xml
@@ -0,0 +1,19 @@
+<block>
+ <name>Packet Header Generator</name>
+ <key>digital_packet_headergenerator_bb</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.packet_headergenerator_bb($header_formatter)</make>
+ <param>
+ <name>Formatter Object</name>
+ <key>header_formatter</key>
+ <type>raw</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_packet_headergenerator_bb_default.xml b/gr-digital/grc/digital_packet_headergenerator_bb_default.xml
new file mode 100644
index 0000000000..645b4cd250
--- /dev/null
+++ b/gr-digital/grc/digital_packet_headergenerator_bb_default.xml
@@ -0,0 +1,26 @@
+<block>
+ <name>Packet Header Generator</name>
+ <key>digital_packet_headergenerator_bb_default</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.packet_headergenerator_bb($header_len, $len_tag_key)</make>
+ <param>
+ <name>Header Length</name>
+ <key>header_len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Name</name>
+ <key>len_tag_key</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
+
diff --git a/gr-digital/grc/digital_packet_headerparser_b.xml b/gr-digital/grc/digital_packet_headerparser_b.xml
new file mode 100644
index 0000000000..bab6bd22ed
--- /dev/null
+++ b/gr-digital/grc/digital_packet_headerparser_b.xml
@@ -0,0 +1,19 @@
+<block>
+ <name>Packet Header Parser</name>
+ <key>digital_packet_headerparser_b</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.packet_headerparser_b($header_formatter)</make>
+ <param>
+ <name>Formatter Object</name>
+ <key>header_formatter</key>
+ <type>raw</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>header_data</name>
+ <type>message</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_packet_headerparser_b_default.xml b/gr-digital/grc/digital_packet_headerparser_b_default.xml
new file mode 100644
index 0000000000..415f4839f4
--- /dev/null
+++ b/gr-digital/grc/digital_packet_headerparser_b_default.xml
@@ -0,0 +1,26 @@
+<block>
+ <name>Packet Header Parser (Default)</name>
+ <key>digital_packet_headerparser_b_default</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.packet_headerparser_b($header_len, $len_tag_key)</make>
+ <param>
+ <name>Header Length</name>
+ <key>header_len</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Name</name>
+ <key>len_tag_key</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>message</type>
+ </source>
+</block>
+
diff --git a/gr-digital/grc/digital_scale_tags.xml b/gr-digital/grc/digital_scale_tags.xml
new file mode 100644
index 0000000000..3e80ee21fe
--- /dev/null
+++ b/gr-digital/grc/digital_scale_tags.xml
@@ -0,0 +1,31 @@
+<block>
+ <name>Tag Scaler</name>
+ <key>digital_scale_tags</key>
+ <category>digital</category>
+ <import>from gnuradio import digital</import>
+ <make>digital.scale_tags($item_size, $tag_name, $scale_factor)</make>
+ <param>
+ <name>Item size</name>
+ <key>item_size</key>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Tag Name</name>
+ <key>tag_name</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Scale Factor</name>
+ <key>scale_factor</key>
+ <type>real</type>
+ </param>
+ <!--FIXME type should be choosable-->
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt
new file mode 100644
index 0000000000..a32f11ed4d
--- /dev/null
+++ b/gr-digital/include/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+########################################################################
+# Install header files
+########################################################################
+install(FILES
+ digital_crc32_bb.h
+ digital_ofdm_carrier_allocator_cvc.h
+ digital_ofdm_chanest_vcvc.h
+ digital_ofdm_cyclic_prefixer.h
+ digital_ofdm_equalizer_base.h
+ digital_ofdm_equalizer_simpledfe.h
+ digital_ofdm_equalizer_static.h
+ digital_ofdm_sync_sc_cfb.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "digital_devel"
+)
diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt
index 11cab88337..06438c092b 100644
--- a/gr-digital/include/digital/CMakeLists.txt
+++ b/gr-digital/include/digital/CMakeLists.txt
@@ -75,54 +75,63 @@ add_custom_target(digital_generated_includes DEPENDS
########################################################################
install(FILES
${generated_includes}
- api.h
- constellation.h
- crc32.h
- lfsr.h
- glfsr.h
- mpsk_snr_est.h
- simple_framer_sync.h
additive_scrambler_bb.h
+ api.h
binary_slicer_fb.h
clock_recovery_mm_cc.h
clock_recovery_mm_ff.h
cma_equalizer_cc.h
- cpmmod_bc.h
- constellation_receiver_cb.h
+ constellation.h
constellation_decoder_cb.h
+ constellation_receiver_cb.h
correlate_access_code_bb.h
correlate_access_code_tag_bb.h
costas_loop_cc.h
+ cpmmod_bc.h
+ crc32.h
descrambler_bb.h
diff_decoder_bb.h
diff_encoder_bb.h
diff_phasor_cc.h
- framer_sink_1.h
fll_band_edge_cc.h
+ framer_sink_1.h
+ glfsr.h
glfsr_source_b.h
glfsr_source_f.h
+ header_payload_demux.h
kurtotic_equalizer_cc.h
+ lfsr.h
lms_dd_equalizer_cc.h
map_bb.h
metric_type.h
mpsk_receiver_cc.h
+ mpsk_snr_est.h
mpsk_snr_est_cc.h
ofdm_cyclic_prefixer.h
ofdm_frame_acquisition.h
+ ofdm_frame_equalizer_vcvc.h
ofdm_frame_sink.h
ofdm_insert_preamble.h
ofdm_mapper_bcv.h
ofdm_sampler.h
+ ofdm_serializer_vcc.h
+ packet_header_default.h
+ packet_header_ofdm.h
+ packet_headergenerator_bb.h
+ packet_headerparser_b.h
packet_sink.h
pfb_clock_sync_ccf.h
pfb_clock_sync_fff.h
pn_correlator_cc.h
probe_density_b.h
probe_mpsk_snr_est_c.h
+ scale_tags.h
scrambler_bb.h
- simple_framer.h
simple_correlator.h
+ simple_framer.h
+ simple_framer_sync.h
+ tagged_stream_check.h
+ ts_insert_zeros_cc.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/digital
COMPONENT "digital_devel"
)
-
diff --git a/gr-digital/include/digital/constellation.h b/gr-digital/include/digital/constellation.h
index ee7a704eb6..a7a2ec2023 100644
--- a/gr-digital/include/digital/constellation.h
+++ b/gr-digital/include/digital/constellation.h
@@ -82,7 +82,7 @@ namespace gr {
//! Calculates metrics for all points in the constellation.
//! For use with the viterbi algorithm.
- virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type);
+ virtual void calc_metric(const gr_complex *sample, float *metric, gr::digital::trellis_metric_type_t type);
virtual void calc_euclidean_metric(const gr_complex *sample, float *metric);
virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric);
diff --git a/gr-digital/include/digital/header_payload_demux.h b/gr-digital/include/digital/header_payload_demux.h
new file mode 100644
index 0000000000..014e0304a2
--- /dev/null
+++ b/gr-digital/include/digital/header_payload_demux.h
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H
+#define INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H
+
+#include <digital/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Header/Payload demuxer.
+ * \ingroup digital
+ *
+ * This block is designed to handle packets from a bursty transmission.
+ * Input 0 takes a continuous transmission of samples.
+ * If used, input 1 is a trigger signal. In this case, a 1 on input 1
+ * is a trigger. Otherwise, a tag with the key specified in \p trigger_tag_key
+ * is used as a trigger (its value is irrelevant).
+ *
+ * Until a trigger signal is detected, all samples are dropped onto the floor.
+ * Once a trigger is detected, a total of \p header_len items are copied to output 0.
+ * The block then stalls until it receives a message on the message port
+ * \p header_data. The message must be a PMT dictionary; all key/value pairs are
+ * copied as tags to the first item of the payload (which is assumed to be the
+ * first item after the header).
+ * The value corresponding to the key specified in \p length_tag_key is read
+ * and taken as the payload length. The payload, together with the header data
+ * as tags, is then copied to output 1.
+ *
+ * If specified, \p guard_interval items are discarded before every symbol.
+ * This is useful for demuxing bursts of OFDM signals.
+ *
+ * Any tags on the input stream are copied to the corresponding output *if* they're
+ * on an item that is propagated. Note that a tag on the header items is copied to the
+ * header stream; that means the header-parsing block must handle these tags if they
+ * should go on the payload.
+ * A special case are tags on items that make up the guard interval. These are copied
+ * to the first item of the following symbol.
+ */
+ class DIGITAL_API header_payload_demux : virtual public gr_block
+ {
+ public:
+ typedef boost::shared_ptr<header_payload_demux> sptr;
+
+ /*!
+ * \param header_len Number of symbols per header
+ * \param items_per_symbol Number of items per symbol
+ * \param guard_interval Number of items between two consecutive symbols
+ * \param length_tag_key Key of the frame length tag
+ * \param trigger_tag_key Key of the trigger tag
+ * \param output_symbols Output symbols (true) or items (false)?
+ * \param itemsize Item size (bytes per item)
+ */
+ static sptr make(
+ int header_len,
+ int items_per_symbol,
+ int guard_interval=0,
+ const std::string &length_tag_key="frame_len",
+ const std::string &trigger_tag_key="",
+ bool output_symbols=false,
+ size_t itemsize=sizeof(gr_complex)
+ );
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H */
+
diff --git a/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h
new file mode 100644
index 0000000000..d5d526ddc3
--- /dev/null
+++ b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H
+#define INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H
+
+#include <digital_ofdm_equalizer_base.h>
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief OFDM frame equalizer
+ * \ingroup ofdm
+ *
+ * Performs equalization in one or two dimensions on a tagged OFDM frame.
+ * Input: a tagged series of OFDM symbols.
+ * Output: The same as the input, but equalized.
+ */
+ class DIGITAL_API ofdm_frame_equalizer_vcvc : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<ofdm_frame_equalizer_vcvc> sptr;
+
+ /*
+ * \param equalizer The equalizer object that will do the actual work
+ * \param len_tag_key Length tag key
+ * \param propagate_channel_state If true, the channel state after the last symbol
+ * will be added to the first symbol as a tag
+ */
+ static sptr make(
+ digital_ofdm_equalizer_base_sptr equalizer,
+ const std::string &len_tag_key = "frame_len",
+ bool propagate_channel_state=false
+ );
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H */
+
diff --git a/gr-digital/include/digital/ofdm_serializer_vcc.h b/gr-digital/include/digital/ofdm_serializer_vcc.h
new file mode 100644
index 0000000000..3893d6674e
--- /dev/null
+++ b/gr-digital/include/digital/ofdm_serializer_vcc.h
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H
+#define INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H
+
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+#include <digital_ofdm_carrier_allocator_cvc.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Serializes complex modulations symbols from OFDM sub-carriers
+ * \ingroup ofdm_blk
+ *
+ * This is the inverse block to the carrier_allocator_cvc. It outputs the
+ * complex data symbols as a tagged stream, discarding the pilot symbols.
+ *
+ * If given, two different tags are parsed: The first key (\p len_tag_key)
+ * specifies the number of OFDM symbols in the frame at the input. The
+ * second key (\p packet_len_tag_key) specifies the number of complex symbols
+ * that are coded into this frame. If given, this second key is then used
+ * at the output, otherwise, \p len_tag_key is used.
+ * If both are given, the packet length specifies the maximum number of
+ * output items, and the frame length specifies the exact number of
+ * consumed input items.
+ *
+ * Input: Complex vectors of length \p fft_len
+ * Output: Complex scalars, in the same order as specified in occupied_carriers.
+ */
+ class DIGITAL_API ofdm_serializer_vcc : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<ofdm_serializer_vcc> sptr;
+
+ /*!
+ * \param fft_len FFT length
+ * \param occupied_carriers See ofdm_carrier_allocator_cvc.
+ * \param len_tag_key The key of the tag identifying the length of the input frame in OFDM symbols.
+ * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet.
+ * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this
+ * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false
+ */
+ static sptr make(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::string &len_tag_key="frame_len",
+ const std::string &packet_len_tag_key="",
+ int symbols_skipped=0,
+ bool input_is_shifted=true
+ );
+
+ /*!
+ * \param allocator The carrier allocator block of which this shall be the inverse
+ * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet.
+ * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this
+ * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false
+ */
+ static sptr make(
+ const digital_ofdm_carrier_allocator_cvc_sptr &allocator,
+ const std::string &packet_len_tag_key="",
+ int symbols_skipped=0,
+ bool input_is_shifted=true
+ );
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H */
+
diff --git a/gr-digital/include/digital/packet_header_default.h b/gr-digital/include/digital/packet_header_default.h
new file mode 100644
index 0000000000..a4158e728c
--- /dev/null
+++ b/gr-digital/include/digital/packet_header_default.h
@@ -0,0 +1,101 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H
+#define INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H
+
+#include <gr_tags.h>
+#include <digital/api.h>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief <+description of block+>
+ * \ingroup digital
+ *
+ */
+ class DIGITAL_API packet_header_default : public boost::enable_shared_from_this<gr::digital::packet_header_default>
+ {
+ public:
+ typedef boost::shared_ptr<packet_header_default> sptr;
+
+ packet_header_default(
+ long header_len,
+ const std::string &len_tag_key="packet_len",
+ const std::string &num_tag_key="packet_num",
+ int bits_per_byte=1);
+ ~packet_header_default();
+
+ sptr base() { return shared_from_this(); };
+ sptr formatter() { return shared_from_this(); };
+
+ void set_header_num(unsigned header_num) { d_header_number = header_num; };
+ long header_len() { return d_header_len; };
+ pmt::pmt_t len_tag_key() { return d_len_tag_key; };
+
+ /* \brief Encodes the header information in the given tags into bits and places them into \p out
+ *
+ * Uses the following header format:
+ * Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key)
+ * Bits 12-27: The header number (counts up everytime this function is called)
+ * Bit 28: Even parity bit
+ * All other bits: Are set to zero
+ *
+ * If the header length is smaller than 29, bits are simply left out. For this
+ * reason, they always start with the LSB.
+ */
+ bool header_formatter(
+ long packet_len,
+ unsigned char *out,
+ const std::vector<gr_tag_t> &tags=std::vector<gr_tag_t>()
+ );
+
+ /* \brief Inverse function to header_formatter().
+ *
+ * Reads the bit stream in \in and writes a corresponding tag into \p tags.
+ *
+ */
+ bool header_parser(
+ const unsigned char *header,
+ std::vector<gr_tag_t> &tags);
+
+ static sptr make(
+ long header_len,
+ const std::string &len_tag_key="packet_len",
+ const std::string &num_tag_key="packet_num",
+ int bits_per_byte=1);
+
+ protected:
+ long d_header_len;
+ pmt::pmt_t d_len_tag_key;
+ pmt::pmt_t d_num_tag_key;
+ int d_bits_per_byte;
+ unsigned d_header_number;
+ unsigned d_mask;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H */
+
diff --git a/gr-digital/include/digital/packet_header_ofdm.h b/gr-digital/include/digital/packet_header_ofdm.h
new file mode 100644
index 0000000000..6c3453ed1d
--- /dev/null
+++ b/gr-digital/include/digital/packet_header_ofdm.h
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H
+#define INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H
+
+#include <vector>
+#include <digital/api.h>
+#include <digital/packet_header_default.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Header utility for OFDM signals.
+ * \ingroup ofdm_blk
+ *
+ */
+ class DIGITAL_API packet_header_ofdm : public packet_header_default
+ {
+ public:
+ typedef boost::shared_ptr<packet_header_ofdm> sptr;
+
+ packet_header_ofdm(
+ const std::vector<std::vector<int> > &occupied_carriers,
+ int n_syms,
+ const std::string &len_tag_key="packet_len",
+ const std::string &frame_len_tag_key="frame_len",
+ const std::string &num_tag_key="packet_num",
+ int bits_per_sym=1);
+ ~packet_header_ofdm();
+
+ /* \brief Inverse function to header_formatter().
+ *
+ * Does the same as packet_header_default::header_parser(), but
+ * adds another tag that stores the number of OFDM symbols in the
+ * packet.
+ * Note that there is usually no linear connection between the number
+ * of OFDM symbols and the packet length, because, a packet might
+ * finish mid-OFDM-symbol.
+ */
+ bool header_parser(
+ const unsigned char *header,
+ std::vector<gr_tag_t> &tags);
+
+ static sptr make(
+ const std::vector<std::vector<int> > &occupied_carriers,
+ int n_syms,
+ const std::string &len_tag_key="packet_len",
+ const std::string &frame_len_tag_key="frame_len",
+ const std::string &num_tag_key="packet_num",
+ int bits_per_sym=1);
+
+
+ protected:
+ pmt::pmt_t d_frame_len_tag_key;
+ const std::vector<std::vector<int> > d_occupied_carriers; //! Which carriers/symbols carry data
+ int d_syms_per_set; //! Helper variable: Total number of elements in d_occupied_carriers
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H */
+
diff --git a/gr-digital/include/digital/packet_headergenerator_bb.h b/gr-digital/include/digital/packet_headergenerator_bb.h
new file mode 100644
index 0000000000..8d92bf84ed
--- /dev/null
+++ b/gr-digital/include/digital/packet_headergenerator_bb.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_PACKET_HEADERGENERATOR_BB_H
+#define INCLUDED_PACKET_HEADERGENERATOR_BB_H
+
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+#include <digital/packet_header_default.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Generates a header for a tagged, streamed packet.
+ * \ingroup digital
+ *
+ * Input: A tagged stream. The first element must have a tag with the key
+ * specified in len_tag_key, which hold the exact number of elements
+ * in the PDU.
+ * Output: An tagged stream of length header_len. The output is determined
+ * by a header formatter.
+ */
+ class DIGITAL_API packet_headergenerator_bb : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<packet_headergenerator_bb> sptr;
+
+ static sptr make(const packet_header_default::sptr &header_formatter);
+ static sptr make(
+ long header_len,
+ const std::string &len_tag_key = "packet_len");
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_PACKET_HEADERGENERATOR_BB_H */
+
diff --git a/gr-digital/include/digital/packet_headerparser_b.h b/gr-digital/include/digital/packet_headerparser_b.h
new file mode 100644
index 0000000000..a3db069cbd
--- /dev/null
+++ b/gr-digital/include/digital/packet_headerparser_b.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H
+#define INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H
+
+#include <digital/api.h>
+#include <gr_sync_block.h>
+#include <digital/packet_header_default.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Post header metadata as a PMT
+ * \ingroup digital
+ *
+ * In a sense, this is the inverse block to packet_headergenerator_bb.
+ * The difference is, the parsed header is not output as a stream,
+ * but as a message.
+ *
+ * If only a header length is given, this block uses the default header
+ * format.
+ */
+ class DIGITAL_API packet_headerparser_b : virtual public gr_sync_block
+ {
+ public:
+ typedef boost::shared_ptr<packet_headerparser_b> sptr;
+
+ /*!
+ * \param header_formatter Header object. This should be the same as used for
+ * packet_headergenerator_bb.
+ */
+ static sptr make(const gr::digital::packet_header_default::sptr &header_formatter);
+
+ /*!
+ * \param header_len Number of bytes per header
+ * \param len_tag_key Length Tag Key
+ */
+ static sptr make(long header_len, const std::string &len_tag_key);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H */
+
diff --git a/gr-digital/include/digital/scale_tags.h b/gr-digital/include/digital/scale_tags.h
new file mode 100644
index 0000000000..8a9e3efba4
--- /dev/null
+++ b/gr-digital/include/digital/scale_tags.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_SCALE_TAGS_H
+#define INCLUDED_DIGITAL_SCALE_TAGS_H
+
+#include <digital_ofdm_equalizer_base.h> // FIXME: Error without this line. No idea why.
+#include <digital/api.h>
+#include <gr_sync_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief <+description of block+>
+ * \ingroup block
+ *
+ */
+ class DIGITAL_API scale_tags : virtual public gr_sync_block
+ {
+ public:
+ typedef boost::shared_ptr<scale_tags> sptr;
+
+ /*!
+ * \brief Return a shared_ptr to a new instance of digital::scale_tags.
+ *
+ * To avoid accidental use of raw pointers, digital::scale_tags's
+ * constructor is in a private implementation
+ * class. digital::scale_tags::make is the public interface for
+ * creating new instances.
+ */
+ static sptr make(size_t itemsize, const std::string&, float scale_factor);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_SCALE_TAGS_H */
+
diff --git a/gr-digital/include/digital/tagged_stream_check.h b/gr-digital/include/digital/tagged_stream_check.h
new file mode 100644
index 0000000000..73b44a5bb9
--- /dev/null
+++ b/gr-digital/include/digital/tagged_stream_check.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_TAGGED_STREAM_CHECK_H
+#define INCLUDED_DIGITAL_TAGGED_STREAM_CHECK_H
+
+#include <digital_ofdm_equalizer_base.h> // FIXME: Error without this line. No idea why.
+#include <digital/api.h>
+#include <gr_sync_block.h>
+
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Checks a tagged stream to make sure it's valid.
+ *
+ * \description
+ * Produces error messages if the tags in a tagged stream aren't where
+ * they should be.
+ *
+ * \ingroup digital
+ *
+ */
+ class DIGITAL_API tagged_stream_check : virtual public gr_sync_block
+ {
+ public:
+ typedef boost::shared_ptr<tagged_stream_check> sptr;
+ static sptr make(size_t itemsize, const std::string &lengthtagname);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_TAGGED_STREAM_CHECK_H */
+
diff --git a/gr-digital/include/digital/ts_insert_zeros_cc.h b/gr-digital/include/digital/ts_insert_zeros_cc.h
new file mode 100644
index 0000000000..299062eb50
--- /dev/null
+++ b/gr-digital/include/digital/ts_insert_zeros_cc.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_TS_INSERT_ZEROS_CC_H
+#define INCLUDED_DIGITAL_TS_INSERT_ZEROS_CC_H
+
+#include <digital_ofdm_equalizer_base.h> // FIXME: Error without this line. No idea why.
+#include <digital/api.h>
+#include <gr_block.h>
+#include <string>
+
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Inserts zeros between the packets of a tagged stream.
+ *
+ * \description
+ * Outputs zeros if a packet is not yet ready at the input, otherwise
+ * passes packets through.
+ *
+ * \ingroup digital
+ *
+ */
+ class DIGITAL_API ts_insert_zeros_cc : virtual public gr_block
+ {
+ public:
+ typedef boost::shared_ptr<ts_insert_zeros_cc> sptr;
+ static sptr make(const std::string &lengthtagname);
+ };
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_TS_INSERT_ZEROS_CC_H */
+
diff --git a/gr-digital/include/digital_crc32_bb.h b/gr-digital/include/digital_crc32_bb.h
new file mode 100644
index 0000000000..efbf2d545a
--- /dev/null
+++ b/gr-digital/include/digital_crc32_bb.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_CRC32_BB_H
+#define INCLUDED_DIGITAL_CRC32_BB_H
+
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+
+class digital_crc32_bb;
+
+typedef boost::shared_ptr<digital_crc32_bb> digital_crc32_bb_sptr;
+
+DIGITAL_API digital_crc32_bb_sptr digital_make_crc32_bb (bool check=false, const std::string& lengthtagname="packet_len");
+
+/*!
+ * \brief Byte-stream CRC block
+ * \ingroup digital
+ *
+ * Input: stream of bytes, which form a packet. The first byte of the packet
+ * has a tag with key "length" and the value being the number of bytes in the
+ * packet.
+ *
+ * Output: The same bytes as incoming, but trailing a CRC32 of the packet.
+ * The tag is re-set to the new length.
+ */
+class DIGITAL_API digital_crc32_bb : public gr_tagged_stream_block
+{
+ private:
+ friend DIGITAL_API digital_crc32_bb_sptr digital_make_crc32_bb (bool check, const std::string& lengthtagname);
+
+ bool d_check;
+
+ digital_crc32_bb(bool check, const std::string& lengthtagname);
+
+ public:
+ ~digital_crc32_bb();
+
+ int calculate_output_stream_length(const std::vector<int> &ninput_items);
+
+ int work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_DIGITAL_CRC32_BB_H */
+
diff --git a/gr-digital/include/digital_ofdm_carrier_allocator_cvc.h b/gr-digital/include/digital_ofdm_carrier_allocator_cvc.h
new file mode 100644
index 0000000000..9052299aa9
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_carrier_allocator_cvc.h
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H
+#define INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H
+
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+
+class digital_ofdm_carrier_allocator_cvc;
+typedef boost::shared_ptr<digital_ofdm_carrier_allocator_cvc> digital_ofdm_carrier_allocator_cvc_sptr;
+
+/*
+ * \param occupied_carriers A vector of vectors of indexes. Example: if
+ * occupied_carriers = ((1, 2, 3), (1, 2, 4)), the first
+ * three input symbols will be mapped to carriers 1, 2
+ * and 3. After that, a new OFDM symbol is started. The next
+ * three input symbols will be placed onto carriers 1, 2
+ * and 4 of the second OFDM symbol. The allocation then
+ * starts from the beginning.
+ * Order matters! The first input symbol is always mapped
+ * onto occupied_carriers[0][0].
+ * \param pilot_carriers The position of the pilot symbols. Same as occupied_carriers,
+ * but the actual symbols are taken from pilot_symbols instead
+ * of the input stream.
+ * \param pilot_symbols The pilot symbols which are placed onto the pilot carriers.
+ * pilot_symbols[0][0] is placed onto the first OFDM symbol, on
+ * carrier index pilot_carriers[0][0] etc.
+ * \param len_tag_key The key of the tag identifying the length of the input packet.
+ */
+DIGITAL_API digital_ofdm_carrier_allocator_cvc_sptr
+digital_make_ofdm_carrier_allocator_cvc (
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ const std::string &len_tag_key = "packet_len");
+
+/*!
+ * \brief Create frequency domain OFDM symbols from complex values, add pilots.
+ * \ingroup ofdm_blk
+ *
+ * This block turns a stream of complex, scalar modulation symbols into vectors
+ * which are the input for an IFFT in an OFDM transmitter. It also supports the
+ * possibility of placing pilot symbols onto the carriers.
+ *
+ * The carriers can be allocated freely, if a carrier is not allocated, it is set
+ * to zero. This allows doing OFDMA-style carrier allocations.
+ *
+ * Input: A tagged stream of complex scalars. The first item must have a tag
+ * containing the number of complex symbols in this frame.
+ * Output: A tagged stream of complex vectors of length fft_len. This can directly
+ * be connected to an FFT block. Make sure to set this block to 'reverse'
+ * for the IFFT and to deactivate FFT shifting.
+ *
+ * Carrier indexes are always such that index 0 is the DC carrier (note: you should
+ * not allocate this carrier). The carriers below the DC carrier are either indexed
+ * with negative numbers, or with indexes larger than fft_len/2. Index -1 and index
+ * fft_len-1 both identify the carrier below the DC carrier.
+ *
+ */
+class DIGITAL_API digital_ofdm_carrier_allocator_cvc : public gr_tagged_stream_block
+{
+ private:
+ friend DIGITAL_API digital_ofdm_carrier_allocator_cvc_sptr digital_make_ofdm_carrier_allocator_cvc (int fft_len, const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, const std::string &len_tag_key);
+
+ digital_ofdm_carrier_allocator_cvc(int fft_len, const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, const std::string &len_tag_key);
+
+ //! FFT length
+ const int d_fft_len;
+ //! Which carriers/symbols carry data
+ std::vector<std::vector<int> > d_occupied_carriers;
+ //! Which carriers/symbols carry pilots symbols
+ std::vector<std::vector<int> > d_pilot_carriers;
+ //! Value of said pilot symbols
+ const std::vector<std::vector<gr_complex> > d_pilot_symbols;
+ int d_symbols_per_set;
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ ~digital_ofdm_carrier_allocator_cvc();
+
+ std::string len_tag_key() { return d_length_tag_key_str; };
+
+ const int fft_len() { return d_fft_len; };
+ std::vector<std::vector<int> > occupied_carriers() { return d_occupied_carriers; };
+
+ int work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H */
+
diff --git a/gr-digital/include/digital_ofdm_chanest_vcvc.h b/gr-digital/include/digital_ofdm_chanest_vcvc.h
new file mode 100644
index 0000000000..da03f96720
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_chanest_vcvc.h
@@ -0,0 +1,133 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
+#define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
+
+#include <digital/api.h>
+#include <gr_block.h>
+
+class digital_ofdm_chanest_vcvc;
+
+typedef boost::shared_ptr<digital_ofdm_chanest_vcvc> digital_ofdm_chanest_vcvc_sptr;
+
+/*
+ * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its length must be
+ * the FFT length. For Schmidl & Cox synchronisation, every second sub-carrier
+ * has to be zero.
+ * \param sync_symbol2 Second synchronisation symbol in the frequency domain. Must be equal to
+ * the FFT length, or zero length if only one synchronisation symbol is used.
+ * Using this symbol is how synchronisation is described in [1]. Leaving this
+ * empty forces us to interpolate the equalizer taps.
+ * If you are using an unusual sub-carrier configuration (e.g. because of OFDMA),
+ * this sync symbol is used to identify the active sub-carriers. If you only
+ * have one synchronisation symbol, set the active sub-carriers to a non-zero
+ * value in here, and also set \p force_one_sync_symbol parameter to true.
+ * \param n_data_symbols The number of data symbols following each set of synchronisation symbols.
+ * Must be at least 1.
+ * \param eq_noise_red_len If non-zero, noise reduction for the equalizer taps is done according
+ * to [2]. In this case, it is the channel influence time in number of
+ * samples. A good value is usually the length of the cyclic prefix.
+ * \param max_carr_offset Limit the number of sub-carriers the frequency offset can maximally be.
+ * Leave this zero to try all possibilities.
+ * \param force_one_sync_symbol See \p sync_symbol2.
+ */
+DIGITAL_API digital_ofdm_chanest_vcvc_sptr
+digital_make_ofdm_chanest_vcvc (
+ const std::vector<gr_complex> &sync_symbol1,
+ const std::vector<gr_complex> &sync_symbol2,
+ int n_data_symbols,
+ int eq_noise_red_len=0,
+ int max_carr_offset=-1,
+ bool force_one_sync_symbol=false);
+
+/*!
+ * \brief Estimate channel and coarse frequency offset for OFDM from preambles
+ * \ingroup ofdm_blk
+ * \ingroup sync_blk
+ *
+ * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected
+ * to be synchronisation symbols, which are used to estimate the coarse freq offset
+ * and the initial equalizer taps (these symbols are removed from the stream).
+ * The following \p n_data_symbols are passed through unmodified (the actual equalisation
+ * must be done elsewhere).
+ * Output: The data symbols, without the synchronisation symbols.
+ * The first data symbol passed through has two tags:
+ * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers,
+ * and 'ofdm_sync_eq_taps' (complex vector).
+ * Any tags attached to the synchronisation symbols are attached to the first data
+ * symbol. All other tags are propagated normally.
+ *
+ * This block assumes the frequency offset is even (i.e. an integer multiple of 2).
+ *
+ * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM",
+ * Communications, IEEE Transactions on, 1997.
+ * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2.
+ */
+class DIGITAL_API digital_ofdm_chanest_vcvc : public gr_block
+{
+ private:
+ friend DIGITAL_API digital_ofdm_chanest_vcvc_sptr digital_make_ofdm_chanest_vcvc (const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
+
+ int d_fft_len; //! FFT length
+ int d_n_data_syms; //! Number of data symbols following the sync symbol(s)
+ int d_n_sync_syms; //! Number of sync symbols (1 or 2)
+ //! 0 if no noise reduction is done for the initial channel state estimation. Otherwise, the maximum length of the channel delay in samples.
+ int d_eq_noise_red_len;
+ //! Is sync_symbol1 if d_n_sync_syms == 1, otherwise sync_symbol2. Used as a reference symbol to estimate the channel.
+ std::vector<gr_complex> d_ref_sym;
+ //! If d_n_sync_syms == 2 this is used as a differential correlation vector (called 'v' in [1]).
+ std::vector<gr_complex> d_corr_v;
+ //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset
+ std::vector<float> d_known_symbol_diffs;
+ //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset (temp. variable)
+ std::vector<float> d_new_symbol_diffs;
+ //! The index of the first carrier with data (index 0 is not DC here, but the lowest frequency)
+ int d_first_active_carrier;
+ //! The index of the last carrier with data
+ int d_last_active_carrier;
+ //! If true, the channel estimation must be interpolated
+ bool d_interpolate;
+ //! Maximum carrier offset (negative value!)
+ int d_max_neg_carr_offset;
+ //! Maximum carrier offset (positive value!)
+ int d_max_pos_carr_offset;
+
+
+ digital_ofdm_chanest_vcvc(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
+
+ //! Calculate the coarse frequency offset in number of carriers
+ int get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2);
+ //! Estimate the channel (phase and amplitude offset per carrier)
+ void get_chan_taps(const gr_complex *sync_sym1, const gr_complex *sync_sym2, int carr_offset, std::vector<gr_complex> &taps);
+
+ public:
+ ~digital_ofdm_chanest_vcvc();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H */
+
diff --git a/gr-digital/include/digital_ofdm_cyclic_prefixer.h b/gr-digital/include/digital_ofdm_cyclic_prefixer.h
new file mode 100644
index 0000000000..563a311fa3
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_cyclic_prefixer.h
@@ -0,0 +1,95 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H
+#define INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H
+
+#include <digital/api.h>
+#include <gr_tagged_stream_block.h>
+
+class digital_ofdm_cyclic_prefixer;
+typedef boost::shared_ptr<digital_ofdm_cyclic_prefixer> digital_ofdm_cyclic_prefixer_sptr;
+
+/*!
+ * \param input_size FFT length (i.e. length of the OFDM symbols)
+ * \param output_size FFT length + cyclic prefix length (in samples)
+ * \param rolloff_len Length of the rolloff flank in samples
+ * \param len_tag_key For framed processing the key of the length tag
+ */
+DIGITAL_API digital_ofdm_cyclic_prefixer_sptr
+digital_make_ofdm_cyclic_prefixer (size_t input_size,
+ size_t output_size,
+ int rolloff_len=0,
+ const std::string &len_tag_key="");
+
+
+/*!
+ * \brief Adds a cyclic prefix and performs pulse shaping on OFDM symbols.
+ * \ingroup ofdm_blk
+ *
+ * Input: OFDM symbols (in the time domain, i.e. after the IFFT). Optionally,
+ * entire frames can be processed. In this case, \p len_tag_key must be
+ * specified which holds the key of the tag that denotes how
+ * many OFDM symbols are in a frame.
+ * Output: A stream of (scalar) complex symbols, which include the cyclic prefix
+ * and the pulse shaping.
+ * Note: If complete frames are processed, and \p rolloff_len is greater
+ * than zero, the final OFDM symbol is followed by the delay line of
+ * the pulse shaping.
+ *
+ * The pulse shape is a raised cosine in the time domain.
+ */
+class DIGITAL_API digital_ofdm_cyclic_prefixer : public gr_tagged_stream_block
+{
+ friend DIGITAL_API digital_ofdm_cyclic_prefixer_sptr
+ digital_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key);
+
+
+ protected:
+ digital_ofdm_cyclic_prefixer (size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key);
+
+ //! Return the number of complex samples from the number of OFDM symbols (includes rolloff)
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ private:
+ size_t d_fft_len;
+ //! FFT length + CP length in samples
+ size_t d_output_size;
+ //! Length of the cyclic prefix in samples
+ int d_cp_size;
+ //! Length of pulse rolloff in samples
+ int d_rolloff_len;
+ //! Buffers the up-flank (at the beginning of the cyclic prefix)
+ std::vector<float> d_up_flank;
+ //! Buffers the down-flank (which trails the symbol)
+ std::vector<float> d_down_flank;
+ std::vector<gr_complex> d_delay_line; // We do this explicitly to avoid outputting zeroes (i.e. no history!)
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H */
+
diff --git a/gr-digital/include/digital_ofdm_equalizer_base.h b/gr-digital/include/digital_ofdm_equalizer_base.h
new file mode 100644
index 0000000000..8665395540
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_equalizer_base.h
@@ -0,0 +1,102 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H
+#define INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H
+
+#include <digital/api.h>
+#include <gr_tags.h>
+#include <gr_complex.h>
+#include <boost/enable_shared_from_this.hpp>
+
+class digital_ofdm_equalizer_base;
+typedef boost::shared_ptr<digital_ofdm_equalizer_base> digital_ofdm_equalizer_base_sptr;
+
+class digital_ofdm_equalizer_1d_pilots;
+typedef boost::shared_ptr<digital_ofdm_equalizer_1d_pilots> digital_ofdm_equalizer_1d_pilots_sptr;
+
+/* \brief Base class for implementation details of frequency-domain OFDM equalizers.
+ * \ingroup ofdm_blk
+ * \ingroup eq_blk
+ *
+ */
+class DIGITAL_API digital_ofdm_equalizer_base : public boost::enable_shared_from_this<digital_ofdm_equalizer_base>
+{
+ protected:
+ int d_fft_len;
+ int d_carr_offset;
+
+ public:
+ digital_ofdm_equalizer_base(int fft_len);
+ ~digital_ofdm_equalizer_base();
+
+ virtual void reset() = 0;
+ void set_carrier_offset(int offset) { d_carr_offset = offset; };
+ virtual void equalize(
+ gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>()) = 0;
+ virtual void get_channel_state(std::vector<gr_complex> &taps) = 0;
+ int fft_len() { return d_fft_len; };
+ digital_ofdm_equalizer_base_sptr base() { return shared_from_this(); };
+};
+
+
+/* \brief Base class for implementation details of 1-dimensional OFDM FDEs which use pilot tones.
+ * \ingroup digital
+ *
+ */
+class DIGITAL_API digital_ofdm_equalizer_1d_pilots : public digital_ofdm_equalizer_base
+{
+ protected:
+ //! If \p d_occupied_carriers[k][l] is true, symbol k, carrier l is carrying data.
+ // (this is a different format than occupied_carriers!)
+ std::vector<bool> d_occupied_carriers;
+ //! If \p d_pilot_carriers[k][l] is true, symbol k, carrier l is carrying data.
+ // (this is a different format than pilot_carriers!)
+ std::vector<std::vector<bool> > d_pilot_carriers;
+ //! If \p d_pilot_carriers[k][l] is true, d_pilot_symbols[k][l] is its tx'd value.
+ // (this is a different format than pilot_symbols!)
+ std::vector<std::vector<gr_complex> > d_pilot_symbols;
+ //! In case the frame doesn't begin with OFDM symbol 0, this is the index of the first symbol
+ int d_symbols_skipped;
+ //! The current position in the set of pilot symbols
+ int d_pilot_carr_set;
+ //! Vector of length d_fft_len saving the current channel state (on the occupied carriers)
+ std::vector<gr_complex> d_channel_state;
+
+ public:
+ digital_ofdm_equalizer_1d_pilots(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ bool input_is_shifted);
+ ~digital_ofdm_equalizer_1d_pilots();
+
+ void reset();
+ void get_channel_state(std::vector<gr_complex> &taps);
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H */
+
diff --git a/gr-digital/include/digital_ofdm_equalizer_simpledfe.h b/gr-digital/include/digital_ofdm_equalizer_simpledfe.h
new file mode 100644
index 0000000000..89b0b5cd6d
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_equalizer_simpledfe.h
@@ -0,0 +1,126 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H
+#define INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H
+
+#include <digital/api.h>
+#include <digital/constellation.h>
+#include <digital_ofdm_equalizer_base.h>
+
+class digital_ofdm_equalizer_simpledfe;
+typedef boost::shared_ptr<digital_ofdm_equalizer_simpledfe> digital_ofdm_equalizer_simpledfe_sptr;
+
+/*
+ * \param fft_len FFT length
+ * \param constellation The constellation object describing the modulation used
+ * on the subcarriers (e.g. QPSK). This is used to decode
+ * the individual symbols.
+ * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator
+ * for a description.
+ * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator
+ * for a description.
+ * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator
+ * for a description.
+ * \param alpha Averaging coefficient (in a nutshell, if \f$H_{i,k}\f$ is the channel
+ * state for carrier i and symbol k,
+ * \f$H_{i,k+1} = \alpha H_{i,k} + (1 - \alpha) H_{i,k+1}\f$. Make this
+ * larger if there's more noise, but keep in mind that larger values
+ * of alpha mean slower response to channel changes).
+ * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers.
+ * If the first symbol of the frame was removed (e.g. to decode the
+ * header), set this make sure the pilot symbols are correctly
+ * identified.
+ * \param input_is_shifted Set this to false if the input signal is not shifted, i.e.
+ * the first input items is on the DC carrier.
+ * Note that a lot of the OFDM receiver blocks operate on shifted
+ * signals!
+ */
+DIGITAL_API digital_ofdm_equalizer_simpledfe_sptr
+digital_make_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const gr::digital::constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ float alpha = 0.1,
+ bool input_is_shifted = true);
+
+/* \brief Simple decision feedback equalizer for OFDM.
+ * \ingroup ofdm_blk
+ * \ingroup eq_blk
+ *
+ * Equalizes an OFDM signal symbol by symbol using knowledge of the
+ * complex modulations symbols.
+ * For every symbol, the following steps are performed:
+ * - On every sub-carrier, decode the modulation symbol
+ * - Use the difference between the decoded symbol and the received symbol
+ * to update the channel state on this carrier
+ * - Whenever a pilot symbol is found, it uses the known pilot symbol to
+ * update the channel state.
+ *
+ * This equalizer makes a lot of assumptions:
+ * - The initial channel state is good enough to decode the first
+ * symbol without error (unless the first symbol only consists of pilot
+ * tones)
+ * - The channel changes only very slowly, such that the channel state
+ * from one symbol is enough to decode the next
+ * - SNR low enough that equalization will always suffice to correctly
+ * decode a symbol
+ * If these assumptions are not met, the most common error is that the
+ * channel state is estimated incorrectly during equalization; after that,
+ * all subsequent symbols will be completely wrong.
+ *
+ * Note that the equalized symbols are *exact points* on the constellation.
+ * This means soft information of the modulation symbols is lost after the
+ * equalization, which is suboptimal for channel codes that use soft decision.
+ *
+ */
+class DIGITAL_API digital_ofdm_equalizer_simpledfe : public digital_ofdm_equalizer_1d_pilots
+{
+ public:
+ digital_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const gr::digital::constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ float alpha = 0.1,
+ bool input_is_shifted = true);
+
+ ~digital_ofdm_equalizer_simpledfe();
+
+ void equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>());
+
+ private:
+ gr::digital::constellation_sptr d_constellation;
+ //! Averaging coefficient
+ float d_alpha;
+
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H */
+
diff --git a/gr-digital/include/digital_ofdm_equalizer_static.h b/gr-digital/include/digital_ofdm_equalizer_static.h
new file mode 100644
index 0000000000..4537d329f4
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_equalizer_static.h
@@ -0,0 +1,97 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H
+#define INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H
+
+#include <digital/api.h>
+#include <digital/constellation.h>
+#include <digital_ofdm_equalizer_base.h>
+
+class digital_ofdm_equalizer_static;
+typedef boost::shared_ptr<digital_ofdm_equalizer_static> digital_ofdm_equalizer_static_sptr;
+
+/*
+ * \param fft_len FFT length
+ * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator
+ * for a description.
+ * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator
+ * for a description.
+ * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator
+ * for a description.
+ * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers.
+ * If the first symbol of the frame was removed (e.g. to decode the
+ * header), set this make sure the pilot symbols are correctly
+ * identified.
+ * \param input_is_shifted Set this to false if the input signal is not shifted, i.e.
+ * the first input items is on the DC carrier.
+ * Note that a lot of the OFDM receiver blocks operate on shifted
+ * signals!
+ */
+DIGITAL_API digital_ofdm_equalizer_static_sptr
+digital_make_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ bool input_is_shifted = true);
+
+/* \brief Very simple static equalizer for OFDM.
+ * \ingroup ofdm_blk
+ * \ingroup eq_blk
+ *
+ * This is an extremely simple equalizer. It will only work for high-SNR, very, very
+ * slowly changing channels.
+ * It simply divides the signal with the currently known channel state. Whenever
+ * a pilot symbol comes around, it updates the channel state on that particular
+ * carrier by dividing the received symbol with the known pilot symbol.
+ */
+class DIGITAL_API digital_ofdm_equalizer_static : public digital_ofdm_equalizer_1d_pilots
+{
+ public:
+ digital_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ bool input_is_shifted = true);
+ ~digital_ofdm_equalizer_static();
+
+ /*! \brief Divide the input signal with the current channel state.
+ *
+ * Does the following (and nothing else):
+ * - Divide every OFDM symbol with the current channel state
+ * - If a pilot symbol is found, re-set the channel state by dividing the received
+ * symbol with the known pilot symbol
+ */
+ void equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>());
+
+ private:
+
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H */
+
diff --git a/gr-digital/include/digital_ofdm_sync_sc_cfb.h b/gr-digital/include/digital_ofdm_sync_sc_cfb.h
new file mode 100644
index 0000000000..cc728814ed
--- /dev/null
+++ b/gr-digital/include/digital_ofdm_sync_sc_cfb.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H
+#define INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H
+
+#include <digital/api.h>
+#include <gr_hier_block2.h>
+
+class digital_ofdm_sync_sc_cfb;
+typedef boost::shared_ptr<digital_ofdm_sync_sc_cfb> digital_ofdm_sync_sc_cfb_sptr;
+
+/*! \param fft_len FFT length
+ * \param cp_len Length of the guard interval (cyclic prefix) in samples
+ */
+DIGITAL_API digital_ofdm_sync_sc_cfb_sptr
+digital_make_ofdm_sync_sc_cfb (int fft_len, int cp_len);
+
+/*!
+ * \brief Schmidl & Cox synchronisation for OFDM
+ * \ingroup ofdm_blk
+ * \ingroup sync_blk
+ *
+ * Input: complex samples.
+ * Output 0: Fine frequency offset, scaled by the OFDM symbol duration.
+ * This is \f$\hat{\varphi}\f$ in [1]. The normalized frequency
+ * offset is then 2.0*output0/fft_len.
+ * Output 1: Beginning of the first OFDM symbol after the first (doubled) OFDM
+ * symbol. The beginning is marked with a 1 (it's 0 everywhere else).
+ *
+ * The evaluation of the coarse frequency offset is *not* done in this block.
+ * Also, the initial equalizer taps are not calculated here.
+ *
+ * Note that we use a different normalization factor in the timing metric than
+ * the authors do in their original work[1]. If the timing metric (8) is
+ * \f[
+ * M(d) = \frac{|P(d)|^2}{(R(d))^2},
+ * \f]
+ * we calculate the normalization as
+ * \f[
+ * R(d) = \frac{1}{2} \sum_{k=0}^{N-1} |r_{k+d}|^2,
+ * \f]
+ * i.e., we estimate the energy from *both* half-symbols. This avoids spurious detects
+ * at the end of a burst, when the energy level suddenly drops.
+ *
+ * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM",
+ * Communications, IEEE Transactions on, 1997.
+ */
+class DIGITAL_API digital_ofdm_sync_sc_cfb : public gr_hier_block2
+{
+ private:
+ friend DIGITAL_API digital_ofdm_sync_sc_cfb_sptr digital_make_ofdm_sync_sc_cfb (int fft_len, int cp_len);
+ digital_ofdm_sync_sc_cfb(int fft_len, int cp_len);
+
+ public:
+ ~digital_ofdm_sync_sc_cfb();
+
+};
+
+#endif /* INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H */
+
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 74141f46af..5178506049 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -26,6 +26,7 @@ include_directories(
${GR_ANALOG_INCLUDE_DIRS}
${GR_FFT_INCLUDE_DIRS}
${GR_FILTER_INCLUDE_DIRS}
+ ${GR_BLOCKS_INCLUDE_DIRS}
${GNURADIO_CORE_INCLUDE_DIRS}
${VOLK_INCLUDE_DIRS}
${GRUEL_INCLUDE_DIRS}
@@ -112,49 +113,67 @@ expand_cc(chunks_to_symbols_XX_impl bf bc sf sc if ic)
########################################################################
list(APPEND digital_sources
${generated_sources}
- constellation.cc
- crc32.cc
- glfsr.cc
- mpsk_snr_est.cc
additive_scrambler_bb_impl.cc
binary_slicer_fb_impl.cc
clock_recovery_mm_cc_impl.cc
clock_recovery_mm_ff_impl.cc
cma_equalizer_cc_impl.cc
- constellation_receiver_cb_impl.cc
+ constellation.cc
constellation_decoder_cb_impl.cc
+ constellation_receiver_cb_impl.cc
correlate_access_code_bb_impl.cc
correlate_access_code_tag_bb_impl.cc
costas_loop_cc_impl.cc
cpmmod_bc_impl.cc
+ crc32.cc
descrambler_bb_impl.cc
diff_decoder_bb_impl.cc
diff_encoder_bb_impl.cc
diff_phasor_cc_impl.cc
+ digital_crc32_bb.cc
+ digital_ofdm_carrier_allocator_cvc.cc
+ digital_ofdm_chanest_vcvc.cc
+ digital_ofdm_cyclic_prefixer.cc
+ digital_ofdm_equalizer_base.cc
+ digital_ofdm_equalizer_simpledfe.cc
+ digital_ofdm_equalizer_static.cc
+ digital_ofdm_sync_sc_cfb.cc
fll_band_edge_cc_impl.cc
framer_sink_1_impl.cc
+ glfsr.cc
glfsr_source_b_impl.cc
glfsr_source_f_impl.cc
+ header_payload_demux_impl.cc
kurtotic_equalizer_cc_impl.cc
lms_dd_equalizer_cc_impl.cc
map_bb_impl.cc
mpsk_receiver_cc_impl.cc
+ mpsk_snr_est.cc
mpsk_snr_est_cc_impl.cc
ofdm_cyclic_prefixer_impl.cc
ofdm_frame_acquisition_impl.cc
+ ofdm_frame_equalizer_vcvc_impl.cc
ofdm_frame_sink_impl.cc
ofdm_insert_preamble_impl.cc
ofdm_mapper_bcv_impl.cc
ofdm_sampler_impl.cc
+ ofdm_serializer_vcc_impl.cc
+ packet_header_default.cc
+ packet_header_ofdm.cc
+ packet_headergenerator_bb_impl.cc
+ packet_headerparser_b_impl.cc
packet_sink_impl.cc
pfb_clock_sync_ccf_impl.cc
pfb_clock_sync_fff_impl.cc
pn_correlator_cc_impl.cc
probe_density_b_impl.cc
probe_mpsk_snr_est_c_impl.cc
+ scale_tags_impl.cc
scrambler_bb_impl.cc
- simple_framer_impl.cc
simple_correlator_impl.cc
+ simple_framer_impl.cc
+ tagged_stream_check_impl.cc
+ ts_insert_zeros_cc_impl.cc
)
#Add Windows DLL resource file if using MSVC
@@ -185,6 +204,13 @@ list(APPEND digital_libs
add_library(gnuradio-digital SHARED ${digital_sources})
target_link_libraries(gnuradio-digital ${digital_libs})
GR_LIBRARY_FOO(gnuradio-digital RUNTIME_COMPONENT "digital_runtime" DEVEL_COMPONENT "digital_devel")
-add_dependencies(gnuradio-digital
- digital_generated_includes digital_generated_swigs
- gnuradio-core gnuradio-filter gnuradio-analog)
+
+add_dependencies(
+ gnuradio-digital
+ digital_generated_includes
+ digital_generated_swigs
+ gnuradio-core
+ gnuradio-filter
+ gnuradio-analog
+ gnuradio-blocks
+)
diff --git a/gr-digital/lib/digital_crc32_bb.cc b/gr-digital/lib/digital_crc32_bb.cc
new file mode 100644
index 0000000000..40d313ba89
--- /dev/null
+++ b/gr-digital/lib/digital_crc32_bb.cc
@@ -0,0 +1,102 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include <digital/crc32.h>
+#include <digital_crc32_bb.h>
+
+digital_crc32_bb_sptr
+digital_make_crc32_bb (bool check, const std::string& lengthtagname)
+{
+ return gnuradio::get_initial_sptr (new digital_crc32_bb(check, lengthtagname));
+}
+
+
+digital_crc32_bb::digital_crc32_bb (bool check, const std::string& lengthtagname)
+ : gr_tagged_stream_block ("crc32_bb",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ lengthtagname),
+ d_check(check)
+{
+ set_tag_propagation_policy(TPP_DONT);
+}
+
+
+digital_crc32_bb::~digital_crc32_bb()
+{
+}
+
+
+int
+digital_crc32_bb::calculate_output_stream_length(const std::vector<int> &ninput_items)
+{
+ if (d_check) {
+ return ninput_items[0] - 4;
+ } else {
+ return ninput_items[0] + 4;
+ }
+}
+
+
+int
+digital_crc32_bb::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+ long packet_length = ninput_items[0];
+ int packet_size_diff = d_check ? -4 : 4;
+ unsigned int crc;
+
+ if (d_check) {
+ crc = gr::digital::crc32(in, packet_length-4);
+ if (crc != *(unsigned int *)(in+packet_length-4)) { // Drop package
+ return 0;
+ }
+ memcpy((void *) out, (const void *) in, packet_length-4);
+ } else {
+ crc = gr::digital::crc32(in, packet_length);
+ memcpy((void *) out, (const void *) in, packet_length);
+ memcpy((void *) (out + packet_length), &crc, 4); // FIXME big-endian/little-endian, this might be wrong
+ }
+
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+packet_length);
+ for (unsigned i = 0; i < tags.size(); i++) {
+ tags[i].offset -= nitems_read(0);
+ if (d_check && tags[i].offset > packet_length+packet_size_diff) {
+ tags[i].offset = packet_length-5;
+ }
+ add_item_tag(0, nitems_written(0) + tags[i].offset,
+ tags[i].key,
+ tags[i].value);
+ }
+
+ return packet_length + packet_size_diff;
+}
+
diff --git a/gr-digital/lib/digital_ofdm_carrier_allocator_cvc.cc b/gr-digital/lib/digital_ofdm_carrier_allocator_cvc.cc
new file mode 100644
index 0000000000..e5b3013302
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_carrier_allocator_cvc.cc
@@ -0,0 +1,156 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "digital_ofdm_carrier_allocator_cvc.h"
+
+digital_ofdm_carrier_allocator_cvc_sptr
+digital_make_ofdm_carrier_allocator_cvc (
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ const std::string &len_tag_key)
+{
+ return gnuradio::get_initial_sptr (new digital_ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, len_tag_key));
+}
+
+
+digital_ofdm_carrier_allocator_cvc::digital_ofdm_carrier_allocator_cvc (
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ const std::string &len_tag_key)
+ : gr_tagged_stream_block ("ofdm_carrier_allocator_cvc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex)),
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * fft_len), len_tag_key),
+ d_fft_len(fft_len),
+ d_occupied_carriers(occupied_carriers),
+ d_pilot_carriers(pilot_carriers),
+ d_pilot_symbols(pilot_symbols),
+ d_symbols_per_set(0)
+{
+ for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ for (unsigned j = 0; j < d_occupied_carriers[i].size(); j++) {
+ if (occupied_carriers[i][j] < 0) {
+ d_occupied_carriers[i][j] += d_fft_len;
+ }
+ if (d_occupied_carriers[i][j] > d_fft_len || d_occupied_carriers[i][j] < 0) {
+ throw std::invalid_argument("data carrier index out of bounds");
+ }
+ }
+ }
+ for (unsigned i = 0; i < d_pilot_carriers.size(); i++) {
+ if (d_pilot_carriers[i].size() != pilot_symbols[i].size()) {
+ throw std::invalid_argument("pilot_carriers do not match pilot_symbols");
+ }
+ for (unsigned j = 0; j < d_pilot_carriers[i].size(); j++) {
+ if (d_pilot_carriers[i][j] < 0) {
+ d_pilot_carriers[i][j] += d_fft_len;
+ }
+ if (d_pilot_carriers[i][j] > d_fft_len || d_pilot_carriers[i][j] < 0) {
+ throw std::invalid_argument("pilot carrier index out of bounds");
+ }
+ }
+ }
+
+ for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ d_symbols_per_set += d_occupied_carriers[i].size();
+ }
+ set_tag_propagation_policy(TPP_DONT);
+ set_relative_rate((double) d_symbols_per_set / d_occupied_carriers.size());
+}
+
+
+digital_ofdm_carrier_allocator_cvc::~digital_ofdm_carrier_allocator_cvc()
+{
+}
+
+
+int
+digital_ofdm_carrier_allocator_cvc::calculate_output_stream_length(const gr_vector_int &ninput_items)
+{
+ int nin = ninput_items[0];
+ int nout = (nin / d_symbols_per_set) * d_occupied_carriers.size();
+ int k = 0;
+ for (int i = 0; i < nin % d_symbols_per_set; k++) {
+ nout++;
+ i += d_occupied_carriers[k % d_occupied_carriers.size()].size();
+ }
+ return nout;
+}
+
+
+int
+digital_ofdm_carrier_allocator_cvc::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ std::vector<gr_tag_t> tags;
+
+ memset((void *) out, 0x00, sizeof(gr_complex) * d_fft_len * noutput_items);
+ long n_ofdm_symbols = 0;
+ int curr_set = 0;
+ int symbols_to_allocate = d_occupied_carriers[0].size();
+ int symbols_allocated = 0;
+ for (int i = 0; i < ninput_items[0]; i++) {
+ if (symbols_allocated == 0) {
+ // Copy all tags associated with these input symbols onto this OFDM symbol
+ get_tags_in_range(tags, 0,
+ nitems_read(0)+i,
+ nitems_read(0)+std::min(i+symbols_to_allocate, (int) ninput_items[0])
+ );
+ for (unsigned t = 0; t < tags.size(); t++) {
+ add_item_tag(0, nitems_written(0)+n_ofdm_symbols,
+ tags[t].key,
+ tags[t].value);
+ }
+ n_ofdm_symbols++;
+ }
+ out[(n_ofdm_symbols-1) * d_fft_len + d_occupied_carriers[curr_set][symbols_allocated]] = in[i];
+ symbols_allocated++;
+ if (symbols_allocated == symbols_to_allocate) {
+ curr_set = (curr_set + 1) % d_occupied_carriers.size();
+ symbols_to_allocate = d_occupied_carriers[curr_set].size();
+ symbols_allocated = 0;
+ }
+ }
+ // 2) Copy pilot symbols
+ curr_set = 0;
+ for (int i = 0; i < n_ofdm_symbols; i++) {
+ for (unsigned k = 0; k < d_pilot_carriers[curr_set].size(); k++) {
+ out[i * d_fft_len + d_pilot_carriers[curr_set][k]] = d_pilot_symbols[curr_set][k];
+ }
+ curr_set = (curr_set + 1) % d_pilot_carriers.size();
+ }
+
+ return n_ofdm_symbols;
+}
+
diff --git a/gr-digital/lib/digital_ofdm_chanest_vcvc.cc b/gr-digital/lib/digital_ofdm_chanest_vcvc.cc
new file mode 100644
index 0000000000..a484594577
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_chanest_vcvc.cc
@@ -0,0 +1,281 @@
+/* -*- c++ -*- */
+// vim: set sw=2:
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "digital_ofdm_chanest_vcvc.h"
+
+digital_ofdm_chanest_vcvc_sptr
+digital_make_ofdm_chanest_vcvc (
+ const std::vector<gr_complex> &sync_symbol1,
+ const std::vector<gr_complex> &sync_symbol2,
+ int n_data_symbols,
+ int eq_noise_red_len,
+ int max_carr_offset,
+ bool force_one_sync_symbol)
+{
+ return gnuradio::get_initial_sptr (new digital_ofdm_chanest_vcvc(
+ sync_symbol1, sync_symbol2, n_data_symbols, eq_noise_red_len, max_carr_offset, force_one_sync_symbol));
+}
+
+
+digital_ofdm_chanest_vcvc::digital_ofdm_chanest_vcvc (
+ const std::vector<gr_complex> &sync_symbol1,
+ const std::vector<gr_complex> &sync_symbol2,
+ int n_data_symbols,
+ int eq_noise_red_len,
+ int max_carr_offset,
+ bool force_one_sync_symbol)
+ : gr_block ("ofdm_chanest_vcvc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * sync_symbol1.size()),
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * sync_symbol1.size())),
+ d_fft_len(sync_symbol1.size()),
+ d_n_data_syms(n_data_symbols),
+ d_n_sync_syms(1),
+ d_eq_noise_red_len(eq_noise_red_len),
+ d_ref_sym((sync_symbol2.size() && !force_one_sync_symbol) ? sync_symbol2 : sync_symbol1),
+ d_corr_v(sync_symbol2),
+ d_known_symbol_diffs(0, 0),
+ d_new_symbol_diffs(0, 0),
+ d_interpolate(false)
+{
+ // Set index of first and last active carrier
+ for (int i = 0; i < d_fft_len; i++) {
+ if (d_ref_sym[i] != gr_complex(0, 0)) {
+ d_first_active_carrier = i;
+ break;
+ }
+ }
+ for (int i = d_fft_len-1; i >= 0; i--) {
+ if (d_ref_sym[i] != gr_complex(0, 0)) {
+ d_last_active_carrier = i;
+ break;
+ }
+ }
+
+ // Sanity checks
+ if (sync_symbol2.size()) {
+ if (sync_symbol1.size() != sync_symbol2.size()) {
+ throw std::invalid_argument("sync symbols must have equal length.");
+ }
+ if (!force_one_sync_symbol) {
+ d_n_sync_syms = 2;
+ }
+ } else {
+ if (sync_symbol1[d_first_active_carrier+1] == gr_complex(0, 0)) {
+ d_last_active_carrier++;
+ d_interpolate = true;
+ }
+ }
+
+ // Set up coarse freq estimation info
+ // Allow all possible values:
+ d_max_neg_carr_offset = -d_first_active_carrier;
+ d_max_pos_carr_offset = d_fft_len - d_last_active_carrier - 1;
+ if (max_carr_offset != -1) {
+ d_max_neg_carr_offset = std::max(-max_carr_offset, d_max_neg_carr_offset);
+ d_max_pos_carr_offset = std::min(max_carr_offset, d_max_pos_carr_offset);
+ }
+ // Carrier offsets must be even
+ if (d_max_neg_carr_offset % 2)
+ d_max_neg_carr_offset++;
+ if (d_max_pos_carr_offset % 2)
+ d_max_pos_carr_offset--;
+
+ if (d_n_sync_syms == 2) {
+ for (int i = 0; i < d_fft_len; i++) {
+ if (sync_symbol1[i] == gr_complex(0, 0)) {
+ d_corr_v[i] = gr_complex(0, 0);
+ } else {
+ d_corr_v[i] /= sync_symbol1[i];
+ }
+ }
+ } else {
+ d_corr_v.resize(0, 0);
+ d_known_symbol_diffs.resize(d_fft_len, 0);
+ d_new_symbol_diffs.resize(d_fft_len, 0);
+ for (int i = d_first_active_carrier; i < d_last_active_carrier-2 && i < d_fft_len-2; i += 2) {
+ d_known_symbol_diffs[i] = std::norm(sync_symbol1[i] - sync_symbol1[i+2]);
+ }
+ }
+
+ set_relative_rate((double) n_data_symbols / (n_data_symbols + d_n_sync_syms));
+ set_tag_propagation_policy(TPP_DONT);
+}
+
+
+digital_ofdm_chanest_vcvc::~digital_ofdm_chanest_vcvc()
+{
+}
+
+void
+digital_ofdm_chanest_vcvc::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ ninput_items_required[0] = (noutput_items/d_n_data_syms) * (d_n_data_syms + d_n_sync_syms);
+}
+
+
+int
+digital_ofdm_chanest_vcvc::get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2)
+{
+ int carr_offset = 0;
+ if (d_corr_v.size()) {
+ // Use Schmidl & Cox method
+ float Bg_max = 0;
+ // g here is 2g in the paper
+ for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) {
+ gr_complex tmp = gr_complex(0, 0);
+ for (int k = 0; k < d_fft_len; k++) {
+ if (d_corr_v[k] != gr_complex(0, 0)) {
+ tmp += std::conj(sync_sym1[k+g]) * std::conj(d_corr_v[k]) * sync_sym2[k+g];
+ }
+ }
+ if (std::abs(tmp) > Bg_max) {
+ Bg_max = std::abs(tmp);
+ carr_offset = g;
+ }
+ }
+ } else {
+ // Correlate
+ std::fill(d_new_symbol_diffs.begin(), d_new_symbol_diffs.end(), 0);
+ for(int i = 0; i < d_fft_len-2; i++) {
+ d_new_symbol_diffs[i] = std::norm(sync_sym1[i] - sync_sym1[i+2]);
+ }
+
+ float sum;
+ float max = 0;
+ for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) {
+ sum = 0;
+ for (int j = 0; j < d_fft_len; j++) {
+ if (d_known_symbol_diffs[j]) {
+ sum += (d_known_symbol_diffs[j] * d_new_symbol_diffs[j + g]);
+ }
+ if(sum > max) {
+ max = sum;
+ carr_offset = g;
+ }
+ }
+ }
+ }
+ return carr_offset;
+}
+
+
+void
+digital_ofdm_chanest_vcvc::get_chan_taps(
+ const gr_complex *sync_sym1,
+ const gr_complex *sync_sym2,
+ int carr_offset,
+ std::vector<gr_complex> &taps)
+{
+ const gr_complex *sym = ((d_n_sync_syms == 2) ? sync_sym2 : sync_sym1);
+ std::fill(taps.begin(), taps.end(), gr_complex(0, 0));
+ int loop_start = 0;
+ int loop_end = d_fft_len;
+ if (carr_offset > 0) {
+ loop_start = carr_offset;
+ } else if (carr_offset < 0) {
+ loop_end = d_fft_len + carr_offset;
+ }
+ for (int i = loop_start; i < loop_end; i++) {
+ if ((d_ref_sym[i-carr_offset] != gr_complex(0, 0))) {
+ taps[i] = sym[i] / d_ref_sym[i-carr_offset];
+ }
+ }
+
+ if (d_interpolate) {
+ for (int i = d_first_active_carrier + 1; i < d_last_active_carrier; i += 2) {
+ taps[i] = (taps[i-1] + taps[i+1]) / gr_complex(2.0, 0);
+ }
+ taps[d_last_active_carrier] = taps[d_last_active_carrier-1];
+ }
+
+ if (d_eq_noise_red_len) {
+ // TODO
+ // 1) IFFT
+ // 2) Set all elements > d_eq_noise_red_len to zero
+ // 3) FFT
+ }
+}
+
+
+// 1) Go through all the frames available on the input buffer
+// 2) Estimate the coarse freq. offset and the eq. taps from the
+// input symbol(s)
+// 3) Copy the data symbols to the output
+// 4) Copy all other tags onto the output. A tag that was on
+// a sync symbol is copied onto the first data symbol.
+// 5) Add the new tags for carrier offset and eq. taps
+int
+digital_ofdm_chanest_vcvc::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+ int n_frames = noutput_items/d_n_data_syms;
+ const int framesize = d_n_sync_syms + d_n_data_syms;
+
+ for (int i = 0; i < n_frames; i++) {
+ int carr_offset = 0;
+ if (d_max_neg_carr_offset || d_max_pos_carr_offset)
+ carr_offset = get_carr_offset(in, in+d_fft_len);
+ std::vector<gr_complex> chan_taps(d_fft_len, 0);
+ get_chan_taps(in, in+d_fft_len, carr_offset, chan_taps);
+
+ memcpy((void *) out,
+ (void *) &in[d_n_sync_syms * d_fft_len],
+ sizeof(gr_complex) * d_fft_len * d_n_data_syms);
+ in += framesize * d_fft_len;
+ out += d_n_data_syms * d_fft_len;
+
+ std::vector<gr_tag_t> tags;
+ this->get_tags_in_range(tags, 0,
+ this->nitems_read(0)+i*framesize,
+ this->nitems_read(0)+(i+1)*framesize);
+ for (unsigned t = 0; t < tags.size(); t++) {
+ int offset = tags[t].offset - (this->nitems_read(0) + i*framesize);
+ if (offset < d_n_sync_syms) {
+ offset = 0;
+ } else {
+ offset -= d_n_sync_syms;
+ }
+ tags[t].offset = offset + this->nitems_written(0) + i*d_n_data_syms;
+ this->add_item_tag(0, tags[t]);
+ }
+
+ this->add_item_tag(0, this->nitems_written(0) + i*d_n_data_syms,
+ pmt::string_to_symbol("ofdm_sync_carr_offset"),
+ pmt::from_long(carr_offset));
+ this->add_item_tag(0, this->nitems_written(0) + i*d_n_data_syms,
+ pmt::string_to_symbol("ofdm_sync_chan_taps"),
+ pmt::init_c32vector(d_fft_len, chan_taps));
+ }
+
+ consume_each(n_frames * framesize);
+ return n_frames * d_n_data_syms;
+}
+
diff --git a/gr-digital/lib/digital_ofdm_cyclic_prefixer.cc b/gr-digital/lib/digital_ofdm_cyclic_prefixer.cc
new file mode 100644
index 0000000000..ada5742a51
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_cyclic_prefixer.cc
@@ -0,0 +1,162 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006,2010,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cmath>
+#include <digital_ofdm_cyclic_prefixer.h>
+#include <gr_io_signature.h>
+
+digital_ofdm_cyclic_prefixer_sptr
+digital_make_ofdm_cyclic_prefixer (size_t input_size,
+ size_t output_size,
+ int rolloff_len,
+ const std::string &len_tag_key)
+{
+ return gnuradio::get_initial_sptr(new digital_ofdm_cyclic_prefixer (input_size,
+ output_size,
+ rolloff_len,
+ len_tag_key));
+}
+
+digital_ofdm_cyclic_prefixer::digital_ofdm_cyclic_prefixer (size_t input_size,
+ size_t output_size,
+ int rolloff_len,
+ const std::string &len_tag_key)
+ : gr_tagged_stream_block ("ofdm_cyclic_prefixer",
+ gr_make_io_signature (1, 1, input_size*sizeof(gr_complex)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)),
+ len_tag_key),
+ d_fft_len(input_size),
+ d_output_size(output_size),
+ d_cp_size(output_size - input_size),
+ d_rolloff_len(rolloff_len),
+ d_up_flank((rolloff_len ? rolloff_len-1 : 0), 0),
+ d_down_flank((rolloff_len ? rolloff_len-1 : 0), 0),
+ d_delay_line(0, 0)
+{
+ set_relative_rate(d_output_size);
+
+ // Flank of length 1 would just be rectangular
+ if (d_rolloff_len == 1) {
+ d_rolloff_len = 0;
+ }
+ if (d_rolloff_len) {
+ d_delay_line.resize(d_rolloff_len-1, 0);
+ if (rolloff_len > d_cp_size) {
+ throw std::invalid_argument("cyclic prefixer: rolloff len must smaller than the cyclic prefix.");
+ }
+ // The actual flanks are one sample shorter than d_rolloff_len, because the
+ // first sample of the up- and down flank is always zero and one, respectively
+ for (int i = 1; i < d_rolloff_len; i++) {
+ d_up_flank[i-1] = 0.5 * (1 + cos(M_PI * i/rolloff_len - M_PI));
+ d_down_flank[i-1] = 0.5 * (1 + cos(M_PI * (rolloff_len-i)/rolloff_len - M_PI));
+ }
+ }
+
+ if (len_tag_key.empty()) {
+ set_output_multiple(d_output_size);
+ } else {
+ set_tag_propagation_policy(TPP_DONT);
+ }
+}
+
+int
+digital_ofdm_cyclic_prefixer::calculate_output_stream_length(const gr_vector_int &ninput_items)
+{
+ int nout = ninput_items[0] * d_output_size + d_delay_line.size();
+ return nout;
+}
+
+// Operates in two ways:
+// - When there's a length tag name specified, operates in packet mode.
+// Here, an entire OFDM frame is processed at once. The final OFDM symbol
+// is postfixed with the delay line of the pulse shape.
+// We manually propagate tags.
+// - Otherwise, we're in freewheeling mode. Process as many OFDM symbols as
+// are space for in the output buffer. The delay line is never flushed.
+// Tags are propagated by the scheduler.
+int
+digital_ofdm_cyclic_prefixer::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ gr_complex *in = (gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+ int symbols_to_read = 0;
+
+ // 1) Figure out if we're in freewheeling or packet mode
+ if (!d_length_tag_key_str.empty()) {
+ symbols_to_read = ninput_items[0];
+ noutput_items = symbols_to_read * d_output_size + d_delay_line.size();
+ } else {
+ symbols_to_read = std::min(noutput_items / (int) d_output_size, ninput_items[0]);
+ noutput_items = symbols_to_read * d_output_size;
+ }
+
+ // 2) Do the cyclic prefixing and, optionally, the pulse shaping
+ for (int sym_idx = 0; sym_idx < symbols_to_read; sym_idx++) {
+ memcpy((void *)(out + d_cp_size), (void *) in, d_fft_len * sizeof(gr_complex));
+ memcpy((void *) out, (void *) (in + d_fft_len - d_cp_size), d_cp_size * sizeof(gr_complex));
+ if (d_rolloff_len) {
+ for (int i = 0; i < d_rolloff_len-1; i++) {
+ out[i] = out[i] * d_up_flank[i] + d_delay_line[i];
+ d_delay_line[i] = in[i] * d_down_flank[i];
+ }
+ }
+ in += d_fft_len;
+ out += d_output_size;
+ }
+
+ // 3) If we're in packet mode:
+ // - flush the delay line, if applicable
+ // - Propagate tags
+ if (!d_length_tag_key_str.empty()) {
+ if (d_rolloff_len) {
+ for (unsigned i = 0; i < d_delay_line.size(); i++) {
+ *out++ = d_delay_line[i];
+ }
+ d_delay_line.assign(d_delay_line.size(), 0);
+ }
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(
+ tags, 0,
+ nitems_read(0), nitems_read(0)+symbols_to_read
+ );
+ for (unsigned i = 0; i < tags.size(); i++) {
+ tags[i].offset = ((tags[i].offset - nitems_read(0)) * d_output_size) + nitems_written(0);
+ add_item_tag(0,
+ tags[i].offset,
+ tags[i].key,
+ tags[i].value
+ );
+ }
+ } else {
+ consume_each(symbols_to_read);
+ }
+
+ return noutput_items;
+}
+
diff --git a/gr-digital/lib/digital_ofdm_equalizer_base.cc b/gr-digital/lib/digital_ofdm_equalizer_base.cc
new file mode 100644
index 0000000000..b4fa5df87e
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_equalizer_base.cc
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "digital_ofdm_equalizer_base.h"
+
+// *** Base class ****************************************************
+digital_ofdm_equalizer_base::digital_ofdm_equalizer_base(int fft_len) :
+ d_fft_len(fft_len),
+ d_carr_offset(0)
+{
+}
+
+
+digital_ofdm_equalizer_base::~digital_ofdm_equalizer_base()
+{
+}
+
+
+// *** Sub-Base class for 1D equalizers using pilot tones *************
+digital_ofdm_equalizer_1d_pilots::digital_ofdm_equalizer_1d_pilots(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ bool input_is_shifted)
+ : digital_ofdm_equalizer_base(fft_len),
+ d_occupied_carriers(fft_len, false),
+ d_pilot_carriers(pilot_carriers.size(), std::vector<bool>(fft_len, false)),
+ d_pilot_symbols(pilot_symbols.size(), std::vector<gr_complex>(fft_len, gr_complex(0, 0))),
+ d_symbols_skipped(symbols_skipped),
+ d_pilot_carr_set(symbols_skipped),
+ d_channel_state(fft_len, gr_complex(1, 0))
+{
+ int fft_shift_width = 0;
+ if (input_is_shifted) {
+ fft_shift_width = fft_len/2;
+ }
+ if (!occupied_carriers.size()) {
+ std::fill(d_occupied_carriers.begin(), d_occupied_carriers.end(), true);
+ } else {
+ for (unsigned i = 0; i < occupied_carriers.size(); i++) {
+ for (unsigned k = 0; k < occupied_carriers[i].size(); k++) {
+ int carr_index = occupied_carriers[i][k];
+ if (occupied_carriers[i][k] < 0) {
+ carr_index += fft_len;
+ }
+ if (carr_index >= fft_len || carr_index < 0) {
+ throw std::invalid_argument("data carrier index out of bounds.");
+ }
+ d_occupied_carriers[(carr_index + fft_shift_width) % fft_len] = true;
+ }
+ }
+ }
+ if (pilot_carriers.size()) {
+ for (unsigned i = 0; i < pilot_carriers.size(); i++) {
+ if (pilot_carriers[i].size() != pilot_symbols[i].size()) {
+ throw std::invalid_argument("pilot carriers and -symbols do not match.");
+ }
+ for (unsigned k = 0; k < pilot_carriers[i].size(); k++) {
+ int carr_index = pilot_carriers[i][k];
+ if (pilot_carriers[i][k] < 0) {
+ carr_index += fft_len;
+ }
+ if (carr_index >= fft_len || carr_index < 0) {
+ throw std::invalid_argument("pilot carrier index out of bounds.");
+ }
+ d_pilot_carriers[i][(carr_index + fft_shift_width) % fft_len] = true;
+ d_pilot_symbols[i][(carr_index + fft_shift_width) % fft_len] = pilot_symbols[i][k];
+ }
+ }
+ }
+}
+
+
+digital_ofdm_equalizer_1d_pilots::~digital_ofdm_equalizer_1d_pilots()
+{
+}
+
+
+void
+digital_ofdm_equalizer_1d_pilots::reset()
+{
+ std::fill(d_channel_state.begin(), d_channel_state.end(), gr_complex(1, 0));
+ d_pilot_carr_set = d_symbols_skipped;
+}
+
+
+void digital_ofdm_equalizer_1d_pilots::get_channel_state(std::vector<gr_complex> &taps)
+{
+ taps = d_channel_state;
+}
+
+
diff --git a/gr-digital/lib/digital_ofdm_equalizer_simpledfe.cc b/gr-digital/lib/digital_ofdm_equalizer_simpledfe.cc
new file mode 100644
index 0000000000..c6a05b9da8
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_equalizer_simpledfe.cc
@@ -0,0 +1,101 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "digital_ofdm_equalizer_simpledfe.h"
+
+digital_ofdm_equalizer_simpledfe_sptr
+digital_make_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const gr::digital::constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ float alpha,
+ bool input_is_shifted)
+{
+ return digital_ofdm_equalizer_simpledfe_sptr(new digital_ofdm_equalizer_simpledfe(
+ fft_len,
+ constellation,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ symbols_skipped,
+ alpha,
+ input_is_shifted));
+}
+
+digital_ofdm_equalizer_simpledfe::digital_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const gr::digital::constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ float alpha,
+ bool input_is_shifted)
+ : digital_ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted),
+ d_constellation(constellation),
+ d_alpha(alpha)
+{
+}
+
+
+digital_ofdm_equalizer_simpledfe::~digital_ofdm_equalizer_simpledfe()
+{
+}
+
+
+void
+digital_ofdm_equalizer_simpledfe::equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps,
+ const std::vector<gr_tag_t> &tags)
+{
+ if (!initial_taps.empty()) {
+ d_channel_state = initial_taps;
+ }
+ gr_complex sym_eq, sym_est;
+
+ for (int i = 0; i < n_sym; i++) {
+ for (int k = 0; k < d_fft_len; k++) {
+ if (!d_occupied_carriers[k]) {
+ continue;
+ }
+ if (d_pilot_carriers.size() && d_pilot_carriers[d_pilot_carr_set][k-d_carr_offset]) {
+ d_channel_state[k] = d_alpha * d_channel_state[k]
+ + (1-d_alpha) * frame[i*d_fft_len + k] / d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset];
+ frame[i*d_fft_len+k] = d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset];
+ } else {
+ sym_eq = frame[i*d_fft_len+k] / d_channel_state[k];
+ d_constellation->map_to_points(d_constellation->decision_maker(&sym_eq), &sym_est);
+ d_channel_state[k] = d_alpha * d_channel_state[k] + frame[i*d_fft_len+k] / sym_est;
+ frame[i*d_fft_len+k] = sym_est;
+ }
+ }
+ d_pilot_carr_set = (d_pilot_carr_set + 1) % d_pilot_carriers.size();
+ }
+}
+
diff --git a/gr-digital/lib/digital_ofdm_equalizer_static.cc b/gr-digital/lib/digital_ofdm_equalizer_static.cc
new file mode 100644
index 0000000000..66903fa90a
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_equalizer_static.cc
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "digital_ofdm_equalizer_static.h"
+
+#include <iostream>
+
+digital_ofdm_equalizer_static_sptr
+digital_make_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ bool input_is_shifted)
+{
+ return digital_ofdm_equalizer_static_sptr(new digital_ofdm_equalizer_static(
+ fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ symbols_skipped,
+ input_is_shifted));
+}
+
+digital_ofdm_equalizer_static::digital_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ bool input_is_shifted)
+ : digital_ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted)
+{
+}
+
+
+digital_ofdm_equalizer_static::~digital_ofdm_equalizer_static()
+{
+}
+
+
+void
+digital_ofdm_equalizer_static::equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps,
+ const std::vector<gr_tag_t> &tags)
+{
+ d_channel_state = initial_taps;
+
+ for (int i = 0; i < n_sym; i++) {
+ for (int k = 0; k < d_fft_len; k++) {
+ if (!d_occupied_carriers[k]) {
+ continue;
+ }
+ if (d_pilot_carriers.size() && d_pilot_carriers[d_pilot_carr_set][k-d_carr_offset]) {
+ d_channel_state[k] = frame[i*d_fft_len + k] / d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset];
+ frame[i*d_fft_len+k] = d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset];
+ } else {
+ frame[i*d_fft_len+k] /= d_channel_state[k];
+ }
+ }
+ if (!d_pilot_carriers.empty()) {
+ d_pilot_carr_set = (d_pilot_carr_set + 1) % d_pilot_carriers.size();
+ }
+ }
+}
+
diff --git a/gr-digital/lib/digital_ofdm_sync_sc_cfb.cc b/gr-digital/lib/digital_ofdm_sync_sc_cfb.cc
new file mode 100644
index 0000000000..dbb8571c28
--- /dev/null
+++ b/gr-digital/lib/digital_ofdm_sync_sc_cfb.cc
@@ -0,0 +1,109 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "digital_ofdm_sync_sc_cfb.h"
+
+#include <analog/plateau_detector_fb.h>
+#include <blocks/complex_to_arg.h>
+#include <blocks/complex_to_mag_squared.h>
+#include <blocks/conjugate_cc.h>
+#include <blocks/delay.h>
+#include <blocks/divide_ff.h>
+#include <blocks/multiply_cc.h>
+#include <blocks/multiply_ff.h>
+#include <blocks/sample_and_hold_ff.h>
+#include <filter/fir_filter_ccf.h>
+#include <filter/fir_filter_fff.h>
+
+// Define this to add a third output for debugging
+//#define SYNC_ADD_DEBUG_OUTPUT
+
+digital_ofdm_sync_sc_cfb_sptr
+digital_make_ofdm_sync_sc_cfb (int fft_len, int cp_len)
+{
+ return gnuradio::get_initial_sptr (new digital_ofdm_sync_sc_cfb(fft_len, cp_len));
+}
+
+
+digital_ofdm_sync_sc_cfb::digital_ofdm_sync_sc_cfb (int fft_len, int cp_len)
+ : gr_hier_block2 ("ofdm_sync_sc_cfb",
+ gr_make_io_signature(1, 1, sizeof (gr_complex)),
+#ifndef SYNC_ADD_DEBUG_OUTPUT
+ gr_make_io_signature2(2, 2, sizeof (float), sizeof (unsigned char)))
+#else
+ gr_make_io_signature3(3, 3, sizeof (float), sizeof (unsigned char), sizeof (float)))
+#endif
+{
+ std::vector<float> ma_taps(fft_len/2, 1.0);
+ gr::blocks::delay::sptr delay(gr::blocks::delay::make(sizeof(gr_complex), fft_len/2));
+ gr::blocks::conjugate_cc::sptr delay_conjugate(gr::blocks::conjugate_cc::make());
+ gr::blocks::multiply_cc::sptr delay_corr(gr::blocks::multiply_cc::make());
+ gr::filter::fir_filter_ccf::sptr delay_ma(gr::filter::fir_filter_ccf::make(1, std::vector<float>(fft_len/2, 1.0)));
+ gr::blocks::complex_to_mag_squared::sptr delay_magsquare(gr::blocks::complex_to_mag_squared::make());
+ gr::blocks::divide_ff::sptr delay_normalize(gr::blocks::divide_ff::make());
+
+ gr::blocks::complex_to_mag_squared::sptr normalizer_magsquare(gr::blocks::complex_to_mag_squared::make());
+ gr::filter::fir_filter_fff::sptr normalizer_ma(gr::filter::fir_filter_fff::make(1, std::vector<float>(fft_len, 0.5)));
+ gr::blocks::multiply_ff::sptr normalizer_square(gr::blocks::multiply_ff::make());
+
+ gr::blocks::complex_to_arg::sptr peak_to_angle(gr::blocks::complex_to_arg::make());
+ gr::blocks::sample_and_hold_ff::sptr sample_and_hold(gr::blocks::sample_and_hold_ff::make());
+
+ gr::analog::plateau_detector_fb::sptr plateau_detector(gr::analog::plateau_detector_fb::make(cp_len));
+
+ // Delay Path
+ connect(self(), 0, delay, 0);
+ connect(delay, 0, delay_conjugate, 0);
+ connect(delay_conjugate, 0, delay_corr, 1);
+ connect(self(), 0, delay_corr, 0);
+ connect(delay_corr, 0, delay_ma, 0);
+ connect(delay_ma, 0, delay_magsquare, 0);
+ connect(delay_magsquare, 0, delay_normalize, 0);
+ // Energy Path
+ connect(self(), 0, normalizer_magsquare, 0);
+ connect(normalizer_magsquare, 0, normalizer_ma, 0);
+ connect(normalizer_ma, 0, normalizer_square, 0);
+ connect(normalizer_ma, 0, normalizer_square, 1);
+ connect(normalizer_square, 0, delay_normalize, 1);
+ // Fine frequency estimate (output 0)
+ connect(delay_ma, 0, peak_to_angle, 0);
+ connect(peak_to_angle, 0, sample_and_hold, 0);
+ connect(sample_and_hold, 0, self(), 0);
+ // Peak detect (output 1)
+ connect(delay_normalize, 0, plateau_detector, 0);
+ connect(plateau_detector, 0, sample_and_hold, 1);
+ connect(plateau_detector, 0, self(), 1);
+#ifdef SYNC_ADD_DEBUG_OUTPUT
+ // Debugging: timing metric (output 2)
+ connect(delay_normalize, 0, self(), 2);
+#endif
+}
+
+
+digital_ofdm_sync_sc_cfb::~digital_ofdm_sync_sc_cfb()
+{
+}
+
diff --git a/gr-digital/lib/header_payload_demux_impl.cc b/gr-digital/lib/header_payload_demux_impl.cc
new file mode 100644
index 0000000000..a2e81c5b8e
--- /dev/null
+++ b/gr-digital/lib/header_payload_demux_impl.cc
@@ -0,0 +1,292 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <climits>
+#include <gr_io_signature.h>
+#include "header_payload_demux_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ enum demux_states_t {
+ STATE_IDLE,
+ STATE_HEADER,
+ STATE_WAIT_FOR_MSG,
+ STATE_PAYLOAD
+ };
+
+#define msg_port_id pmt::mp("header_data")
+
+ header_payload_demux::sptr
+ header_payload_demux::make(
+ int header_len,
+ int items_per_symbol,
+ int guard_interval,
+ const std::string &length_tag_key,
+ const std::string &trigger_tag_key,
+ bool output_symbols,
+ size_t itemsize)
+ {
+ return gnuradio::get_initial_sptr (
+ new header_payload_demux_impl(
+ header_len,
+ items_per_symbol,
+ guard_interval,
+ length_tag_key,
+ trigger_tag_key,
+ output_symbols,
+ itemsize
+ )
+ );
+ }
+
+ header_payload_demux_impl::header_payload_demux_impl(
+ int header_len,
+ int items_per_symbol,
+ int guard_interval,
+ const std::string &length_tag_key,
+ const std::string &trigger_tag_key,
+ bool output_symbols,
+ size_t itemsize
+ ) : gr_block("header_payload_demux",
+ gr_make_io_signature2(1, 2, itemsize, sizeof(char)),
+ gr_make_io_signature(2, 2, (output_symbols ? itemsize * items_per_symbol : itemsize))),
+ d_header_len(header_len),
+ d_items_per_symbol(items_per_symbol),
+ d_gi(guard_interval),
+ d_len_tag_key(pmt::string_to_symbol(length_tag_key)),
+ d_trigger_tag_key(pmt::string_to_symbol(trigger_tag_key)),
+ d_output_symbols(output_symbols),
+ d_itemsize(itemsize),
+ d_uses_trigger_tag(!trigger_tag_key.empty()),
+ d_state(STATE_IDLE)
+ {
+ if (d_header_len < 1) {
+ throw std::invalid_argument("Header length must be at least 1 symbol.");
+ }
+ if (d_items_per_symbol < 1 || d_gi < 0 || d_itemsize < 1) {
+ throw std::invalid_argument("Items and symbol sizes must be at least 1.");
+ }
+ set_output_multiple(d_items_per_symbol);
+ message_port_register_in(msg_port_id);
+ }
+
+ header_payload_demux_impl::~header_payload_demux_impl()
+ {
+ }
+
+ void
+ header_payload_demux_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ // noutput_items is an integer multiple of d_items_per_symbol!
+ for (unsigned i = 0; i < ninput_items_required.size(); i++) {
+ ninput_items_required[i] =
+ noutput_items / d_items_per_symbol * (d_items_per_symbol + d_gi);
+ }
+ }
+
+ int
+ header_payload_demux_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 unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out_header = (unsigned char *) output_items[0];
+ unsigned char *out_payload = (unsigned char *) output_items[1];
+
+ int nread = 0;
+ bool exit_loop = false;
+
+ int produced_hdr = 0;
+ int produced_payload = 0;
+
+ while (nread < noutput_items && !exit_loop) {
+ switch (d_state) {
+ case STATE_IDLE:
+ // 1) Search for a trigger signal on input 1 (if present)
+ // 2) Search for a trigger tag, make sure it's the first one
+ // The first trigger to be found is used!
+ // 3) Make sure the right number of items is skipped
+ // 4) If trigger found, switch to STATE_HEADER
+ if (find_trigger_signal(nread, noutput_items, input_items)) {
+ d_remaining_symbols = d_header_len;
+ d_state = STATE_HEADER;
+ in += nread * d_itemsize;
+ }
+ break;
+
+ case STATE_HEADER:
+ copy_symbol(in, out_header, 0, nread, produced_hdr);
+ if (d_remaining_symbols == 0) {
+ d_state = STATE_WAIT_FOR_MSG;
+ exit_loop = true;
+ }
+ break;
+
+ case STATE_WAIT_FOR_MSG:
+ // If we're in this state, nread is zero (because previous state exits loop)
+ // 1) Wait for msg (blocking call)
+ // 2) set d_remaining_symbols
+ // 3) Write tags
+ // 4) fall through to next state
+ d_remaining_symbols = -1;
+ if (!parse_header_data_msg()) {
+ exit_loop = true;
+ break;
+ }
+ d_state = STATE_PAYLOAD;
+
+ case STATE_PAYLOAD:
+ copy_symbol(in, out_payload, 1, nread, produced_payload);
+ if (d_remaining_symbols == 0) {
+ d_state = STATE_IDLE;
+ exit_loop = true;
+ }
+ break;
+
+ default:
+ throw std::runtime_error("invalid state");
+ } /* switch */
+ } /* while(nread < noutput_items) */
+
+ if (!d_output_symbols) {
+ produced_hdr *= d_items_per_symbol;
+ produced_payload *= d_items_per_symbol;
+ }
+ produce(0, produced_hdr);
+ produce(1, produced_payload);
+ consume_each (nread);
+ return WORK_CALLED_PRODUCE;
+ } /* general_work() */
+
+
+ bool
+ header_payload_demux_impl::find_trigger_signal(
+ int &pos,
+ int noutput_items,
+ gr_vector_const_void_star &input_items)
+ {
+ if (input_items.size() == 2) {
+ unsigned char *in_trigger = (unsigned char *) input_items[1];
+ for (int i = 0; i < noutput_items; i++) {
+ if (in_trigger[i]) {
+ pos = i;
+ return true;
+ }
+ }
+ }
+ if (d_uses_trigger_tag) {
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items);
+ uint64_t min_offset = ULLONG_MAX;
+ int tag_index = -1;
+ for (unsigned i = 0; i < tags.size(); i++) {
+ if (tags[i].key == d_trigger_tag_key && tags[i].offset < min_offset) {
+ tag_index = (int) i;
+ min_offset = tags[i].offset;
+ }
+ }
+ if (tag_index != -1) {
+ pos = min_offset - nitems_read(0);
+ return true;
+ }
+ }
+ pos += noutput_items;
+ return false;
+ }
+
+
+ bool
+ header_payload_demux_impl::parse_header_data_msg()
+ {
+ pmt::pmt_t msg(delete_head_blocking(msg_port_id));
+ if (pmt::is_integer(msg)) {
+ d_remaining_symbols = pmt::to_long(msg);
+ add_item_tag(1, nitems_written(1), d_len_tag_key, msg);
+ } else if (pmt::is_dict(msg)) {
+ pmt::pmt_t dict_items(pmt::dict_items(msg));
+ while (!pmt::is_null(dict_items)) {
+ pmt::pmt_t this_item(pmt::car(dict_items));
+ add_item_tag(1, nitems_written(1), pmt::car(this_item), pmt::cdr(this_item));
+ if (pmt::equal(pmt::car(this_item), d_len_tag_key)) {
+ d_remaining_symbols = pmt::to_long(pmt::cdr(this_item));
+ }
+ dict_items = pmt::cdr(dict_items);
+ }
+ if (d_remaining_symbols == -1) {
+ throw std::runtime_error("no length tag passed from header data");
+ }
+ } else if (pmt::is_null(msg)) { // Blocking call was interrupted
+ return false;
+ } else {
+ throw std::runtime_error("Received illegal header data");
+ }
+ return true;
+ }
+
+ void
+ header_payload_demux_impl::copy_symbol(const unsigned char *&in, unsigned char *&out, int port, int &nread, int &nproduced)
+ {
+ std::vector<gr_tag_t> tags;
+ memcpy((void *) out,
+ (void *) (in + d_gi * d_itemsize),
+ d_itemsize * d_items_per_symbol
+ );
+ // Tags on GI
+ get_tags_in_range(tags, 0,
+ nitems_read(0) + nread,
+ nitems_read(0) + nread + d_gi
+ );
+ for (unsigned t = 0; t < tags.size(); t++) {
+ add_item_tag(port,
+ nitems_written(port)+nproduced,
+ tags[t].key,
+ tags[t].value
+ );
+ }
+ // Tags on symbol
+ get_tags_in_range(
+ tags, 0,
+ nitems_read(port) + nread + d_gi,
+ nitems_read(port) + nread + d_gi + d_items_per_symbol
+ );
+ for (unsigned t = 0; t < tags.size(); t++) {
+ add_item_tag(0,
+ tags[t].offset - nitems_read(0)-nread + nitems_written(port)+nproduced,
+ tags[t].key,
+ tags[t].value
+ );
+ }
+ in += d_itemsize * (d_items_per_symbol + d_gi);
+ out += d_items_per_symbol * d_itemsize;
+ nread += d_items_per_symbol + d_gi;
+ nproduced++;
+ d_remaining_symbols--;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/header_payload_demux_impl.h b/gr-digital/lib/header_payload_demux_impl.h
new file mode 100644
index 0000000000..ceab9a8629
--- /dev/null
+++ b/gr-digital/lib/header_payload_demux_impl.h
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H
+#define INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H
+
+#include <digital/header_payload_demux.h>
+
+namespace gr {
+ namespace digital {
+
+ class header_payload_demux_impl : public header_payload_demux
+ {
+ private:
+ int d_header_len; //! Number of bytes per header
+ int d_items_per_symbol; //! Bytes per symbol
+ int d_gi; //! Bytes per guard interval
+ pmt::pmt_t d_len_tag_key; //! Key of length tag
+ pmt::pmt_t d_trigger_tag_key; //! Key of trigger tag (if used)
+ bool d_output_symbols; //! If true, output is symbols, not items
+ size_t d_itemsize; //! Bytes per item
+ bool d_uses_trigger_tag; //! If a trigger tag is used
+ int d_ninput_items_reqd; //! Helper for forecast()
+ int d_state; //! Current read state
+ int d_remaining_symbols; //! When in payload or header state, the number of symbols still to transmit
+
+ // Helpers to make the state machine more readable
+
+ //! Helper function that does the reading from the msg port
+ bool parse_header_data_msg();
+
+ //! Helper function that returns true if a trigger signal is detected.
+ // Searches input 1 (if active), then the tags. Sets \p pos to the position
+ // of the first tag.
+ bool find_trigger_signal(
+ int &pos,
+ int noutput_items,
+ gr_vector_const_void_star &input_items);
+
+ //! Helper function, copies one symbol from in to out and updates all pointers and counters
+ void copy_symbol(const unsigned char *&in, unsigned char *&out, int port, int &nread, int &nproduced);
+
+ public:
+
+ header_payload_demux_impl(
+ int header_len,
+ int items_per_symbol,
+ int guard_interval,
+ const std::string &length_tag_key,
+ const std::string &trigger_tag_key,
+ bool output_symbols,
+ size_t itemsize);
+ ~header_payload_demux_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc
new file mode 100644
index 0000000000..49235db5bb
--- /dev/null
+++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "ofdm_frame_equalizer_vcvc_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ ofdm_frame_equalizer_vcvc::sptr
+ ofdm_frame_equalizer_vcvc::make(digital_ofdm_equalizer_base_sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state)
+ {
+ return gnuradio::get_initial_sptr (new ofdm_frame_equalizer_vcvc_impl(equalizer, len_tag_key, propagate_channel_state));
+ }
+
+ ofdm_frame_equalizer_vcvc_impl::ofdm_frame_equalizer_vcvc_impl(digital_ofdm_equalizer_base_sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state)
+ : gr_tagged_stream_block("ofdm_frame_equalizer_vcvc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * equalizer->fft_len()),
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * equalizer->fft_len()),
+ len_tag_key),
+ d_fft_len(equalizer->fft_len()),
+ d_eq(equalizer),
+ d_propagate_channel_state(propagate_channel_state),
+ d_channel_state(equalizer->fft_len(), gr_complex(1, 0))
+ {}
+
+ ofdm_frame_equalizer_vcvc_impl::~ofdm_frame_equalizer_vcvc_impl()
+ {
+ }
+
+
+ int
+ ofdm_frame_equalizer_vcvc_impl::work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+ int carrier_offset = 0;
+
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1);
+ for (unsigned i = 0; i < tags.size(); i++) {
+ if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") {
+ d_channel_state = pmt::c32vector_elements(tags[i].value);
+ remove_item_tag(0, tags[i]);
+ }
+ }
+
+ memcpy((void *) out, (void *) in, sizeof(gr_complex) * d_fft_len * ninput_items[0]);
+ d_eq->reset();
+ d_eq->set_carrier_offset(carrier_offset);
+ d_eq->equalize(out, ninput_items[0], d_channel_state);
+ d_eq->get_channel_state(d_channel_state);
+ if (d_propagate_channel_state) {
+ add_item_tag(0, nitems_written(0),
+ pmt::string_to_symbol("ofdm_sync_chan_taps"),
+ pmt::init_c32vector(d_fft_len, d_channel_state));
+ }
+
+ return ninput_items[0];
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h
new file mode 100644
index 0000000000..cba2d513ea
--- /dev/null
+++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H
+#define INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H
+
+#include <digital/ofdm_frame_equalizer_vcvc.h>
+
+namespace gr {
+ namespace digital {
+
+ class ofdm_frame_equalizer_vcvc_impl : public ofdm_frame_equalizer_vcvc
+ {
+ private:
+ const int d_fft_len;
+ digital_ofdm_equalizer_base_sptr d_eq;
+ bool d_propagate_channel_state;
+ std::vector<gr_complex> d_channel_state;
+
+ protected:
+ // This aren't really necessary, so let's override them with nuthin'
+ void remove_length_tags(const std::vector<std::vector<gr_tag_t> > &tags) {};
+ void update_length_tags(int n_produced, int n_ports) {};
+
+ public:
+ ofdm_frame_equalizer_vcvc_impl(digital_ofdm_equalizer_base_sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state);
+ ~ofdm_frame_equalizer_vcvc_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.cc b/gr-digital/lib/ofdm_serializer_vcc_impl.cc
new file mode 100644
index 0000000000..9c41daae77
--- /dev/null
+++ b/gr-digital/lib/ofdm_serializer_vcc_impl.cc
@@ -0,0 +1,205 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "ofdm_serializer_vcc_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ ofdm_serializer_vcc::sptr
+ ofdm_serializer_vcc::make(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::string &len_tag_key,
+ const std::string &packet_len_tag_key,
+ int symbols_skipped,
+ bool input_is_shifted
+ )
+ {
+ return gnuradio::get_initial_sptr (
+ new ofdm_serializer_vcc_impl(
+ fft_len, occupied_carriers,
+ len_tag_key, packet_len_tag_key,
+ symbols_skipped, input_is_shifted
+ )
+ );
+ }
+
+ ofdm_serializer_vcc::sptr
+ ofdm_serializer_vcc::make(
+ const digital_ofdm_carrier_allocator_cvc_sptr &allocator,
+ const std::string &packet_len_tag_key,
+ int symbols_skipped,
+ bool input_is_shifted
+ )
+ {
+ return gnuradio::get_initial_sptr(
+ new ofdm_serializer_vcc_impl(
+ allocator->fft_len(),
+ allocator->occupied_carriers(),
+ allocator->len_tag_key(),
+ packet_len_tag_key,
+ symbols_skipped,
+ input_is_shifted
+ )
+ );
+ }
+
+ ofdm_serializer_vcc_impl::ofdm_serializer_vcc_impl (
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::string &len_tag_key,
+ const std::string &packet_len_tag_key,
+ int symbols_skipped,
+ bool input_is_shifted)
+ : gr_tagged_stream_block ("ofdm_serializer_vcc",
+ gr_make_io_signature(1, 1, sizeof (gr_complex) * fft_len),
+ gr_make_io_signature(1, 1, sizeof (gr_complex)),
+ len_tag_key),
+ d_fft_len(fft_len),
+ d_occupied_carriers(occupied_carriers),
+ d_packet_len_tag_key(pmt::string_to_symbol(packet_len_tag_key)),
+ d_out_len_tag_key(pmt::string_to_symbol((packet_len_tag_key.empty() ? len_tag_key : packet_len_tag_key))),
+ d_symbols_skipped(symbols_skipped % occupied_carriers.size()),
+ d_curr_set(symbols_skipped % occupied_carriers.size()),
+ d_symbols_per_set(0)
+ {
+ for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ for (unsigned k = 0; k < d_occupied_carriers[i].size(); k++) {
+ if (d_occupied_carriers[i][k] < 0) {
+ d_occupied_carriers[i][k] += fft_len;
+ }
+ if (d_occupied_carriers[i][k] >= fft_len || d_occupied_carriers[i][k] < 0) {
+ throw std::invalid_argument("ofdm_serializer_vcc: trying to occupy a carrier outside the fft length.");
+ }
+ if (input_is_shifted) {
+ d_occupied_carriers[i][k] = (d_occupied_carriers[i][k] + fft_len) % fft_len;
+ }
+ }
+ }
+
+ for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ d_symbols_per_set += d_occupied_carriers[i].size();
+ }
+ set_relative_rate((double) d_symbols_per_set / d_occupied_carriers.size());
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ ofdm_serializer_vcc_impl::~ofdm_serializer_vcc_impl()
+ {
+ }
+
+ int
+ ofdm_serializer_vcc_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int nout = (ninput_items[0] / d_occupied_carriers.size()) * d_symbols_per_set;
+ for (unsigned i = 0; i < ninput_items[0] % d_occupied_carriers.size(); i++) {
+ nout += d_occupied_carriers[(i + d_curr_set) % d_occupied_carriers.size()].size();
+ }
+ return nout;
+ }
+
+ void
+ ofdm_serializer_vcc_impl::update_length_tags(int n_produced, int n_ports)
+ {
+ add_item_tag(0, nitems_written(0),
+ d_out_len_tag_key,
+ pmt::from_long(n_produced)
+ );
+ }
+
+ int
+ ofdm_serializer_vcc_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+ long frame_length = ninput_items[0]; // Input frame
+ long packet_length = 0; // Output frame
+ int carr_offset = 0;
+
+ std::vector<gr_tag_t> tags;
+ // Packet mode
+ if (!d_length_tag_key_str.empty()) {
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1);
+ for (unsigned i = 0; i < tags.size(); i++) {
+ if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") {
+ carr_offset = pmt::to_long(tags[i].value);
+ }
+ if (tags[i].key == d_packet_len_tag_key) {
+ packet_length = pmt::to_long(tags[i].value);
+ remove_item_tag(0, tags[i]);
+ }
+ }
+ } else {
+ // recalc frame length from noutput_items
+ frame_length = 0;
+ int sym_per_frame = 0;
+ while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < noutput_items) {
+ frame_length++;
+ sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size();
+ }
+ }
+
+ // Copy symbols
+ int n_out_symbols = 0;
+ for (int i = 0; i < frame_length; i++) {
+ // Copy all tags associated with this input OFDM symbol onto the first output symbol
+ get_tags_in_range(tags, 0,
+ nitems_read(0)+i,
+ nitems_read(0)+i+1
+ );
+ for (unsigned t = 0; t < tags.size(); t++) {
+ add_item_tag(0, nitems_written(0)+n_out_symbols,
+ tags[i].key,
+ tags[i].value
+ );
+ }
+ for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) {
+ out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset];
+ }
+ if (packet_length && n_out_symbols > packet_length) {
+ n_out_symbols = packet_length;
+ break;
+ }
+ d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size();
+ }
+
+ // Housekeeping
+ if (d_length_tag_key_str.empty()) {
+ consume_each(frame_length);
+ } else {
+ d_curr_set = d_symbols_skipped;
+ }
+
+ return n_out_symbols;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.h b/gr-digital/lib/ofdm_serializer_vcc_impl.h
new file mode 100644
index 0000000000..ef2f1c83b1
--- /dev/null
+++ b/gr-digital/lib/ofdm_serializer_vcc_impl.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H
+#define INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H
+
+#include <digital/ofdm_serializer_vcc.h>
+
+namespace gr {
+ namespace digital {
+
+ class ofdm_serializer_vcc_impl : public ofdm_serializer_vcc
+ {
+ private:
+ int d_fft_len; //! FFT length
+ std::vector<std::vector<int> > d_occupied_carriers; //! Which carriers/symbols carry data
+ pmt::pmt_t d_packet_len_tag_key; //! Key of the length tag
+ pmt::pmt_t d_out_len_tag_key; //! Key of the length tag
+ const int d_symbols_skipped; //! Start position in d_occupied_carriers
+ int d_curr_set; //! Current position in d_occupied_carriers
+ int d_symbols_per_set;
+
+ protected:
+ /* Calculate the number of scalar complex symbols given a number of
+ * OFDM symbols.
+ */
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+ void update_length_tags(int n_produced, int n_ports);
+
+ public:
+ ofdm_serializer_vcc_impl(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::string &len_tag_key,
+ const std::string &packet_len_tag_key,
+ int symbols_skipped,
+ bool input_is_shifted
+ );
+ ~ofdm_serializer_vcc_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H */
+
diff --git a/gr-digital/lib/packet_header_default.cc b/gr-digital/lib/packet_header_default.cc
new file mode 100644
index 0000000000..8906985331
--- /dev/null
+++ b/gr-digital/lib/packet_header_default.cc
@@ -0,0 +1,128 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital/packet_header_default.h>
+
+namespace gr {
+ namespace digital {
+
+ packet_header_default::sptr
+ packet_header_default::make(
+ long header_len,
+ const std::string &len_tag_key,
+ const std::string &num_tag_key,
+ int bits_per_byte)
+ {
+ return packet_header_default::sptr(new packet_header_default(header_len, len_tag_key, num_tag_key, bits_per_byte));
+ }
+
+ const unsigned MASK_LUT[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x2F, 0x7F, 0xFF};
+ packet_header_default::packet_header_default(
+ long header_len,
+ const std::string &len_tag_key,
+ const std::string &num_tag_key,
+ int bits_per_byte)
+ : d_header_len(header_len),
+ d_len_tag_key(pmt::string_to_symbol(len_tag_key)),
+ d_num_tag_key(pmt::string_to_symbol(num_tag_key)),
+ d_bits_per_byte(bits_per_byte),
+ d_header_number(0)
+ {
+ if (d_bits_per_byte < 1 || d_bits_per_byte > 8) {
+ throw std::invalid_argument("bits_per_byte must be in [1, 8]");
+ }
+ d_mask = MASK_LUT[d_bits_per_byte];
+ }
+
+ packet_header_default::~packet_header_default()
+ {
+ }
+
+ bool packet_header_default::header_formatter(
+ long packet_len,
+ unsigned char *out,
+ const std::vector<gr_tag_t> &tags
+ )
+ {
+ packet_len &= 0x0FFF;
+
+ memset(out, 0x00, d_header_len);
+ int parity = 0;
+ int k = 0; // Position in out
+ for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) {
+ out[k] = (unsigned char) ((packet_len >> i) & d_mask);
+ parity += out[k];
+ }
+ for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) {
+ out[k] = (unsigned char) ((d_header_number >> i) & d_mask);
+ parity += out[k];
+ }
+ if (k < d_header_len) {
+ out[k] = (unsigned char) (parity % 2);
+ }
+ d_header_number++;
+
+ return true;
+ }
+
+
+ bool packet_header_default::header_parser(
+ const unsigned char *in,
+ std::vector<gr_tag_t> &tags)
+ {
+ unsigned header_len = 0;
+ unsigned header_num = 0;
+ gr_tag_t tag;
+
+ int k = 0; // Position in "in"
+ for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) {
+ header_len |= (((int) in[k]) & d_mask) << i;
+ }
+ tag.key = d_len_tag_key;
+ tag.value = pmt::from_long(header_len);
+ tags.push_back(tag);
+ if (k >= d_header_len) {
+ return true;
+ }
+ for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) {
+ header_num |= (((int) in[k]) & d_mask) << i;
+ }
+ tag.key = d_num_tag_key;
+ tag.value = pmt::from_long(header_num);
+ tags.push_back(tag);
+ if (k >= d_header_len) {
+ return true;
+ }
+
+ int parity = in[k];
+ for (int i = 0; i < 28; i++) {
+ parity += in[i];
+ }
+ return !(parity % 2);
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/packet_header_ofdm.cc b/gr-digital/lib/packet_header_ofdm.cc
new file mode 100644
index 0000000000..ed3d3586cb
--- /dev/null
+++ b/gr-digital/lib/packet_header_ofdm.cc
@@ -0,0 +1,115 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital/packet_header_ofdm.h>
+
+namespace gr {
+ namespace digital {
+
+ int _get_header_len_from_occupied_carriers(const std::vector<std::vector<int> > &occupied_carriers, int n_syms)
+ {
+ int header_len = 0;
+ for (int i = 0; i < n_syms; i++) {
+ header_len += occupied_carriers[i].size();
+ }
+
+ return header_len;
+ }
+
+ packet_header_ofdm::sptr
+ packet_header_ofdm::make(
+ const std::vector<std::vector<int> > &occupied_carriers,
+ int n_syms,
+ const std::string &len_tag_key,
+ const std::string &frame_len_tag_key,
+ const std::string &num_tag_key,
+ int bits_per_sym)
+ {
+ return packet_header_ofdm::sptr(
+ new packet_header_ofdm(
+ occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, bits_per_sym
+ )
+ );
+ }
+
+ packet_header_ofdm::packet_header_ofdm(
+ const std::vector<std::vector<int> > &occupied_carriers,
+ int n_syms,
+ const std::string &len_tag_key,
+ const std::string &frame_len_tag_key,
+ const std::string &num_tag_key,
+ int bits_per_sym)
+ : packet_header_default(
+ _get_header_len_from_occupied_carriers(occupied_carriers, n_syms),
+ len_tag_key,
+ num_tag_key,
+ bits_per_sym),
+ d_frame_len_tag_key(pmt::string_to_symbol(frame_len_tag_key)),
+ d_occupied_carriers(occupied_carriers),
+ d_syms_per_set(0)
+ {
+ for (unsigned i = 0; i < d_occupied_carriers.size(); i++) {
+ d_syms_per_set += d_occupied_carriers[i].size();
+ }
+ }
+
+ packet_header_ofdm::~packet_header_ofdm()
+ {
+ }
+
+
+ bool packet_header_ofdm::header_parser(
+ const unsigned char *in,
+ std::vector<gr_tag_t> &tags)
+ {
+ if (!packet_header_default::header_parser(in, tags)) {
+ return false;
+ }
+ int packet_len = 0; // # of OFDM symbols
+ for (unsigned i = 0; i < tags.size(); i++) {
+ if (pmt::equal(tags[i].key, d_len_tag_key)) {
+ packet_len = pmt::to_long(tags[i].value);
+ break;
+ }
+ }
+
+ int frame_len = packet_len / d_syms_per_set;
+ int k = 0;
+ int i = frame_len * d_syms_per_set;
+ while (i < packet_len) {
+ frame_len++;
+ i += d_occupied_carriers[k].size();
+ }
+ gr_tag_t tag;
+ tag.key = d_frame_len_tag_key;
+ tag.value = pmt::from_long(frame_len);
+ tags.push_back(tag);
+
+ return true;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/packet_headergenerator_bb_impl.cc b/gr-digital/lib/packet_headergenerator_bb_impl.cc
new file mode 100644
index 0000000000..bcfaf6b63d
--- /dev/null
+++ b/gr-digital/lib/packet_headergenerator_bb_impl.cc
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "packet_headergenerator_bb_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ packet_headergenerator_bb::sptr
+ packet_headergenerator_bb::make(const packet_header_default::sptr &header_formatter)
+ {
+ return gnuradio::get_initial_sptr (new packet_headergenerator_bb_impl(header_formatter));
+ }
+
+
+ packet_headergenerator_bb::sptr
+ packet_headergenerator_bb::make(
+ long header_len,
+ const std::string &len_tag_key
+ )
+ {
+ const packet_header_default::sptr header_formatter(
+ new packet_header_default(header_len, len_tag_key)
+ );
+ return gnuradio::get_initial_sptr (new packet_headergenerator_bb_impl(header_formatter));
+ }
+
+
+ packet_headergenerator_bb_impl::packet_headergenerator_bb_impl(
+ const gr::digital::packet_header_default::sptr &header_formatter
+ )
+ : gr_tagged_stream_block("packet_headergenerator_bb_impl",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ pmt::symbol_to_string(header_formatter->len_tag_key())),
+ d_formatter(header_formatter),
+ d_input_size(1),
+ d_header_len(header_formatter->header_len()),
+ d_len_tag_value(pmt::from_long(d_header_len))
+ {
+ set_output_multiple(d_header_len);
+ // This is the worst case rate, because we don't know the true value, of course
+ set_relative_rate(d_header_len);
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ packet_headergenerator_bb_impl::~packet_headergenerator_bb_impl()
+ {
+ }
+
+ int
+ packet_headergenerator_bb_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ unsigned char *out = (unsigned char *) output_items[0];
+ if (!d_formatter->header_formatter(ninput_items[0], out)) {
+ throw std::runtime_error("header formatter returned false.");
+ }
+
+ return d_header_len;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/packet_headergenerator_bb_impl.h b/gr-digital/lib/packet_headergenerator_bb_impl.h
new file mode 100644
index 0000000000..7d2494cf8b
--- /dev/null
+++ b/gr-digital/lib/packet_headergenerator_bb_impl.h
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H
+#define INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H
+
+#include <digital/packet_headergenerator_bb.h>
+
+namespace gr {
+ namespace digital {
+
+ class packet_headergenerator_bb_impl : public packet_headergenerator_bb
+ {
+ private:
+ gr::digital::packet_header_default::sptr d_formatter;
+ int d_input_size;
+ int d_header_len;
+ pmt::pmt_t d_len_tag_value;
+
+ public:
+ packet_headergenerator_bb_impl(const packet_header_default::sptr &header_formatter);
+ ~packet_headergenerator_bb_impl();
+
+ void remove_length_tags(const std::vector<std::vector<gr_tag_t> > &tags) {};
+ int calculate_output_stream_length(const gr_vector_int &ninput_items) { return d_header_len; };
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H */
+
diff --git a/gr-digital/lib/packet_headerparser_b_impl.cc b/gr-digital/lib/packet_headerparser_b_impl.cc
new file mode 100644
index 0000000000..825cfa3d86
--- /dev/null
+++ b/gr-digital/lib/packet_headerparser_b_impl.cc
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "packet_headerparser_b_impl.h"
+
+#define msg_port_id pmt::mp("header_data")
+
+namespace gr {
+ namespace digital {
+
+ packet_headerparser_b::sptr
+ packet_headerparser_b::make(long header_len, const std::string &len_tag_key)
+ {
+ const packet_header_default::sptr header_formatter(
+ new packet_header_default(header_len, len_tag_key)
+ );
+ return gnuradio::get_initial_sptr (new packet_headerparser_b_impl(header_formatter));
+ }
+
+ packet_headerparser_b::sptr
+ packet_headerparser_b::make(const gr::digital::packet_header_default::sptr &header_formatter)
+ {
+ return gnuradio::get_initial_sptr (new packet_headerparser_b_impl(header_formatter));
+ }
+
+ packet_headerparser_b_impl::packet_headerparser_b_impl(const gr::digital::packet_header_default::sptr &header_formatter)
+ : gr_sync_block("packet_headerparser_b",
+ gr_make_io_signature(1, 1, sizeof (unsigned char)),
+ gr_make_io_signature(0, 0, 0)),
+ d_header_formatter(header_formatter)
+ {
+ message_port_register_out(msg_port_id);
+ set_output_multiple(header_formatter->header_len());
+ }
+
+ packet_headerparser_b_impl::~packet_headerparser_b_impl()
+ {
+ }
+
+ int
+ packet_headerparser_b_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+
+ if (noutput_items < d_header_formatter->header_len()) {
+ return 0;
+ }
+
+ std::vector<gr_tag_t> tags;
+ if (!d_header_formatter->header_parser(in, tags)) {
+ message_port_pub(msg_port_id, pmt::PMT_F);
+ } else {
+ pmt::pmt_t dict(pmt::make_dict());
+ for (unsigned i = 0; i < tags.size(); i++) {
+ pmt::dict_add(dict, tags[i].key, tags[i].value);
+ }
+ message_port_pub(msg_port_id, dict);
+ }
+
+ return d_header_formatter->header_len();
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/packet_headerparser_b_impl.h b/gr-digital/lib/packet_headerparser_b_impl.h
new file mode 100644
index 0000000000..a7ded1143f
--- /dev/null
+++ b/gr-digital/lib/packet_headerparser_b_impl.h
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H
+#define INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H
+
+#include <digital/packet_headerparser_b.h>
+
+namespace gr {
+ namespace digital {
+
+ class packet_headerparser_b_impl : public packet_headerparser_b
+ {
+ private:
+ packet_header_default::sptr d_header_formatter;
+
+ public:
+ packet_headerparser_b_impl(const gr::digital::packet_header_default::sptr &header_formatter);
+ ~packet_headerparser_b_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H */
+
diff --git a/gr-digital/lib/scale_tags_impl.cc b/gr-digital/lib/scale_tags_impl.cc
new file mode 100644
index 0000000000..33d1002381
--- /dev/null
+++ b/gr-digital/lib/scale_tags_impl.cc
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "scale_tags_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ scale_tags::sptr
+ scale_tags::make(size_t itemsize, const std::string& tagname, float scale_factor)
+ {
+ return gnuradio::get_initial_sptr (new scale_tags_impl(itemsize, tagname, scale_factor));
+ }
+
+ /*
+ * The private constructor
+ */
+ scale_tags_impl::scale_tags_impl(size_t itemsize, const std::string& tagname, float scale_factor)
+ : gr_sync_block("scale_tags",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_itemsize(itemsize),
+ d_tagname(tagname),
+ d_scale_factor(scale_factor)
+ {
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ scale_tags_impl::~scale_tags_impl()
+ {
+ }
+
+ int
+ scale_tags_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const char *in = (const char *) input_items[0];
+ char *out = (char *) output_items[0];
+ std::vector<gr_tag_t> tags;
+ this->get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items);
+ //const size_t ninput_items = noutput_items; //assumption for sync block, this can change
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ long value = pmt::to_long(tags[j].value);
+ if (pmt::symbol_to_string(tags[j].key) == d_tagname) {
+ value = long(value*d_scale_factor);
+ }
+ this->add_item_tag(0, tags[j].offset, tags[j].key, pmt::from_long(value));
+ }
+ memcpy((void *) out, (const void *) in, noutput_items*d_itemsize);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/scale_tags_impl.h b/gr-digital/lib/scale_tags_impl.h
new file mode 100644
index 0000000000..667cda36eb
--- /dev/null
+++ b/gr-digital/lib/scale_tags_impl.h
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_SCALE_TAGS_IMPL_H
+#define INCLUDED_DIGITAL_SCALE_TAGS_IMPL_H
+
+#include <digital/scale_tags.h>
+
+namespace gr {
+ namespace digital {
+
+ class scale_tags_impl : public scale_tags
+ {
+ private:
+ size_t d_itemsize;
+ std::string d_tagname;
+ float d_scale_factor;
+
+ public:
+ scale_tags_impl(size_t itemsize, const std::string&, float scale_factor);
+ ~scale_tags_impl();
+
+ // Where all the action really happens
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_SCALE_TAGS_IMPL_H */
+
diff --git a/gr-digital/lib/tagged_stream_check_impl.cc b/gr-digital/lib/tagged_stream_check_impl.cc
new file mode 100644
index 0000000000..625645804f
--- /dev/null
+++ b/gr-digital/lib/tagged_stream_check_impl.cc
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 <+YOU OR YOUR COMPANY+>.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "tagged_stream_check_impl.h"
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <sstream>
+
+namespace gr {
+ namespace digital {
+
+ bool sort_tag_by_offset(gr_tag_t const & L, gr_tag_t const & R) {
+ return L.offset < R.offset;
+ }
+
+ tagged_stream_check::sptr
+ tagged_stream_check::make(size_t itemsize, const std::string &lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new tagged_stream_check_impl(itemsize, lengthtagname));
+ }
+
+ /*
+ * The private constructor
+ */
+ tagged_stream_check_impl::tagged_stream_check_impl(size_t itemsize, const std::string &lengthtagname)
+ : gr_sync_block("tagged_stream_check",
+ gr_make_io_signature(1, 1, itemsize),
+ gr_make_io_signature(1, 1, itemsize)),
+ d_lengthtagname(lengthtagname), d_itemsize(itemsize)
+ {
+ d_expected_offset = 0;
+ d_last_offset = 0;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ tagged_stream_check_impl::~tagged_stream_check_impl()
+ {
+ }
+
+ int
+ tagged_stream_check_impl::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ char *out = (char *) output_items[0];
+ const char *in = (const char*) input_items[0];
+ // Find all the length tags
+ std::vector<gr_tag_t> tags;
+ std::vector<gr_tag_t> lengthtags;
+ this->get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ if (pmt::symbol_to_string(tags[j].key) == d_lengthtagname) {
+ lengthtags.push_back(tags[j]);
+ }
+ }
+ // If there are no lengthtags then check that we weren't expecting one.
+ if (lengthtags.size() == 0) {
+ if (d_expected_offset < nitems_read(0)+noutput_items) {
+ std::ostringstream ss;
+ ss << "ERROR: "<<this->unique_id()<<" Expected a lengthtag at offset="<<d_expected_offset<<" but didn't find it";
+ std::cout << ss.str() << std::endl;
+ }
+ }
+ // Sort them and make sure the lengthtags are in the proper places.
+ sort(lengthtags.begin(), lengthtags.end(), sort_tag_by_offset);
+ for (unsigned int j = 0; j < lengthtags.size(); j++) {
+ if (lengthtags[j].offset != d_expected_offset) {
+ std::cout << "****************************" << std::endl;
+ std::cout << "ERROR: "<<this->unique_id()<<" offset: " << lengthtags[j].offset << " The last tag had a length of " << d_expected_offset - d_last_offset << " but we got a length of " << lengthtags[j].offset - d_last_offset << std::endl;
+ }
+ long packet_length = pmt::to_long(lengthtags[j].value);
+ std::cout << "INFO: "<<this->unique_id()<<" offset: " << lengthtags[j].offset << std::endl;
+ d_expected_offset = lengthtags[j].offset + packet_length;
+ d_last_offset = lengthtags[j].offset;
+ }
+ memcpy((void *) out, (const void *) in, noutput_items*d_itemsize);
+ std::ostringstream ss;
+ ss << "checker: Produced data from " << nitems_read(0) << " to " << nitems_read(0) + noutput_items;
+ std::cout << ss.str() << std::endl;
+ return noutput_items;
+ }
+
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/tagged_stream_check_impl.h b/gr-digital/lib/tagged_stream_check_impl.h
new file mode 100644
index 0000000000..0b0dfe5b1a
--- /dev/null
+++ b/gr-digital/lib/tagged_stream_check_impl.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 <+YOU OR YOUR COMPANY+>.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_TAGGED_STREAM_CHECK_IMPL_H
+#define INCLUDED_DIGITAL_TAGGED_STREAM_CHECK_IMPL_H
+
+#include <digital/tagged_stream_check.h>
+#include <vector>
+
+namespace gr {
+ namespace digital {
+
+ class tagged_stream_check_impl : public tagged_stream_check
+ {
+ private:
+ const std::string d_lengthtagname;
+ size_t d_itemsize;
+ uint64_t d_expected_offset;
+ uint64_t d_last_offset;
+
+ public:
+ tagged_stream_check_impl(size_t itemsize, const std::string &lengthtagname);
+ ~tagged_stream_check_impl();
+
+ // Where all the action really happens
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif
+
diff --git a/gr-digital/lib/ts_insert_zeros_cc_impl.cc b/gr-digital/lib/ts_insert_zeros_cc_impl.cc
new file mode 100644
index 0000000000..1a78851c18
--- /dev/null
+++ b/gr-digital/lib/ts_insert_zeros_cc_impl.cc
@@ -0,0 +1,130 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 <+YOU OR YOUR COMPANY+>.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include "ts_insert_zeros_cc_impl.h"
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <sstream>
+
+namespace gr {
+ namespace digital {
+
+ ts_insert_zeros_cc::sptr
+ ts_insert_zeros_cc::make(const std::string &lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new ts_insert_zeros_cc_impl(lengthtagname));
+ }
+
+ /*
+ * The private constructor
+ */
+ ts_insert_zeros_cc_impl::ts_insert_zeros_cc_impl(const std::string &lengthtagname)
+ : gr_block("ts_insert_zeros_cc",
+ gr_make_io_signature(1, 1, sizeof(gr_complex)),
+ gr_make_io_signature(1, 1, sizeof(gr_complex))),
+ d_lengthtagname(lengthtagname)
+ {
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ ts_insert_zeros_cc_impl::~ts_insert_zeros_cc_impl()
+ {
+ }
+
+ void
+ ts_insert_zeros_cc_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = 0;
+ }
+
+ int
+ ts_insert_zeros_cc_impl::general_work (
+ int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ )
+ {
+ gr_complex *out = (gr_complex *) output_items[0];
+ const gr_complex*in = (const gr_complex*) input_items[0];
+
+ if (ninput_items[0]) {
+ // Check if we have an entire packet.
+ long packet_length = 0;
+ std::vector<gr_tag_t> tags;
+ // Get any tags associated with the first item on the input.
+ this->get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ if (pmt::symbol_to_string(tags[j].key) == d_lengthtagname) {
+ packet_length = pmt::to_long(tags[j].value);
+ }
+ }
+ if (!packet_length) {
+ throw std::runtime_error("no tag");
+ }
+ if (ninput_items[0] < packet_length ) {
+ // We don't have enough input to produce a packet.
+ // Produces zeros instead.
+ } else {
+ // We have enough input.
+ if (noutput_items < packet_length) {
+ // But we don't have enough output space.
+ // We don't want to produce zeros, so return.
+ set_output_multiple(packet_length);
+ return 0;
+ } else {
+ // And we have enough output space.
+ // Produce the packet.
+ std::vector<gr_tag_t> tags;
+ this->get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+packet_length);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ const uint64_t offset = tags[j].offset - nitems_read(0) + nitems_written(0);
+ this->add_item_tag(0, offset, tags[j].key, tags[j].value);
+ }
+ if (noutput_items < packet_length) {
+ throw std::runtime_error("Not enough room in the output buffer.");
+ }
+ memcpy(out, in, packet_length*sizeof(gr_complex));
+ consume(0, packet_length);
+ return packet_length;
+ }
+ }
+ }
+ // We're just producing zeros.
+ // Either we have no input data, or not an entire packet yet.
+ for (int i=0; i<noutput_items; i++) {
+ out[i] = 0;
+ }
+ return noutput_items;
+ }
+
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ts_insert_zeros_cc_impl.h b/gr-digital/lib/ts_insert_zeros_cc_impl.h
new file mode 100644
index 0000000000..4bdfbfe9fd
--- /dev/null
+++ b/gr-digital/lib/ts_insert_zeros_cc_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 <+YOU OR YOUR COMPANY+>.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_TS_INSERT_ZEROS_CC_IMPL_H
+#define INCLUDED_DIGITAL_TS_INSERT_ZEROS_CC_IMPL_H
+
+#include <digital/ts_insert_zeros_cc.h>
+#include <vector>
+
+namespace gr {
+ namespace digital {
+
+ class ts_insert_zeros_cc_impl : public ts_insert_zeros_cc
+ {
+ private:
+ const std::string d_lengthtagname;
+
+ public:
+ ts_insert_zeros_cc_impl(const std::string &lengthtagname);
+ ~ts_insert_zeros_cc_impl();
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ // Where all the action really happens
+ int general_work(
+ int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items
+ );
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif
+
diff --git a/gr-digital/python/CMakeLists.txt b/gr-digital/python/CMakeLists.txt
index 7f35e3c2be..4dfaac362a 100644
--- a/gr-digital/python/CMakeLists.txt
+++ b/gr-digital/python/CMakeLists.txt
@@ -28,6 +28,7 @@ GR_PYTHON_INSTALL(
bpsk.py
cpm.py
crc.py
+ fftshift.py
generic_mod_demod.py
gmsk.py
gfsk.py
@@ -39,6 +40,7 @@ GR_PYTHON_INSTALL(
ofdm_sync_ml.py
ofdm_sync_pnac.py
ofdm_sync_pn.py
+ ofdm_txrx.py
packet_utils.py
pkt.py
psk.py
@@ -55,6 +57,7 @@ GR_PYTHON_INSTALL(
utils/gray_code.py
utils/mod_codes.py
utils/alignment.py
+ utils/tagged_streams.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital/utils
COMPONENT "digital_python"
)
@@ -73,8 +76,10 @@ list(APPEND GR_TEST_PYTHON_DIRS
${CMAKE_BINARY_DIR}/gr-analog/swig
${CMAKE_BINARY_DIR}/gr-blocks/python
${CMAKE_BINARY_DIR}/gr-blocks/swig
+ ${CMAKE_BINARY_DIR}/gr-fft/python
+ ${CMAKE_BINARY_DIR}/gr-fft/swig
)
-list(APPEND GR_TEST_TARGET_DEPS gnuradio-digital gnuradio-filter gnuradio-fft gnuradio-analog)
+list(APPEND GR_TEST_TARGET_DEPS gnuradio-digital gnuradio-filter gnuradio-fft gnuradio-analog gnuradio-blocks)
include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")
diff --git a/gr-digital/python/__init__.py b/gr-digital/python/__init__.py
index 962f210324..28b74261f7 100644
--- a/gr-digital/python/__init__.py
+++ b/gr-digital/python/__init__.py
@@ -42,6 +42,8 @@ from ofdm_sync_fixed import *
from ofdm_sync_ml import *
from ofdm_sync_pnac import *
from ofdm_sync_pn import *
+from fftshift import fftshift, ifftshift
+from ofdm_txrx import ofdm_tx, ofdm_rx
import packet_utils
import ofdm_packet_utils
diff --git a/gr-digital/python/fftshift.py b/gr-digital/python/fftshift.py
new file mode 100644
index 0000000000..c8c7c7f140
--- /dev/null
+++ b/gr-digital/python/fftshift.py
@@ -0,0 +1,31 @@
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+# Aliases for fftpack.(i)fftshift()
+
+from scipy import fftpack
+
+def fftshift(x):
+ return fftpack.fftshift(x)
+
+def ifftshift(x):
+ return fftpack.ifftshift(x)
+
diff --git a/gr-digital/python/ofdm_txrx.py b/gr-digital/python/ofdm_txrx.py
new file mode 100644
index 0000000000..2734e9cc1c
--- /dev/null
+++ b/gr-digital/python/ofdm_txrx.py
@@ -0,0 +1,268 @@
+#
+# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+"""
+OFDM Transmitter / Receiver hier blocks.
+
+For simple configurations, no need to connect all the relevant OFDM blocks
+to form an OFDM Tx/Rx--simply use these.
+"""
+
+import numpy
+from gnuradio import gr
+import digital_swig as digital
+from utils import tagged_streams
+
+try:
+ # This will work when feature #505 is added.
+ from gnuradio import fft
+ from gnuradio import blocks
+ from gnuradio import analog
+except ImportError:
+ # Until then this will work.
+ import fft_swig as fft
+ import blocks_swig as blocks
+ import analog_swig as analog
+
+_def_fft_len = 64
+_def_cp_len = 16
+_def_frame_length_tag_key = "frame_length"
+_def_packet_length_tag_key = "frame_length"
+_def_packet_num_tag_key = ""
+_def_occupied_carriers=(range(1, 27) + range(38, 64),)
+_def_pilot_carriers=((0,),)
+_def_pilot_symbols=((100,),)
+_seq_seed = 42
+
+def _make_sync_word(fft_len, occupied_carriers, constellation):
+ """ Makes a random sync sequence """
+ occupied_carriers = list(occupied_carriers[0])
+ occupied_carriers = [occupied_carriers[x] + fft_len if occupied_carriers[x] < 0 else occupied_carriers[x] for x in range(len(occupied_carriers))]
+ numpy.random.seed(_seq_seed)
+ sync_sequence = [constellation.map_to_points_v(numpy.random.randint(constellation.arity()))[0] * numpy.sqrt(2) if x in occupied_carriers and x % 3 else 0 for x in range(fft_len)]
+ return sync_sequence
+
+def _get_constellation(bps):
+ """ Returns a modulator block for a given number of bits per symbol """
+ constellation = {
+ 1: digital.constellation_bpsk(),
+ 2: digital.constellation_qpsk(),
+ 3: digital.constellation_8psk()
+ }
+ try:
+ return constellation[bps]
+ except KeyError:
+ print 'Modulation not supported.'
+ exit(1)
+
+class ofdm_tx(gr.hier_block2):
+ """
+ Hierarchical block for OFDM modulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ Args:
+ fft_len: The length of FFT (integer).
+ cp_len: The length of cyclic prefix (integer).
+ occupied_carriers: ??
+ pilot_carriers: ??
+ pilot_symbols: ??
+ length_tag_key: The name of the tag giving packet length.
+ """
+ def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len,
+ frame_length_tag_key=_def_frame_length_tag_key,
+ occupied_carriers=_def_occupied_carriers,
+ pilot_carriers=_def_pilot_carriers,
+ pilot_symbols=_def_pilot_symbols,
+ bps_header=1,
+ bps_payload=1,
+ sync_word1=None,
+ sync_word2=None,
+ rolloff=0
+ ):
+ gr.hier_block2.__init__(self, "ofdm_tx",
+ gr.io_signature(1, 1, gr.sizeof_char),
+ gr.io_signature(1, 1, gr.sizeof_gr_complex))
+ self.fft_len = fft_len
+ self.cp_len = cp_len
+ self.frame_length_tag_key = frame_length_tag_key
+ self.occupied_carriers = occupied_carriers
+ self.pilot_carriers = pilot_carriers
+ self.pilot_symbols = pilot_symbols
+ self.bps_header = bps_header
+ self.bps_payload = bps_payload
+ n_sync_words = 1
+ header_constellation = _get_constellation(bps_header)
+ header_mod = digital.chunks_to_symbols_bc(header_constellation.points())
+ self.sync_word1 = sync_word1
+ if sync_word1 is None:
+ self.sync_word1 = _make_sync_word(fft_len, occupied_carriers, header_constellation)
+ else:
+ if len(sync_word1) != self.fft_len:
+ raise ValueError("Length of sync sequence(s) must be FFT length.")
+ total_sync_word = self.sync_word1
+ self.sync_word2 = ()
+ if sync_word2 is not None:
+ if len(sync_word2) != fft_len:
+ raise ValueError("Length of sync sequence(s) must be FFT length.")
+ self.sync_word2 = sync_word2
+ n_sync_words = 2
+ total_sync_word = sync_word1 + sync_word2
+ crc = digital.crc32_bb(False, self.frame_length_tag_key)
+ formatter_object = digital.packet_header_ofdm(
+ occupied_carriers, 1, "", "", "",
+ bps_header
+ )
+ header_gen = digital.packet_headergenerator_bb(formatter_object.base())
+ header_payload_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*1, self.frame_length_tag_key)
+ self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0))
+ payload_constellation = _get_constellation(bps_payload)
+ payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points())
+ self.connect(
+ crc,
+ blocks.repack_bits_bb(8, bps_payload, frame_length_tag_key),
+ payload_mod,
+ (header_payload_mux, 1)
+ )
+ self.connect(payload_mod, gr.tag_debug(gr.sizeof_gr_complex, "pmod"))
+ sync_word_gen = gr.vector_source_c(
+ total_sync_word, True, self.fft_len,
+ tagged_streams.make_lengthtags((n_sync_words,), (0,), self.frame_length_tag_key)
+ )
+ allocator = digital.ofdm_carrier_allocator_cvc(
+ self.fft_len,
+ occupied_carriers=self.occupied_carriers,
+ pilot_carriers=self.pilot_carriers,
+ pilot_symbols=self.pilot_symbols,
+ len_tag_key=self.frame_length_tag_key
+ )
+ syncword_data_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*self.fft_len, self.frame_length_tag_key)
+ self.connect(sync_word_gen, (syncword_data_mux, 0))
+ self.connect(header_payload_mux, allocator, (syncword_data_mux, 1))
+ ffter = fft.fft_vcc(self.fft_len, False, (), False)
+ cyclic_prefixer = digital.ofdm_cyclic_prefixer(
+ self.fft_len,
+ self.fft_len+self.cp_len,
+ rolloff,
+ self.frame_length_tag_key
+ )
+ self.connect(syncword_data_mux, ffter, cyclic_prefixer, self)
+
+
+class ofdm_rx(gr.hier_block2):
+ """
+ Hierarchical block for OFDM demodulation.
+
+ The input is a byte stream (unsigned char) and the
+ output is the complex modulated signal at baseband.
+
+ Args:
+ fft_len: The length of FFT (integer).
+ cp_len: The length of cyclic prefix (integer).
+ occupied_carriers: ??
+ pilot_carriers: ??
+ pilot_symbols: ??
+ length_tag_key: The name of the tag giving packet length.
+ """
+ def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len,
+ frame_length_tag_key=_def_frame_length_tag_key,
+ packet_length_tag_key=_def_packet_length_tag_key,
+ packet_num_tag_key=_def_packet_num_tag_key,
+ occupied_carriers=_def_occupied_carriers,
+ pilot_carriers=_def_pilot_carriers,
+ pilot_symbols=_def_pilot_symbols,
+ bps_header=1,
+ bps_payload=1,
+ sync_word1=None,
+ sync_word2=None
+ ):
+ gr.hier_block2.__init__(self, "ofdm_rx",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex),
+ gr.io_signature(1, 1, gr.sizeof_char))
+ self.fft_len = fft_len
+ self.cp_len = cp_len
+ self.frame_length_tag_key = frame_length_tag_key
+ self.packet_length_tag_key = packet_length_tag_key
+ self.occupied_carriers = occupied_carriers
+ self.bps_header = bps_header
+ self.bps_payload = bps_payload
+ n_sync_words = 1
+ header_constellation = _get_constellation(bps_header)
+ if sync_word1 is None:
+ self.sync_word1 = _make_sync_word(fft_len, occupied_carriers, header_constellation)
+ else:
+ if len(sync_word1) != self.fft_len:
+ raise ValueError("Length of sync sequence(s) must be FFT length.")
+ self.sync_word1 = sync_word1
+ self.sync_word2 = ()
+ if sync_word2 is not None:
+ if len(sync_word2) != fft_len:
+ raise ValueError("Length of sync sequence(s) must be FFT length.")
+ self.sync_word2 = sync_word2
+ n_sync_words = 2
+ else:
+ sync_word2 = ()
+ # Receiver path
+ sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
+ oscillator = analog.frequency_modulator_fc(-2.0 / fft_len)
+ delay = gr.delay(gr.sizeof_gr_complex, fft_len+cp_len)
+ mixer = gr.multiply_cc()
+ hpd = digital.header_payload_demux(n_sync_words, fft_len, cp_len,
+ frame_length_tag_key, "", True)
+ self.connect(self, sync_detect)
+ self.connect((sync_detect, 0), oscillator, (mixer, 0))
+ self.connect(self, delay, (mixer, 1))
+ self.connect(mixer, (hpd, 0))
+ self.connect((sync_detect, 1), (hpd, 1))
+ # Header demodulation
+ header_fft = fft.fft_vcc(self.fft_len, True, (), True)
+ chanest = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2, 1)
+ header_equalizer = digital.ofdm_equalizer_simpledfe(
+ fft_len, header_constellation.base(),
+ occupied_carriers, pilot_carriers, pilot_symbols
+ )
+ header_eq = digital.ofdm_frame_equalizer_vcvc(header_equalizer.base(), frame_length_tag_key, True)
+ header_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers)
+ header_constellation = _get_constellation(bps_header)
+ header_demod = digital.constellation_decoder_cb(header_constellation.base())
+ header_formatter = digital.packet_header_ofdm(
+ occupied_carriers, 1,
+ packet_length_tag_key,
+ frame_length_tag_key,
+ packet_num_tag_key,
+ bps_header
+ )
+ header_parser = digital.packet_headerparser_b(header_formatter.formatter())
+ self.connect((hpd, 0), header_fft, chanest, header_eq, header_serializer, header_demod, header_parser)
+ self.msg_connect(header_parser, "header_data", hpd, "header_data")
+ # Payload demodulation
+ payload_fft = fft.fft_vcc(self.fft_len, True, (), True)
+ payload_equalizer = digital.ofdm_equalizer_simpledfe(
+ fft_len, header_constellation.base(),
+ occupied_carriers, pilot_carriers, pilot_symbols, 1
+ )
+ payload_eq = digital.ofdm_frame_equalizer_vcvc(payload_equalizer.base(), frame_length_tag_key)
+ payload_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers)
+ payload_constellation = _get_constellation(bps_payload)
+ payload_demod = digital.constellation_decoder_cb(payload_constellation.base())
+ bit_packer = blocks.repack_bits_bb(bps_payload, 8, packet_length_tag_key, True)
+ self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer, payload_demod, bit_packer, self)
+
diff --git a/gr-digital/python/qa_crc32_bb.py b/gr-digital/python/qa_crc32_bb.py
new file mode 100755
index 0000000000..4574b9dca7
--- /dev/null
+++ b/gr-digital/python/qa_crc32_bb.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import blocks_swig as blocks
+import digital_swig as digital
+try: import pmt
+except: from gruel import pmt
+
+class qa_crc32_bb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_crc_len (self):
+ """ Make sure the output of a CRC set is 4 bytes longer than the input. """
+ data = range(16)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(data))
+ src = gr.vector_source_b(data, False, 1, (tag,))
+ crc = digital.crc32_bb(False, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, crc, sink)
+ self.tb.run()
+ # Check that the packets before crc_check are 4 bytes longer that the input.
+ self.assertEqual(len(data)+4, len(sink.data()))
+
+ def test_002_crc_equal (self):
+ """ Go through CRC set / CRC check and make sure the output
+ is the same as the input. """
+ data = (0, 1, 2, 3, 4, 5, 6, 7, 8)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(data))
+ src = gr.vector_source_b(data, False, 1, (tag,))
+ crc = digital.crc32_bb(False, tag_name)
+ crc_check = digital.crc32_bb(True, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, crc, crc_check, sink)
+ self.tb.run()
+ # Check that the packets after crc_check are the same as input.
+ self.assertEqual(data, sink.data())
+
+ def test_003_crc_correct_lentag (self):
+ tag_name = "length"
+ pack_len = 8
+ packets = range(pack_len*2)
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tag_name)
+ tag1.value = pmt.from_long(pack_len)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = pack_len
+ tag2.key = pmt.string_to_symbol(tag_name)
+ tag2.value = pmt.from_long(pack_len)
+ testtag1 = gr.gr_tag_t()
+ testtag1.offset = 1
+ testtag1.key = pmt.string_to_symbol("tag1")
+ testtag1.value = pmt.from_long(0)
+ testtag2 = gr.gr_tag_t()
+ testtag2.offset = pack_len
+ testtag2.key = pmt.string_to_symbol("tag2")
+ testtag2.value = pmt.from_long(0)
+ testtag3 = gr.gr_tag_t()
+ testtag3.offset = len(packets)-1
+ testtag3.key = pmt.string_to_symbol("tag3")
+ testtag3.value = pmt.from_long(0)
+ src = gr.vector_source_b(packets, False, 1, (tag1, tag2, testtag1, testtag2, testtag3))
+ crc = digital.crc32_bb(False, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, crc, sink)
+ self.tb.run()
+ self.assertEqual(len(sink.data()), 2*(pack_len+4))
+ correct_offsets = {'tag1': 1, 'tag2': 12, 'tag3': 19}
+ tags_found = {'tag1': False, 'tag2': False, 'tag3': False}
+ for tag in sink.tags():
+ key = pmt.symbol_to_string(tag.key)
+ if key in correct_offsets.keys():
+ tags_found[key] = True
+ self.assertEqual(correct_offsets[key], tag.offset)
+ if key == tag_name:
+ self.assertTrue(tag.offset == 0 or tag.offset == pack_len+4)
+ self.assertTrue(all(tags_found.values()))
+
+
+ def test_004_fail (self):
+ """ Corrupt the data and make sure it fails CRC test. """
+ data = (0, 1, 2, 3, 4, 5, 6, 7)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(data))
+ src = gr.vector_source_b(data, False, 1, (tag,))
+ crc = digital.crc32_bb(False, tag_name)
+ crc_check = digital.crc32_bb(True, tag_name)
+ corruptor = blocks.add_const_bb(1)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, crc, corruptor, crc_check, sink)
+ self.tb.run()
+ # crc_check will drop invalid packets
+ self.assertEqual(len(sink.data()), 0)
+
+ def test_005_tag_propagation (self):
+ """ Make sure tags on the CRC aren't lost. """
+ data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 230, 166, 39, 8)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(data))
+ testtag = gr.gr_tag_t()
+ testtag.offset = len(data)-1
+ testtag.key = pmt.string_to_symbol('tag1')
+ testtag.value = pmt.from_long(0)
+ src = gr.vector_source_b(data, False, 1, (tag, testtag))
+ crc_check = digital.crc32_bb(True, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, crc_check, sink)
+ self.tb.run()
+ self.assertEqual([len(data)-5,], [tag.offset for tag in sink.tags() if pmt.symbol_to_string(tag.key) == 'tag1'])
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_crc32_bb, "qa_crc32_bb.xml")
diff --git a/gr-digital/python/qa_header_payload_demux.py b/gr-digital/python/qa_header_payload_demux.py
new file mode 100755
index 0000000000..4073f24ace
--- /dev/null
+++ b/gr-digital/python/qa_header_payload_demux.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import digital_swig as digital
+import time
+
+class qa_header_payload_demux (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_t (self):
+ """ Simplest possible test: put in zeros, then header,
+ then payload, trigger signal, try to demux.
+ The return signal from the header parser is faked via _post()
+ """
+ n_zeros = 100
+ header = (1, 2, 3)
+ payload = tuple(range(17))
+ data_signal = (0,) * n_zeros + header + payload
+ trigger_signal = [0,] * len(data_signal)
+ trigger_signal[n_zeros] = 1
+
+ data_src = gr.vector_source_f(data_signal, False)
+ trigger_src = gr.vector_source_b(trigger_signal, False)
+ hpd = digital.header_payload_demux(
+ len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float
+ )
+ self.assertEqual(pmt.length(hpd.message_ports_in()), 1)
+ header_sink = gr.vector_sink_f()
+ payload_sink = gr.vector_sink_f()
+
+ self.tb.connect(data_src, (hpd, 0))
+ self.tb.connect(trigger_src, (hpd, 1))
+ self.tb.connect((hpd, 0), header_sink)
+ self.tb.connect((hpd, 1), payload_sink)
+ self.tb.start()
+ time.sleep(.2) # Need this, otherwise, the next message is ignored
+ hpd.to_basic_block()._post(
+ pmt.intern('header_data'),
+ pmt.from_long(len(payload))
+ )
+ while len(payload_sink.data()) < len(payload):
+ time.sleep(.2)
+ self.tb.stop()
+ self.tb.wait()
+
+ self.assertEqual(header_sink.data(), header)
+ self.assertEqual(payload_sink.data(), payload)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_header_payload_demux, "qa_header_payload_demux.xml")
+
diff --git a/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py b/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py
new file mode 100755
index 0000000000..2105727e04
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import digital_swig as digital
+
+class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_t (self):
+ """
+ pretty simple
+ """
+ fft_len = 6
+ tx_symbols = (1, 2, 3)
+ pilot_symbols = ((1j,),)
+ occupied_carriers = ((0, 1, 2),)
+ pilot_carriers = ((3,),)
+ expected_result = (1, 2, 3, 1j, 0, 0)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(tx_symbols))
+ src = gr.vector_source_c(tx_symbols, False, 1, (tag,))
+ alloc = digital.ofdm_carrier_allocator_cvc(fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ tag_name)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, alloc, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result)
+
+ def test_002_t (self):
+ """
+ same, but using negative carrier indices
+ """
+ fft_len = 6
+ tx_symbols = (1, 2, 3)
+ pilot_symbols = ((1j,),)
+ occupied_carriers = ((-1, 1, 2),)
+ pilot_carriers = ((3,),)
+ expected_result = (0, 2, 3, 1j, 0, 1)
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(tx_symbols))
+ src = gr.vector_source_c(tx_symbols, False, 1, (tag,))
+ alloc = digital.ofdm_carrier_allocator_cvc(fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ tag_name)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, alloc, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result)
+
+ def test_003_t (self):
+ """
+ more advanced:
+ - 6 symbols per carrier
+ - 2 pilots per carrier
+ - have enough data for nearly 3 OFDM symbols
+ - send that twice
+ - add some random tags
+ """
+ tx_symbols = range(1, 16); # 15 symbols
+ pilot_symbols = ((1j, 2j), (3j, 4j))
+ occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),)
+ pilot_carriers = ((2, 13), (3, 12))
+ expected_result = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0,
+ 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0,
+ 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0)
+ fft_len = 16
+ tag_name = "len"
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tag_name)
+ tag1.value = pmt.from_long(len(tx_symbols))
+ tag2 = gr.gr_tag_t()
+ tag2.offset = len(tx_symbols)
+ tag2.key = pmt.string_to_symbol(tag_name)
+ tag2.value = pmt.from_long(len(tx_symbols))
+ testtag1 = gr.gr_tag_t()
+ testtag1.offset = 0
+ testtag1.key = pmt.string_to_symbol('tag1')
+ testtag1.value = pmt.from_long(0)
+ testtag2 = gr.gr_tag_t()
+ testtag2.offset = 7 # On the 2nd OFDM symbol
+ testtag2.key = pmt.string_to_symbol('tag2')
+ testtag2.value = pmt.from_long(0)
+ testtag3 = gr.gr_tag_t()
+ testtag3.offset = len(tx_symbols)+1 # First OFDM symbol of packet 2
+ testtag3.key = pmt.string_to_symbol('tag3')
+ testtag3.value = pmt.from_long(0)
+ testtag4 = gr.gr_tag_t()
+ testtag4.offset = 2*len(tx_symbols)-1 # Last OFDM symbol of packet 2
+ testtag4.key = pmt.string_to_symbol('tag4')
+ testtag4.value = pmt.from_long(0)
+ src = gr.vector_source_c(tx_symbols * 2, False, 1, (tag1, tag2, testtag1, testtag2, testtag3, testtag4))
+ alloc = digital.ofdm_carrier_allocator_cvc(fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ tag_name)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, alloc, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result * 2)
+ tags_found = {'tag1': False, 'tag2': False, 'tag3': False, 'tag4': False}
+ correct_offsets = {'tag1': 0, 'tag2': 1, 'tag3': 3, 'tag4': 5}
+ for tag in sink.tags():
+ key = pmt.symbol_to_string(tag.key)
+ if key in tags_found.keys():
+ tags_found[key] = True
+ self.assertEqual(correct_offsets[key], tag.offset)
+ if key == tag_name:
+ self.assertTrue(tag.offset == 0 or tag.offset == 3)
+ self.assertTrue(pmt.to_long(tag.value) == 3)
+ self.assertTrue(all(tags_found.values()))
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_digital_carrier_allocator_cvc, "qa_digital_carrier_allocator_cvc.xml")
+
diff --git a/gr-digital/python/qa_ofdm_chanest_vcvc.py b/gr-digital/python/qa_ofdm_chanest_vcvc.py
new file mode 100755
index 0000000000..c7c0d83a84
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_chanest_vcvc.py
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import blocks_swig as blocks
+import analog_swig as analog
+import digital_swig as digital
+import sys
+import numpy
+import random
+
+def shift_tuple(vec, N):
+ """ Shifts a vector by N elements. Fills up with zeros. """
+ if N > 0:
+ return (0,) * N + tuple(vec[0:-N])
+ else:
+ N = -N
+ return tuple(vec[N:]) + (0,) * N
+
+def rand_range(min_val, max_val):
+ """ Returns a random value (uniform) from the interval min_val, max_val """
+ return random.random() * (max_val - min_val) + min_val
+
+
+class qa_ofdm_sync_eqinit_vcvc (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_offset_2sym (self):
+ """ Add a frequency offset, check if it's correctly detected.
+ Also add some random tags and see if they come out at the correct
+ position. """
+ fft_len = 16
+ carr_offset = -2
+ sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ sync_symbol2 = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ tx_data = shift_tuple(sync_symbol1, carr_offset) + \
+ shift_tuple(sync_symbol2, carr_offset) + \
+ shift_tuple(data_symbol, carr_offset)
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol("test_tag_1")
+ tag1.value = pmt.from_long(23)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 2
+ tag2.key = pmt.string_to_symbol("test_tag_2")
+ tag2.value = pmt.from_long(42)
+ src = gr.vector_source_c(tx_data, False, fft_len, (tag1, tag2))
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chanest, sink)
+ self.tb.run()
+ self.assertEqual(shift_tuple(sink.data(), -carr_offset), data_symbol)
+ tags = sink.tags()
+ detected_tags = {
+ 'ofdm_sync_carr_offset': False,
+ 'test_tag_1': False,
+ 'test_tag_2': False
+ }
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ carr_offset_hat = pmt.to_long(tag.value)
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+ if pmt.symbol_to_string(tag.key) == 'test_tag_1':
+ self.assertEqual(tag.offset, 0)
+ if pmt.symbol_to_string(tag.key) == 'test_tag_2':
+ self.assertEqual(tag.offset, 0)
+ detected_tags[pmt.symbol_to_string(tag.key)] = True
+ self.assertTrue(all(detected_tags.values()))
+
+ def test_002_offset_1sym (self):
+ """ Add a frequency offset, check if it's correctly detected.
+ Difference to previous test is, it only uses one synchronisation symbol. """
+ fft_len = 16
+ carr_offset = -2
+ # This will not correct for +2 because it thinks carrier 14 is used
+ # (because of interpolation)
+ sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ tx_data = shift_tuple(sync_symbol, carr_offset) + \
+ shift_tuple(data_symbol, carr_offset)
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ # 17 is out of bounds!
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol, (), 1, 0, 17)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chanest, sink)
+ self.tb.run()
+ self.assertEqual(shift_tuple(sink.data(), -carr_offset), data_symbol)
+ tags = sink.tags()
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ carr_offset_hat = pmt.to_long(tag.value)
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+
+ def test_003_channel_no_carroffset (self):
+ """ Add a channel, check if it's correctly estimated """
+ fft_len = 16
+ carr_offset = 0
+ sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ sync_symbol2 = (0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ tx_data = sync_symbol1 + sync_symbol2 + data_symbol
+ channel = (0, 0, 0, 2, -2, 2, 3j, 2, 0, 2, 2, 2, 2, 3, 0, 0)
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ chan = blocks.multiply_const_vcc(channel)
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chan, chanest, sink)
+ self.tb.run()
+ tags = sink.tags()
+ self.assertEqual(shift_tuple(sink.data(), -carr_offset), tuple(numpy.multiply(data_symbol, channel)))
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps':
+ self.assertEqual(pmt.c32vector_elements(tag.value), channel)
+
+ def test_004_channel_no_carroffset_1sym (self):
+ """ Add a channel, check if it's correctly estimated.
+ Only uses 1 synchronisation symbol. """
+ fft_len = 16
+ carr_offset = 0
+ sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ tx_data = sync_symbol + data_symbol
+ channel = (0, 0, 0, 2, 2, 2, 2.5, 3, 2.5, 2, 2.5, 3, 2, 1, 1, 0)
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ chan = blocks.multiply_const_vcc(channel)
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol, (), 1)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chan, chanest, sink)
+ self.tb.run()
+ tags = sink.tags()
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps':
+ self.assertEqual(pmt.c32vector_elements(tag.value), channel)
+
+ def test_005_both_1sym_force (self):
+ """ Add a channel, check if it's correctly estimated.
+ Only uses 1 synchronisation symbol. """
+ fft_len = 16
+ carr_offset = 0
+ sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ ref_symbol = (0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ tx_data = sync_symbol + data_symbol
+ channel = (0, 0, 0, 2, 2, 2, 2.5, 3, 2.5, 2, 2.5, 3, 2, 1, 1, 0)
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ chan = blocks.multiply_const_vcc(channel)
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol, ref_symbol, 1)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chan, chanest, sink)
+ self.tb.run()
+ tags = sink.tags()
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps':
+ self.assertEqual(pmt.c32vector_elements(tag.value), channel)
+
+ def test_006_channel_and_carroffset (self):
+ """ Add a channel, check if it's correctly estimated """
+ fft_len = 16
+ carr_offset = 2
+ # Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0)
+ sync_symbol2 = (0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1, 0, 0)
+ data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0)
+ # Channel 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ # Shifted (0, 0, 0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1)
+ tx_data = shift_tuple(sync_symbol1, carr_offset) + \
+ shift_tuple(sync_symbol2, carr_offset) + \
+ shift_tuple(data_symbol, carr_offset)
+ channel = range(fft_len)
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ chan = blocks.multiply_const_vcc(channel)
+ chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, chan, chanest, sink)
+ self.tb.run()
+ tags = sink.tags()
+ chan_est = None
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ self.assertEqual(pmt.to_long(tag.value), carr_offset)
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps':
+ chan_est = pmt.c32vector_elements(tag.value)
+ for i in range(fft_len):
+ if shift_tuple(sync_symbol2, carr_offset)[i]: # Only here the channel can be estimated
+ self.assertEqual(chan_est[i], channel[i])
+ self.assertEqual(sink.data(), tuple(numpy.multiply(shift_tuple(data_symbol, carr_offset), channel)))
+
+
+ def test_999_all_at_once(self):
+ """docstring for test_999_all_at_once"""
+ fft_len = 32
+ # 6 carriers empty, 10 carriers full, 1 DC carrier, 10 carriers full, 5 carriers empty
+ syncsym_mask = (0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0)
+ carrier_mask = (0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0)
+ max_offset = 4
+ wgn_amplitude = 0.05
+ min_chan_ampl = 0.1
+ max_chan_ampl = 5
+ n_iter = 100
+ def run_flow_graph(sync_sym1, sync_sym2, data_sym):
+ top_block = gr.top_block()
+ carr_offset = random.randint(-max_offset/2, max_offset/2) * 2
+ tx_data = shift_tuple(sync_sym1, carr_offset) + \
+ shift_tuple(sync_sym2, carr_offset) + \
+ shift_tuple(data_sym, carr_offset)
+ channel = [rand_range(min_chan_ampl, max_chan_ampl) * numpy.exp(1j * rand_range(0, 2 * numpy.pi)) for x in range(fft_len)]
+ src = gr.vector_source_c(tx_data, False, fft_len)
+ chan = blocks.multiply_const_vcc(channel)
+ noise = analog.noise_source_c(analog.GR_GAUSSIAN, wgn_amplitude)
+ add = blocks.add_cc(fft_len)
+ chanest = digital.ofdm_chanest_vcvc(sync_sym1, sync_sym2, 1)
+ sink = gr.vector_sink_c(fft_len)
+ top_block.connect(src, chan, (add, 0), chanest, sink)
+ top_block.connect(noise, blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), (add, 1))
+ top_block.run()
+ channel_est = None
+ carr_offset_hat = 0
+ rx_sym_est = [0,] * fft_len
+ tags = sink.tags()
+ for tag in tags:
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
+ carr_offset_hat = pmt.to_long(tag.value)
+ self.assertEqual(carr_offset, carr_offset_hat)
+ if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps':
+ channel_est = pmt.c32vector_elements(tag.value)
+ shifted_carrier_mask = shift_tuple(carrier_mask, carr_offset)
+ for i in range(fft_len):
+ if shifted_carrier_mask[i] and channel_est[i]:
+ self.assertAlmostEqual(channel[i], channel_est[i], places=0)
+ rx_sym_est[i] = (sink.data()[i] / channel_est[i]).real
+ return (carr_offset, list(shift_tuple(rx_sym_est, -carr_offset_hat)))
+ bit_errors = 0
+ for k in xrange(n_iter):
+ sync_sym = [(random.randint(0, 1) * 2 - 1) * syncsym_mask[i] for i in range(fft_len)]
+ ref_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)]
+ data_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)]
+ data_sym[26] = 1
+ (carr_offset, rx_sym) = run_flow_graph(sync_sym, ref_sym, data_sym)
+ rx_sym_est = [0,] * fft_len
+ for i in xrange(fft_len):
+ if carrier_mask[i] == 0:
+ continue
+ rx_sym_est[i] = {True: 1, False: -1}[rx_sym[i] > 0]
+ if rx_sym_est[i] != data_sym[i]:
+ bit_errors += 1
+ # This is much more than we could allow
+ self.assertTrue(bit_errors < n_iter)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_ofdm_sync_eqinit_vcvc, "qa_ofdm_sync_eqinit_vcvc.xml")
+
diff --git a/gr-digital/python/qa_ofdm_cyclic_prefixer.py b/gr-digital/python/qa_ofdm_cyclic_prefixer.py
new file mode 100755
index 0000000000..003e987e95
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_cyclic_prefixer.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+# Copyright 2007,2010,2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import digital_swig as digital
+
+class test_ofdm_cyclic_prefixer (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_wo_tags_no_rolloff(self):
+ " The easiest test: make sure the CP is added correctly. "
+ fft_len = 8
+ cp_len = 2
+ expected_result = (6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
+ 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)
+ src = gr.vector_source_c(range(fft_len) * 2, False, fft_len)
+ cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, cp, sink)
+ self.tb.run()
+ self.assertEqual(sink.data(), expected_result)
+
+ def test_wo_tags_2s_rolloff(self):
+ " No tags, but have a 2-sample rolloff "
+ fft_len = 8
+ cp_len = 2
+ rolloff = 2
+ expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2
+ 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8)
+ src = gr.vector_source_c(range(1, fft_len+1) * 2, False, fft_len)
+ cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, rolloff)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, cp, sink)
+ self.tb.run()
+ self.assertEqual(sink.data(), expected_result)
+
+ def test_with_tags_2s_rolloff(self):
+ " With tags and a 2-sample rolloff "
+ fft_len = 8
+ cp_len = 2
+ tag_name = "length"
+ expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2
+ 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0/2)
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(2)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 1
+ tag2.key = pmt.string_to_symbol("random_tag")
+ tag2.value = pmt.from_long(42)
+ src = gr.vector_source_c(range(1, fft_len+1) * 2, False, fft_len, (tag, tag2))
+ cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, cp, sink)
+ self.tb.run()
+ self.assertEqual(sink.data(), expected_result)
+ tags = [gr.tag_to_python(x) for x in sink.tags()]
+ tags = sorted([(x.offset, x.key, x.value) for x in tags])
+ expected_tags = [
+ (0, tag_name, len(expected_result)),
+ (fft_len+cp_len, "random_tag", 42)
+ ]
+ self.assertEqual(tags, expected_tags)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_ofdm_cyclic_prefixer, "test_ofdm_cyclic_prefixer.xml")
+
diff --git a/gr-digital/python/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/qa_ofdm_frame_equalizer_vcvc.py
new file mode 100755
index 0000000000..9faface03f
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_frame_equalizer_vcvc.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import numpy
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import digital_swig as digital
+
+class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_simple (self):
+ """ Very simple functionality testing """
+ fft_len = 8
+ equalizer = digital.ofdm_equalizer_static(fft_len)
+ n_syms = 3
+ len_tag_key = "frame_len"
+ tx_data = (1,) * fft_len * n_syms
+ len_tag = gr.gr_tag_t()
+ len_tag.offset = 0
+ len_tag.key = pmt.string_to_symbol(len_tag_key)
+ len_tag.value = pmt.from_long(n_syms)
+ chan_tag = gr.gr_tag_t()
+ chan_tag.offset = 0
+ chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps")
+ chan_tag.value = pmt.init_c32vector(fft_len, (1,) * fft_len)
+ src = gr.vector_source_c(tx_data, False, fft_len, (len_tag, chan_tag))
+ eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, eq, sink)
+ self.tb.run ()
+ # Check data
+ self.assertEqual(tx_data, sink.data())
+ for tag in sink.tags():
+ self.assertEqual(pmt.symbol_to_string(tag.key), len_tag_key)
+ self.assertEqual(pmt.to_long(tag.value), n_syms)
+
+ def test_002_static (self):
+ fft_len = 8
+ # 4 5 6 7 0 1 2 3
+ tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0
+ -1, -1, 0, 2, -1, 2, 0, -1, # 8
+ -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols)
+ -1, -1, 1, 1, -1, 0, 2, -1] # 24
+ cnst = digital.constellation_qpsk()
+ tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data]
+ occupied_carriers = ((1, 2, 6, 7),)
+ pilot_carriers = ((), (), (1, 2, 6, 7), ())
+ pilot_symbols = (
+ [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], []
+ )
+ equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers, pilot_carriers, pilot_symbols)
+ channel = [
+ 0, 0, 1, 1, 0, 1, 1, 0,
+ 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly...
+ 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here!
+ 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here.
+ ]
+ for idx in range(fft_len, 2*fft_len):
+ channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5))
+ idx2 = idx+2*fft_len
+ channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5))
+ len_tag_key = "frame_len"
+ len_tag = gr.gr_tag_t()
+ len_tag.offset = 0
+ len_tag.key = pmt.string_to_symbol(len_tag_key)
+ len_tag.value = pmt.from_long(4)
+ chan_tag = gr.gr_tag_t()
+ chan_tag.offset = 0
+ chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps")
+ chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len])
+ src = gr.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (len_tag, chan_tag))
+ eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key, True)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, eq, sink)
+ self.tb.run ()
+ rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()]
+ self.assertEqual(tx_data, rx_data)
+ for tag in sink.tags():
+ if pmt.symbol_to_string(tag.key) == len_tag_key:
+ self.assertEqual(pmt.to_long(tag.value), 4)
+ if pmt.symbol_to_string(tag.key) == "ofdm_sync_chan_taps":
+ self.assertEqual(list(pmt.c32vector_elements(tag.value)), channel[-fft_len:])
+
+ def test_002_simpledfe (self):
+ fft_len = 8
+ # 4 5 6 7 0 1 2 3
+ tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0
+ -1, -1, 0, 2, -1, 2, 0, -1, # 8
+ -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols)
+ -1, -1, 1, 1, -1, 0, 2, -1] # 24
+ cnst = digital.constellation_qpsk()
+ tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data]
+ occupied_carriers = ((1, 2, 6, 7),)
+ pilot_carriers = ((), (), (1, 2, 6, 7), ())
+ pilot_symbols = (
+ [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], []
+ )
+ equalizer = digital.ofdm_equalizer_simpledfe(
+ fft_len, cnst.base(), occupied_carriers, pilot_carriers, pilot_symbols, 0, 0.01
+ )
+ channel = [
+ 0, 0, 1, 1, 0, 1, 1, 0,
+ 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly...
+ 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here!
+ 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here.
+ ]
+ for idx in range(fft_len, 2*fft_len):
+ channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5))
+ idx2 = idx+2*fft_len
+ channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5))
+ len_tag_key = "frame_len"
+ len_tag = gr.gr_tag_t()
+ len_tag.offset = 0
+ len_tag.key = pmt.string_to_symbol(len_tag_key)
+ len_tag.value = pmt.from_long(4)
+ chan_tag = gr.gr_tag_t()
+ chan_tag.offset = 0
+ chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps")
+ chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len])
+ src = gr.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (len_tag, chan_tag))
+ eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key, True)
+ sink = gr.vector_sink_c(fft_len)
+ self.tb.connect(src, eq, sink)
+ self.tb.run ()
+ rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()]
+ self.assertEqual(tx_data, rx_data)
+ for tag in sink.tags():
+ if pmt.symbol_to_string(tag.key) == len_tag_key:
+ self.assertEqual(pmt.to_long(tag.value), 4)
+ if pmt.symbol_to_string(tag.key) == "ofdm_sync_chan_taps":
+ self.assertComplexTuplesAlmostEqual(list(pmt.c32vector_elements(tag.value)), channel[-fft_len:], places=1)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_ofdm_frame_equalizer_vcvc, "qa_ofdm_frame_equalizer_vcvc.xml")
+
diff --git a/gr-digital/python/qa_ofdm_serializer_vcc.py b/gr-digital/python/qa_ofdm_serializer_vcc.py
new file mode 100755
index 0000000000..107d6076c5
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_serializer_vcc.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import blocks_swig as blocks
+import fft_swig as fft
+import analog_swig as analog
+import digital_swig as digital
+try: import pmt
+except: from gruel import pmt
+import numpy
+
+class qa_ofdm_serializer_vcc (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_simple (self):
+ """ Standard test """
+ fft_len = 16
+ tx_symbols = range(1, 16);
+ tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0,
+ 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0,
+ 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0)
+ expected_result = tuple(range(1, 16)) + (0, 0, 0)
+ occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),)
+ n_syms = len(tx_symbols)/fft_len
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(n_syms)
+ src = gr.vector_source_c(tx_symbols, False, fft_len, (tag,))
+ serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "", 0, False)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, serializer, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result)
+ self.assertEqual(len(sink.tags()), 1)
+ result_tag = sink.tags()[0]
+ self.assertEqual(pmt.symbol_to_string(result_tag.key), tag_name)
+ self.assertEqual(pmt.to_long(result_tag.value), n_syms * len(occupied_carriers[0]))
+
+ def test_002_with_offset (self):
+ """ Standard test, carrier offset """
+ fft_len = 16
+ tx_symbols = range(1, 16);
+ tx_symbols = (0, 0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6,
+ 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12,
+ 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0)
+ carr_offset = 1 # Compare this with tx_symbols from the previous test
+ expected_result = tuple(range(1, 16)) + (0, 0, 0)
+ occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),)
+ n_syms = len(tx_symbols)/fft_len
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(n_syms)
+ offsettag = gr.gr_tag_t()
+ offsettag.offset = 0
+ offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset")
+ offsettag.value = pmt.from_long(carr_offset)
+ src = gr.vector_source_c(tx_symbols, False, fft_len, (tag, offsettag))
+ serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "", 0, False)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, serializer, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result)
+ self.assertEqual(len(sink.tags()), 2)
+ for tag in sink.tags():
+ if pmt.symbol_to_string(tag.key) == tag_name:
+ self.assertEqual(pmt.to_long(tag.value), n_syms * len(occupied_carriers[0]))
+
+ def test_003_connect (self):
+ """ Connect carrier_allocator to ofdm_serializer,
+ make sure output==input """
+ fft_len = 8
+ n_syms = 10
+ occupied_carriers = ((1, 2, 6, 7),)
+ pilot_carriers = ((3,),(5,))
+ pilot_symbols = ((1j,),(-1j,))
+ tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)])
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(tx_data))
+ src = gr.vector_source_c(tx_data, False, 1, (tag,))
+ alloc = digital.ofdm_carrier_allocator_cvc(fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ tag_name)
+ serializer = digital.ofdm_serializer_vcc(alloc)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, alloc, serializer, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), tx_data)
+
+ def test_004_connect (self):
+ """
+ Advanced test:
+ - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer
+ - FFT does shift (moves DC to middle)
+ - Make sure input == output
+ - Frequency offset is -2 carriers
+ """
+ fft_len = 8
+ n_syms = 2
+ carr_offset = -2
+ freq_offset = 2 * numpy.pi * carr_offset / fft_len # If the sampling rate == 1
+ occupied_carriers = ((1, 2, -2, -1),)
+ pilot_carriers = ((3,),(5,))
+ pilot_symbols = ((1j,),(-1j,))
+ tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)])
+ #tx_data = (1,) * occupied_carriers[0] * n_syms
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(len(tx_data))
+ offsettag = gr.gr_tag_t()
+ offsettag.offset = 0
+ offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset")
+ offsettag.value = pmt.from_long(carr_offset)
+ src = gr.vector_source_c(tx_data, False, 1, (tag, offsettag))
+ alloc = digital.ofdm_carrier_allocator_cvc(fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ tag_name)
+ tx_ifft = fft.fft_vcc(fft_len, False, ())
+ offset_sig = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0)
+ mixer = blocks.multiply_cc()
+ rx_fft = fft.fft_vcc(fft_len, True, (), True)
+ serializer = digital.ofdm_serializer_vcc(alloc)
+ sink = gr.vector_sink_c()
+ self.tb.connect(
+ src, alloc, tx_ifft,
+ blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len),
+ (mixer, 0),
+ blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len),
+ rx_fft, serializer, sink
+ )
+ self.tb.connect(offset_sig, (mixer, 1))
+ self.tb.run ()
+ # FIXME check this
+ #self.assertEqual(sink.data(), tx_data)
+
+ def test_005_packet_len_tag (self):
+ """ Standard test """
+ fft_len = 16
+ tx_symbols = range(1, 16);
+ tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0,
+ 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0,
+ 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0)
+ expected_result = tuple(range(1, 16))
+ occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),)
+ n_syms = len(tx_symbols)/fft_len
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.string_to_symbol(tag_name)
+ tag.value = pmt.from_long(n_syms)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 0
+ tag2.key = pmt.string_to_symbol("packet_len")
+ tag2.value = pmt.from_long(len(expected_result))
+ src = gr.vector_source_c(tx_symbols, False, fft_len, (tag, tag2))
+ serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "packet_len", 0, False)
+ sink = gr.vector_sink_c()
+ self.tb.connect(src, serializer, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_result)
+ self.assertEqual(len(sink.tags()), 1)
+ result_tag = sink.tags()[0]
+ self.assertEqual(pmt.symbol_to_string(result_tag.key), "packet_len")
+ self.assertEqual(pmt.to_long(result_tag.value), len(expected_result))
+
+ def test_099 (self):
+ """ Make sure it fails if it should """
+ fft_len = 16
+ occupied_carriers = ((1, 3, 4, 11, 12, 17),)
+ tag_name = "len"
+ self.assertRaises(RuntimeError, digital.ofdm_serializer_vcc, fft_len, occupied_carriers, tag_name)
+
+
+if __name__ == '__main__':
+ #gr_unittest.run(qa_ofdm_serializer_vcc, "qa_ofdm_serializer_vcc.xml")
+ gr_unittest.run(qa_ofdm_serializer_vcc)
+
diff --git a/gr-digital/python/qa_ofdm_sync_sc_cfb.py b/gr-digital/python/qa_ofdm_sync_sc_cfb.py
new file mode 100755
index 0000000000..806ef931de
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_sync_sc_cfb.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import numpy
+import random
+
+from gnuradio import gr, gr_unittest
+import blocks_swig as blocks
+import analog_swig as analog
+
+try:
+ # This will work when feature #505 is added.
+ from gnuradio import digital
+ from gnuradio.digital.utils import tagged_streams
+ from gnuradio.digital.ofdm_txrx import ofdm_tx
+except ImportError:
+ # Until then this will work.
+ import digital_swig as digital
+ from utils import tagged_streams
+ from ofdm_txrx import ofdm_tx
+
+
+class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_detect (self):
+ """ Send two bursts, with zeros in between, and check
+ they are both detected at the correct position and no
+ false alarms occur """
+ n_zeros = 15
+ fft_len = 32
+ cp_len = 4
+ sig_len = (fft_len + cp_len) * 10
+ sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2
+ tx_signal = [0,] * n_zeros + \
+ sync_symbol[-cp_len:] + \
+ sync_symbol + \
+ [(random.randint(0, 1)*2)-1 for x in range(sig_len)]
+ tx_signal = tx_signal * 2
+ add = blocks.add_cc()
+ sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
+ sink_freq = gr.vector_sink_f()
+ sink_detect = gr.vector_sink_b()
+ self.tb.connect(gr.vector_source_c(tx_signal), (add, 0))
+ self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .01), (add, 1))
+ self.tb.connect(add, sync)
+ self.tb.connect((sync, 0), sink_freq)
+ self.tb.connect((sync, 1), sink_detect)
+ self.tb.run()
+ sig1_detect = sink_detect.data()[0:len(tx_signal)/2]
+ sig2_detect = sink_detect.data()[len(tx_signal)/2:]
+ self.assertTrue(abs(sig1_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len)
+ self.assertTrue(abs(sig2_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len)
+ self.assertEqual(numpy.sum(sig1_detect), 1)
+ self.assertEqual(numpy.sum(sig2_detect), 1)
+
+
+ def test_002_freq (self):
+ """ Add a fine frequency offset and see if that get's detected properly """
+ fft_len = 32
+ cp_len = 4
+ freq_offset = 0.1 # Must stay < 2*pi/fft_len = 0.196 (otherwise, it's coarse)
+ sig_len = (fft_len + cp_len) * 10
+ sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2
+ tx_signal = sync_symbol[-cp_len:] + \
+ sync_symbol + \
+ [(random.randint(0, 1)*2)-1 for x in range(sig_len)]
+ mult = blocks.multiply_cc()
+ add = blocks.add_cc()
+ sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
+ sink_freq = gr.vector_sink_f()
+ sink_detect = gr.vector_sink_b()
+ self.tb.connect(gr.vector_source_c(tx_signal), (mult, 0), (add, 0))
+ self.tb.connect(analog.sig_source_c(2 * numpy.pi, analog.GR_SIN_WAVE, freq_offset, 1.0), (mult, 1))
+ self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .01), (add, 1))
+ self.tb.connect(add, sync)
+ self.tb.connect((sync, 0), sink_freq)
+ self.tb.connect((sync, 1), sink_detect)
+ self.tb.run()
+ phi_hat = sink_freq.data()[sink_detect.data().index(1)]
+ est_freq_offset = 2 * phi_hat / fft_len
+ self.assertAlmostEqual(est_freq_offset, freq_offset, places=2)
+
+
+ def test_003_multiburst (self):
+ """ Send several bursts, see if the number of detects is correct.
+ Burst lengths and content are random.
+ """
+ n_bursts = 42
+ fft_len = 32
+ cp_len = 4
+ tx_signal = []
+ for i in xrange(n_bursts):
+ sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2
+ tx_signal += [0,] * random.randint(0, 2*fft_len) + \
+ sync_symbol[-cp_len:] + \
+ sync_symbol + \
+ [(random.randint(0, 1)*2)-1 for x in range(fft_len * random.randint(5,23))]
+ add = blocks.add_cc()
+ sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
+ sink_freq = gr.vector_sink_f()
+ sink_detect = gr.vector_sink_b()
+ self.tb.connect(gr.vector_source_c(tx_signal), (add, 0))
+ self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .005), (add, 1))
+ self.tb.connect(add, sync)
+ self.tb.connect((sync, 0), sink_freq)
+ self.tb.connect((sync, 1), sink_detect)
+ self.tb.run()
+ self.assertEqual(numpy.sum(sink_detect.data()), n_bursts,
+ msg="""Because of statistics, it is possible (though unlikely)
+that the number of detected bursts differs slightly. If the number of detects is
+off by one or two, run the test again and see what happen.
+Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts)
+ )
+
+ # FIXME ofdm_mod is currently not working
+ #def test_004_ofdm_packets (self):
+ #"""
+ #Send several bursts, see if the number of detects is correct.
+ #Burst lengths and content are random.
+ #"""
+ #n_bursts = 42
+ #fft_len = 64
+ #cp_len = 12
+ #tx_signal = []
+ #packets = []
+ #tagname = "length"
+ #min_packet_length = 100
+ #max_packet_length = 100
+ #sync_sequence = [random.randint(0, 1)*2-1 for x in range(fft_len/2)]
+ #for i in xrange(n_bursts):
+ #packet_length = random.randint(min_packet_length,
+ #max_packet_length+1)
+ #packet = [random.randint(0, 255) for i in range(packet_length)]
+ #packets.append(packet)
+ #data, tags = tagged_streams.packets_to_vectors(
+ #packets, tagname, vlen=1)
+ #total_length = len(data)
+
+ #src = gr.vector_source_b(data, False, 1, tags)
+ #mod = ofdm_tx(
+ #fft_len=fft_len,
+ #cp_len=cp_len,
+ #length_tag_name=tagname,
+ #occupied_carriers=(range(1, 27) + range(38, 64),),
+ #pilot_carriers=((0,),),
+ #pilot_symbols=((100,),),
+ #)
+ #rate_in = 16000
+ #rate_out = 48000
+ #ratio = float(rate_out) / rate_in
+ #throttle1 = gr.throttle(gr.sizeof_gr_complex, rate_in)
+ #insert_zeros = digital.ts_insert_zeros_cc(tagname)
+ #throttle2 = gr.throttle(gr.sizeof_gr_complex, rate_out)
+ #sink_countbursts = gr.vector_sink_c()
+ #head = gr.head(gr.sizeof_gr_complex, int(total_length * ratio*2))
+ #add = gr.add_cc()
+ #sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
+ #sink_freq = gr.vector_sink_f()
+ #sink_detect = gr.vector_sink_b()
+ #noise_level = 0.01
+ #noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_level)
+ #self.tb.connect(src, mod, gr.null_sink(gr.sizeof_gr_complex))
+ #self.tb.connect(insert_zeros, sink_countbursts)
+ #self.tb.connect(noise, (add, 1))
+ #self.tb.connect(add, sync)
+ #self.tb.connect((sync, 0), sink_freq)
+ #self.tb.connect((sync, 1), sink_detect)
+ #self.tb.run()
+ #count_data = sink_countbursts.data()
+ #count_tags = sink_countbursts.tags()
+ #burstcount = tagged_streams.count_bursts(count_data, count_tags, tagname)
+ #self.assertEqual(numpy.sum(sink_detect.data()), burstcount)
+
+
+if __name__ == '__main__':
+ #gr_unittest.run(qa_ofdm_sync_sc_cfb, "qa_ofdm_sync_sc_cfb.xml")
+ gr_unittest.run(qa_ofdm_sync_sc_cfb)
+
diff --git a/gr-digital/python/qa_ofdm_txrx.py b/gr-digital/python/qa_ofdm_txrx.py
new file mode 100755
index 0000000000..778f03f515
--- /dev/null
+++ b/gr-digital/python/qa_ofdm_txrx.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import numpy
+from gnuradio import gr, gr_unittest
+import digital_swig
+
+class test_ofdm_txrx (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001 (self):
+ pass
+ #len_tag_key = 'frame_len'
+ #n_bytes = 100
+ #test_data = [random.randint(0, 255) for x in range(n_bytes)]
+ #tx_data, tags = tagged_streams.packets_to_vectors((test_data,), len_tag_key)
+ #src = gr.vector_source_b(test_data, False, 1, tags)
+ #tx = ofdm_tx(frame_length_tag_key=len_tag_key)
+ #rx = ofdm_rx(frame_length_tag_key=len_tag_key)
+ #self.assertEqual(tx.sync_word1, rx.sync_word1)
+ #self.assertEqual(tx.sync_word2, rx.sync_word2)
+ #delay = gr.delay(gr.sizeof_gr_complex, 100)
+ #noise = gr.noise_source_c(gr.GR_GAUSSIAN, 0.05)
+ #add = gr.add_cc()
+ #sink = gr.vector_sink_b()
+ ##self.tb.connect(src, tx, add, rx, sink)
+ ##self.tb.connect(noise, (add, 1))
+ #self.tb.connect(src, tx, gr.null_sink(gr.sizeof_gr_complex))
+ #self.tb.run()
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_ofdm_txrx, "test_ofdm_txrx.xml")
+
diff --git a/gr-digital/python/qa_packet_headergenerator_bb.py b/gr-digital/python/qa_packet_headergenerator_bb.py
new file mode 100755
index 0000000000..2e6e401566
--- /dev/null
+++ b/gr-digital/python/qa_packet_headergenerator_bb.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import digital_swig as digital
+try: import pmt
+except: from gruel import pmt
+
+class qa_packet_headergenerator_bb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_12bits (self):
+ # 3 PDUs: | | | |
+ data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4)
+ tagname = "packet_len"
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tagname)
+ tag1.value = pmt.from_long(4)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 4
+ tag2.key = pmt.string_to_symbol(tagname)
+ tag2.value = pmt.from_long(2)
+ tag3 = gr.gr_tag_t()
+ tag3.offset = 6
+ tag3.key = pmt.string_to_symbol(tagname)
+ tag3.value = pmt.from_long(4)
+ src = gr.vector_source_b(data, False, 1, (tag1, tag2, tag3))
+ header = digital.packet_headergenerator_bb(12, tagname)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, header, sink)
+ self.tb.run()
+ expected_data = (
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ )
+ self.assertEqual(sink.data(), expected_data)
+
+
+ def test_002_32bits (self):
+ # 3 PDUs: | | | |
+ data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4)
+ tagname = "packet_len"
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tagname)
+ tag1.value = pmt.from_long(4)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 4
+ tag2.key = pmt.string_to_symbol(tagname)
+ tag2.value = pmt.from_long(2)
+ tag3 = gr.gr_tag_t()
+ tag3.offset = 6
+ tag3.key = pmt.string_to_symbol(tagname)
+ tag3.value = pmt.from_long(4)
+ src = gr.vector_source_b(data, False, 1, (tag1, tag2, tag3))
+ header = digital.packet_headergenerator_bb(32, tagname)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, header, sink)
+ self.tb.run()
+ expected_data = (
+ # | Number of symbols | Packet number | Parity
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ )
+ self.assertEqual(sink.data(), expected_data)
+
+
+ def test_003_12bits_formatter_object (self):
+ # 3 PDUs: | | | |
+ data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4)
+ tagname = "packet_len"
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tagname)
+ tag1.value = pmt.from_long(4)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 4
+ tag2.key = pmt.string_to_symbol(tagname)
+ tag2.value = pmt.from_long(2)
+ tag3 = gr.gr_tag_t()
+ tag3.offset = 6
+ tag3.key = pmt.string_to_symbol(tagname)
+ tag3.value = pmt.from_long(4)
+ src = gr.vector_source_b(data, False, 1, (tag1, tag2, tag3))
+ formatter_object = digital.packet_header_default(12, tagname)
+ header = digital.packet_headergenerator_bb(formatter_object.formatter())
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, header, sink)
+ self.tb.run()
+ expected_data = (
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ )
+ self.assertEqual(sink.data(), expected_data)
+
+ def test_004_8bits_formatter_ofdm (self):
+ occupied_carriers = ((1, 2, 3, 5, 6, 7),)
+ # 3 PDUs: | | | |
+ data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4)
+ tagname = "packet_len"
+ tag1 = gr.gr_tag_t()
+ tag1.offset = 0
+ tag1.key = pmt.string_to_symbol(tagname)
+ tag1.value = pmt.from_long(4)
+ tag2 = gr.gr_tag_t()
+ tag2.offset = 4
+ tag2.key = pmt.string_to_symbol(tagname)
+ tag2.value = pmt.from_long(2)
+ tag3 = gr.gr_tag_t()
+ tag3.offset = 6
+ tag3.key = pmt.string_to_symbol(tagname)
+ tag3.value = pmt.from_long(4)
+ src = gr.vector_source_b(data, False, 1, (tag1, tag2, tag3))
+ formatter_object = digital.packet_header_ofdm(occupied_carriers, 1, tagname)
+ self.assertEqual(formatter_object.header_len(), 6)
+ self.assertEqual(pmt.symbol_to_string(formatter_object.len_tag_key()), tagname)
+ header = digital.packet_headergenerator_bb(formatter_object.formatter())
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, header, sink)
+ self.tb.run()
+ expected_data = (
+ 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0
+ )
+ self.assertEqual(sink.data(), expected_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_packet_headergenerator_bb, "qa_packet_headergenerator_bb.xml")
+
diff --git a/gr-digital/python/qa_packet_headerparser_b.py b/gr-digital/python/qa_packet_headerparser_b.py
new file mode 100755
index 0000000000..aec2f96b57
--- /dev/null
+++ b/gr-digital/python/qa_packet_headerparser_b.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import time
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import blocks_swig as blocks
+import digital_swig as digital
+
+class qa_packet_headerparser_b (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_t (self):
+ expected_data = (
+ # | Number of symbols | Packet number | Parity
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+ )
+ tagname = "packet_len"
+
+ src = gr.vector_source_b(expected_data)
+ parser = digital.packet_headerparser_b(32, tagname)
+ sink = blocks.message_debug()
+
+ self.tb.connect(src, parser)
+ self.tb.msg_connect(parser, "header_data", sink, "store")
+ self.tb.start ()
+ time.sleep(1)
+ self.tb.stop()
+ self.tb.wait()
+
+ self.assertEqual(sink.num_messages(), 3)
+ msg = sink.get_message(0)
+ #try:
+ #self.assertEqual(4, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol(tagname), pmt.PMT_F)))
+ #self.assertEqual(0, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol("packet_num"), pmt.PMT_F)))
+
+ #except:
+ #self.fail()
+ # msg1: length 4, number 0
+ # msg2: length 2, number 1
+ # msg3: PMT_F because parity fail
+
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_packet_headerparser_b, "qa_packet_headerparser_b.xml")
diff --git a/gr-digital/python/qa_scale_tags.py b/gr-digital/python/qa_scale_tags.py
new file mode 100755
index 0000000000..deee775579
--- /dev/null
+++ b/gr-digital/python/qa_scale_tags.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import time
+import itertools
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import blocks_swig as blocks
+import digital_swig as digital
+from utils import tagged_streams
+
+class qa_scale_tags (gr_unittest.TestCase):
+
+ def test_utils(self):
+ packets = ((1, 2, 3), (4, 5, 6, 7, 8), (9, 10))
+ tagname = "vector_length"
+ data, tags = tagged_streams.packets_to_vectors(packets, tagname)
+ new_packets = tagged_streams.vectors_to_packets(data, tags, tagname)
+ for np, op in zip(new_packets, packets):
+ for n, o in zip(np, op):
+ self.assertEqual(n, o)
+
+ def test_001_t (self):
+ packets = ((1, 2, 3), (4, 5, 6, 7, 8), (9, 10))
+ tagname = "packet_length"
+ data, tags = tagged_streams.packets_to_vectors(packets, tagname)
+ tb = gr.top_block()
+ src = gr.vector_source_b(data, False, 1, tags)
+ tag_scaler = digital.scale_tags(1, tagname, 2)
+ unpacker = blocks.packed_to_unpacked_bb(4, blocks.GR_MSB_FIRST)
+ snk = gr.vector_sink_b()
+ tb.connect(src, unpacker, tag_scaler, snk)
+ tb.run()
+ packets = tagged_streams.vectors_to_packets(snk.data(), snk.tags(), tagname)
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_scale_tags, "qa_scale_tags.xml")
diff --git a/gr-digital/python/qa_ts_insert_zeros.py b/gr-digital/python/qa_ts_insert_zeros.py
new file mode 100644
index 0000000000..d13a4c1c2b
--- /dev/null
+++ b/gr-digital/python/qa_ts_insert_zeros.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# Copyright 2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import time
+import itertools
+
+from gnuradio import gr, gr_unittest
+try: import pmt
+except: from gruel import pmt
+import blocks_swig as blocks
+import digital_swig as digital
+from utils import tagged_streams
+
+class qa_ts_insert_zeros (gr_unittest.TestCase):
+
+ def test_one(self):
+ n_packets = 10
+ packet_length = 1000
+ packets = [[i]*packet_length for i in range(1, n_packets+1)]
+ tagname = "packet_length"
+ data, tags = tagged_streams.packets_to_vectors(packets, tagname)
+ tb = gr.top_block()
+ src = gr.vector_source_c(data, False, 1, tags)
+ rate_in = 16000
+ rate_out = 48000
+ ratio = float(rate_out) / rate_in
+ throttle1 = blocks.throttle(gr.sizeof_gr_complex, rate_in)
+ insert_zeros = digital.ts_insert_zeros_cc(tagname)
+ throttle2 = blocks.throttle(gr.sizeof_gr_complex, rate_out)
+ head = gr.head(gr.sizeof_gr_complex, int(n_packets * packet_length * ratio*2))
+ snk = gr.vector_sink_c()
+ tb.connect(src, throttle1, insert_zeros, throttle2, head, snk)
+ tb.run()
+ data = snk.data()
+ state = 1
+ pos = 0
+ last_non_zero = 0
+ for i, d in enumerate(data):
+ if d != 0:
+ last_non_zero = i
+ if pos == 0:
+ if (d == state):
+ pos = pos + 1
+ elif (d != 0):
+ raise ValueError("Invalid")
+ elif pos > 0:
+ if (d != state):
+ raise ValueError("Invalid")
+ pos = pos + 1
+ if pos == packet_length:
+ state += 1
+ pos = 0
+ min_ratio = ratio-1
+ max_ratio = ratio+1
+ self.assertEqual(state-1, n_packets)
+ self.assertTrue(last_non_zero > min_ratio*packet_length*n_packets)
+ self.assertTrue(last_non_zero < max_ratio*packet_length*n_packets)
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_ts_insert_zeros, "qa_ts_insert_zeros.xml")
diff --git a/gr-digital/python/utils/tagged_streams.py b/gr-digital/python/utils/tagged_streams.py
new file mode 100644
index 0000000000..6a956aa642
--- /dev/null
+++ b/gr-digital/python/utils/tagged_streams.py
@@ -0,0 +1,112 @@
+from gnuradio import gr
+try: import pmt
+except: from gruel import pmt
+
+def make_lengthtags(lengths, offsets, tagname='length', vlen=1):
+ tags = []
+ assert(len(offsets) == len(lengths))
+ for offset, length in zip(offsets, lengths):
+ tag = gr.gr_tag_t()
+ tag.offset = offset/vlen
+ tag.key = pmt.string_to_symbol(tagname)
+ tag.value = pmt.from_long(length/vlen)
+ tags.append(tag)
+ return tags
+
+def string_to_vector(string):
+ v = []
+ for s in string:
+ v.append(ord(s))
+ return v
+
+def strings_to_vectors(strings, lengthtagname):
+ vs = [string_to_vector(string) for string in strings]
+ return packets_to_vectors(vs, lengthtagname)
+
+def vector_to_string(v):
+ s = []
+ for d in v:
+ s.append(chr(d))
+ return ''.join(s)
+
+def vectors_to_strings(data, tags, lengthtagname):
+ packets = vectors_to_packets(data, tags, lengthtagname)
+ return [vector_to_string(packet) for packet in packets]
+
+def count_bursts(data, tags, lengthtagname, vlen=1):
+ lengthtags = [t for t in tags
+ if pmt.symbol_to_string(t.key) == lengthtagname]
+ lengths = {}
+ for tag in lengthtags:
+ if tag.offset in lengths:
+ raise ValueError(
+ "More than one tags with key {0} with the same offset={1}."
+ .format(lengthtagname, tag.offset))
+ lengths[tag.offset] = pmt.to_long(tag.value)*vlen
+ in_burst = False
+ in_packet = False
+ packet_length = None
+ packet_pos = None
+ burst_count = 0
+ for pos in range(len(data)):
+ if pos in lengths:
+ if in_packet:
+ print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos))
+ raise StandardError("Received packet tag while in packet.")
+ packet_pos = -1
+ packet_length = lengths[pos]
+ in_packet = True
+ if not in_burst:
+ burst_count += 1
+ in_burst = True
+ elif not in_packet:
+ in_burst = False
+ if in_packet:
+ packet_pos += 1
+ if packet_pos == packet_length-1:
+ in_packet = False
+ packet_pos = None
+ return burst_count
+
+def vectors_to_packets(data, tags, lengthtagname, vlen=1):
+ lengthtags = [t for t in tags
+ if pmt.symbol_to_string(t.key) == lengthtagname]
+ lengths = {}
+ for tag in lengthtags:
+ if tag.offset in lengths:
+ raise ValueError(
+ "More than one tags with key {0} with the same offset={1}."
+ .format(lengthtagname, tag.offset))
+ lengths[tag.offset] = pmt.to_long(tag.value)*vlen
+ if 0 not in lengths:
+ raise ValueError("There is no tag with key {0} and an offset of 0"
+ .format(lengthtagname))
+ pos = 0
+ packets = []
+ while pos < len(data):
+ if pos not in lengths:
+ raise ValueError("There is no tag with key {0} and an offset of {1}."
+ "We were expecting one."
+ .format(lengthtagname, pos))
+ length = lengths[pos]
+ if length == 0:
+ raise ValueError("Packets cannot have zero length.")
+ if pos+length > len(data):
+ raise ValueError("The final packet is incomplete.")
+ packets.append(data[pos: pos+length])
+ pos += length
+ return packets
+
+def packets_to_vectors(packets, lengthtagname, vlen=1):
+ tags = []
+ data = []
+ offset = 0
+ for packet in packets:
+ data.extend(packet)
+ tag = gr.gr_tag_t()
+ tag.offset = offset/vlen
+ tag.key = pmt.string_to_symbol(lengthtagname)
+ tag.value = pmt.from_long(len(packet)/vlen)
+ tags.append(tag)
+ offset = offset + len(packet)
+ return data, tags
diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt
index 4142657d58..0db5140429 100644
--- a/gr-digital/swig/CMakeLists.txt
+++ b/gr-digital/swig/CMakeLists.txt
@@ -58,6 +58,15 @@ GR_SWIG_INSTALL(
install(
FILES
digital_swig.i
+ constellation.i
+ digital_crc32_bb.i
+ digital_ofdm_carrier_allocator_cvc.i
+ digital_ofdm_chanest_vcvc.i
+ digital_ofdm_equalizer_base.i
+ digital_ofdm_equalizer_simpledfe.i
+ digital_ofdm_equalizer_static.i
+ digital_ofdm_sync_sc_cfb.i
+ packet_header.i
${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig
COMPONENT "digital_swig"
diff --git a/gr-digital/swig/digital_crc32_bb.i b/gr-digital/swig/digital_crc32_bb.i
new file mode 100644
index 0000000000..45b240793d
--- /dev/null
+++ b/gr-digital/swig/digital_crc32_bb.i
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, crc32_bb)
+
+digital_crc32_bb_sptr
+digital_make_crc32_bb (bool check=false, const std::string& lengthtagname="packet_len");
+
+class digital_crc32_bb : public gr_block
+{
+ private:
+ digital_crc32_bb(bool check, const std::string& lengthtagname);
+};
+
diff --git a/gr-digital/swig/digital_ofdm_carrier_allocator_cvc.i b/gr-digital/swig/digital_ofdm_carrier_allocator_cvc.i
new file mode 100644
index 0000000000..1663a4de3d
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_carrier_allocator_cvc.i
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, ofdm_carrier_allocator_cvc);
+
+digital_ofdm_carrier_allocator_cvc_sptr
+digital_make_ofdm_carrier_allocator_cvc (
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ const std::string &len_tag_key = "packet_len");
+
+class digital_ofdm_carrier_allocator_cvc : public gr_tagged_stream_block
+{
+ private:
+ digital_ofdm_carrier_allocator_cvc(int fft_len, const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, const std::string &len_tag_key);
+};
+
diff --git a/gr-digital/swig/digital_ofdm_chanest_vcvc.i b/gr-digital/swig/digital_ofdm_chanest_vcvc.i
new file mode 100644
index 0000000000..aa6e79b5c2
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_chanest_vcvc.i
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, ofdm_chanest_vcvc);
+
+digital_ofdm_chanest_vcvc_sptr
+digital_make_ofdm_chanest_vcvc (
+ const std::vector<gr_complex> &sync_symbol1,
+ const std::vector<gr_complex> &sync_symbol2,
+ int n_data_symbols,
+ int eq_noise_red_len=0,
+ int max_carr_offset=-1,
+ bool force_one_sync_symbol=false);
+
+class digital_ofdm_chanest_vcvc : public gr_block
+{
+ private:
+ digital_ofdm_chanest_vcvc(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
+
+ public:
+};
+
diff --git a/gr-digital/swig/digital_ofdm_cyclic_prefixer.i b/gr-digital/swig/digital_ofdm_cyclic_prefixer.i
new file mode 100644
index 0000000000..19ffd6a12b
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_cyclic_prefixer.i
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004-2006,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital,ofdm_cyclic_prefixer);
+
+digital_ofdm_cyclic_prefixer_sptr
+digital_make_ofdm_cyclic_prefixer (size_t input_size,
+ size_t output_size,
+ int rolloff_len=0,
+ const std::string &len_tag_key="");
+
+
+class digital_ofdm_cyclic_prefixer : public gr_tagged_stream_block
+{
+};
+
diff --git a/gr-digital/swig/digital_ofdm_equalizer_base.i b/gr-digital/swig/digital_ofdm_equalizer_base.i
new file mode 100644
index 0000000000..c862fed09d
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_equalizer_base.i
@@ -0,0 +1,64 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+
+class digital_ofdm_equalizer_base;
+typedef boost::shared_ptr<digital_ofdm_equalizer_base> digital_ofdm_equalizer_base_sptr;
+%template(digital_ofdm_equalizer_base_sptr) boost::shared_ptr<digital_ofdm_equalizer_base>;
+%ignore digital_ofdm_equalizer_base;
+
+class digital_ofdm_equalizer_1d_pilots;
+typedef boost::shared_ptr<digital_ofdm_equalizer_1d_pilots> digital_ofdm_equalizer_1d_pilots_sptr;
+%template(digital_ofdm_equalizer_1d_pilots_sptr) boost::shared_ptr<digital_ofdm_equalizer_1d_pilots>;
+%ignore digital_ofdm_equalizer_1d_pilots;
+
+class digital_ofdm_equalizer_base
+{
+ public:
+ digital_ofdm_equalizer_base(int fft_len);
+
+ virtual void reset() = 0;
+ void set_carrier_offset(int offset) { d_carr_offset = offset; };
+ virtual void equalize(
+ gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>()) = 0;
+ virtual void get_channel_state(std::vector<gr_complex> &taps) = 0;
+ digital_ofdm_equalizer_base_sptr base();
+};
+
+
+class digital_ofdm_equalizer_1d_pilots : public digital_ofdm_equalizer_base
+{
+ public:
+ digital_ofdm_equalizer_1d_pilots(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers,
+ const std::vector<std::vector<int> > &pilot_carriers,
+ const std::vector<std::vector<gr_complex> > &pilot_symbols,
+ int symbols_skipped,
+ bool input_is_shifted);
+
+ void reset();
+};
+
diff --git a/gr-digital/swig/digital_ofdm_equalizer_simpledfe.i b/gr-digital/swig/digital_ofdm_equalizer_simpledfe.i
new file mode 100644
index 0000000000..1ca31c1edd
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_equalizer_simpledfe.i
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+class digital_ofdm_equalizer_simpledfe;
+typedef boost::shared_ptr<digital_ofdm_equalizer_simpledfe> digital_ofdm_equalizer_simpledfe_sptr;
+%template(digital_ofdm_equalizer_simpledfe_sptr) boost::shared_ptr<digital_ofdm_equalizer_simpledfe>;
+%rename(ofdm_equalizer_simpledfe) digital_make_ofdm_equalizer_simpledfe;
+digital_ofdm_equalizer_simpledfe_sptr
+digital_make_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const gr::digital::constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ float alpha = 0.1,
+ bool input_is_shifted = true);
+%ignore digital_ofdm_equalizer_simpledfe;
+
+class digital_ofdm_equalizer_simpledfe : public digital_ofdm_equalizer_1d_pilots
+{
+ public:
+ digital_ofdm_equalizer_simpledfe(
+ int fft_len,
+ const digital_constellation_sptr &constellation,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ float alpha = 0.1,
+ bool input_is_shifted = true);
+
+ void equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>());
+ void get_channel_state(std::vector<gr_complex> &taps);
+};
+
diff --git a/gr-digital/swig/digital_ofdm_equalizer_static.i b/gr-digital/swig/digital_ofdm_equalizer_static.i
new file mode 100644
index 0000000000..3e99403ff7
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_equalizer_static.i
@@ -0,0 +1,55 @@
+/* -*- c++ -*- */
+/* Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+class digital_ofdm_equalizer_static;
+typedef boost::shared_ptr<digital_ofdm_equalizer_static> digital_ofdm_equalizer_static_sptr;
+%template(digital_ofdm_equalizer_static_sptr) boost::shared_ptr<digital_ofdm_equalizer_static>;
+%rename(ofdm_equalizer_static) digital_make_ofdm_equalizer_static;
+digital_ofdm_equalizer_static_sptr
+digital_make_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ bool input_is_shifted = true);
+%ignore digital_ofdm_equalizer_static;
+
+class digital_ofdm_equalizer_static : public digital_ofdm_equalizer_1d_pilots
+{
+ public:
+ digital_ofdm_equalizer_static(
+ int fft_len,
+ const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(),
+ const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(),
+ int symbols_skipped = 0,
+ bool input_is_shifted = true);
+ ~digital_ofdm_equalizer_static();
+
+ void equalize(gr_complex *frame,
+ int n_sym,
+ const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(),
+ const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>());
+ void get_channel_state(std::vector<gr_complex> &taps);
+};
+
diff --git a/gr-digital/swig/digital_ofdm_sync_sc_cfb.i b/gr-digital/swig/digital_ofdm_sync_sc_cfb.i
new file mode 100644
index 0000000000..6a863ca3f9
--- /dev/null
+++ b/gr-digital/swig/digital_ofdm_sync_sc_cfb.i
@@ -0,0 +1,33 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(digital, ofdm_sync_sc_cfb)
+
+digital_ofdm_sync_sc_cfb_sptr
+digital_make_ofdm_sync_sc_cfb (int fft_len, int cp_len);
+
+class digital_ofdm_sync_sc_cfb : public gr_hier_block2
+{
+ private:
+ digital_ofdm_sync_sc_cfb(int fft_len, int cp_len);
+};
+
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 8462048659..94e186d7bf 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -38,23 +38,20 @@
%template(unsigned_int_vector) std::vector<unsigned int>;
%{
-#include "digital/metric_type.h"
-#include "digital/mpsk_snr_est.h"
-#include "digital/lfsr.h"
#include "digital/additive_scrambler_bb.h"
#include "digital/binary_slicer_fb.h"
-#include "digital/chunks_to_symbols_bf.h"
#include "digital/chunks_to_symbols_bc.h"
-#include "digital/chunks_to_symbols_sf.h"
-#include "digital/chunks_to_symbols_sc.h"
-#include "digital/chunks_to_symbols_if.h"
+#include "digital/chunks_to_symbols_bf.h"
#include "digital/chunks_to_symbols_ic.h"
+#include "digital/chunks_to_symbols_if.h"
+#include "digital/chunks_to_symbols_sc.h"
+#include "digital/chunks_to_symbols_sf.h"
#include "digital/clock_recovery_mm_cc.h"
#include "digital/clock_recovery_mm_ff.h"
#include "digital/cma_equalizer_cc.h"
#include "digital/constellation.h"
-#include "digital/constellation_receiver_cb.h"
#include "digital/constellation_decoder_cb.h"
+#include "digital/constellation_receiver_cb.h"
#include "digital/correlate_access_code_bb.h"
#include "digital/correlate_access_code_tag_bb.h"
#include "digital/costas_loop_cc.h"
@@ -68,45 +65,54 @@
#include "digital/framer_sink_1.h"
#include "digital/glfsr_source_b.h"
#include "digital/glfsr_source_f.h"
+#include "digital/header_payload_demux.h"
#include "digital/kurtotic_equalizer_cc.h"
+#include "digital/lfsr.h"
#include "digital/lms_dd_equalizer_cc.h"
#include "digital/map_bb.h"
+#include "digital/metric_type.h"
#include "digital/mpsk_receiver_cc.h"
+#include "digital/mpsk_snr_est.h"
#include "digital/mpsk_snr_est_cc.h"
-#include "digital/ofdm_cyclic_prefixer.h"
#include "digital/ofdm_frame_acquisition.h"
+#include "digital/ofdm_frame_equalizer_vcvc.h"
#include "digital/ofdm_frame_sink.h"
#include "digital/ofdm_insert_preamble.h"
#include "digital/ofdm_mapper_bcv.h"
#include "digital/ofdm_sampler.h"
+#include "digital/ofdm_serializer_vcc.h"
+#include "digital/packet_header_default.h"
+#include "digital/packet_header_ofdm.h"
+#include "digital/packet_headergenerator_bb.h"
+#include "digital/packet_headerparser_b.h"
#include "digital/packet_sink.h"
#include "digital/pfb_clock_sync_ccf.h"
#include "digital/pfb_clock_sync_fff.h"
#include "digital/pn_correlator_cc.h"
#include "digital/probe_density_b.h"
#include "digital/probe_mpsk_snr_est_c.h"
+#include "digital/scale_tags.h"
#include "digital/scrambler_bb.h"
-#include "digital/simple_framer.h"
#include "digital/simple_correlator.h"
+#include "digital/simple_framer.h"
+#include "digital/tagged_stream_check.h"
+#include "digital/ts_insert_zeros_cc.h"
%}
-%include "digital/metric_type.h"
-%include "digital/mpsk_snr_est.h"
-%include "digital/lfsr.h"
%include "digital/additive_scrambler_bb.h"
%include "digital/binary_slicer_fb.h"
-%include "digital/chunks_to_symbols_bf.h"
%include "digital/chunks_to_symbols_bc.h"
-%include "digital/chunks_to_symbols_sf.h"
-%include "digital/chunks_to_symbols_sc.h"
-%include "digital/chunks_to_symbols_if.h"
+%include "digital/chunks_to_symbols_bf.h"
%include "digital/chunks_to_symbols_ic.h"
+%include "digital/chunks_to_symbols_if.h"
+%include "digital/chunks_to_symbols_sc.h"
+%include "digital/chunks_to_symbols_sf.h"
%include "digital/clock_recovery_mm_cc.h"
%include "digital/clock_recovery_mm_ff.h"
%include "digital/cma_equalizer_cc.h"
%include "digital/constellation.h"
-%include "digital/constellation_receiver_cb.h"
%include "digital/constellation_decoder_cb.h"
+%include "digital/constellation_receiver_cb.h"
%include "digital/correlate_access_code_bb.h"
%include "digital/correlate_access_code_tag_bb.h"
%include "digital/costas_loop_cc.h"
@@ -120,43 +126,57 @@
%include "digital/framer_sink_1.h"
%include "digital/glfsr_source_b.h"
%include "digital/glfsr_source_f.h"
+%include "digital/header_payload_demux.h"
%include "digital/kurtotic_equalizer_cc.h"
+%include "digital/lfsr.h"
%include "digital/lms_dd_equalizer_cc.h"
%include "digital/map_bb.h"
+%include "digital/metric_type.h"
%include "digital/mpsk_receiver_cc.h"
+%include "digital/mpsk_snr_est.h"
%include "digital/mpsk_snr_est_cc.h"
-%include "digital/ofdm_cyclic_prefixer.h"
+//%include "digital/ofdm_cyclic_prefixer.h"
%include "digital/ofdm_frame_acquisition.h"
+%include "digital/ofdm_frame_equalizer_vcvc.h"
%include "digital/ofdm_frame_sink.h"
%include "digital/ofdm_insert_preamble.h"
%include "digital/ofdm_mapper_bcv.h"
%include "digital/ofdm_sampler.h"
+%include "digital/ofdm_serializer_vcc.h"
+%include "digital/packet_header_default.h"
+%include "digital/packet_header_ofdm.h"
+%include "digital/packet_headergenerator_bb.h"
+%include "digital/packet_headerparser_b.h"
%include "digital/packet_sink.h"
%include "digital/pfb_clock_sync_ccf.h"
%include "digital/pfb_clock_sync_fff.h"
%include "digital/pn_correlator_cc.h"
%include "digital/probe_density_b.h"
%include "digital/probe_mpsk_snr_est_c.h"
+%include "digital/scale_tags.h"
%include "digital/scrambler_bb.h"
-%include "digital/simple_framer.h"
%include "digital/simple_correlator.h"
+%include "digital/simple_framer.h"
+%include "digital/tagged_stream_check.h"
+%include "digital/ts_insert_zeros_cc.h"
GR_SWIG_BLOCK_MAGIC2(digital, additive_scrambler_bb);
GR_SWIG_BLOCK_MAGIC2(digital, binary_slicer_fb);
-GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bf);
GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bc);
-GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sf);
-GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sc);
-GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_if);
+GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bf);
GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_ic);
+GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_if);
+GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sc);
+GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sf);
GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_cc);
GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_ff);
GR_SWIG_BLOCK_MAGIC2(digital, cma_equalizer_cc);
-GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb);
GR_SWIG_BLOCK_MAGIC2(digital, constellation_decoder_cb);
+GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb);
GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_bb);
GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_tag_bb);
GR_SWIG_BLOCK_MAGIC2(digital, costas_loop_cc);
+//GR_SWIG_BLOCK_MAGIC2(digital, ofdm_cyclic_prefixer);
GR_SWIG_BLOCK_MAGIC2(digital, cpmmod_bc);
GR_SWIG_BLOCK_MAGIC2(digital, descrambler_bb);
GR_SWIG_BLOCK_MAGIC2(digital, diff_decoder_bb);
@@ -166,28 +186,59 @@ GR_SWIG_BLOCK_MAGIC2(digital, fll_band_edge_cc);
GR_SWIG_BLOCK_MAGIC2(digital, framer_sink_1);
GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_b);
GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_f);
+GR_SWIG_BLOCK_MAGIC2(digital, header_payload_demux);
GR_SWIG_BLOCK_MAGIC2(digital, kurtotic_equalizer_cc);
GR_SWIG_BLOCK_MAGIC2(digital, lms_dd_equalizer_cc);
GR_SWIG_BLOCK_MAGIC2(digital, map_bb);
GR_SWIG_BLOCK_MAGIC2(digital, mpsk_receiver_cc);
GR_SWIG_BLOCK_MAGIC2(digital, mpsk_snr_est_cc);
-GR_SWIG_BLOCK_MAGIC2(digital, ofdm_cyclic_prefixer);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_acquisition);
+GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_equalizer_vcvc);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_sink);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_insert_preamble);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_mapper_bcv);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sampler);
+GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b);
GR_SWIG_BLOCK_MAGIC2(digital, packet_sink);
GR_SWIG_BLOCK_MAGIC2(digital, pfb_clock_sync_ccf);
GR_SWIG_BLOCK_MAGIC2(digital, pfb_clock_sync_fff);
GR_SWIG_BLOCK_MAGIC2(digital, pn_correlator_cc);
GR_SWIG_BLOCK_MAGIC2(digital, probe_density_b);
GR_SWIG_BLOCK_MAGIC2(digital, probe_mpsk_snr_est_c);
+GR_SWIG_BLOCK_MAGIC2(digital, scale_tags);
GR_SWIG_BLOCK_MAGIC2(digital, scrambler_bb);
-GR_SWIG_BLOCK_MAGIC2(digital, simple_framer);
GR_SWIG_BLOCK_MAGIC2(digital, simple_correlator);
+GR_SWIG_BLOCK_MAGIC2(digital, simple_framer);
+GR_SWIG_BLOCK_MAGIC2(digital, tagged_stream_check);
+GR_SWIG_BLOCK_MAGIC2(digital, ts_insert_zeros_cc);
GR_SWIG_BLOCK_MAGIC_FACTORY(digital, cpmmod_bc, gmskmod_bc);
// Properly package up constellation objects
%include "constellation.i"
+
+%include "packet_header.i"
+
+// Old-style blocks to be converted to 3.7
+%{
+#include <digital_crc32_bb.h>
+#include <digital_ofdm_carrier_allocator_cvc.h>
+#include <digital_ofdm_cyclic_prefixer.h>
+#include <digital_ofdm_chanest_vcvc.h>
+#include <digital_ofdm_cyclic_prefixer.h>
+#include <digital_ofdm_equalizer_base.h>
+#include <digital_ofdm_equalizer_simpledfe.h>
+#include <digital_ofdm_equalizer_static.h>
+#include <digital_ofdm_sync_sc_cfb.h>
+%}
+
+%include "digital_crc32_bb.i"
+%include "digital_ofdm_carrier_allocator_cvc.i"
+%include "digital_ofdm_chanest_vcvc.i"
+%include "digital_ofdm_cyclic_prefixer.i"
+%include "digital_ofdm_equalizer_base.i"
+%include "digital_ofdm_equalizer_simpledfe.i"
+%include "digital_ofdm_equalizer_static.i"
+%include "digital_ofdm_sync_sc_cfb.i"
diff --git a/gr-digital/swig/packet_header.i b/gr-digital/swig/packet_header.i
new file mode 100644
index 0000000000..7c06d19f71
--- /dev/null
+++ b/gr-digital/swig/packet_header.i
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+%template(packet_header_default_sptr) boost::shared_ptr<gr::digital::packet_header_default>;
+%pythoncode %{
+packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>"
+packet_header_default = packet_header_default .make;
+%}
+
+%template(packet_header_ofdm_sptr) boost::shared_ptr<gr::digital::packet_header_ofdm>;
+%pythoncode %{
+packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>"
+packet_header_ofdm = packet_header_ofdm .make;
+%}
+
diff --git a/grc/blocks/gr_vector_source_x.xml b/grc/blocks/gr_vector_source_x.xml
index 7a6a3aeff8..992a6a787d 100644
--- a/grc/blocks/gr_vector_source_x.xml
+++ b/grc/blocks/gr_vector_source_x.xml
@@ -8,7 +8,8 @@
<name>Vector Source</name>
<key>gr_vector_source_x</key>
<import>from gnuradio import gr</import>
- <make>gr.vector_source_$(type.fcn)($vector, $repeat, $vlen)</make>
+ <make>gr.vector_source_$(type.fcn)($vector, $repeat, $vlen, $tags)
+ </make>
<param>
<name>Output Type</name>
<key>type</key>
@@ -48,7 +49,13 @@
<name>Vector</name>
<key>vector</key>
<value>0, 0, 0</value>
- <type>$type.vec_type</type>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Tags</name>
+ <key>tags</key>
+ <value>[]</value>
+ <type>raw</type>
</param>
<param>
<name>Repeat</name>