summaryrefslogtreecommitdiff
path: root/gr-digital/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gr-digital/lib')
-rw-r--r--gr-digital/lib/CMakeLists.txt54
-rw-r--r--gr-digital/lib/constellation_receiver_cb_impl.cc2
-rw-r--r--gr-digital/lib/constellation_receiver_cb_impl.h6
-rw-r--r--gr-digital/lib/costas_loop_cc_impl.cc2
-rw-r--r--gr-digital/lib/costas_loop_cc_impl.h3
-rw-r--r--gr-digital/lib/crc32_bb_impl.cc105
-rw-r--r--gr-digital/lib/crc32_bb_impl.h51
-rw-r--r--gr-digital/lib/fll_band_edge_cc_impl.cc16
-rw-r--r--gr-digital/lib/fll_band_edge_cc_impl.h2
-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/map_bb_impl.cc4
-rw-r--r--gr-digital/lib/map_bb_impl.h4
-rw-r--r--gr-digital/lib/mpsk_receiver_cc_impl.cc2
-rw-r--r--gr-digital/lib/mpsk_receiver_cc_impl.h6
-rw-r--r--gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc193
-rw-r--r--gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h77
-rw-r--r--gr-digital/lib/ofdm_chanest_vcvc_impl.cc273
-rw-r--r--gr-digital/lib/ofdm_chanest_vcvc_impl.h78
-rw-r--r--gr-digital/lib/ofdm_cyclic_prefixer_impl.cc146
-rw-r--r--gr-digital/lib/ofdm_cyclic_prefixer_impl.h37
-rw-r--r--gr-digital/lib/ofdm_equalizer_base.cc121
-rw-r--r--gr-digital/lib/ofdm_equalizer_simpledfe.cc110
-rw-r--r--gr-digital/lib/ofdm_equalizer_static.cc97
-rw-r--r--gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc93
-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.h70
-rw-r--r--gr-digital/lib/ofdm_sync_sc_cfb_impl.cc111
-rw-r--r--gr-digital/lib/ofdm_sync_sc_cfb_impl.h42
-rw-r--r--gr-digital/lib/packet_header_default.cc129
-rw-r--r--gr-digital/lib/packet_header_ofdm.cc115
-rw-r--r--gr-digital/lib/packet_headergenerator_bb_impl.cc93
-rw-r--r--gr-digital/lib/packet_headergenerator_bb_impl.h55
-rw-r--r--gr-digital/lib/packet_headerparser_b_impl.cc92
-rw-r--r--gr-digital/lib/packet_headerparser_b_impl.h48
36 files changed, 2795 insertions, 81 deletions
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index d47e7fb1f3..a17c91a85a 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -26,15 +26,15 @@ include_directories(
${GR_ANALOG_INCLUDE_DIRS}
${GR_FFT_INCLUDE_DIRS}
${GR_FILTER_INCLUDE_DIRS}
- ${GNURADIO_CORE_INCLUDE_DIRS}
+ ${GR_BLOCKS_INCLUDE_DIRS}
+ ${GNURADIO_RUNTIME_INCLUDE_DIRS}
${VOLK_INCLUDE_DIRS}
- ${GRUEL_INCLUDE_DIRS}
- ${LOG4CXX_INCLUDE_DIRS}
+ ${LOG4CPP_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
link_directories(${Boost_LIBRARY_DIRS})
-link_directories(${LOG4CXX_LIBRARY_DIRS})
+link_directories(${LOG4CPP_LIBRARY_DIRS})
if(ENABLE_GR_CTRLPORT)
ADD_DEFINITIONS(-DGR_CTRLPORT)
@@ -50,7 +50,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py "
#!${PYTHON_EXECUTABLE}
import sys, os, re
-sys.path.append('${GR_CORE_PYTHONPATH}')
+sys.path.append('${GR_RUNTIME_PYTHONPATH}')
os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}'
os.chdir('${CMAKE_CURRENT_BINARY_DIR}')
@@ -112,40 +112,54 @@ 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
+ crc32_bb_impl.cc
descrambler_bb_impl.cc
diff_decoder_bb_impl.cc
diff_encoder_bb_impl.cc
diff_phasor_cc_impl.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_carrier_allocator_cvc_impl.cc
+ ofdm_chanest_vcvc_impl.cc
ofdm_cyclic_prefixer_impl.cc
+ ofdm_equalizer_base.cc
+ ofdm_equalizer_simpledfe.cc
+ ofdm_equalizer_static.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
+ ofdm_sync_sc_cfb_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
@@ -153,8 +167,9 @@ list(APPEND digital_sources
probe_density_b_impl.cc
probe_mpsk_snr_est_c_impl.cc
scrambler_bb_impl.cc
- simple_framer_impl.cc
simple_correlator_impl.cc
+ simple_framer_impl.cc
+ header_payload_demux_impl.cc
)
#Add Windows DLL resource file if using MSVC
@@ -173,18 +188,25 @@ ENDIF(MSVC)
list(APPEND digital_libs
volk
- gnuradio-core
+ gnuradio-runtime
gnuradio-filter
gnuradio-blocks
gnuradio-analog
${Boost_LIBRARIES}
- ${LOG4CXX_LIBRARIES}
+ ${LOG4CPP_LIBRARIES}
)
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-runtime
+ gnuradio-filter
+ gnuradio-analog
+ gnuradio-blocks
+)
diff --git a/gr-digital/lib/constellation_receiver_cb_impl.cc b/gr-digital/lib/constellation_receiver_cb_impl.cc
index c3203e9079..30be24aab9 100644
--- a/gr-digital/lib/constellation_receiver_cb_impl.cc
+++ b/gr-digital/lib/constellation_receiver_cb_impl.cc
@@ -54,7 +54,7 @@ namespace gr {
: gr_block("constellation_receiver_cb",
gr_make_io_signature(1, 1, sizeof(gr_complex)),
gr_make_io_signaturev(1, 5, iosig)),
- gri_control_loop(loop_bw, fmax, fmin),
+ blocks::control_loop(loop_bw, fmax, fmin),
d_constellation(constellation),
d_current_const_point(0)
{
diff --git a/gr-digital/lib/constellation_receiver_cb_impl.h b/gr-digital/lib/constellation_receiver_cb_impl.h
index 50946840ae..7c34518340 100644
--- a/gr-digital/lib/constellation_receiver_cb_impl.h
+++ b/gr-digital/lib/constellation_receiver_cb_impl.h
@@ -24,15 +24,15 @@
#define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_IMPL_H
#include <digital/constellation_receiver_cb.h>
-#include <gruel/attributes.h>
+#include <attributes.h>
#include <gr_complex.h>
-#include <gri_control_loop.h>
+#include <blocks/control_loop.h>
namespace gr {
namespace digital {
class constellation_receiver_cb_impl
- : public constellation_receiver_cb, gri_control_loop
+ : public constellation_receiver_cb, blocks::control_loop
{
public:
constellation_receiver_cb_impl(constellation_sptr constell,
diff --git a/gr-digital/lib/costas_loop_cc_impl.cc b/gr-digital/lib/costas_loop_cc_impl.cc
index 5afabf4294..fcdd45045b 100644
--- a/gr-digital/lib/costas_loop_cc_impl.cc
+++ b/gr-digital/lib/costas_loop_cc_impl.cc
@@ -44,7 +44,7 @@ namespace gr {
: gr_sync_block("costas_loop_cc",
gr_make_io_signature(1, 1, sizeof(gr_complex)),
gr_make_io_signature2(1, 2, sizeof(gr_complex), sizeof(float))),
- gri_control_loop(loop_bw, 1.0, -1.0),
+ blocks::control_loop(loop_bw, 1.0, -1.0),
d_order(order), d_phase_detector(NULL)
{
// Set up the phase detector to use based on the constellation order
diff --git a/gr-digital/lib/costas_loop_cc_impl.h b/gr-digital/lib/costas_loop_cc_impl.h
index 9310368b4d..ecba2cdd4f 100644
--- a/gr-digital/lib/costas_loop_cc_impl.h
+++ b/gr-digital/lib/costas_loop_cc_impl.h
@@ -25,12 +25,11 @@
#define INCLUDED_DIGITAL_COSTAS_LOOP_CC_IMPL_H
#include <digital/costas_loop_cc.h>
-#include <gri_control_loop.h>
namespace gr {
namespace digital {
- class costas_loop_cc_impl : public costas_loop_cc, gri_control_loop
+ class costas_loop_cc_impl : public costas_loop_cc
{
private:
int d_order;
diff --git a/gr-digital/lib/crc32_bb_impl.cc b/gr-digital/lib/crc32_bb_impl.cc
new file mode 100644
index 0000000000..608c5758ac
--- /dev/null
+++ b/gr-digital/lib/crc32_bb_impl.cc
@@ -0,0 +1,105 @@
+/* -*- 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_io_signature.h>
+#include "crc32_bb_impl.h"
+#include <digital/crc32.h>
+
+namespace gr {
+ namespace digital {
+
+ crc32_bb::sptr
+ crc32_bb::make(bool check, const std::string& lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new crc32_bb_impl(check, lengthtagname));
+ }
+
+ crc32_bb_impl::crc32_bb_impl(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);
+ }
+
+ crc32_bb_impl::~crc32_bb_impl()
+ {
+ }
+
+ int
+ crc32_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ if (d_check) {
+ return ninput_items[0] - 4;
+ } else {
+ return ninput_items[0] + 4;
+ }
+ }
+
+ int
+ crc32_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];
+ 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;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/crc32_bb_impl.h b/gr-digital/lib/crc32_bb_impl.h
new file mode 100644
index 0000000000..7b9dbb6351
--- /dev/null
+++ b/gr-digital/lib/crc32_bb_impl.h
@@ -0,0 +1,51 @@
+/* -*- 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_DIGITAL_CRC32_BB_IMPL_H
+#define INCLUDED_DIGITAL_CRC32_BB_IMPL_H
+
+#include <digital/crc32_bb.h>
+
+namespace gr {
+ namespace digital {
+
+ class crc32_bb_impl : public crc32_bb
+ {
+ private:
+ bool d_check;
+
+ public:
+ crc32_bb_impl(bool check, const std::string& lengthtagname);
+ ~crc32_bb_impl();
+
+ int calculate_output_stream_length(const gr_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);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_CRC32_BB_IMPL_H */
+
diff --git a/gr-digital/lib/fll_band_edge_cc_impl.cc b/gr-digital/lib/fll_band_edge_cc_impl.cc
index 980d3ab464..c438b813f4 100644
--- a/gr-digital/lib/fll_band_edge_cc_impl.cc
+++ b/gr-digital/lib/fll_band_edge_cc_impl.cc
@@ -58,25 +58,25 @@ namespace gr {
: gr_sync_block("fll_band_edge_cc",
gr_make_io_signature(1, 1, sizeof(gr_complex)),
gr_make_io_signaturev(1, 4, iosig)),
- gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym),
- -M_TWOPI*(2.0/samps_per_sym)),
+ blocks::control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym),
+ -M_TWOPI*(2.0/samps_per_sym)),
d_updated(false)
{
// Initialize samples per symbol
if(samps_per_sym <= 0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
+ throw std::out_of_range("fll_band_edge_cc: invalid number of sps. Must be > 0.");
}
d_sps = samps_per_sym;
// Initialize rolloff factor
if(rolloff < 0 || rolloff > 1.0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
+ throw std::out_of_range("fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
}
d_rolloff = rolloff;
// Initialize filter length
if(filter_size <= 0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
+ throw std::out_of_range("fll_band_edge_cc: invalid filter size. Must be > 0.");
}
d_filter_size = filter_size;
@@ -97,7 +97,7 @@ namespace gr {
fll_band_edge_cc_impl::set_samples_per_symbol(float sps)
{
if(sps <= 0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0.");
+ throw std::out_of_range("fll_band_edge_cc: invalid number of sps. Must be > 0.");
}
d_sps = sps;
design_filter(d_sps, d_rolloff, d_filter_size);
@@ -107,7 +107,7 @@ namespace gr {
fll_band_edge_cc_impl::set_rolloff(float rolloff)
{
if(rolloff < 0 || rolloff > 1.0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
+ throw std::out_of_range("fll_band_edge_cc: invalid rolloff factor. Must be in [0,1].");
}
d_rolloff = rolloff;
design_filter(d_sps, d_rolloff, d_filter_size);
@@ -117,7 +117,7 @@ namespace gr {
fll_band_edge_cc_impl::set_filter_size(int filter_size)
{
if(filter_size <= 0) {
- throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0.");
+ throw std::out_of_range("fll_band_edge_cc: invalid filter size. Must be > 0.");
}
d_filter_size = filter_size;
design_filter(d_sps, d_rolloff, d_filter_size);
diff --git a/gr-digital/lib/fll_band_edge_cc_impl.h b/gr-digital/lib/fll_band_edge_cc_impl.h
index 55e338b38c..9eb3e6e7ae 100644
--- a/gr-digital/lib/fll_band_edge_cc_impl.h
+++ b/gr-digital/lib/fll_band_edge_cc_impl.h
@@ -24,7 +24,7 @@
#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_IMPL_H
#include <digital/fll_band_edge_cc.h>
-#include <gri_control_loop.h>
+#include <blocks/control_loop.h>
#include <filter/fir_filter.h>
namespace gr {
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..dc8cc7883a
--- /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/map_bb_impl.cc b/gr-digital/lib/map_bb_impl.cc
index 3a06394ec4..4ea91835a9 100644
--- a/gr-digital/lib/map_bb_impl.cc
+++ b/gr-digital/lib/map_bb_impl.cc
@@ -51,7 +51,7 @@ namespace gr {
void
map_bb_impl::set_map(const std::vector<int> &map)
{
- gruel::scoped_lock guard(d_mutex);
+ gr::thread::scoped_lock guard(d_mutex);
for(int i = 0; i < 0x100; i++)
d_map[i] = i;
@@ -75,7 +75,7 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- gruel::scoped_lock guard(d_mutex);
+ gr::thread::scoped_lock guard(d_mutex);
const unsigned char *in = (const unsigned char*)input_items[0];
unsigned char *out = (unsigned char*)output_items[0];
diff --git a/gr-digital/lib/map_bb_impl.h b/gr-digital/lib/map_bb_impl.h
index bce2b9b1b3..59f1e834b7 100644
--- a/gr-digital/lib/map_bb_impl.h
+++ b/gr-digital/lib/map_bb_impl.h
@@ -24,7 +24,7 @@
#define INCLUDED_GR_MAP_BB_IMPL_H
#include <digital/map_bb.h>
-#include <gruel/thread.h>
+#include <thread/thread.h>
namespace gr {
namespace digital {
@@ -33,7 +33,7 @@ namespace gr {
{
private:
unsigned char d_map[0x100];
- gruel::mutex d_mutex;
+ gr::thread::mutex d_mutex;
public:
map_bb_impl(const std::vector<int> &map);
diff --git a/gr-digital/lib/mpsk_receiver_cc_impl.cc b/gr-digital/lib/mpsk_receiver_cc_impl.cc
index 31355c5653..ea11b7cdaa 100644
--- a/gr-digital/lib/mpsk_receiver_cc_impl.cc
+++ b/gr-digital/lib/mpsk_receiver_cc_impl.cc
@@ -63,7 +63,7 @@ namespace gr {
: gr_block("mpsk_receiver_cc",
gr_make_io_signature(1, 1, sizeof(gr_complex)),
gr_make_io_signature(1, 1, sizeof(gr_complex))),
- gri_control_loop(loop_bw, fmax, fmin),
+ blocks::control_loop(loop_bw, fmax, fmin),
d_M(M), d_theta(theta),
d_current_const_point(0),
d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega),
diff --git a/gr-digital/lib/mpsk_receiver_cc_impl.h b/gr-digital/lib/mpsk_receiver_cc_impl.h
index 3db6fa8b62..ed53d0f2e4 100644
--- a/gr-digital/lib/mpsk_receiver_cc_impl.h
+++ b/gr-digital/lib/mpsk_receiver_cc_impl.h
@@ -24,8 +24,8 @@
#define INCLUDED_DIGITAL_MPSK_RECEIVER_CC_IMPL_H
#include <digital/mpsk_receiver_cc.h>
-#include <gruel/attributes.h>
-#include <gri_control_loop.h>
+#include <attributes.h>
+#include <blocks/control_loop.h>
#include <gr_complex.h>
#include <fstream>
#include <filter/mmse_fir_interpolator_cc.h>
@@ -34,7 +34,7 @@ namespace gr {
namespace digital {
class mpsk_receiver_cc_impl
- : public mpsk_receiver_cc, public gri_control_loop
+ : public mpsk_receiver_cc, public blocks::control_loop
{
public:
mpsk_receiver_cc_impl(unsigned int M, float theta,
diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc
new file mode 100644
index 0000000000..afeb10e1d5
--- /dev/null
+++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc
@@ -0,0 +1,193 @@
+/* -*- 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_io_signature.h>
+#include "ofdm_carrier_allocator_cvc_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ ofdm_carrier_allocator_cvc::sptr
+ ofdm_carrier_allocator_cvc::make(
+ 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::vector<std::vector<gr_complex> > &sync_words,
+ const std::string &len_tag_key,
+ const bool output_is_shifted
+ )
+ {
+ return gnuradio::get_initial_sptr(
+ new ofdm_carrier_allocator_cvc_impl(
+ fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ sync_words,
+ len_tag_key,
+ output_is_shifted
+ )
+ );
+ }
+
+ ofdm_carrier_allocator_cvc_impl::ofdm_carrier_allocator_cvc_impl(
+ 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::vector<std::vector<gr_complex> > &sync_words,
+ const std::string &len_tag_key,
+ const bool output_is_shifted
+ ) : 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_sync_words(sync_words),
+ d_symbols_per_set(0),
+ d_output_is_shifted(output_is_shifted)
+ {
+ 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");
+ }
+ if (d_output_is_shifted) {
+ d_occupied_carriers[i][j] = (d_occupied_carriers[i][j] + fft_len/2) % fft_len;
+ }
+ }
+ }
+ 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");
+ }
+ if (d_output_is_shifted) {
+ d_pilot_carriers[i][j] = (d_pilot_carriers[i][j] + fft_len/2) % fft_len;
+ }
+ }
+ }
+ for (unsigned i = 0; i < d_sync_words.size(); i++) {
+ if (d_sync_words[i].size() != (unsigned) d_fft_len) {
+ throw std::invalid_argument("sync words must be fft length");
+ }
+ }
+
+ 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());
+ }
+
+ ofdm_carrier_allocator_cvc_impl::~ofdm_carrier_allocator_cvc_impl()
+ {
+ }
+
+ int
+ ofdm_carrier_allocator_cvc_impl::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 + d_sync_words.size();
+ }
+
+ int
+ ofdm_carrier_allocator_cvc_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];
+ std::vector<gr_tag_t> tags;
+
+ memset((void *) out, 0x00, sizeof(gr_complex) * d_fft_len * noutput_items);
+ // Copy Sync word
+ for (unsigned i = 0; i < d_sync_words.size(); i++) {
+ memcpy((void *) out, (void *) &d_sync_words[i][0], sizeof(gr_complex) * d_fft_len);
+ out += d_fft_len;
+ }
+
+ // Copy data symbols
+ 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;
+ }
+ }
+ // 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 + d_sync_words.size();
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h
new file mode 100644
index 0000000000..6e478b3389
--- /dev/null
+++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h
@@ -0,0 +1,77 @@
+/* -*- 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_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H
+#define INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H
+
+#include <digital/ofdm_carrier_allocator_cvc.h>
+
+namespace gr {
+ namespace digital {
+
+ class ofdm_carrier_allocator_cvc_impl : public ofdm_carrier_allocator_cvc
+ {
+ private:
+ //! 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;
+ //! Synch words
+ const std::vector<std::vector<gr_complex> > d_sync_words;
+ int d_symbols_per_set;
+ const bool d_output_is_shifted;
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ ofdm_carrier_allocator_cvc_impl(
+ 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::vector<std::vector<gr_complex> > &sync_words,
+ const std::string &len_tag_key,
+ const bool output_is_shifted
+ );
+ ~ofdm_carrier_allocator_cvc_impl();
+
+ 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);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_chanest_vcvc_impl.cc b/gr-digital/lib/ofdm_chanest_vcvc_impl.cc
new file mode 100644
index 0000000000..d0d8faba59
--- /dev/null
+++ b/gr-digital/lib/ofdm_chanest_vcvc_impl.cc
@@ -0,0 +1,273 @@
+/* -*- 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_io_signature.h>
+#include "ofdm_chanest_vcvc_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ ofdm_chanest_vcvc::sptr
+ ofdm_chanest_vcvc::make(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 ofdm_chanest_vcvc_impl(
+ sync_symbol1,
+ sync_symbol2,
+ n_data_symbols,
+ eq_noise_red_len,
+ max_carr_offset,
+ force_one_sync_symbol
+ )
+ );
+ }
+
+ ofdm_chanest_vcvc_impl::ofdm_chanest_vcvc_impl(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);
+ }
+
+ ofdm_chanest_vcvc_impl::~ofdm_chanest_vcvc_impl()
+ {
+ }
+
+ void
+ ofdm_chanest_vcvc_impl::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
+ ofdm_chanest_vcvc_impl::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
+ ofdm_chanest_vcvc_impl::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
+ }
+ }
+
+
+ int
+ ofdm_chanest_vcvc_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 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;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_chanest_vcvc_impl.h b/gr-digital/lib/ofdm_chanest_vcvc_impl.h
new file mode 100644
index 0000000000..def8734e64
--- /dev/null
+++ b/gr-digital/lib/ofdm_chanest_vcvc_impl.h
@@ -0,0 +1,78 @@
+/* -*- 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_DIGITAL_OFDM_CHANEST_VCVC_IMPL_H
+#define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_IMPL_H
+
+#include <digital/ofdm_chanest_vcvc.h>
+
+namespace gr {
+ namespace digital {
+
+ class ofdm_chanest_vcvc_impl : public ofdm_chanest_vcvc
+ {
+ private:
+ 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;
+
+ //! 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:
+ ofdm_chanest_vcvc_impl(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);
+ ~ofdm_chanest_vcvc_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_OFDM_CHANEST_VCVC_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc b/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc
index 67cfba615f..d48c5f7e45 100644
--- a/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc
+++ b/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
-/*
- * Copyright 2004,2006,2010-2012 Free Software Foundation, Inc.
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -24,56 +24,142 @@
#include "config.h"
#endif
-#include "ofdm_cyclic_prefixer_impl.h"
#include <gr_io_signature.h>
+#include "ofdm_cyclic_prefixer_impl.h"
namespace gr {
namespace digital {
-
+
ofdm_cyclic_prefixer::sptr
- ofdm_cyclic_prefixer::make(size_t input_size, size_t output_size)
+ ofdm_cyclic_prefixer::make(size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key)
{
- return gnuradio::get_initial_sptr
- (new ofdm_cyclic_prefixer_impl(input_size, output_size));
+ return gnuradio::get_initial_sptr (new ofdm_cyclic_prefixer_impl(input_size, output_size, rolloff_len, len_tag_key));
}
- ofdm_cyclic_prefixer_impl::ofdm_cyclic_prefixer_impl(size_t input_size,
- size_t output_size)
- : gr_sync_interpolator("ofdm_cyclic_prefixer",
- gr_make_io_signature(1, 1, input_size*sizeof(gr_complex)),
- gr_make_io_signature(1, 1, sizeof(gr_complex)),
- output_size),
- d_input_size(input_size),
- d_output_size(output_size)
+
+ ofdm_cyclic_prefixer_impl::ofdm_cyclic_prefixer_impl(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);
+ }
}
ofdm_cyclic_prefixer_impl::~ofdm_cyclic_prefixer_impl()
{
}
+
int
- ofdm_cyclic_prefixer_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
+ ofdm_cyclic_prefixer_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
{
- gr_complex *in = (gr_complex*)input_items[0];
- gr_complex *out = (gr_complex*)output_items[0];
- size_t cp_size = d_output_size - d_input_size;
- unsigned int i=0, j=0;
-
- j = cp_size;
- for(i=0; i < d_input_size; i++,j++) {
- out[j] = in[i];
+ 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
+ ofdm_cyclic_prefixer_impl::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;
}
- j = d_input_size - cp_size;
- for(i=0; i < cp_size; i++, j++) {
- out[i] = in[j];
+ // 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 d_output_size;
+ return noutput_items;
}
} /* namespace digital */
} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_cyclic_prefixer_impl.h b/gr-digital/lib/ofdm_cyclic_prefixer_impl.h
index 20f0489d7c..5a5766f131 100644
--- a/gr-digital/lib/ofdm_cyclic_prefixer_impl.h
+++ b/gr-digital/lib/ofdm_cyclic_prefixer_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
-/*
- * Copyright 2004-2006,2011,2012 Free Software Foundation, Inc.
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,23 +27,38 @@
namespace gr {
namespace digital {
-
+
class ofdm_cyclic_prefixer_impl : public ofdm_cyclic_prefixer
{
- private:
- size_t d_input_size;
+ 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!)
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
- public:
- ofdm_cyclic_prefixer_impl(size_t input_size, size_t output_size);
+ public:
+ ofdm_cyclic_prefixer_impl(size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key);
~ofdm_cyclic_prefixer_impl();
int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
};
- } /* namespace digital */
-} /* namespace gr */
+ } // namespace digital
+} // namespace gr
#endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_equalizer_base.cc b/gr-digital/lib/ofdm_equalizer_base.cc
new file mode 100644
index 0000000000..5209b09c29
--- /dev/null
+++ b/gr-digital/lib/ofdm_equalizer_base.cc
@@ -0,0 +1,121 @@
+/* -*- 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>
+
+namespace gr {
+ namespace digital {
+
+ // *** Base class ****************************************************
+ ofdm_equalizer_base::ofdm_equalizer_base(int fft_len) :
+ d_fft_len(fft_len),
+ d_carr_offset(0)
+ {
+ }
+
+
+ ofdm_equalizer_base::~ofdm_equalizer_base()
+ {
+ }
+
+
+ // *** Sub-Base class for 1D equalizers using pilot tones *************
+ ofdm_equalizer_1d_pilots::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)
+ : 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];
+ }
+ }
+ }
+ }
+
+
+ ofdm_equalizer_1d_pilots::~ofdm_equalizer_1d_pilots()
+ {
+ }
+
+
+ void
+ 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 ofdm_equalizer_1d_pilots::get_channel_state(std::vector<gr_complex> &taps)
+ {
+ taps = d_channel_state;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_equalizer_simpledfe.cc b/gr-digital/lib/ofdm_equalizer_simpledfe.cc
new file mode 100644
index 0000000000..fcb0e18cbf
--- /dev/null
+++ b/gr-digital/lib/ofdm_equalizer_simpledfe.cc
@@ -0,0 +1,110 @@
+/* -*- 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>
+
+namespace gr {
+ namespace digital {
+
+ ofdm_equalizer_simpledfe::sptr
+ ofdm_equalizer_simpledfe::make(
+ 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 ofdm_equalizer_simpledfe::sptr(
+ new ofdm_equalizer_simpledfe(
+ fft_len,
+ constellation,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ symbols_skipped,
+ alpha,
+ input_is_shifted
+ )
+ );
+ }
+
+ ofdm_equalizer_simpledfe::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)
+ : ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted),
+ d_constellation(constellation),
+ d_alpha(alpha)
+ {
+ }
+
+
+ ofdm_equalizer_simpledfe::~ofdm_equalizer_simpledfe()
+ {
+ }
+
+
+ void
+ 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();
+ }
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_equalizer_static.cc b/gr-digital/lib/ofdm_equalizer_static.cc
new file mode 100644
index 0000000000..8601eff430
--- /dev/null
+++ b/gr-digital/lib/ofdm_equalizer_static.cc
@@ -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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <digital/ofdm_equalizer_static.h>
+
+namespace gr {
+ namespace digital {
+
+ ofdm_equalizer_static::sptr
+ ofdm_equalizer_static::make(
+ 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 ofdm_equalizer_static::sptr(
+ new ofdm_equalizer_static(
+ fft_len,
+ occupied_carriers,
+ pilot_carriers,
+ pilot_symbols,
+ symbols_skipped,
+ input_is_shifted
+ )
+ );
+ }
+
+ ofdm_equalizer_static::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)
+ : ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted)
+ {
+ }
+
+
+ ofdm_equalizer_static::~ofdm_equalizer_static()
+ {
+ }
+
+
+ void
+ 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();
+ }
+ }
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
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..594b2df838
--- /dev/null
+++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_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 "ofdm_frame_equalizer_vcvc_impl.h"
+
+namespace gr {
+ namespace digital {
+
+ ofdm_frame_equalizer_vcvc::sptr
+ ofdm_frame_equalizer_vcvc::make(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(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..f86451e839
--- /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;
+ ofdm_equalizer_base::sptr d_eq;
+ bool d_propagate_channel_state;
+ std::vector<gr_complex> d_channel_state;
+
+ protected:
+ // These 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(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..09c0039a1c
--- /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 gr::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..4f750eac71
--- /dev/null
+++ b/gr-digital/lib/ofdm_serializer_vcc_impl.h
@@ -0,0 +1,70 @@
+/* -*- 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/ofdm_sync_sc_cfb_impl.cc b/gr-digital/lib/ofdm_sync_sc_cfb_impl.cc
new file mode 100644
index 0000000000..822b9021e2
--- /dev/null
+++ b/gr-digital/lib/ofdm_sync_sc_cfb_impl.cc
@@ -0,0 +1,111 @@
+/* -*- 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_io_signature.h>
+#include "ofdm_sync_sc_cfb_impl.h"
+
+#include <blocks/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>
+
+namespace gr {
+ namespace digital {
+
+ ofdm_sync_sc_cfb::sptr
+ ofdm_sync_sc_cfb::make(int fft_len, int cp_len)
+ {
+ return gnuradio::get_initial_sptr (new ofdm_sync_sc_cfb_impl(fft_len, cp_len));
+ }
+
+ ofdm_sync_sc_cfb_impl::ofdm_sync_sc_cfb_impl(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::blocks::plateau_detector_fb::sptr plateau_detector(gr::blocks::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
+ }
+
+ ofdm_sync_sc_cfb_impl::~ofdm_sync_sc_cfb_impl()
+ {
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/ofdm_sync_sc_cfb_impl.h b/gr-digital/lib/ofdm_sync_sc_cfb_impl.h
new file mode 100644
index 0000000000..207ea41ae1
--- /dev/null
+++ b/gr-digital/lib/ofdm_sync_sc_cfb_impl.h
@@ -0,0 +1,42 @@
+/* -*- 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_DIGITAL_OFDM_SYNC_SC_CFB_IMPL_H
+#define INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_IMPL_H
+
+#include <digital/ofdm_sync_sc_cfb.h>
+
+namespace gr {
+ namespace digital {
+
+ class ofdm_sync_sc_cfb_impl : public ofdm_sync_sc_cfb
+ {
+ public:
+ ofdm_sync_sc_cfb_impl(int fft_len, int cp_len);
+ ~ofdm_sync_sc_cfb_impl();
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_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..ef5e44ac8d
--- /dev/null
+++ b/gr-digital/lib/packet_header_default.cc
@@ -0,0 +1,129 @@
+/* -*- 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 <string.h>
+#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..3232858148
--- /dev/null
+++ b/gr-digital/lib/packet_headergenerator_bb_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 <boost/format.hpp>
+#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,
+ const std::string &len_tag_key
+ )
+ {
+ return gnuradio::get_initial_sptr (new packet_headergenerator_bb_impl(header_formatter, len_tag_key));
+ }
+
+
+ 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, len_tag_key));
+ }
+
+
+ packet_headergenerator_bb_impl::packet_headergenerator_bb_impl(
+ const gr::digital::packet_header_default::sptr &header_formatter,
+ const std::string &len_tag_key
+ )
+ : gr_tagged_stream_block("packet_headergenerator_bb_impl",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ len_tag_key),
+ d_formatter(header_formatter)
+ {
+ set_output_multiple(d_formatter->header_len());
+ // This is the worst case rate, because we don't know the true value, of course
+ set_relative_rate(d_formatter->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)) {
+ GR_LOG_FATAL(d_logger, boost::format("header_formatter() returned false (this shouldn't happen). Offending header started at %1%") % nitems_read(0));
+ throw std::runtime_error("header formatter returned false.");
+ }
+
+ return d_formatter->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..ce60fdf76c
--- /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;
+
+ public:
+ packet_headergenerator_bb_impl(
+ const packet_header_default::sptr &header_formatter,
+ const std::string &len_tag_key
+ );
+ ~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_formatter->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..60e1fdef0b
--- /dev/null
+++ b/gr-digital/lib/packet_headerparser_b_impl.cc
@@ -0,0 +1,92 @@
+/* -*- 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 <boost/format.hpp>
+#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)) {
+ GR_LOG_INFO(d_logger, boost::format("Detected an invalid packet at item %1%") % nitems_read(0));
+ 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 */
+