summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@kit.edu>2013-05-25 09:38:49 +0200
committerMartin Braun <martin.braun@kit.edu>2013-05-30 08:46:33 -0400
commit495a44dabf6c6a6a184eda526711c06f68cccd9d (patch)
tree68746dd1ed1333d99bb89412eda1571821fce321
parenta7b3a9339106aaba72195b693dfeaa98f194e0d5 (diff)
digital: bugfixes to ofdm_chanest, HPD and frame EQ
-rw-r--r--gr-digital/examples/ofdm/ofdm_loopback.grc558
-rw-r--r--gr-digital/grc/digital_ofdm_chanest_vcvc.xml7
-rw-r--r--gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml9
-rw-r--r--gr-digital/include/CMakeLists.txt1
-rw-r--r--gr-digital/include/digital/CMakeLists.txt4
-rw-r--r--gr-digital/include/digital/ofdm_chanest_vcvc.h97
-rw-r--r--gr-digital/include/digital_ofdm_chanest_vcvc.h135
-rw-r--r--gr-digital/lib/CMakeLists.txt2
-rw-r--r--gr-digital/lib/digital_ofdm_chanest_vcvc.cc296
-rw-r--r--gr-digital/lib/header_payload_demux_impl.cc115
-rw-r--r--gr-digital/lib/ofdm_chanest_vcvc_impl.cc282
-rw-r--r--gr-digital/lib/ofdm_chanest_vcvc_impl.h78
-rw-r--r--gr-digital/python/ofdm_txrx.py26
-rwxr-xr-xgr-digital/python/qa_ofdm_chanest_vcvc.py27
-rw-r--r--gr-digital/swig/digital_ofdm_chanest_vcvc.i40
-rw-r--r--gr-digital/swig/digital_swig.i27
16 files changed, 869 insertions, 835 deletions
diff --git a/gr-digital/examples/ofdm/ofdm_loopback.grc b/gr-digital/examples/ofdm/ofdm_loopback.grc
index 45a6ca0869..0207f68fc3 100644
--- a/gr-digital/examples/ofdm/ofdm_loopback.grc
+++ b/gr-digital/examples/ofdm/ofdm_loopback.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Tue May 7 15:42:23 2013</timestamp>
+ <timestamp>Thu May 30 08:10:19 2013</timestamp>
<block>
<key>options</key>
<param>
@@ -107,54 +107,68 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>import</key>
<param>
<key>id</key>
- <value>freq_offset</value>
+ <value>import_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Frequency Offset (Multiples of Sub-carrier spacing)</value>
+ <key>import</key>
+ <value>import numpy</value>
</param>
<param>
- <key>value</key>
+ <key>_coordinate</key>
+ <value>(536, -1)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
<value>0</value>
</param>
+ </block>
+ <block>
+ <key>import</key>
<param>
- <key>min</key>
- <value>-3</value>
+ <key>id</key>
+ <value>import_0_0</value>
</param>
<param>
- <key>max</key>
- <value>3</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>num_steps</key>
- <value>100</value>
+ <key>import</key>
+ <value>from gnuradio.digital.utils import tagged_streams</value>
</param>
<param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
+ <key>_coordinate</key>
+ <value>(633, -1)</value>
</param>
<param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>grid_pos</key>
- <value></value>
+ <key>id</key>
+ <value>tx_signal</value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[numpy.sin(2 * numpy.pi * 1.0/8 * x) for x in range(8*2)]</value>
</param>
<param>
<key>_coordinate</key>
- <value>(652, 285)</value>
+ <value>(176, -1)</value>
</param>
<param>
<key>_rotation</key>
@@ -162,42 +176,105 @@
</param>
</block>
<block>
- <key>variable_slider</key>
+ <key>blocks_throttle</key>
<param>
<key>id</key>
- <value>noise_voltage</value>
+ <value>blocks_throttle_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value>Noise Amplitude</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>value</key>
- <value>0.01</value>
+ <key>samples_per_second</key>
+ <value>100e3</value>
</param>
<param>
- <key>min</key>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(354, 230)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Rx Spectrum</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>100e3</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
<value>0</value>
</param>
<param>
- <key>max</key>
- <value>1</value>
+ <key>y_per_div</key>
+ <value>10</value>
</param>
<param>
- <key>num_steps</key>
- <value>100</value>
+ <key>y_divs</key>
+ <value>10</value>
</param>
<param>
- <key>style</key>
- <value>wx.SL_HORIZONTAL</value>
+ <key>ref_level</key>
+ <value>0</value>
</param>
<param>
- <key>converver</key>
- <value>float_converter</value>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
</param>
<param>
<key>grid_pos</key>
@@ -208,8 +285,12 @@
<value></value>
</param>
<param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(651, 416)</value>
+ <value>(92, 463)</value>
</param>
<param>
<key>_rotation</key>
@@ -217,45 +298,38 @@
</param>
</block>
<block>
- <key>import</key>
+ <key>blocks_vector_source_x</key>
<param>
<key>id</key>
- <value>import_0</value>
+ <value>blocks_vector_source_x_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>import</key>
- <value>import numpy</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(536, -1)</value>
+ <key>type</key>
+ <value>float</value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>vector</key>
+ <value>tx_signal</value>
</param>
- </block>
- <block>
- <key>import</key>
<param>
- <key>id</key>
- <value>import_0_0</value>
+ <key>tags</key>
+ <value>tagged_streams.make_lengthtags((8*2*gr.sizeof_float,), (0,), tagname=len_tag_key)</value>
</param>
<param>
- <key>_enabled</key>
+ <key>repeat</key>
<value>True</value>
</param>
<param>
- <key>import</key>
- <value>from gnuradio.digital.utils import tagged_streams</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(633, -1)</value>
+ <value>(-1, 101)</value>
</param>
<param>
<key>_rotation</key>
@@ -263,10 +337,10 @@
</param>
</block>
<block>
- <key>digital_ofdm_tx</key>
+ <key>digital_ofdm_rx</key>
<param>
<key>id</key>
- <value>digital_ofdm_tx_0</value>
+ <value>digital_ofdm_rx_0</value>
</param>
<param>
<key>_enabled</key>
@@ -282,7 +356,7 @@
</param>
<param>
<key>packet_len_key</key>
- <value>len_tag_key</value>
+ <value>"rx_len"</value>
</param>
<param>
<key>occupied_carriers</key>
@@ -313,16 +387,12 @@
<value>"BPSK"</value>
</param>
<param>
- <key>rolloff</key>
- <value>0</value>
- </param>
- <param>
<key>log</key>
<value>False</value>
</param>
<param>
<key>_coordinate</key>
- <value>(390, 78)</value>
+ <value>(92, 307)</value>
</param>
<param>
<key>_rotation</key>
@@ -330,18 +400,30 @@
</param>
</block>
<block>
- <key>blocks_float_to_uchar</key>
+ <key>blocks_vector_to_stream</key>
<param>
<key>id</key>
- <value>blocks_float_to_uchar_0</value>
+ <value>blocks_vector_to_stream_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(230, 119)</value>
+ <value>(256, 117)</value>
</param>
<param>
<key>_rotation</key>
@@ -349,61 +431,54 @@
</param>
</block>
<block>
- <key>variable</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>tx_signal</value>
+ <value>freq_offset</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>value</key>
- <value>[numpy.sin(2 * numpy.pi * 1.0/8 * x) for x in range(8*2)]</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(176, -1)</value>
+ <key>label</key>
+ <value>Frequency Offset (Multiples of Sub-carrier spacing)</value>
</param>
<param>
- <key>_rotation</key>
+ <key>value</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_vector_source_x</key>
<param>
- <key>id</key>
- <value>blocks_vector_source_x_0</value>
+ <key>min</key>
+ <value>-3</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>max</key>
+ <value>3</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>num_steps</key>
+ <value>100</value>
</param>
<param>
- <key>vector</key>
- <value>tx_signal</value>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
</param>
<param>
- <key>tags</key>
- <value>tagged_streams.make_lengthtags((8*2*gr.sizeof_float,), (0,), tagname=len_tag_key)</value>
+ <key>converver</key>
+ <value>float_converter</value>
</param>
<param>
- <key>repeat</key>
- <value>True</value>
+ <key>grid_pos</key>
+ <value></value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>notebook</key>
+ <value></value>
</param>
<param>
<key>_coordinate</key>
- <value>(-1, 101)</value>
+ <value>(727, 282)</value>
</param>
<param>
<key>_rotation</key>
@@ -411,41 +486,65 @@
</param>
</block>
<block>
- <key>blocks_throttle</key>
+ <key>variable_slider</key>
<param>
<key>id</key>
- <value>blocks_throttle_0</value>
+ <value>noise_voltage</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>label</key>
+ <value>Noise Amplitude</value>
</param>
<param>
- <key>samples_per_second</key>
- <value>100e3</value>
+ <key>value</key>
+ <value>0.01</value>
</param>
<param>
- <key>vlen</key>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max</key>
<value>1</value>
</param>
<param>
+ <key>num_steps</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>float_converter</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(354, 230)</value>
+ <value>(726, 457)</value>
</param>
<param>
<key>_rotation</key>
- <value>180</value>
+ <value>0</value>
</param>
</block>
<block>
- <key>blocks_tag_gate</key>
+ <key>blocks_stream_to_vector</key>
<param>
<key>id</key>
- <value>blocks_tag_gate_0</value>
+ <value>blocks_stream_to_vector_0</value>
</param>
<param>
<key>_enabled</key>
@@ -453,30 +552,30 @@
</param>
<param>
<key>type</key>
- <value>complex</value>
+ <value>byte</value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>num_items</key>
+ <value>4</value>
</param>
<param>
- <key>propagate_tags</key>
- <value>False</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
<key>_coordinate</key>
- <value>(539, 230)</value>
+ <value>(369, 339)</value>
</param>
<param>
<key>_rotation</key>
- <value>180</value>
+ <value>0</value>
</param>
</block>
<block>
- <key>wxgui_fftsink2</key>
+ <key>wxgui_scopesink2</key>
<param>
<key>id</key>
- <value>wxgui_fftsink2_0</value>
+ <value>wxgui_scopesink2_0</value>
</param>
<param>
<key>_enabled</key>
@@ -484,59 +583,39 @@
</param>
<param>
<key>type</key>
- <value>complex</value>
+ <value>float</value>
</param>
<param>
<key>title</key>
- <value>Rx Spectrum</value>
+ <value>Scope Plot</value>
</param>
<param>
<key>samp_rate</key>
- <value>100e3</value>
+ <value>1.0</value>
</param>
<param>
- <key>baseband_freq</key>
+ <key>v_scale</key>
<value>0</value>
</param>
<param>
- <key>y_per_div</key>
- <value>10</value>
- </param>
- <param>
- <key>y_divs</key>
- <value>10</value>
- </param>
- <param>
- <key>ref_level</key>
+ <key>v_offset</key>
<value>0</value>
</param>
<param>
- <key>ref_scale</key>
- <value>2.0</value>
- </param>
- <param>
- <key>fft_size</key>
- <value>1024</value>
- </param>
- <param>
- <key>fft_rate</key>
- <value>15</value>
+ <key>t_scale</key>
+ <value>0</value>
</param>
<param>
- <key>peak_hold</key>
+ <key>ac_couple</key>
<value>False</value>
</param>
<param>
- <key>average</key>
+ <key>xy_mode</key>
<value>False</value>
</param>
<param>
- <key>avg_alpha</key>
- <value>0</value>
- </param>
- <param>
- <key>win</key>
- <value>None</value>
+ <key>num_inputs</key>
+ <value>1</value>
</param>
<param>
<key>win_size</key>
@@ -551,12 +630,16 @@
<value></value>
</param>
<param>
- <key>freqvar</key>
- <value>None</value>
+ <key>trig_mode</key>
+ <value>wxgui.TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
</param>
<param>
<key>_coordinate</key>
- <value>(92, 463)</value>
+ <value>(565, 315)</value>
</param>
<param>
<key>_rotation</key>
@@ -564,38 +647,38 @@
</param>
</block>
<block>
- <key>channel_model</key>
+ <key>blocks_tag_debug</key>
<param>
<key>id</key>
- <value>chan_model</value>
+ <value>blocks_tag_debug_0</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>noise_voltage</key>
- <value>noise_voltage</value>
+ <key>type</key>
+ <value>byte</value>
</param>
<param>
- <key>freq_offset</key>
- <value>1.0/fft_len * freq_offset</value>
+ <key>name</key>
+ <value>Rx Packets</value>
</param>
<param>
- <key>epsilon</key>
- <value>1.0</value>
+ <key>num_inputs</key>
+ <value>1</value>
</param>
<param>
- <key>taps</key>
- <value>1.0</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
<param>
- <key>seed</key>
- <value>0</value>
+ <key>display</key>
+ <value>True</value>
</param>
<param>
<key>_coordinate</key>
- <value>(615, 86)</value>
+ <value>(366, 416)</value>
</param>
<param>
<key>_rotation</key>
@@ -603,14 +686,14 @@
</param>
</block>
<block>
- <key>digital_ofdm_rx</key>
+ <key>digital_ofdm_tx</key>
<param>
<key>id</key>
- <value>digital_ofdm_rx_0</value>
+ <value>digital_ofdm_tx_0</value>
</param>
<param>
<key>_enabled</key>
- <value>False</value>
+ <value>True</value>
</param>
<param>
<key>fft_len</key>
@@ -622,7 +705,7 @@
</param>
<param>
<key>packet_len_key</key>
- <value>"rx_len"</value>
+ <value>len_tag_key</value>
</param>
<param>
<key>occupied_carriers</key>
@@ -653,31 +736,16 @@
<value>"BPSK"</value>
</param>
<param>
- <key>log</key>
- <value>False</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(92, 307)</value>
- </param>
- <param>
- <key>_rotation</key>
+ <key>rolloff</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_uchar_to_float</key>
- <param>
- <key>id</key>
- <value>blocks_uchar_to_float_0</value>
- </param>
<param>
- <key>_enabled</key>
+ <key>log</key>
<value>False</value>
</param>
<param>
<key>_coordinate</key>
- <value>(332, 340)</value>
+ <value>(455, 77)</value>
</param>
<param>
<key>_rotation</key>
@@ -685,113 +753,69 @@
</param>
</block>
<block>
- <key>blocks_tag_debug</key>
+ <key>blocks_tag_gate</key>
<param>
<key>id</key>
- <value>blocks_tag_debug_0</value>
+ <value>blocks_tag_gate_0</value>
</param>
<param>
<key>_enabled</key>
- <value>False</value>
+ <value>True</value>
</param>
<param>
<key>type</key>
- <value>byte</value>
- </param>
- <param>
- <key>name</key>
- <value>Rx Packets</value>
- </param>
- <param>
- <key>num_inputs</key>
- <value>1</value>
+ <value>complex</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
<param>
- <key>display</key>
- <value>True</value>
+ <key>propagate_tags</key>
+ <value>False</value>
</param>
<param>
<key>_coordinate</key>
- <value>(336, 412)</value>
+ <value>(539, 230)</value>
</param>
<param>
<key>_rotation</key>
- <value>0</value>
+ <value>180</value>
</param>
</block>
<block>
- <key>wxgui_scopesink2</key>
+ <key>channels_channel_model</key>
<param>
<key>id</key>
- <value>wxgui_scopesink2_0</value>
+ <value>channels_channel_model_0</value>
</param>
<param>
<key>_enabled</key>
- <value>False</value>
+ <value>True</value>
</param>
<param>
- <key>type</key>
- <value>float</value>
+ <key>noise_voltage</key>
+ <value>noise_voltage</value>
</param>
<param>
- <key>title</key>
- <value>Scope Plot</value>
+ <key>freq_offset</key>
+ <value>1.0/fft_len * freq_offset</value>
</param>
<param>
- <key>samp_rate</key>
+ <key>epsilon</key>
<value>1.0</value>
</param>
<param>
- <key>v_scale</key>
- <value>0</value>
- </param>
- <param>
- <key>v_offset</key>
- <value>0</value>
+ <key>taps</key>
+ <value>1.0 + 1.0j</value>
</param>
<param>
- <key>t_scale</key>
+ <key>seed</key>
<value>0</value>
</param>
<param>
- <key>ac_couple</key>
- <value>False</value>
- </param>
- <param>
- <key>xy_mode</key>
- <value>False</value>
- </param>
- <param>
- <key>num_inputs</key>
- <value>1</value>
- </param>
- <param>
- <key>win_size</key>
- <value></value>
- </param>
- <param>
- <key>grid_pos</key>
- <value></value>
- </param>
- <param>
- <key>notebook</key>
- <value></value>
- </param>
- <param>
- <key>trig_mode</key>
- <value>gr.gr_TRIG_MODE_AUTO</value>
- </param>
- <param>
- <key>y_axis_label</key>
- <value>Counts</value>
- </param>
- <param>
<key>_coordinate</key>
- <value>(504, 314)</value>
+ <value>(775, 85)</value>
</param>
<param>
<key>_rotation</key>
@@ -799,62 +823,62 @@
</param>
</block>
<connection>
- <source_block_id>blocks_vector_source_x_0</source_block_id>
- <sink_block_id>blocks_float_to_uchar_0</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>digital_ofdm_rx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_tx_0</source_block_id>
- <sink_block_id>chan_model</sink_block_id>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_float_to_uchar_0</source_block_id>
- <sink_block_id>digital_ofdm_tx_0</sink_block_id>
+ <source_block_id>digital_ofdm_rx_0</source_block_id>
+ <sink_block_id>blocks_tag_debug_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_throttle_0</source_block_id>
- <sink_block_id>digital_ofdm_rx_0</sink_block_id>
+ <source_block_id>blocks_tag_gate_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_throttle_0</source_block_id>
- <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_block_id>blocks_vector_source_x_0</source_block_id>
+ <sink_block_id>blocks_vector_to_stream_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_rx_0</source_block_id>
- <sink_block_id>blocks_uchar_to_float_0</sink_block_id>
+ <source_block_id>blocks_vector_to_stream_0</source_block_id>
+ <sink_block_id>digital_ofdm_tx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_uchar_to_float_0</source_block_id>
- <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_block_id>digital_ofdm_rx_0</source_block_id>
+ <sink_block_id>blocks_stream_to_vector_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>digital_ofdm_rx_0</source_block_id>
- <sink_block_id>blocks_tag_debug_0</sink_block_id>
+ <source_block_id>blocks_stream_to_vector_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>chan_model</source_block_id>
- <sink_block_id>blocks_tag_gate_0</sink_block_id>
+ <source_block_id>digital_ofdm_tx_0</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>blocks_tag_gate_0</source_block_id>
- <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>blocks_tag_gate_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-digital/grc/digital_ofdm_chanest_vcvc.xml b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml
index ea9855fdb6..5cc2145456 100644
--- a/gr-digital/grc/digital_ofdm_chanest_vcvc.xml
+++ b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml
@@ -5,12 +5,12 @@
<import>from gnuradio import digital</import>
<make>digital.ofdm_chanest_vcvc($sync_symbol1, $sync_symbol2, $n_data_symbols, $eq_noise_red_len, $max_carr_offset, $force_one_symbol)</make>
<param>
- <name>Synchronisation preamble symbol 1</name>
+ <name>Synch. symbol 1</name>
<key>sync_symbol1</key>
<type>complex_vector</type>
</param>
<param>
- <name>Synchronisation preamble symbol 2</name>
+ <name>Synch. symbol 2</name>
<key>sync_symbol2</key>
<value>()</value>
<type>complex_vector</type>
@@ -26,17 +26,20 @@
<key>eq_noise_red_len</key>
<value>0</value>
<type>int</type>
+ <hide>all</hide>
</param>
<param>
<name>Maximum carrier offset</name>
<key>max_carr_offset</key>
<value>-1</value>
<type>int</type>
+ <hide>#if $max_carr_offset &lt; 0 then 'part' else 'none'#</hide>
</param>
<param>
<name>Force One Synchronisation Symbol</name>
<key>force_one_symbol</key>
<type>enum</type>
+ <hide>#if not $force_one_symbol then 'part' else 'none'#</hide>
<option>
<name>No</name>
<key>False</key>
diff --git a/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml
index 28b33ef3c5..2a0c24e528 100644
--- a/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml
+++ b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml
@@ -2,7 +2,7 @@
<name>OFDM Frame Equalizer</name>
<key>digital_ofdm_frame_equalizer_vcvc</key>
<import>from gnuradio import digital</import>
- <make>digital.ofdm_frame_equalizer_vcvc($equalizer, $cp_len, $len_tag_key, $propagate_channel_state)</make>
+ <make>digital.ofdm_frame_equalizer_vcvc($equalizer, $cp_len, $len_tag_key, $propagate_channel_state, $fixed_frame_len)</make>
<param>
<name>FFT length</name>
<key>fft_len</key>
@@ -38,6 +38,13 @@
<key>False</key>
</option>
</param>
+ <param>
+ <name>Fixed frame length</name>
+ <key>fixed_frame_len</key>
+ <value>0</value>
+ <type>int</type>
+ <hide>#if $fixed_frame_len then 'none' else 'part'#</hide>
+ </param>
<sink>
<name>in</name>
<type>complex</type>
diff --git a/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt
index 06300cc27b..ecabb26d19 100644
--- a/gr-digital/include/CMakeLists.txt
+++ b/gr-digital/include/CMakeLists.txt
@@ -124,7 +124,6 @@ install(FILES
digital_simple_framer.h
digital_simple_framer_sync.h
digital_ofdm_sync_sc_cfb.h
- digital_ofdm_chanest_vcvc.h
digital_crc32_bb.h
digital_ofdm_carrier_allocator_cvc.h
digital_ofdm_equalizer_base.h
diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt
index 1042517294..9c62f54967 100644
--- a/gr-digital/include/digital/CMakeLists.txt
+++ b/gr-digital/include/digital/CMakeLists.txt
@@ -27,14 +27,14 @@ include(GrPython)
########################################################################
install(FILES
api.h
+ ofdm_chanest_vcvc.h
ofdm_frame_equalizer_vcvc.h
ofdm_serializer_vcc.h
packet_header_default.h
packet_header_ofdm.h
packet_headergenerator_bb.h
packet_headerparser_b.h
- header_payload_demux.h
- DESTINATION ${GR_INCLUDE_DIR}/gnuradio/digital
+ header_payload_demux.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio/digital
COMPONENT "digital_devel"
)
diff --git a/gr-digital/include/digital/ofdm_chanest_vcvc.h b/gr-digital/include/digital/ofdm_chanest_vcvc.h
new file mode 100644
index 0000000000..da9479399a
--- /dev/null
+++ b/gr-digital/include/digital/ofdm_chanest_vcvc.h
@@ -0,0 +1,97 @@
+/* -*- 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_H
+#define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
+
+#include <digital/api.h>
+#include <gr_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Estimate channel and coarse frequency offset for OFDM from preambles
+ * \ingroup ofdm_blk
+ * \ingroup syncronizers_blk
+ *
+ * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected
+ * to be synchronisation symbols, which are used to estimate the coarse freq offset
+ * and the initial equalizer taps (these symbols are removed from the stream).
+ * The following \p n_data_symbols are passed through unmodified (the actual equalisation
+ * must be done elsewhere).
+ * Output: The data symbols, without the synchronisation symbols.
+ * The first data symbol passed through has two tags:
+ * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers,
+ * and 'ofdm_sync_eq_taps' (complex vector).
+ * Any tags attached to the synchronisation symbols are attached to the first data
+ * symbol. All other tags are propagated as expected.
+ *
+ * Note: The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest is not.
+ *
+ * This block assumes the frequency offset is even (i.e. an integer multiple of 2).
+ *
+ * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM",
+ * Communications, IEEE Transactions on, 1997.
+ * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2.
+ */
+ class DIGITAL_API ofdm_chanest_vcvc : virtual public gr_block
+ {
+ public:
+ typedef boost::shared_ptr<ofdm_chanest_vcvc> sptr;
+
+ /*!
+ * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its length must be
+ * the FFT length. For Schmidl & Cox synchronisation, every second sub-carrier
+ * has to be zero.
+ * \param sync_symbol2 Second synchronisation symbol in the frequency domain. Must be equal to
+ * the FFT length, or zero length if only one synchronisation symbol is used.
+ * Using this symbol is how synchronisation is described in [1]. Leaving this
+ * empty forces us to interpolate the equalizer taps.
+ * If you are using an unusual sub-carrier configuration (e.g. because of OFDMA),
+ * this sync symbol is used to identify the active sub-carriers. If you only
+ * have one synchronisation symbol, set the active sub-carriers to a non-zero
+ * value in here, and also set \p force_one_sync_symbol parameter to true.
+ * \param n_data_symbols The number of data symbols following each set of synchronisation symbols.
+ * Must be at least 1.
+ * \param eq_noise_red_len If non-zero, noise reduction for the equalizer taps is done according
+ * to [2]. In this case, it is the channel influence time in number of
+ * samples. A good value is usually the length of the cyclic prefix.
+ * \param max_carr_offset Limit the number of sub-carriers the frequency offset can maximally be.
+ * Leave this zero to try all possibilities.
+ * \param force_one_sync_symbol See \p sync_symbol2.
+ */
+ static sptr make(
+ const std::vector<gr_complex> &sync_symbol1,
+ const std::vector<gr_complex> &sync_symbol2,
+ int n_data_symbols,
+ int eq_noise_red_len=0,
+ int max_carr_offset=-1,
+ bool force_one_sync_symbol=false
+ );
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H */
+
diff --git a/gr-digital/include/digital_ofdm_chanest_vcvc.h b/gr-digital/include/digital_ofdm_chanest_vcvc.h
deleted file mode 100644
index afea16994c..0000000000
--- a/gr-digital/include/digital_ofdm_chanest_vcvc.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- c++ -*- */
-/* Copyright 2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
-#define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H
-
-#include <digital_api.h>
-#include <gr_block.h>
-
-class digital_ofdm_chanest_vcvc;
-
-typedef boost::shared_ptr<digital_ofdm_chanest_vcvc> digital_ofdm_chanest_vcvc_sptr;
-
-/*
- * \param sync_symbol1 First synchronisation symbol in the frequency domain. Its length must be
- * the FFT length. For Schmidl & Cox synchronisation, every second sub-carrier
- * has to be zero.
- * \param sync_symbol2 Second synchronisation symbol in the frequency domain. Must be equal to
- * the FFT length, or zero length if only one synchronisation symbol is used.
- * Using this symbol is how synchronisation is described in [1]. Leaving this
- * empty forces us to interpolate the equalizer taps.
- * If you are using an unusual sub-carrier configuration (e.g. because of OFDMA),
- * this sync symbol is used to identify the active sub-carriers. If you only
- * have one synchronisation symbol, set the active sub-carriers to a non-zero
- * value in here, and also set \p force_one_sync_symbol parameter to true.
- * \param n_data_symbols The number of data symbols following each set of synchronisation symbols.
- * Must be at least 1.
- * \param eq_noise_red_len If non-zero, noise reduction for the equalizer taps is done according
- * to [2]. In this case, it is the channel influence time in number of
- * samples. A good value is usually the length of the cyclic prefix.
- * \param max_carr_offset Limit the number of sub-carriers the frequency offset can maximally be.
- * Leave this zero to try all possibilities.
- * \param force_one_sync_symbol See \p sync_symbol2.
- */
-DIGITAL_API digital_ofdm_chanest_vcvc_sptr
-digital_make_ofdm_chanest_vcvc (
- const std::vector<gr_complex> &sync_symbol1,
- const std::vector<gr_complex> &sync_symbol2,
- int n_data_symbols,
- int eq_noise_red_len=0,
- int max_carr_offset=-1,
- bool force_one_sync_symbol=false);
-
-/*!
- * \brief Estimate channel and coarse frequency offset for OFDM from preambles
- * \ingroup ofdm_blk
- * \ingroup syncronizers_blk
- *
- * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected
- * to be synchronisation symbols, which are used to estimate the coarse freq offset
- * and the initial equalizer taps (these symbols are removed from the stream).
- * The following \p n_data_symbols are passed through unmodified (the actual equalisation
- * must be done elsewhere).
- * Output: The data symbols, without the synchronisation symbols.
- * The first data symbol passed through has two tags:
- * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers,
- * and 'ofdm_sync_eq_taps' (complex vector).
- * Any tags attached to the synchronisation symbols are attached to the first data
- * symbol. All other tags are propagated as expected.
- *
- * Note: The vector on ofdm_sync_eq_taps is already frequency-corrected, whereas the rest is not.
- *
- * This block assumes the frequency offset is even (i.e. an integer multiple of 2).
- *
- * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM",
- * Communications, IEEE Transactions on, 1997.
- * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2.
- */
-class DIGITAL_API digital_ofdm_chanest_vcvc : public gr_block
-{
- private:
- friend DIGITAL_API digital_ofdm_chanest_vcvc_sptr digital_make_ofdm_chanest_vcvc (const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
-
- int d_fft_len; //! FFT length
- int d_n_data_syms; //! Number of data symbols following the sync symbol(s)
- int d_n_sync_syms; //! Number of sync symbols (1 or 2)
- //! 0 if no noise reduction is done for the initial channel state estimation. Otherwise, the maximum length of the channel delay in samples.
- int d_eq_noise_red_len;
- //! Is sync_symbol1 if d_n_sync_syms == 1, otherwise sync_symbol2. Used as a reference symbol to estimate the channel.
- std::vector<gr_complex> d_ref_sym;
- //! If d_n_sync_syms == 2 this is used as a differential correlation vector (called 'v' in [1]).
- std::vector<gr_complex> d_corr_v;
- //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset
- std::vector<float> d_known_symbol_diffs;
- //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset (temp. variable)
- std::vector<float> d_new_symbol_diffs;
- //! The index of the first carrier with data (index 0 is not DC here, but the lowest frequency)
- int d_first_active_carrier;
- //! The index of the last carrier with data
- int d_last_active_carrier;
- //! If true, the channel estimation must be interpolated
- bool d_interpolate;
- //! Maximum carrier offset (negative value!)
- int d_max_neg_carr_offset;
- //! Maximum carrier offset (positive value!)
- int d_max_pos_carr_offset;
-
-
- digital_ofdm_chanest_vcvc(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
-
- //! Calculate the coarse frequency offset in number of carriers
- int get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2);
- //! Estimate the channel (phase and amplitude offset per carrier)
- void get_chan_taps(const gr_complex *sync_sym1, const gr_complex *sync_sym2, int carr_offset, std::vector<gr_complex> &taps);
-
- public:
- ~digital_ofdm_chanest_vcvc();
-
- void forecast (int noutput_items, gr_vector_int &ninput_items_required);
- int general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-};
-
-#endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_H */
-
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index 42340b6c2a..dffdb78aca 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -142,12 +142,12 @@ list(APPEND gr_digital_sources
digital_scrambler_bb.cc
digital_simple_framer.cc
digital_ofdm_sync_sc_cfb.cc
- digital_ofdm_chanest_vcvc.cc
digital_crc32_bb.cc
digital_ofdm_carrier_allocator_cvc.cc
digital_ofdm_equalizer_base.cc
digital_ofdm_equalizer_static.cc
digital_ofdm_equalizer_simpledfe.cc
+ ofdm_chanest_vcvc_impl.cc
ofdm_frame_equalizer_vcvc_impl.cc
ofdm_serializer_vcc_impl.cc
packet_header_default.cc
diff --git a/gr-digital/lib/digital_ofdm_chanest_vcvc.cc b/gr-digital/lib/digital_ofdm_chanest_vcvc.cc
deleted file mode 100644
index 1e3adbb67f..0000000000
--- a/gr-digital/lib/digital_ofdm_chanest_vcvc.cc
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*- c++ -*- */
-/* Copyright 2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_io_signature.h>
-#include "digital_ofdm_chanest_vcvc.h"
-
-digital_ofdm_chanest_vcvc_sptr
-digital_make_ofdm_chanest_vcvc (
- const std::vector<gr_complex> &sync_symbol1,
- const std::vector<gr_complex> &sync_symbol2,
- int n_data_symbols,
- int eq_noise_red_len,
- int max_carr_offset,
- bool force_one_sync_symbol)
-{
- return gnuradio::get_initial_sptr (
- new digital_ofdm_chanest_vcvc(
- sync_symbol1,
- sync_symbol2,
- n_data_symbols,
- eq_noise_red_len,
- max_carr_offset,
- force_one_sync_symbol
- )
- );
-}
-
-
-digital_ofdm_chanest_vcvc::digital_ofdm_chanest_vcvc (
- const std::vector<gr_complex> &sync_symbol1,
- const std::vector<gr_complex> &sync_symbol2,
- int n_data_symbols,
- int eq_noise_red_len,
- int max_carr_offset,
- bool force_one_sync_symbol)
- : gr_block ("ofdm_chanest_vcvc",
- gr_make_io_signature(1, 1, sizeof (gr_complex) * sync_symbol1.size()),
- gr_make_io_signature(1, 2, sizeof (gr_complex) * sync_symbol1.size())),
- d_fft_len(sync_symbol1.size()),
- d_n_data_syms(n_data_symbols),
- d_n_sync_syms(1),
- d_eq_noise_red_len(eq_noise_red_len),
- d_ref_sym((sync_symbol2.size() && !force_one_sync_symbol) ? sync_symbol2 : sync_symbol1),
- d_corr_v(sync_symbol2),
- d_known_symbol_diffs(0, 0),
- d_new_symbol_diffs(0, 0),
- d_interpolate(false)
-{
- // Set index of first and last active carrier
- for (int i = 0; i < d_fft_len; i++) {
- if (d_ref_sym[i] != gr_complex(0, 0)) {
- d_first_active_carrier = i;
- break;
- }
- }
- for (int i = d_fft_len-1; i >= 0; i--) {
- if (d_ref_sym[i] != gr_complex(0, 0)) {
- d_last_active_carrier = i;
- break;
- }
- }
-
- // Sanity checks
- if (sync_symbol2.size()) {
- if (sync_symbol1.size() != sync_symbol2.size()) {
- throw std::invalid_argument("sync symbols must have equal length.");
- }
- if (!force_one_sync_symbol) {
- d_n_sync_syms = 2;
- }
- } else {
- if (sync_symbol1[d_first_active_carrier+1] == gr_complex(0, 0)) {
- d_last_active_carrier++;
- d_interpolate = true;
- }
- }
-
- // Set up coarse freq estimation info
- // Allow all possible values:
- d_max_neg_carr_offset = -d_first_active_carrier;
- d_max_pos_carr_offset = d_fft_len - d_last_active_carrier - 1;
- if (max_carr_offset != -1) {
- d_max_neg_carr_offset = std::max(-max_carr_offset, d_max_neg_carr_offset);
- d_max_pos_carr_offset = std::min(max_carr_offset, d_max_pos_carr_offset);
- }
- // Carrier offsets must be even
- if (d_max_neg_carr_offset % 2)
- d_max_neg_carr_offset++;
- if (d_max_pos_carr_offset % 2)
- d_max_pos_carr_offset--;
-
- if (d_n_sync_syms == 2) {
- for (int i = 0; i < d_fft_len; i++) {
- if (sync_symbol1[i] == gr_complex(0, 0)) {
- d_corr_v[i] = gr_complex(0, 0);
- } else {
- d_corr_v[i] /= sync_symbol1[i];
- }
- }
- } else {
- d_corr_v.resize(0, 0);
- d_known_symbol_diffs.resize(d_fft_len, 0);
- d_new_symbol_diffs.resize(d_fft_len, 0);
- for (int i = d_first_active_carrier; i < d_last_active_carrier-2 && i < d_fft_len-2; i += 2) {
- d_known_symbol_diffs[i] = std::norm(sync_symbol1[i] - sync_symbol1[i+2]);
- }
- }
-
- set_relative_rate((double) n_data_symbols / (n_data_symbols + d_n_sync_syms));
- set_tag_propagation_policy(TPP_DONT);
-}
-
-
-digital_ofdm_chanest_vcvc::~digital_ofdm_chanest_vcvc()
-{
-}
-
-void
-digital_ofdm_chanest_vcvc::forecast (int noutput_items, gr_vector_int &ninput_items_required)
-{
- ninput_items_required[0] = (noutput_items/d_n_data_syms) * (d_n_data_syms + d_n_sync_syms);
-}
-
-
-int
-digital_ofdm_chanest_vcvc::get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2)
-{
- int carr_offset = 0;
- if (d_corr_v.size()) {
- // Use Schmidl & Cox method
- float Bg_max = 0;
- // g here is 2g in the paper
- for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) {
- gr_complex tmp = gr_complex(0, 0);
- for (int k = 0; k < d_fft_len; k++) {
- if (d_corr_v[k] != gr_complex(0, 0)) {
- tmp += std::conj(sync_sym1[k+g]) * std::conj(d_corr_v[k]) * sync_sym2[k+g];
- }
- }
- if (std::abs(tmp) > Bg_max) {
- Bg_max = std::abs(tmp);
- carr_offset = g;
- }
- }
- } else {
- // Correlate
- std::fill(d_new_symbol_diffs.begin(), d_new_symbol_diffs.end(), 0);
- for(int i = 0; i < d_fft_len-2; i++) {
- d_new_symbol_diffs[i] = std::norm(sync_sym1[i] - sync_sym1[i+2]);
- }
-
- float sum;
- float max = 0;
- for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) {
- sum = 0;
- for (int j = 0; j < d_fft_len; j++) {
- if (d_known_symbol_diffs[j]) {
- sum += (d_known_symbol_diffs[j] * d_new_symbol_diffs[j + g]);
- }
- if(sum > max) {
- max = sum;
- carr_offset = g;
- }
- }
- }
- }
- return carr_offset;
-}
-
-
-void
-digital_ofdm_chanest_vcvc::get_chan_taps(
- const gr_complex *sync_sym1,
- const gr_complex *sync_sym2,
- int carr_offset,
- std::vector<gr_complex> &taps)
-{
- const gr_complex *sym = ((d_n_sync_syms == 2) ? sync_sym2 : sync_sym1);
- std::fill(taps.begin(), taps.end(), gr_complex(0, 0));
- int loop_start = 0;
- int loop_end = d_fft_len;
- if (carr_offset > 0) {
- loop_start = carr_offset;
- } else if (carr_offset < 0) {
- loop_end = d_fft_len + carr_offset;
- }
- for (int i = loop_start; i < loop_end; i++) {
- if ((d_ref_sym[i-carr_offset] != gr_complex(0, 0))) {
- taps[i-carr_offset] = sym[i] / d_ref_sym[i-carr_offset];
- }
- }
-
- if (d_interpolate) {
- // FIXME check this out re offset + update docs
- for (int i = d_first_active_carrier + 1; i < d_last_active_carrier; i += 2) {
- taps[i] = taps[i-1];
- }
- taps[d_last_active_carrier] = taps[d_last_active_carrier-1];
- }
-
- if (d_eq_noise_red_len) {
- // TODO
- // 1) IFFT
- // 2) Set all elements > d_eq_noise_red_len to zero
- // 3) FFT
- }
-}
-
-
-// 1) Go through all the frames available on the input buffer
-// 2) Estimate the coarse freq. offset and the eq. taps from the
-// input symbol(s)
-// 3) Copy the data symbols to the output
-// 4) Copy all other tags onto the output. A tag that was on
-// a sync symbol is copied onto the first data symbol.
-// 5) Add the new tags for carrier offset and eq. taps
-int
-digital_ofdm_chanest_vcvc::general_work (int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- const gr_complex *in = (const gr_complex *) input_items[0];
- gr_complex *out = (gr_complex *) output_items[0];
- int n_frames = noutput_items/d_n_data_syms;
- const int framesize = d_n_sync_syms + d_n_data_syms;
-
- for (int i = 0; i < n_frames; i++) {
- int carr_offset = 0;
- if (d_max_neg_carr_offset || d_max_pos_carr_offset)
- carr_offset = get_carr_offset(in, in+d_fft_len);
- std::vector<gr_complex> chan_taps(d_fft_len, 0);
- get_chan_taps(in, in+d_fft_len, carr_offset, chan_taps);
-
- if (output_items.size() == 2) {
- gr_complex *out_chantaps = ((gr_complex *) output_items[1]) + i * d_fft_len;
- memcpy((void *) out_chantaps, (void *) &chan_taps[0], sizeof(gr_complex) * d_fft_len);
- produce(1, 1);
- }
-
- 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;
- get_tags_in_range(tags, 0,
- nitems_read(0)+i*framesize,
- nitems_read(0)+(i+1)*framesize);
- for (unsigned t = 0; t < tags.size(); t++) {
- int offset = tags[t].offset - (nitems_read(0) + i*framesize);
- if (offset < d_n_sync_syms) {
- offset = 0;
- } else {
- offset -= d_n_sync_syms;
- }
- tags[t].offset = offset + nitems_written(0) + i*d_n_data_syms;
- add_item_tag(0, tags[t]);
- }
-
- add_item_tag(0, nitems_written(0) + i*d_n_data_syms,
- pmt::pmt_string_to_symbol("ofdm_sync_carr_offset"),
- pmt::pmt_from_long(carr_offset));
- add_item_tag(0, nitems_written(0) + i*d_n_data_syms,
- pmt::pmt_string_to_symbol("ofdm_sync_chan_taps"),
- pmt::pmt_init_c32vector(d_fft_len, chan_taps));
- }
- produce(0, n_frames * d_n_data_syms);
- consume_each(n_frames * framesize);
-
- return WORK_CALLED_PRODUCE;
-}
-
diff --git a/gr-digital/lib/header_payload_demux_impl.cc b/gr-digital/lib/header_payload_demux_impl.cc
index ab3f2875f3..fbc13f4069 100644
--- a/gr-digital/lib/header_payload_demux_impl.cc
+++ b/gr-digital/lib/header_payload_demux_impl.cc
@@ -89,7 +89,9 @@ namespace gr {
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);
+ if (!d_output_symbols) {
+ set_output_multiple(d_items_per_symbol);
+ }
message_port_register_in(msg_port_id);
}
@@ -100,10 +102,20 @@ namespace gr {
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!
+ int n_items_reqd = 0;
+ if (d_state == STATE_HEADER) {
+ n_items_reqd = d_header_len * (d_items_per_symbol + d_gi);
+ //} else if (d_state == STATE_HEADER) {
+ } else {
+ n_items_reqd = noutput_items * (d_items_per_symbol + d_gi);
+ if (!d_output_symbols) {
+ // here, noutput_items is an integer multiple of d_items_per_symbol!
+ n_items_reqd /= 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);
+ ninput_items_required[i] = n_items_reqd;
}
}
@@ -119,59 +131,62 @@ namespace gr {
int nread = 0;
bool exit_loop = false;
-
int produced_hdr = 0;
int produced_payload = 0;
- // FIXME ninput_items[1] does not have to be defined O_o
- while (nread < noutput_items && nread < ninput_items[0] && nread < ninput_items[1] && !exit_loop) {
+ while (
+ nread < noutput_items
+ && nread < ninput_items[0]
+ && (ninput_items.size() == 1 || nread < ninput_items[1])
+ && !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_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_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 (empty_p(msg_port_id)) return 0; //no message available
- // 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()) {
- d_state = STATE_IDLE;
- exit_loop = true;
- break;
- }
- d_state = STATE_PAYLOAD;
+ case STATE_WAIT_FOR_MSG:
+ if (empty_p(msg_port_id)) return 0; //no message available
+ // 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()) {
+ d_state = STATE_IDLE;
+ 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;
+ 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");
+ default:
+ throw std::runtime_error("invalid state");
} /* switch */
} /* while(nread < noutput_items) */
@@ -225,7 +240,7 @@ namespace gr {
bool
header_payload_demux_impl::parse_header_data_msg()
{
- pmt::pmt_t msg(delete_head_blocking(msg_port_id));
+ pmt::pmt_t msg(delete_head_nowait(msg_port_id));
if (pmt::pmt_is_integer(msg)) {
d_remaining_symbols = pmt::pmt_to_long(msg);
add_item_tag(1, nitems_written(1), d_len_tag_key, msg);
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..8c847bf974
--- /dev/null
+++ b/gr-digital/lib/ofdm_chanest_vcvc_impl.cc
@@ -0,0 +1,282 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012,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, 2, 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_output_multiple(d_n_data_syms);
+ set_relative_rate((double) d_n_data_syms / (d_n_data_syms + 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-carr_offset] = 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[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
+ }
+ }
+
+
+ // Operates on a per-frame basis
+ 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];
+ const int framesize = d_n_sync_syms + d_n_data_syms;
+
+ // Channel info estimation
+ int 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);
+ add_item_tag(0, nitems_written(0),
+ pmt::pmt_string_to_symbol("ofdm_sync_carr_offset"),
+ pmt::pmt_from_long(carr_offset));
+ add_item_tag(0, nitems_written(0),
+ pmt::pmt_string_to_symbol("ofdm_sync_chan_taps"),
+ pmt::pmt_init_c32vector(d_fft_len, chan_taps));
+
+ // Copy data symbols
+ if (output_items.size() == 2) {
+ gr_complex *out_chantaps = ((gr_complex *) output_items[1]);
+ memcpy((void *) out_chantaps, (void *) &chan_taps[0], sizeof(gr_complex) * d_fft_len);
+ produce(1, 1);
+ }
+ memcpy((void *) out,
+ (void *) &in[d_n_sync_syms * d_fft_len],
+ sizeof(gr_complex) * d_fft_len * d_n_data_syms);
+
+ // Propagate tags
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, 0,
+ nitems_read(0),
+ nitems_read(0)+framesize);
+ for (unsigned t = 0; t < tags.size(); t++) {
+ int offset = tags[t].offset - nitems_read(0);
+ if (offset < d_n_sync_syms) {
+ offset = 0;
+ } else {
+ offset -= d_n_sync_syms;
+ }
+ tags[t].offset = offset + nitems_written(0);
+ add_item_tag(0, tags[t]);
+ }
+
+ produce(0, d_n_data_syms);
+ consume_each(framesize);
+ return WORK_CALLED_PRODUCE;
+ }
+
+ } /* 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/python/ofdm_txrx.py b/gr-digital/python/ofdm_txrx.py
index ea5f682edd..17f38f8329 100644
--- a/gr-digital/python/ofdm_txrx.py
+++ b/gr-digital/python/ofdm_txrx.py
@@ -350,11 +350,12 @@ class ofdm_rx(gr.hier_block2):
self.connect((hpd, 0), header_fft, chanest, header_eq, header_serializer, header_demod, header_parser)
self.msg_connect(header_parser, "header_data", hpd, "header_data")
if debug_log:
- self.connect((chanest, 1), blocks.file_sink(512, 'channel-estimate.dat'))
- self.connect((chanest, 0), blocks.file_sink(512, 'post-hdr-chanest.dat'))
- self.connect(header_eq, blocks.file_sink(512, 'post-hdr-eq.dat'))
- self.connect(header_serializer, blocks.file_sink(8, 'post-hdr-serializer.dat'))
- self.connect(header_demod, blocks.file_sink(1, 'post-hdr-demod.dat'))
+ self.connect((chanest, 1), blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'channel-estimate.dat'))
+ self.connect((chanest, 0), blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'post-hdr-chanest.dat'))
+ self.connect((chanest, 0), blocks.tag_debug(gr.sizeof_gr_complex * fft_len, 'post-hdr-chanest'))
+ self.connect(header_eq, blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'post-hdr-eq.dat'))
+ self.connect(header_serializer, blocks.file_sink(gr.sizeof_gr_complex, 'post-hdr-serializer.dat'))
+ self.connect(header_demod, blocks.file_sink(1, 'post-hdr-demod.dat'))
### Payload demod ####################################################
payload_fft = fft.fft_vcc(self.fft_len, True, (), True)
payload_constellation = _get_constellation(bps_payload)
@@ -381,13 +382,12 @@ class ofdm_rx(gr.hier_block2):
crc = digital.crc32_bb(True, self.packet_length_tag_key)
self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer, payload_demod, repack, crc, self)
if debug_log:
- self.connect((hpd, 1), blocks.tag_debug(8*64, 'post-hpd'));
- self.connect(payload_fft, blocks.file_sink(8*64, 'post-payload-fft.dat'))
- self.connect(payload_eq, blocks.file_sink(8*64, 'post-payload-eq.dat'))
- self.connect(payload_serializer, blocks.file_sink(8, 'post-payload-serializer.dat'))
- self.connect(payload_demod, blocks.file_sink(1, 'post-payload-demod.dat'))
- self.connect(repack, blocks.file_sink(1, 'post-payload-repack.dat'))
- self.connect(crc, blocks.file_sink(1, 'post-payload-crc.dat'))
- self.connect(crc, blocks.tag_debug(1, 'post-payload-crc'))
+ self.connect((hpd, 1), blocks.tag_debug(gr.sizeof_gr_complex*fft_len, 'post-hpd'));
+ self.connect(payload_fft, blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-fft.dat'))
+ self.connect(payload_eq, blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-eq.dat'))
+ self.connect(payload_serializer, blocks.file_sink(gr.sizeof_gr_complex, 'post-payload-serializer.dat'))
+ self.connect(payload_demod, blocks.file_sink(1, 'post-payload-demod.dat'))
+ self.connect(repack, blocks.file_sink(1, 'post-payload-repack.dat'))
+ self.connect(crc, blocks.file_sink(1, 'post-payload-crc.dat'))
diff --git a/gr-digital/python/qa_ofdm_chanest_vcvc.py b/gr-digital/python/qa_ofdm_chanest_vcvc.py
index 3b1ca15a05..34524fff01 100755
--- a/gr-digital/python/qa_ofdm_chanest_vcvc.py
+++ b/gr-digital/python/qa_ofdm_chanest_vcvc.py
@@ -77,21 +77,20 @@ class qa_ofdm_sync_eqinit_vcvc (gr_unittest.TestCase):
self.tb.run()
self.assertEqual(shift_tuple(sink.data(), -carr_offset), data_symbol)
tags = sink.tags()
- detected_tags = {
- 'ofdm_sync_carr_offset': False,
- 'test_tag_1': False,
- 'test_tag_2': False
- }
+ ptags = {}
for tag in tags:
- if pmt.pmt_symbol_to_string(tag.key) == 'ofdm_sync_carr_offset':
- carr_offset_hat = pmt.pmt_to_long(tag.value)
- self.assertEqual(pmt.pmt_to_long(tag.value), carr_offset)
- if pmt.pmt_symbol_to_string(tag.key) == 'test_tag_1':
- self.assertEqual(tag.offset, 0)
- if pmt.pmt_symbol_to_string(tag.key) == 'test_tag_2':
- self.assertEqual(tag.offset, 0)
- detected_tags[pmt.pmt_symbol_to_string(tag.key)] = True
- self.assertTrue(all(detected_tags.values()))
+ ptag = gr.tag_to_python(tag)
+ ptags[ptag.key] = (ptag.value, ptag.offset)
+ if ptag.key == 'ofdm_sync_chan_taps':
+ ptags[ptag.key] = (None, ptag.offset)
+ expected_tags = {
+ 'ofdm_sync_carr_offset': (-2, 0),
+ 'ofdm_sync_chan_taps': (None, 0),
+ 'test_tag_1': (23, 0),
+ 'test_tag_2': (42, 0),
+ }
+ self.assertEqual(ptags, expected_tags)
+
def test_002_offset_1sym (self):
""" Add a frequency offset, check if it's correctly detected.
diff --git a/gr-digital/swig/digital_ofdm_chanest_vcvc.i b/gr-digital/swig/digital_ofdm_chanest_vcvc.i
deleted file mode 100644
index aa6e79b5c2..0000000000
--- a/gr-digital/swig/digital_ofdm_chanest_vcvc.i
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- c++ -*- */
-/* Copyright 2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-GR_SWIG_BLOCK_MAGIC(digital, ofdm_chanest_vcvc);
-
-digital_ofdm_chanest_vcvc_sptr
-digital_make_ofdm_chanest_vcvc (
- const std::vector<gr_complex> &sync_symbol1,
- const std::vector<gr_complex> &sync_symbol2,
- int n_data_symbols,
- int eq_noise_red_len=0,
- int max_carr_offset=-1,
- bool force_one_sync_symbol=false);
-
-class digital_ofdm_chanest_vcvc : public gr_block
-{
- private:
- digital_ofdm_chanest_vcvc(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol);
-
- public:
-};
-
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 2f36e13c8e..36f16b41d0 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -84,7 +84,7 @@ enum snr_est_type_t {
#include "digital_scrambler_bb.h"
#include "digital_simple_framer.h"
#include "digital_ofdm_sync_sc_cfb.h"
-#include "digital_ofdm_chanest_vcvc.h"
+#include "digital/ofdm_chanest_vcvc.h"
#include "digital_crc32_bb.h"
#include "digital_ofdm_carrier_allocator_cvc.h"
#include "digital_ofdm_equalizer_base.h"
@@ -143,27 +143,28 @@ enum snr_est_type_t {
%include "digital_scrambler_bb.i"
%include "digital_simple_framer.i"
%include "digital_ofdm_sync_sc_cfb.i"
-%include "digital_ofdm_chanest_vcvc.i"
+%include "digital/ofdm_chanest_vcvc.h"
%include "digital_crc32_bb.i"
%include "digital_ofdm_carrier_allocator_cvc.i"
%include "digital_ofdm_equalizer_base.i"
%include "digital_ofdm_equalizer_simpledfe.i"
%include "digital_ofdm_equalizer_static.i"
%include "digital/ofdm_frame_equalizer_vcvc.h"
-GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_equalizer_vcvc);
-
+%include "digital/ofdm_serializer_vcc.h"
%include "digital/packet_header_default.h"
%include "digital/packet_header_ofdm.h"
-%include "packet_header.i"
-
%include "digital/packet_headergenerator_bb.h"
-GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb);
-
-%include "digital/ofdm_serializer_vcc.h"
-GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc);
-
%include "digital/packet_headerparser_b.h"
-GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b);
%include "digital/header_payload_demux.h"
-GR_SWIG_BLOCK_MAGIC2(digital, header_payload_demux);
%include "digital_simple_correlator.i"
+
+GR_SWIG_BLOCK_MAGIC2(digital, header_payload_demux);
+GR_SWIG_BLOCK_MAGIC2(digital, ofdm_chanest_vcvc);
+GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_equalizer_vcvc);
+GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb);
+GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b);
+
+// Properly package up non-block objects
+%include "packet_header.i"
+