diff options
author | Martin Braun <martin.braun@kit.edu> | 2013-05-25 09:38:49 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@kit.edu> | 2013-05-30 08:46:33 -0400 |
commit | 495a44dabf6c6a6a184eda526711c06f68cccd9d (patch) | |
tree | 68746dd1ed1333d99bb89412eda1571821fce321 | |
parent | a7b3a9339106aaba72195b693dfeaa98f194e0d5 (diff) |
digital: bugfixes to ofdm_chanest, HPD and frame EQ
-rw-r--r-- | gr-digital/examples/ofdm/ofdm_loopback.grc | 558 | ||||
-rw-r--r-- | gr-digital/grc/digital_ofdm_chanest_vcvc.xml | 7 | ||||
-rw-r--r-- | gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml | 9 | ||||
-rw-r--r-- | gr-digital/include/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-digital/include/digital/CMakeLists.txt | 4 | ||||
-rw-r--r-- | gr-digital/include/digital/ofdm_chanest_vcvc.h | 97 | ||||
-rw-r--r-- | gr-digital/include/digital_ofdm_chanest_vcvc.h | 135 | ||||
-rw-r--r-- | gr-digital/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gr-digital/lib/digital_ofdm_chanest_vcvc.cc | 296 | ||||
-rw-r--r-- | gr-digital/lib/header_payload_demux_impl.cc | 115 | ||||
-rw-r--r-- | gr-digital/lib/ofdm_chanest_vcvc_impl.cc | 282 | ||||
-rw-r--r-- | gr-digital/lib/ofdm_chanest_vcvc_impl.h | 78 | ||||
-rw-r--r-- | gr-digital/python/ofdm_txrx.py | 26 | ||||
-rwxr-xr-x | gr-digital/python/qa_ofdm_chanest_vcvc.py | 27 | ||||
-rw-r--r-- | gr-digital/swig/digital_ofdm_chanest_vcvc.i | 40 | ||||
-rw-r--r-- | gr-digital/swig/digital_swig.i | 27 |
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 < 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" + |