diff options
author | Ben Reynwar <ben@reynwar.net> | 2013-04-02 23:04:08 -0700 |
---|---|---|
committer | Ben Reynwar <ben@reynwar.net> | 2013-04-02 23:04:08 -0700 |
commit | c6dbde23b256a41b3d92cb4ad6b63287095d53c7 (patch) | |
tree | 71db12ea2e1667770c22568dcdf5e0857d5f1e59 /gr-digital | |
parent | 22b70d0889ef3c51e27a31ee18d153093a55cbb8 (diff) | |
parent | 98758cbfa9a2aff714952d19e773bc370dfa2185 (diff) |
Merged next into uninstalled import branch.
Diffstat (limited to 'gr-digital')
153 files changed, 9586 insertions, 577 deletions
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt index 49702b627d..3a725b3f4b 100644 --- a/gr-digital/CMakeLists.txt +++ b/gr-digital/CMakeLists.txt @@ -29,11 +29,13 @@ include(GrComponent) GR_REGISTER_COMPONENT("gr-digital" ENABLE_GR_DIGITAL Boost_FOUND ENABLE_VOLK - ENABLE_GR_CORE + ENABLE_GNURADIO_RUNTIME ENABLE_GR_FFT ENABLE_GR_FILTER ENABLE_GR_BLOCKS ENABLE_GR_ANALOG + ENABLE_GR_BLOCKS + ENABLE_GR_FILTER ) GR_SET_GLOBAL(GR_DIGITAL_INCLUDE_DIRS diff --git a/gr-digital/examples/berawgn.py b/gr-digital/examples/berawgn.py index 6f9679d555..7fd1a2337d 100755 --- a/gr-digital/examples/berawgn.py +++ b/gr-digital/examples/berawgn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -91,7 +91,7 @@ class BERAWGNSimu(gr.top_block): self.const = digital.qpsk_constellation() # Source is N_BITS bits, non-repeated data = map(int, numpy.random.randint(0, self.const.arity(), N_BITS/self.const.bits_per_symbol())) - src = gr.vector_source_b(data, False) + src = blocks.vector_source_b(data, False) mod = digital.chunks_to_symbols_bc((self.const.points()), 1) add = blocks.add_vcc() noise = analog.noise_source_c(analog.GR_GAUSSIAN, @@ -99,7 +99,7 @@ class BERAWGNSimu(gr.top_block): RAND_SEED) demod = digital.constellation_decoder_cb(self.const.base()) ber = BitErrors(self.const.bits_per_symbol()) - self.sink = gr.vector_sink_f() + self.sink = blocks.vector_sink_f() self.connect(src, mod, add, demod, ber, self.sink) self.connect(noise, (add, 1)) self.connect(src, (ber, 1)) diff --git a/gr-digital/examples/demod/ber_simulation.grc b/gr-digital/examples/demod/ber_simulation.grc index b216912a6f..d0bec741c3 100644 --- a/gr-digital/examples/demod/ber_simulation.grc +++ b/gr-digital/examples/demod/ber_simulation.grc @@ -537,7 +537,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> diff --git a/gr-digital/examples/demod/digital_freq_lock.grc b/gr-digital/examples/demod/digital_freq_lock.grc index 965768ece3..399d52488d 100644 --- a/gr-digital/examples/demod/digital_freq_lock.grc +++ b/gr-digital/examples/demod/digital_freq_lock.grc @@ -244,7 +244,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -630,7 +630,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> diff --git a/gr-digital/examples/demod/dpsk_loopback.grc b/gr-digital/examples/demod/dpsk_loopback.grc index 9befa69b6c..daa076c47b 100644 --- a/gr-digital/examples/demod/dpsk_loopback.grc +++ b/gr-digital/examples/demod/dpsk_loopback.grc @@ -374,7 +374,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> diff --git a/gr-digital/examples/demod/mpsk_demod.grc b/gr-digital/examples/demod/mpsk_demod.grc index 1045ef5797..c252bb6e4f 100644 --- a/gr-digital/examples/demod/mpsk_demod.grc +++ b/gr-digital/examples/demod/mpsk_demod.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Mon Aug 20 19:51:38 2012</timestamp> + <timestamp>Sun Mar 17 21:08:14 2013</timestamp> <block> <key>options</key> <param> @@ -123,49 +123,6 @@ </param> </block> <block> - <key>digital_dxpsk_mod</key> - <param> - <key>id</key> - <value>digital_dxpsk_mod_0</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>type</key> - <value>dqpsk</value> - </param> - <param> - <key>samples_per_symbol</key> - <value>samps_per_sym</value> - </param> - <param> - <key>excess_bw</key> - <value>0.35</value> - </param> - <param> - <key>mod_code</key> - <value>"gray"</value> - </param> - <param> - <key>verbose</key> - <value>False</value> - </param> - <param> - <key>log</key> - <value>False</value> - </param> - <param> - <key>_coordinate</key> - <value>(361, 119)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> <key>variable</key> <param> <key>id</key> @@ -346,38 +303,58 @@ </param> </block> <block> - <key>channel_model</key> + <key>qtgui_const_sink_x</key> <param> <key>id</key> - <value>channel_model_0</value> + <value>qtgui_const_sink_x_0</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>noise_voltage</key> - <value>noise</value> + <key>type</key> + <value>complex</value> </param> <param> - <key>freq_offset</key> - <value>freq_off</value> + <key>name</key> + <value>QT GUI Plot</value> </param> <param> - <key>epsilon</key> - <value>1.0</value> + <key>size</key> + <value>1024</value> </param> <param> - <key>taps</key> - <value>1.0</value> + <key>ymin</key> + <value>-2</value> </param> <param> - <key>seed</key> - <value>0</value> + <key>ymax</key> + <value>2</value> + </param> + <param> + <key>xmin</key> + <value>-2</value> + </param> + <param> + <key>xmax</key> + <value>2</value> + </param> + <param> + <key>nconnections</key> + <value>1</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>gui_hint</key> + <value>notebook@0</value> </param> <param> <key>_coordinate</key> - <value>(369, 264)</value> + <value>(810, 184)</value> </param> <param> <key>_rotation</key> @@ -385,10 +362,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>qtgui_freq_sink_x</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>qtgui_freq_sink_x_0</value> </param> <param> <key>_enabled</key> @@ -399,16 +376,48 @@ <value>complex</value> </param> <param> - <key>samples_per_second</key> + <key>name</key> + <value>QT GUI Plot</value> + </param> + <param> + <key>fftsize</key> + <value>1024</value> + </param> + <param> + <key>wintype</key> + <value>firdes.WIN_BLACKMAN_hARRIS</value> + </param> + <param> + <key>fc</key> + <value>0</value> + </param> + <param> + <key>bw</key> <value>samp_rate</value> </param> <param> - <key>vlen</key> + <key>ymin</key> + <value>-140</value> + </param> + <param> + <key>ymax</key> + <value>10</value> + </param> + <param> + <key>nconnections</key> <value>1</value> </param> <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>gui_hint</key> + <value>notebook@1</value> + </param> + <param> <key>_coordinate</key> - <value>(597, 142)</value> + <value>(810, 65)</value> </param> <param> <key>_rotation</key> @@ -416,10 +425,10 @@ </param> </block> <block> - <key>qtgui_const_sink_x</key> + <key>digital_dxpsk_mod</key> <param> <key>id</key> - <value>qtgui_const_sink_x_0</value> + <value>digital_dxpsk_mod_0</value> </param> <param> <key>_enabled</key> @@ -427,27 +436,31 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>dqpsk</value> </param> <param> - <key>name</key> - <value>QT GUI Plot</value> + <key>samples_per_symbol</key> + <value>samps_per_sym</value> </param> <param> - <key>size</key> - <value>1024</value> + <key>excess_bw</key> + <value>0.35</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>mod_code</key> + <value>"gray"</value> </param> <param> - <key>gui_hint</key> - <value>notebook@0</value> + <key>verbose</key> + <value>False</value> + </param> + <param> + <key>log</key> + <value>False</value> </param> <param> <key>_coordinate</key> - <value>(810, 184)</value> + <value>(361, 119)</value> </param> <param> <key>_rotation</key> @@ -455,10 +468,10 @@ </param> </block> <block> - <key>qtgui_freq_sink_x</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>qtgui_freq_sink_x_0</value> + <value>blocks_throttle_0</value> </param> <param> <key>_enabled</key> @@ -469,40 +482,55 @@ <value>complex</value> </param> <param> - <key>name</key> - <value>QT GUI Plot</value> + <key>samples_per_second</key> + <value>samp_rate</value> </param> <param> - <key>fftsize</key> - <value>1024</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>wintype</key> - <value>firdes.WIN_BLACKMAN_hARRIS</value> + <key>_coordinate</key> + <value>(597, 142)</value> </param> <param> - <key>fc</key> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>channels_channel_model</key> <param> - <key>bw</key> - <value>samp_rate</value> + <key>id</key> + <value>channels_channel_model_0</value> </param> <param> - <key>rate</key> - <value>10</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>nconnections</key> - <value>1</value> + <key>noise_voltage</key> + <value>noise</value> </param> <param> - <key>gui_hint</key> - <value>notebook@1</value> + <key>freq_offset</key> + <value>freq_off</value> + </param> + <param> + <key>epsilon</key> + <value>1.0</value> + </param> + <param> + <key>taps</key> + <value>1.0 + 1.0j</value> + </param> + <param> + <key>seed</key> + <value>0</value> </param> <param> <key>_coordinate</key> - <value>(810, 65)</value> + <value>(494, 263)</value> </param> <param> <key>_rotation</key> @@ -516,26 +544,26 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>digital_dxpsk_mod_0</source_block_id> - <sink_block_id>channel_model_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>qtgui_freq_sink_x_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>channel_model_0</source_block_id> - <sink_block_id>blocks_throttle_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>qtgui_const_sink_x_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>qtgui_freq_sink_x_0</sink_block_id> + <source_block_id>digital_dxpsk_mod_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_throttle_0</source_block_id> - <sink_block_id>qtgui_const_sink_x_0</sink_block_id> + <source_block_id>channels_channel_model_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> diff --git a/gr-digital/examples/demod/pam_sync.grc b/gr-digital/examples/demod/pam_sync.grc index 4785482e3f..d8497e423d 100644 --- a/gr-digital/examples/demod/pam_sync.grc +++ b/gr-digital/examples/demod/pam_sync.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Tue Jan 15 15:21:49 2013</timestamp> + <timestamp>Sun Mar 17 21:08:58 2013</timestamp> <block> <key>options</key> <param> @@ -228,7 +228,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -1054,7 +1054,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> diff --git a/gr-digital/examples/demod/pam_timing.grc b/gr-digital/examples/demod/pam_timing.grc index 632477821a..50dd8a1c86 100644 --- a/gr-digital/examples/demod/pam_timing.grc +++ b/gr-digital/examples/demod/pam_timing.grc @@ -519,7 +519,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -594,7 +594,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -669,7 +669,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -744,7 +744,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> @@ -819,7 +819,7 @@ </param> <param> <key>trig_mode</key> - <value>gr.gr_TRIG_MODE_AUTO</value> + <value>wxgui.TRIG_MODE_AUTO</value> </param> <param> <key>y_axis_label</key> diff --git a/gr-digital/examples/example_costas.py b/gr-digital/examples/example_costas.py index 726e0756d8..dbb5e42cdf 100755 --- a/gr-digital/examples/example_costas.py +++ b/gr-digital/examples/example_costas.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,8 @@ # from gnuradio import gr, digital, filter +from gnuradio import blocks +from gnuradio import channels from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -47,14 +49,14 @@ class example_costas(gr.top_block): data = 2.0*scipy.random.randint(0, 2, N) - 1.0 data = scipy.exp(1j*poffset) * data - self.src = gr.vector_source_c(data.tolist(), False) + self.src = blocks.vector_source_c(data.tolist(), False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) - self.chn = filter.channel_model(noise, foffset, toffset) + self.chn = channels.channel_model(noise, foffset, toffset) self.cst = digital.costas_loop_cc(bw, 2) - self.vsnk_src = gr.vector_sink_c() - self.vsnk_cst = gr.vector_sink_c() - self.vsnk_frq = gr.vector_sink_f() + self.vsnk_src = blocks.vector_sink_c() + self.vsnk_cst = blocks.vector_sink_c() + self.vsnk_frq = blocks.vector_sink_f() self.connect(self.src, self.rrc, self.chn, self.cst, self.vsnk_cst) self.connect(self.rrc, self.vsnk_src) diff --git a/gr-digital/examples/example_fll.py b/gr-digital/examples/example_fll.py index ef6e1b1658..4fb12f5aae 100755 --- a/gr-digital/examples/example_fll.py +++ b/gr-digital/examples/example_fll.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,8 @@ # from gnuradio import gr, digital, filter +from gnuradio import blocks +from gnuradio import channels from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -47,16 +49,16 @@ class example_fll(gr.top_block): data = 2.0*scipy.random.randint(0, 2, N) - 1.0 data = scipy.exp(1j*poffset) * data - self.src = gr.vector_source_c(data.tolist(), False) + self.src = blocks.vector_source_c(data.tolist(), False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) - self.chn = filter.channel_model(noise, foffset, toffset) + self.chn = channels.channel_model(noise, foffset, toffset) self.fll = digital.fll_band_edge_cc(sps, rolloff, ntaps, bw) - self.vsnk_src = gr.vector_sink_c() - self.vsnk_fll = gr.vector_sink_c() - self.vsnk_frq = gr.vector_sink_f() - self.vsnk_phs = gr.vector_sink_f() - self.vsnk_err = gr.vector_sink_f() + self.vsnk_src = blocks.vector_sink_c() + self.vsnk_fll = blocks.vector_sink_c() + self.vsnk_frq = blocks.vector_sink_f() + self.vsnk_phs = blocks.vector_sink_f() + self.vsnk_err = blocks.vector_sink_f() self.connect(self.src, self.rrc, self.chn, self.fll, self.vsnk_fll) self.connect(self.rrc, self.vsnk_src) diff --git a/gr-digital/examples/example_timing.py b/gr-digital/examples/example_timing.py index d51aebb31d..73a05b05dc 100755 --- a/gr-digital/examples/example_timing.py +++ b/gr-digital/examples/example_timing.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,8 @@ # from gnuradio import gr, digital, filter +from gnuradio import blocks +from gnuradio import channels from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -55,9 +57,9 @@ class example_timing(gr.top_block): data = 2.0*scipy.random.randint(0, 2, N) - 1.0 data = scipy.exp(1j*poffset) * data - self.src = gr.vector_source_c(data.tolist(), False) + self.src = blocks.vector_source_c(data.tolist(), False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) - self.chn = filter.channel_model(noise, foffset, toffset) + self.chn = channels.channel_model(noise, foffset, toffset) self.off = filter.fractional_interpolator_cc(0.20, 1.0) if mode == 0: @@ -66,9 +68,9 @@ class example_timing(gr.top_block): self.taps = self.clk.taps() self.dtaps = self.clk.diff_taps() - self.vsnk_err = gr.vector_sink_f() - self.vsnk_rat = gr.vector_sink_f() - self.vsnk_phs = gr.vector_sink_f() + self.vsnk_err = blocks.vector_sink_f() + self.vsnk_rat = blocks.vector_sink_f() + self.vsnk_phs = blocks.vector_sink_f() self.connect((self.clk,1), self.vsnk_err) self.connect((self.clk,2), self.vsnk_rat) @@ -83,12 +85,12 @@ class example_timing(gr.top_block): mu, gain_mu, omega_rel_lim) - self.vsnk_err = gr.vector_sink_f() + self.vsnk_err = blocks.vector_sink_f() self.connect((self.clk,1), self.vsnk_err) - self.vsnk_src = gr.vector_sink_c() - self.vsnk_clk = gr.vector_sink_c() + self.vsnk_src = blocks.vector_sink_c() + self.vsnk_clk = blocks.vector_sink_c() self.connect(self.src, self.rrc, self.chn, self.off, self.clk, self.vsnk_clk) self.connect(self.off, self.vsnk_src) diff --git a/gr-digital/examples/gen_whitener.py b/gr-digital/examples/gen_whitener.py index 0b1591c3ab..63616605ba 100755 --- a/gr-digital/examples/gen_whitener.py +++ b/gr-digital/examples/gen_whitener.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr, gru +from gnuradio import blocks from gnuradio.eng_option import eng_option from optparse import OptionParser import sys @@ -36,9 +37,9 @@ class my_graph(gr.top_block): parser.print_help() raise SystemExit, 1 - src = gr.lfsr_32k_source_s() - head = gr.head(gr.sizeof_short, 2048) - self.dst = gr.vector_sink_s() + src = blocks.lfsr_32k_source_s() + head = blocks.head(gr.sizeof_short, 2048) + self.dst = blocks.vector_sink_s() self.connect(src, head, self.dst) if __name__ == '__main__': diff --git a/gr-digital/examples/narrowband/benchmark_add_channel.py b/gr-digital/examples/narrowband/benchmark_add_channel.py index 28824dff4b..b614895b63 100755 --- a/gr-digital/examples/narrowband/benchmark_add_channel.py +++ b/gr-digital/examples/narrowband/benchmark_add_channel.py @@ -42,14 +42,14 @@ class my_top_block(gr.top_block): noise_power = power_in_signal/SNR noise_voltage = math.sqrt(noise_power) - self.src = gr.file_source(gr.sizeof_gr_complex, ifile) + self.src = blocks.file_source(gr.sizeof_gr_complex, ifile) #self.throttle = blocks.throttle(gr.sizeof_gr_complex, options.sample_rate) self.channel = filter.channel_model(noise_voltage, frequency_offset, time_offset, noise_seed=-random.randint(0,100000)) self.phase = blocks.multiply_const_cc(complex(math.cos(phase_offset), math.sin(phase_offset))) - self.snk = gr.file_sink(gr.sizeof_gr_complex, ofile) + self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk) diff --git a/gr-digital/examples/narrowband/benchmark_rx.py b/gr-digital/examples/narrowband/benchmark_rx.py index 1962fdc4b0..622773aac5 100755 --- a/gr-digital/examples/narrowband/benchmark_rx.py +++ b/gr-digital/examples/narrowband/benchmark_rx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2010,2011 Free Software Foundation, Inc. +# Copyright 2010,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr, gru +from gnuradio import blocks from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -57,10 +58,10 @@ class my_top_block(gr.top_block): elif(options.from_file is not None): sys.stderr.write(("Reading samples from '%s'.\n\n" % (options.from_file))) - self.source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + self.source = blocks.file_source(gr.sizeof_gr_complex, options.from_file) else: sys.stderr.write("No source defined, pulling samples from null source.\n\n") - self.source = gr.null_source(gr.sizeof_gr_complex) + self.source = blocks.null_source(gr.sizeof_gr_complex) # Set up receive path # do this after for any adjustments to the options that may diff --git a/gr-digital/examples/narrowband/benchmark_tx.py b/gr-digital/examples/narrowband/benchmark_tx.py index 9afacb4952..11ad7ea26e 100755 --- a/gr-digital/examples/narrowband/benchmark_tx.py +++ b/gr-digital/examples/narrowband/benchmark_tx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2010,2011 Free Software Foundation, Inc. +# Copyright 2010,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr +from gnuradio import blocks from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -56,10 +57,10 @@ class my_top_block(gr.top_block): elif(options.to_file is not None): sys.stderr.write(("Saving samples to '%s'.\n\n" % (options.to_file))) - self.sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) + self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) else: sys.stderr.write("No sink defined, dumping samples to null sink.\n\n") - self.sink = gr.null_sink(gr.sizeof_gr_complex) + self.sink = blocks.null_sink(gr.sizeof_gr_complex) # do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py index cc66456e93..c04c76762f 100755 --- a/gr-digital/examples/narrowband/digital_bert_rx.py +++ b/gr-digital/examples/narrowband/digital_bert_rx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2011 Free Software Foundation, Inc. +# Copyright 2008,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -27,6 +27,7 @@ import gnuradio.gr.gr_threading as _threading import sys, time, math from gnuradio import digital +from gnuradio import blocks # from current dir from uhd_interface import uhd_receiver @@ -124,9 +125,9 @@ class rx_psk_block(gr.top_block): options.samples_per_symbol = self._source._sps elif(options.from_file is not None): - self._source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + self._source = blocks.file_source(gr.sizeof_gr_complex, options.from_file) else: - self._source = gr.null_source(gr.sizeof_gr_complex) + self._source = blocks.null_source(gr.sizeof_gr_complex) # Create the BERT receiver self._receiver = bert_receiver(options.bitrate, diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py index 3be9d68f87..6859d2e7af 100755 --- a/gr-digital/examples/narrowband/digital_bert_tx.py +++ b/gr-digital/examples/narrowband/digital_bert_tx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2011 Free Software Foundation, Inc. +# Copyright 2008,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -43,7 +43,7 @@ class bert_transmit(gr.hier_block2): gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Input signature # Create BERT data bit stream - self._bits = gr.vector_source_b([1,], True) # Infinite stream of ones + self._bits = blocks.vector_source_b([1,], True) # Infinite stream of ones self._scrambler = digital.scrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit scrambler self._mod = digital.generic_mod(constellation, differential, @@ -78,9 +78,9 @@ class tx_psk_block(gr.top_block): options.samples_per_symbol = self._sink._sps elif(options.to_file is not None): - self._sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) + self._sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) else: - self._sink = gr.null_sink(gr.sizeof_gr_complex) + self._sink = blocks.null_sink(gr.sizeof_gr_complex) self._transmitter = bert_transmit(self._modulator._constellation, diff --git a/gr-digital/examples/narrowband/rx_voice.py b/gr-digital/examples/narrowband/rx_voice.py index f5d12b5689..8a0e9844be 100755 --- a/gr-digital/examples/narrowband/rx_voice.py +++ b/gr-digital/examples/narrowband/rx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2009,2011 Free Software Foundation, Inc. +# Copyright 2005,2006,2009,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,6 +21,7 @@ # from gnuradio import gr, audio, uhd +from gnuradio import blocks from gnuradio import filter from gnuradio import eng_notation from gnuradio.eng_option import eng_option @@ -83,12 +84,12 @@ class my_top_block(gr.top_block): elif(options.from_file is not None): self.thr = blocks.throttle(gr.sizeof_gr_complex, options.bitrate) - self.source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + self.source = blocks.file_source(gr.sizeof_gr_complex, options.from_file) self.connect(self.source, self.thr, self.rxpath) else: self.thr = blocks.throttle(gr.sizeof_gr_complex, 1e6) - self.source = gr.null_source(gr.sizeof_gr_complex) + self.source = blocks.null_source(gr.sizeof_gr_complex) self.connect(self.source, self.thr, self.rxpath) self.connect(self.audio_tx) diff --git a/gr-digital/examples/narrowband/tx_voice.py b/gr-digital/examples/narrowband/tx_voice.py index 3fc4fa46f3..afdb4406e6 100755 --- a/gr-digital/examples/narrowband/tx_voice.py +++ b/gr-digital/examples/narrowband/tx_voice.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005-2007,2009,2011 Free Software Foundation, Inc. +# Copyright 2005-2007,2009,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -80,10 +80,10 @@ class my_top_block(gr.top_block): rrate = usrp_rate / audio_rate elif(options.to_file is not None): - self.sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) + self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) rrate = 1 else: - self.sink = gr.null_sink(gr.sizeof_gr_complex) + self.sink = blocks.null_sink(gr.sizeof_gr_complex) rrate = 1 self.resampler = filter.pfb.arb_resampler_ccf(rrate) diff --git a/gr-digital/examples/ofdm/benchmark_add_channel.py b/gr-digital/examples/ofdm/benchmark_add_channel.py index 0d17efd052..f97214f78d 100755 --- a/gr-digital/examples/ofdm/benchmark_add_channel.py +++ b/gr-digital/examples/ofdm/benchmark_add_channel.py @@ -44,14 +44,14 @@ class my_top_block(gr.top_block): frequency_offset = options.frequency_offset / options.fft_length - self.src = gr.file_source(gr.sizeof_gr_complex, ifile) + self.src = blocks.file_source(gr.sizeof_gr_complex, ifile) #self.throttle = blocks.throttle(gr.sizeof_gr_complex, options.sample_rate) self.channel = filter.channel_model(noise_voltage, frequency_offset, time_offset, noise_seed=-random.randint(0,100000)) self.phase = blocks.multiply_const_cc(complex(math.cos(phase_offset), math.sin(phase_offset))) - self.snk = gr.file_sink(gr.sizeof_gr_complex, ofile) + self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk) diff --git a/gr-digital/examples/ofdm/benchmark_rx.py b/gr-digital/examples/ofdm/benchmark_rx.py index f1b65276d0..dbcd866ad2 100755 --- a/gr-digital/examples/ofdm/benchmark_rx.py +++ b/gr-digital/examples/ofdm/benchmark_rx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2011 Free Software Foundation, Inc. +# Copyright 2006,2007,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,6 +25,7 @@ from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser +from gnuradio import blocks from gnuradio import digital # from current dir @@ -44,9 +45,9 @@ class my_top_block(gr.top_block): options.spec, options.antenna, options.verbose) elif(options.from_file is not None): - self.source = gr.file_source(gr.sizeof_gr_complex, options.from_file) + self.source = blocks.file_source(gr.sizeof_gr_complex, options.from_file) else: - self.source = gr.null_source(gr.sizeof_gr_complex) + self.source = blocks.null_source(gr.sizeof_gr_complex) # Set up receive path # do this after for any adjustments to the options that may diff --git a/gr-digital/examples/ofdm/benchmark_tx.py b/gr-digital/examples/ofdm/benchmark_tx.py index 5962fe7ecb..2942178ccf 100755 --- a/gr-digital/examples/ofdm/benchmark_tx.py +++ b/gr-digital/examples/ofdm/benchmark_tx.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005,2006,2011 Free Software Foundation, Inc. +# Copyright 2005,2006,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -27,6 +27,7 @@ from optparse import OptionParser import time, struct, sys from gnuradio import digital +from gnuradio import blocks # from current dir from transmit_path import transmit_path @@ -43,9 +44,9 @@ class my_top_block(gr.top_block): options.spec, options.antenna, options.verbose) elif(options.to_file is not None): - self.sink = gr.file_sink(gr.sizeof_gr_complex, options.to_file) + self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) else: - self.sink = gr.null_sink(gr.sizeof_gr_complex) + self.sink = blocks.null_sink(gr.sizeof_gr_complex) # do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) diff --git a/gr-digital/examples/ofdm/rx_ofdm.grc b/gr-digital/examples/ofdm/rx_ofdm.grc new file mode 100644 index 0000000000..47e165508c --- /dev/null +++ b/gr-digital/examples/ofdm/rx_ofdm.grc @@ -0,0 +1,1092 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Thu Feb 14 15:49:35 2013</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>rx_ofdm</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value>OFDM Rx</value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value>Example of an OFDM receiver</value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>wx_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(0, -1)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_symbols_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((100,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(762, 64)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_carriers</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((0,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(557, 64)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>header_formatter</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_name)</value> + </param> + <param> + <key>_coordinate</key> + <value>(876, 64)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_symbols</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((100,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(659, 64)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>occupied_carriers</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(404, 64)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>analog_noise_source_x</key> + <param> + <key>id</key> + <value>analog_noise_source_x_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> + </param> + <param> + <key>amp</key> + <value>1</value> + </param> + <param> + <key>seed</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(-1, 185)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_sync_sc_cfb</key> + <param> + <key>id</key> + <value>digital_ofdm_sync_sc_cfb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>cp_len</key> + <value>fft_len/4</value> + </param> + <param> + <key>_coordinate</key> + <value>(368, 178)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>analog_frequency_modulator_fc</key> + <param> + <key>id</key> + <value>analog_frequency_modulator_fc_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>sensitivity</key> + <value>-2.0/fft_len</value> + </param> + <param> + <key>_coordinate</key> + <value>(692, 175)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_multiply_xx</key> + <param> + <key>id</key> + <value>blocks_multiply_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>num_inputs</key> + <value>2</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(885, 223)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_delay</key> + <param> + <key>id</key> + <value>blocks_delay_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>delay</key> + <value>fft_len+fft_len/4</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(368, 253)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>3200000</value> + </param> + <param> + <key>_coordinate</key> + <value>(0, 91)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>from gnuradio.digital.utils import tagged_streams</value> + </param> + <param> + <key>_coordinate</key> + <value>(163, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>sync_word</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>[0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0]</value> + </param> + <param> + <key>_coordinate</key> + <value>(165, 46)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>header_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.constellation_bpsk()</value> + </param> + <param> + <key>_coordinate</key> + <value>(655, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>payload_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.constellation_qpsk()</value> + </param> + <param> + <key>_coordinate</key> + <value>(813, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>n_sync_symbols</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(168, 108)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(181, 200)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_constellation_decoder_cb</key> + <param> + <key>id</key> + <value>digital_constellation_decoder_cb_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>constellation</key> + <value>header_mod.base()</value> + </param> + <param> + <key>_coordinate</key> + <value>(854, 343)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_frame_equalizer_vcvc</key> + <param> + <key>id</key> + <value>digital_ofdm_frame_equalizer_vcvc_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>equalizer</key> + <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols).base()</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_name</value> + </param> + <param> + <key>propagate_channel_state</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(421, 320)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_packet_headerparser_b</key> + <param> + <key>id</key> + <value>digital_packet_headerparser_b_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>header_formatter</key> + <value>header_formatter.formatter()</value> + </param> + <param> + <key>_coordinate</key> + <value>(651, 466)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>fft_vxx</key> + <param> + <key>id</key> + <value>fft_vxx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>fft_size</key> + <value>fft_len</value> + </param> + <param> + <key>forward</key> + <value>True</value> + </param> + <param> + <key>window</key> + <value></value> + </param> + <param> + <key>shift</key> + <value>True</value> + </param> + <param> + <key>nthreads</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(53, 429)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>fft_len</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>64</value> + </param> + <param> + <key>_coordinate</key> + <value>(301, -1)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>length_tag_name</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>"frame_len"</value> + </param> + <param> + <key>_coordinate</key> + <value>(367, -1)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_constellation_decoder_cb</key> + <param> + <key>id</key> + <value>digital_constellation_decoder_cb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>constellation</key> + <value>payload_mod.base()</value> + </param> + <param> + <key>_coordinate</key> + <value>(718, 635)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_null_sink</key> + <param> + <key>id</key> + <value>blocks_null_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(938, 638)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_frame_equalizer_vcvc</key> + <param> + <key>id</key> + <value>digital_ofdm_frame_equalizer_vcvc_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>equalizer</key> + <value>digital.ofdm_equalizer_simpledfe(fft_len, header_mod.base(), occupied_carriers, pilot_carriers, pilot_symbols, n_sync_symbols).base()</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_key</value> + </param> + <param> + <key>propagate_channel_state</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(265, 612)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>fft_vxx</key> + <param> + <key>id</key> + <value>fft_vxx_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>fft_size</key> + <value>fft_len</value> + </param> + <param> + <key>forward</key> + <value>True</value> + </param> + <param> + <key>window</key> + <value></value> + </param> + <param> + <key>shift</key> + <value>True</value> + </param> + <param> + <key>nthreads</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(57, 605)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_serializer_vcc</key> + <param> + <key>id</key> + <value>digital_ofdm_serializer_vcc_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>occupied_carriers</key> + <value>occupied_carriers</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_name</value> + </param> + <param> + <key>packet_len_tag_key</key> + <value>""</value> + </param> + <param> + <key>symbols_skipped</key> + <value>0</value> + </param> + <param> + <key>input_is_shifted</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(649, 305)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_serializer_vcc</key> + <param> + <key>id</key> + <value>digital_ofdm_serializer_vcc_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>occupied_carriers</key> + <value>occupied_carriers</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_key</value> + </param> + <param> + <key>packet_len_tag_key</key> + <value>""</value> + </param> + <param> + <key>symbols_skipped</key> + <value>1</value> + </param> + <param> + <key>input_is_shifted</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(496, 597)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_ofdm_chanest_vcvc</key> + <param> + <key>id</key> + <value>digital_ofdm_chanest_vcvc_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>sync_symbol1</key> + <value>sync_word</value> + </param> + <param> + <key>sync_symbol2</key> + <value>()</value> + </param> + <param> + <key>n_data_symbols</key> + <value>n_sync_symbols</value> + </param> + <param> + <key>eq_noise_red_len</key> + <value>0</value> + </param> + <param> + <key>max_carr_offset</key> + <value>-1</value> + </param> + <param> + <key>force_one_symbol</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(52, 305)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_header_payload_demux</key> + <param> + <key>id</key> + <value>digital_header_payload_demux_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>header_len</key> + <value>2</value> + </param> + <param> + <key>items_per_symbol</key> + <value>fft_len</value> + </param> + <param> + <key>guard_interval</key> + <value>fft_len/4</value> + </param> + <param> + <key>length_tag_key</key> + <value>length_tag_name</value> + </param> + <param> + <key>trigger_tag_key</key> + <value>""</value> + </param> + <param> + <key>output_symbols</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>_coordinate</key> + <value>(340, 461)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <connection> + <source_block_id>fft_vxx_0</source_block_id> + <sink_block_id>digital_ofdm_chanest_vcvc_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>analog_frequency_modulator_fc_0</source_block_id> + <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id> + <sink_block_id>analog_frequency_modulator_fc_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>analog_noise_source_x_0</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>digital_ofdm_sync_sc_cfb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_delay_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_delay_0</source_block_id> + <sink_block_id>blocks_multiply_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>digital_constellation_decoder_cb_0_0</source_block_id> + <sink_block_id>digital_packet_headerparser_b_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_serializer_vcc_0</source_block_id> + <sink_block_id>digital_constellation_decoder_cb_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_sync_sc_cfb_0</source_block_id> + <sink_block_id>digital_header_payload_demux_0</sink_block_id> + <source_key>1</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_chanest_vcvc_0</source_block_id> + <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_frame_equalizer_vcvc_0_0</source_block_id> + <sink_block_id>digital_ofdm_serializer_vcc_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_packet_headerparser_b_0</source_block_id> + <sink_block_id>digital_header_payload_demux_0</sink_block_id> + <source_key>0</source_key> + <sink_key>2</sink_key> + </connection> + <connection> + <source_block_id>digital_header_payload_demux_0</source_block_id> + <sink_block_id>fft_vxx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_header_payload_demux_0</source_block_id> + <sink_block_id>fft_vxx_0_0</sink_block_id> + <source_key>1</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_multiply_xx_0</source_block_id> + <sink_block_id>digital_header_payload_demux_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_constellation_decoder_cb_0</source_block_id> + <sink_block_id>blocks_null_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_frame_equalizer_vcvc_0</source_block_id> + <sink_block_id>digital_ofdm_serializer_vcc_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_serializer_vcc_1</source_block_id> + <sink_block_id>digital_constellation_decoder_cb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fft_vxx_0_0</source_block_id> + <sink_block_id>digital_ofdm_frame_equalizer_vcvc_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gr-digital/examples/ofdm/tx_ofdm.grc b/gr-digital/examples/ofdm/tx_ofdm.grc new file mode 100644 index 0000000000..a2deb05f9f --- /dev/null +++ b/gr-digital/examples/ofdm/tx_ofdm.grc @@ -0,0 +1,1143 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Tue Feb 5 14:47:32 2013</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>tx_ofdm</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value>OFDM Tx</value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value>Example of an OFDM Transmitter</value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>no_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>run</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(0, -1)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>from gnuradio.digital.utils import tagged_streams</value> + </param> + <param> + <key>_coordinate</key> + <value>(164, 45)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>length_tag_name</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>"packet_len"</value> + </param> + <param> + <key>_coordinate</key> + <value>(399, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_symbols_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((100,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(735, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>occupied_carriers</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>(range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(377, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_symbols</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((100,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(632, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>pilot_carriers</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>((0,),)</value> + </param> + <param> + <key>_coordinate</key> + <value>(530, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>fft_len</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>64</value> + </param> + <param> + <key>_coordinate</key> + <value>(311, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>header_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.constellation_bpsk()</value> + </param> + <param> + <key>_coordinate</key> + <value>(620, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>payload_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.constellation_qpsk()</value> + </param> + <param> + <key>_coordinate</key> + <value>(783, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>samples_per_second</key> + <value>bit_rate/8</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(234, 167)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import numpy</value> + </param> + <param> + <key>_coordinate</key> + <value>(164, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import random</value> + </param> + <param> + <key>_coordinate</key> + <value>(-1, 90)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>sync_word</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>[0, 0, 0, 0, 0, 0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, -1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, 1.0, 0, -1.0, 0, 1.0, 0, -1.0, 0, 0, 0, 0, 0, 0]</value> + </param> + <param> + <key>_coordinate</key> + <value>(95, 90)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>rolloff</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(234, 91)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>header_formatter</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>digital.packet_header_ofdm(occupied_carriers, 1, length_tag_name)</value> + </param> + <param> + <key>_coordinate</key> + <value>(849, 63)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>vector</key> + <value>range(packet_len)</value> + </param> + <param> + <key>tags</key> + <value>tagged_streams.make_lengthtags((packet_len,), (0,), length_tag_name)</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(-1, 152)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>packet_len</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>96</value> + </param> + <param> + <key>_coordinate</key> + <value>(528, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>digital_packet_headergenerator_bb</key> + <param> + <key>id</key> + <value>digital_packet_headergenerator_bb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>header_formatter</key> + <value>header_formatter.formatter()</value> + </param> + <param> + <key>_coordinate</key> + <value>(761, 167)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>bit_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>3200000</value> + </param> + <param> + <key>_coordinate</key> + <value>(311, 0)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_repack_bits_bb</key> + <param> + <key>id</key> + <value>blocks_repack_bits_bb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>k</key> + <value>8</value> + </param> + <param> + <key>l</key> + <value>payload_mod.bits_per_symbol()</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_name</value> + </param> + <param> + <key>align_output</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(516, 228)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> + <param> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>in_type</key> + <value>byte</value> + </param> + <param> + <key>out_type</key> + <value>complex</value> + </param> + <param> + <key>symbol_table</key> + <value>payload_mod.points()</value> + </param> + <param> + <key>dimension</key> + <value>1</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(279, 243)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>digital_chunks_to_symbols_xx</key> + <param> + <key>id</key> + <value>digital_chunks_to_symbols_xx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>in_type</key> + <value>byte</value> + </param> + <param> + <key>out_type</key> + <value>complex</value> + </param> + <param> + <key>symbol_table</key> + <value>header_mod.points()</value> + </param> + <param> + <key>dimension</key> + <value>1</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(319, 305)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>blocks_tagged_stream_mux</key> + <param> + <key>id</key> + <value>blocks_tagged_stream_mux_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>ninputs</key> + <value>2</value> + </param> + <param> + <key>lengthtagname</key> + <value>length_tag_name</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(44, 254)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>digital_ofdm_carrier_allocator_cvc</key> + <param> + <key>id</key> + <value>digital_ofdm_carrier_allocator_cvc_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>fft_len</key> + <value>fft_len</value> + </param> + <param> + <key>occupied_carriers</key> + <value>occupied_carriers</value> + </param> + <param> + <key>pilot_carriers</key> + <value>pilot_carriers</value> + </param> + <param> + <key>pilot_symbols</key> + <value>pilot_symbols</value> + </param> + <param> + <key>len_tag_key</key> + <value>length_tag_name</value> + </param> + <param> + <key>_coordinate</key> + <value>(56, 453)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>sync_word_source</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>vector</key> + <value>numpy.array(sync_word) * numpy.sqrt(2)</value> + </param> + <param> + <key>tags</key> + <value>tagged_streams.make_lengthtags((len(sync_word)/fft_len,), (0,), length_tag_name)</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>fft_len</value> + </param> + <param> + <key>_coordinate</key> + <value>(56, 356)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_tagged_stream_mux</key> + <param> + <key>id</key> + <value>blocks_tagged_stream_mux_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>ninputs</key> + <value>2</value> + </param> + <param> + <key>lengthtagname</key> + <value>length_tag_name</value> + </param> + <param> + <key>vlen</key> + <value>fft_len</value> + </param> + <param> + <key>_coordinate</key> + <value>(374, 382)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>fft_vxx</key> + <param> + <key>id</key> + <value>fft_vxx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>fft_size</key> + <value>fft_len</value> + </param> + <param> + <key>forward</key> + <value>False</value> + </param> + <param> + <key>window</key> + <value></value> + </param> + <param> + <key>shift</key> + <value>False</value> + </param> + <param> + <key>nthreads</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(765, 498)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>digital_ofdm_cyclic_prefixer</key> + <param> + <key>id</key> + <value>digital_ofdm_cyclic_prefixer_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>input_size</key> + <value>fft_len</value> + </param> + <param> + <key>output_size</key> + <value>fft_len+fft_len/4</value> + </param> + <param> + <key>rolloff</key> + <value>rolloff</value> + </param> + <param> + <key>tagname</key> + <value>length_tag_name</value> + </param> + <param> + <key>_coordinate</key> + <value>(488, 505)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>wxgui_fftsink2_0</value> + </param> + <param> + <key>_enabled</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>FFT Plot</value> + </param> + <param> + <key>samp_rate</key> + <value>1.0</value> + </param> + <param> + <key>baseband_freq</key> + <value>0</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>50</value> + </param> + <param> + <key>ref_scale</key> + <value>2.0</value> + </param> + <param> + <key>fft_size</key> + <value>1024</value> + </param> + <param> + <key>fft_rate</key> + <value>15</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>win</key> + <value>None</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value></value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>freqvar</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(291, 460)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>blocks_null_sink</key> + <param> + <key>id</key> + <value>blocks_null_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(438, 633)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>digital_crc32_bb</key> + <param> + <key>id</key> + <value>digital_crc32_bb_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>check</key> + <value>False</value> + </param> + <param> + <key>lengthtagname</key> + <value>length_tag_name</value> + </param> + <param> + <key>_coordinate</key> + <value>(472, 159)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_tag_debug</key> + <param> + <key>id</key> + <value>blocks_tag_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>name</key> + <value>tdb</value> + </param> + <param> + <key>num_inputs</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>display</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(819, 232)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>blocks_vector_source_x_1</source_block_id> + <sink_block_id>blocks_throttle_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>digital_crc32_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>digital_packet_headergenerator_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_tagged_stream_mux_0</source_block_id> + <sink_block_id>digital_ofdm_carrier_allocator_cvc_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_carrier_allocator_cvc_0</source_block_id> + <sink_block_id>blocks_tagged_stream_mux_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>sync_word_source</source_block_id> + <sink_block_id>blocks_tagged_stream_mux_1</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_packet_headergenerator_bb_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_repack_bits_bb_0</source_block_id> + <sink_block_id>digital_chunks_to_symbols_xx_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_chunks_to_symbols_xx_0</source_block_id> + <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_chunks_to_symbols_xx_0_0</source_block_id> + <sink_block_id>blocks_tagged_stream_mux_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>blocks_repack_bits_bb_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_tagged_stream_mux_1</source_block_id> + <sink_block_id>fft_vxx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id> + <sink_block_id>wxgui_fftsink2_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fft_vxx_0</source_block_id> + <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id> + <sink_block_id>blocks_null_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>digital_crc32_bb_0</source_block_id> + <sink_block_id>blocks_tag_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gr-digital/examples/snr_estimators.py b/gr-digital/examples/snr_estimators.py index e310ec2937..9eae7865e5 100755 --- a/gr-digital/examples/snr_estimators.py +++ b/gr-digital/examples/snr_estimators.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -36,6 +36,8 @@ except ImportError: sys.exit(1) from gnuradio import gr, digital, filter +from gnuradio import blocks +from gnuradio import channels from optparse import OptionParser from gnuradio.eng_option import eng_option @@ -165,10 +167,10 @@ def main(): snrdB, snr = py_est(yy) snr_python.append(snrdB) - gr_src = gr.vector_source_c(bits.tolist(), False) + gr_src = blocks.vector_source_c(bits.tolist(), False) gr_snr = digital.mpsk_snr_est_cc(gr_est, ntag, 0.001) - gr_chn = filter.channel_model(1.0/scale) - gr_snk = gr.null_sink(gr.sizeof_gr_complex) + gr_chn = channels.channel_model(1.0/scale) + gr_snk = blocks.null_sink(gr.sizeof_gr_complex) tb = gr.top_block() tb.connect(gr_src, gr_chn, gr_snr, gr_snk) tb.run() diff --git a/gr-digital/gnuradio-digital.pc.in b/gr-digital/gnuradio-digital.pc.in index 6c0a7ccf8e..9c7247c755 100644 --- a/gr-digital/gnuradio-digital.pc.in +++ b/gr-digital/gnuradio-digital.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: gnuradio-digital Description: GNU Radio blocks for digital communications -Requires: gnuradio-core +Requires: gnuradio-runtime Version: @LIBVER@ Libs: -L${libdir} -lgnuradio-digital Cflags: -I${includedir} diff --git a/gr-digital/grc/CMakeLists.txt b/gr-digital/grc/CMakeLists.txt index bace20847f..9888247ca2 100644 --- a/gr-digital/grc/CMakeLists.txt +++ b/gr-digital/grc/CMakeLists.txt @@ -18,4 +18,6 @@ # Boston, MA 02110-1301, USA. file(GLOB xml_files "*.xml") -install(FILES ${xml_files} DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "digital_python") +install(FILES ${xml_files} + DESTINATION ${GRC_BLOCKS_DIR} COMPONENT "digital_python" +) diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml index 04c679d355..762ac66538 100644 --- a/gr-digital/grc/digital_block_tree.xml +++ b/gr-digital/grc/digital_block_tree.xml @@ -1,7 +1,6 @@ <?xml version="1.0"?> - <!-- - Copyright 2011 Free Software Foundation, Inc. + Copyright 2011,2012 Free Software Foundation, Inc. This file is part of GNU Radio @@ -31,8 +30,35 @@ <cat> <name>Coding</name> <block>digital_additive_scrambler_bb</block> - <block>digital_descrambler_bb</block> <block>digital_scrambler_bb</block> + <block>digital_descrambler_bb</block> + <block>digital_binary_slicer_fb</block> + <block>digital_bytes_to_syms</block> + <block>digital_chunks_to_symbols_xx</block> + <block>digital_clock_recovery_mm_xx</block> + <block>digital_cma_equalizer_cc</block> + <block>digital_constellation_decoder_cb</block> + <block>digital_constellation_receiver_cb</block> + <block>digital_correlate_access_code_bb</block> + <block>digital_costas_loop_cc</block> + <block>digital_crc32_bb</block> + <block>digital_descrambler_bb</block> + <block>digital_fll_band_edge_cc</block> + <block>digital_glfsr_source_x</block> + <block>digital_header_payload_demux</block> + <block>digital_kurtotic_equalizer_cc</block> + <block>digital_lms_dd_equalizer_cc</block> + <block>digital_map_bb</block> + <block>digital_mpsk_receiver_cc</block> + <block>digital_mpsk_snr_est_cc</block> + <block>digital_packet_headergenerator_bb</block> + <block>digital_packet_headergenerator_bb_default</block> + <block>digital_packet_headerparser_b</block> + <block>digital_packet_headerparser_b_default</block> + <block>digital_pfb_clock_sync_xxx</block> + <block>digital_pn_correlator_cc</block> + <block>digital_probe_density_b</block> + <block>digital_probe_mpsk_snr_est_c</block> </cat> <cat> <name>Converters</name> @@ -92,14 +118,20 @@ <block>digital_gmsk_demod</block> </cat> <cat> - <name>OFDM</name> + <name>OFDM</name> <block>digital_ofdm_mod</block> + <block>digital_ofdm_mod2</block> <block>digital_ofdm_demod</block> + <block>digital_ofdm_carrier_allocator_cvc</block> + <block>digital_ofdm_chanest_vcvc</block> <block>digital_ofdm_cyclic_prefixer</block> <block>digital_ofdm_frame_acquisition</block> <block>digital_ofdm_frame_sink</block> + <block>digital_ofdm_frame_equalizer_vcvc</block> <block>digital_ofdm_insert_preamble</block> <block>digital_ofdm_sampler</block> + <block>digital_ofdm_serializer_vcc</block> <block>digital_ofdm_sync_pn</block> + <block>digital_ofdm_sync_sc_cfb</block> </cat> </cat> diff --git a/gr-digital/grc/digital_crc32_bb.xml b/gr-digital/grc/digital_crc32_bb.xml new file mode 100644 index 0000000000..d60f08f814 --- /dev/null +++ b/gr-digital/grc/digital_crc32_bb.xml @@ -0,0 +1,33 @@ +<block> + <name>Stream CRC32</name> + <key>digital_crc32_bb</key> + <import>from gnuradio import digital</import> + <make>digital.crc32_bb($check, $lengthtagname)</make> + <param> + <name>Mode</name> + <key>check</key> + <type>enum</type> + <option> + <name>Generate CRC</name> + <key>False</key> + </option> + <option> + <name>Check CRC</name> + <key>True</key> + </option> + </param> + <param> + <name>Length tag name</name> + <key>lengthtagname</key> + <value>"packet_len"</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>byte</type> + </source> +</block> diff --git a/gr-digital/grc/digital_header_payload_demux.xml b/gr-digital/grc/digital_header_payload_demux.xml new file mode 100644 index 0000000000..b29d86435b --- /dev/null +++ b/gr-digital/grc/digital_header_payload_demux.xml @@ -0,0 +1,94 @@ +<block> + <name>Header payload demux</name> + <key>digital_header_payload_demux</key> + <import>from gnuradio import digital</import> + <make>digital.header_payload_demux($header_len, $items_per_symbol, $guard_interval, $length_tag_key, $trigger_tag_key, $output_symbols, $(type.itemsize))</make> + <param> + <name>Header Length (Symbols)</name> + <key>header_len</key> + <type>int</type> + </param> + <param> + <name>Items per symbol</name> + <key>items_per_symbol</key> + <type>int</type> + </param> + <param> + <name>Guard Interval (items)</name> + <key>guard_interval</key> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Length tag key</name> + <key>length_tag_key</key> + <value>"frame_len"</value> + <type>string</type> + </param> + <param> + <name>Trigger tag key</name> + <key>trigger_tag_key</key> + <value>""</value> + <type>string</type> + </param> + <param> + <name>Output Format</name> + <key>output_symbols</key> + <type>enum</type> + <option> + <name>Items</name> + <key>False</key> + </option> + <option> + <name>Symbols</name> + <key>True</key> + </option> + </param> + <param> + <name>IO Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>itemsize:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>itemsize:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>itemsize:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>itemsize:gr.sizeof_short</opt> + </option> + </param> + <sink> + <name>in</name> + <type>$type</type> + </sink> + <sink> + <name>trigger</name> + <type>byte</type> + </sink> + <sink> + <name>header_data</name> + <type>message</type> + </sink> + <source> + <name>out_hdr</name> + <type>$type</type> + <vlen>{True: $items_per_symbol, False: 1}[$output_symbols]</vlen> + </source> + <source> + <name>out_payload</name> + <type>$type</type> + <vlen>{True: $items_per_symbol, False: 1}[$output_symbols]</vlen> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml new file mode 100644 index 0000000000..b9bdde543d --- /dev/null +++ b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<block> + <name>OFDM Carrier Allocator</name> + <key>digital_ofdm_carrier_allocator_cvc</key> + <import>from gnuradio import digital</import> + <make>digital.ofdm_carrier_allocator_cvc($fft_len, $occupied_carriers, $pilot_carriers, $pilot_symbols, $sync_words, $len_tag_key)</make> + <param> + <name>FFT length</name> + <key>fft_len</key> + <value>fft_len</value> + <type>int</type> + </param> + <param> + <name>Occupied Carriers</name> + <key>occupied_carriers</key> + <type>raw</type> + </param> + <param> + <name>Pilot Carriers</name> + <key>pilot_carriers</key> + <value>()</value> + <type>raw</type> + </param> + <param> + <name>Pilot Symbols</name> + <key>pilot_symbols</key> + <value>()</value> + <type>raw</type> + </param> + <param> + <name>Sync Words</name> + <key>sync_words</key> + <value>()</value> + <type>raw</type> + </param> + <param> + <name>Length tag key</name> + <key>len_tag_key</key> + <value>"packet_len"</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$fft_len</vlen> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_chanest_vcvc.xml b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml new file mode 100644 index 0000000000..e8b1571eb6 --- /dev/null +++ b/gr-digital/grc/digital_ofdm_chanest_vcvc.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<block> + <name>OFDM channel & coarse frequency offset estimation</name> + <key>digital_ofdm_chanest_vcvc</key> + <import>from gnuradio import digital</import> + <make>digital.ofdm_chanest_vcvc($sync_symbol1, $sync_symbol2, $n_data_symbols, $eq_noise_red_len, $max_carr_offset, $force_one_symbol)</make> + <param> + <name>Synchronisation preamble symbol 1</name> + <key>sync_symbol1</key> + <type>complex_vector</type> + </param> + <param> + <name>Synchronisation preamble symbol 2</name> + <key>sync_symbol2</key> + <value>()</value> + <type>complex_vector</type> + </param> + <param> + <name>Number of data symbols</name> + <key>n_data_symbols</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Channel taps noise reduction length</name> + <key>eq_noise_red_len</key> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Maximum carrier offset</name> + <key>max_carr_offset</key> + <value>-1</value> + <type>int</type> + </param> + <param> + <name>Force One Synchronisation Symbol</name> + <key>force_one_symbol</key> + <type>enum</type> + <option> + <name>No</name> + <key>False</key> + </option> + <option> + <name>Yes</name> + <key>True</key> + </option> + </param> + <check>len($sync_symbol1)</check> + <check>len($sync_symbol2) == 0 or len($sync_symbol2) == len($sync_symbol1)</check> + <sink> + <name>in</name> + <type>complex</type> + <vlen>len($sync_symbol1)</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>len($sync_symbol1)</vlen> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml b/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml index d5e5d38940..80bf339cbe 100644 --- a/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml +++ b/gr-digital/grc/digital_ofdm_cyclic_prefixer.xml @@ -29,17 +29,31 @@ <name>OFDM Cyclic Prefixer</name> <key>digital_ofdm_cyclic_prefixer</key> <import>from gnuradio import digital</import> - <make>digital.ofdm_cyclic_prefixer($input_size, $output_size)</make> + <make>digital.ofdm_cyclic_prefixer($input_size, $output_size, $rolloff, $tagname)</make> <param> - <name>Input Size</name> + <name>FFT Length</name> <key>input_size</key> + <value>fft_len</value> <type>int</type> </param> <param> - <name>Output Size</name> + <name>Output Size (FFT length + CP length)</name> <key>output_size</key> + <value>fft_len+fft_len/4</value> <type>int</type> </param> + <param> + <name>Rolloff</name> + <key>rolloff</key> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Length Tag Key</name> + <key>tagname</key> + <value>"frame_len"</value> + <type>string</type> + </param> <sink> <name>in</name> <type>complex</type> diff --git a/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml new file mode 100644 index 0000000000..330b29a2fb --- /dev/null +++ b/gr-digital/grc/digital_ofdm_frame_equalizer_vcvc.xml @@ -0,0 +1,45 @@ +<block> + <name>OFDM Frame Equalizer</name> + <key>digital_ofdm_frame_equalizer_vcvc</key> + <import>from gnuradio import digital</import> + <make>digital.ofdm_frame_equalizer_vcvc($equalizer, $len_tag_key, $propagate_channel_state)</make> + <param> + <name>FFT length</name> + <key>fft_len</key> + <value>fft_len</value> + <type>int</type> + </param> + <param> + <name>Equalizer</name> + <key>equalizer</key> + <type>raw</type> + </param> + <param> + <name>Length Tag Key</name> + <key>len_tag_key</key> + <type>string</type> + </param> + <param> + <name>Propagate Channel State</name> + <key>propagate_channel_state</key> + <type>enum</type> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$fft_len</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$fft_len</vlen> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_mod2.xml b/gr-digital/grc/digital_ofdm_mod2.xml new file mode 100644 index 0000000000..7de9ff7865 --- /dev/null +++ b/gr-digital/grc/digital_ofdm_mod2.xml @@ -0,0 +1,65 @@ +<block> + <name>OFDM Mod 2</name> + <key>digital_ofdm_mod2</key> + <category>OFDM</category> + <import>from gnuradio import digital</import> + <make>digital.ofdm_mod2(fft_len=$fft_len, + cp_len=$cp_len, + length_tag_name=$length_tag_name, + occupied_carriers=$occupied_carriers, + pilot_carriers=$pilot_carriers, + pilot_symbols=$pilot_symbols, + sync_sequence=$sync_sequence, + ) + </make> + <param> + <name>Cyclic Prefix Length</name> + <key>cp_len</key> + <value>16</value> + <type>int</type> + </param> + <param> + <name>FFT Length</name> + <key>fft_len</key> + <value>64</value> + <type>int</type> + </param> + <param> + <name>Length Tag Name</name> + <key>length_tag_name</key> + <value>length</value> + <type>string</type> + </param> + <param> + <name>Occupied Carriers</name> + <key>occupied_carriers</key> + <value>(range(1, 27) + range(38, 64),)</value> + <type>raw</type> + </param> + <param> + <name>Pilot Carriers</name> + <key>pilot_carriers</key> + <value>((0,),)</value> + <type>raw</type> + </param> + <param> + <name>Pilot Symbols</name> + <key>pilot_symbols</key> + <value>((100,),)</value> + <type>raw</type> + </param> + <param> + <name>Synchronization Sequence</name> + <key>sync_sequence</key> + <value>None</value> + <type>raw</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_serializer_vcc.xml b/gr-digital/grc/digital_ofdm_serializer_vcc.xml new file mode 100644 index 0000000000..c7596bbb0d --- /dev/null +++ b/gr-digital/grc/digital_ofdm_serializer_vcc.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<block> + <name>OFDM Serializer</name> + <key>digital_ofdm_serializer_vcc</key> + <import>from gnuradio import digital</import> + <make>digital.ofdm_serializer_vcc($fft_len, $occupied_carriers, $len_tag_key, $packet_len_tag_key, $symbols_skipped, $input_is_shifted)</make> + <param> + <name>FFT length</name> + <key>fft_len</key> + <value>fft_len</value> + <type>int</type> + </param> + <param> + <name>Occupied Carriers</name> + <key>occupied_carriers</key> + <type>raw</type> + </param> + <param> + <name>Length Tag Key</name> + <key>len_tag_key</key> + <type>string</type> + </param> + <param> + <name>Packet Length Tag Key</name> + <key>packet_len_tag_key</key> + <value>""</value> + <type>string</type> + </param> + <param> + <name>Symbols skipped</name> + <key>symbols_skipped</key> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Input is shifted</name> + <key>input_is_shifted</key> + <value>True</value> + <type>bool</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <vlen>$fft_len</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml b/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml new file mode 100644 index 0000000000..7865d248d5 --- /dev/null +++ b/gr-digital/grc/digital_ofdm_sync_sc_cfb.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<block> + <name>Schmidl & Cox OFDM synchronisation</name> + <key>digital_ofdm_sync_sc_cfb</key> + <import>from gnuradio import digital</import> + <make>digital.ofdm_sync_sc_cfb($fft_len, $cp_len)</make> + <param> + <name>FFT length</name> + <key>fft_len</key> + <type>int</type> + </param> + <param> + <name>Cyclic Prefix length</name> + <key>cp_len</key> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>freq_offset</name> + <type>float</type> + </source> + <source> + <name>detect</name> + <type>byte</type> + </source> +</block> diff --git a/gr-digital/grc/digital_packet_headergenerator_bb.xml b/gr-digital/grc/digital_packet_headergenerator_bb.xml new file mode 100644 index 0000000000..a0ec14ae80 --- /dev/null +++ b/gr-digital/grc/digital_packet_headergenerator_bb.xml @@ -0,0 +1,19 @@ +<block> + <name>Packet Header Generator</name> + <key>digital_packet_headergenerator_bb</key> + <import>from gnuradio import digital</import> + <make>digital.packet_headergenerator_bb($header_formatter)</make> + <param> + <name>Formatter Object</name> + <key>header_formatter</key> + <type>raw</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>byte</type> + </source> +</block> diff --git a/gr-digital/grc/digital_packet_headergenerator_bb_default.xml b/gr-digital/grc/digital_packet_headergenerator_bb_default.xml new file mode 100644 index 0000000000..645b4cd250 --- /dev/null +++ b/gr-digital/grc/digital_packet_headergenerator_bb_default.xml @@ -0,0 +1,26 @@ +<block> + <name>Packet Header Generator</name> + <key>digital_packet_headergenerator_bb_default</key> + <import>from gnuradio import digital</import> + <make>digital.packet_headergenerator_bb($header_len, $len_tag_key)</make> + <param> + <name>Header Length</name> + <key>header_len</key> + <type>int</type> + </param> + <param> + <name>Length Tag Name</name> + <key>len_tag_key</key> + <value>"packet_len"</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>byte</type> + </source> +</block> + diff --git a/gr-digital/grc/digital_packet_headerparser_b.xml b/gr-digital/grc/digital_packet_headerparser_b.xml new file mode 100644 index 0000000000..bab6bd22ed --- /dev/null +++ b/gr-digital/grc/digital_packet_headerparser_b.xml @@ -0,0 +1,19 @@ +<block> + <name>Packet Header Parser</name> + <key>digital_packet_headerparser_b</key> + <import>from gnuradio import digital</import> + <make>digital.packet_headerparser_b($header_formatter)</make> + <param> + <name>Formatter Object</name> + <key>header_formatter</key> + <type>raw</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>header_data</name> + <type>message</type> + </source> +</block> diff --git a/gr-digital/grc/digital_packet_headerparser_b_default.xml b/gr-digital/grc/digital_packet_headerparser_b_default.xml new file mode 100644 index 0000000000..415f4839f4 --- /dev/null +++ b/gr-digital/grc/digital_packet_headerparser_b_default.xml @@ -0,0 +1,26 @@ +<block> + <name>Packet Header Parser (Default)</name> + <key>digital_packet_headerparser_b_default</key> + <import>from gnuradio import digital</import> + <make>digital.packet_headerparser_b($header_len, $len_tag_key)</make> + <param> + <name>Header Length</name> + <key>header_len</key> + <type>int</type> + </param> + <param> + <name>Length Tag Name</name> + <key>len_tag_key</key> + <value>"packet_len"</value> + <type>string</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>message</type> + </source> +</block> + diff --git a/gr-digital/include/digital/CMakeLists.txt b/gr-digital/include/digital/CMakeLists.txt index 11cab88337..275da16d87 100644 --- a/gr-digital/include/digital/CMakeLists.txt +++ b/gr-digital/include/digital/CMakeLists.txt @@ -26,7 +26,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " #!${PYTHON_EXECUTABLE} import sys, os, re -sys.path.append('${GR_CORE_PYTHONPATH}') +sys.path.append('${GR_RUNTIME_PYTHONPATH}') os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' os.chdir('${CMAKE_CURRENT_BINARY_DIR}') @@ -75,44 +75,57 @@ add_custom_target(digital_generated_includes DEPENDS ######################################################################## install(FILES ${generated_includes} - api.h - constellation.h - crc32.h - lfsr.h - glfsr.h - mpsk_snr_est.h - simple_framer_sync.h additive_scrambler_bb.h + api.h binary_slicer_fb.h clock_recovery_mm_cc.h clock_recovery_mm_ff.h cma_equalizer_cc.h - cpmmod_bc.h - constellation_receiver_cb.h + constellation.h constellation_decoder_cb.h + constellation_receiver_cb.h correlate_access_code_bb.h correlate_access_code_tag_bb.h costas_loop_cc.h + cpmmod_bc.h + crc32.h + crc32_bb.h descrambler_bb.h diff_decoder_bb.h diff_encoder_bb.h diff_phasor_cc.h - framer_sink_1.h fll_band_edge_cc.h + framer_sink_1.h + glfsr.h glfsr_source_b.h glfsr_source_f.h + header_payload_demux.h kurtotic_equalizer_cc.h + lfsr.h lms_dd_equalizer_cc.h map_bb.h metric_type.h mpsk_receiver_cc.h + mpsk_snr_est.h mpsk_snr_est_cc.h + ofdm_carrier_allocator_cvc.h + ofdm_chanest_vcvc.h ofdm_cyclic_prefixer.h + ofdm_equalizer_base.h + ofdm_equalizer_simpledfe.h + ofdm_equalizer_static.h ofdm_frame_acquisition.h + ofdm_frame_equalizer_vcvc.h ofdm_frame_sink.h ofdm_insert_preamble.h ofdm_mapper_bcv.h ofdm_sampler.h + ofdm_serializer_vcc.h + ofdm_sync_sc_cfb.h + packet_header_default.h + packet_header_ofdm.h + packet_headergenerator_bb.h + packet_headerparser_b.h packet_sink.h pfb_clock_sync_ccf.h pfb_clock_sync_fff.h @@ -120,8 +133,10 @@ install(FILES probe_density_b.h probe_mpsk_snr_est_c.h scrambler_bb.h - simple_framer.h simple_correlator.h + simple_framer.h + simple_framer_sync.h + header_payload_demux.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio/digital COMPONENT "digital_devel" ) diff --git a/gr-digital/include/digital/api.h b/gr-digital/include/digital/api.h index d45ace13f2..815f7b6627 100644 --- a/gr-digital/include/digital/api.h +++ b/gr-digital/include/digital/api.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_DIGITAL_API_H #define INCLUDED_DIGITAL_API_H -#include <gruel/attributes.h> +#include <attributes.h> #ifdef gnuradio_digital_EXPORTS # define DIGITAL_API __GR_ATTR_EXPORT diff --git a/gr-digital/include/digital/constellation.h b/gr-digital/include/digital/constellation.h index ee7a704eb6..a7a2ec2023 100644 --- a/gr-digital/include/digital/constellation.h +++ b/gr-digital/include/digital/constellation.h @@ -82,7 +82,7 @@ namespace gr { //! Calculates metrics for all points in the constellation. //! For use with the viterbi algorithm. - virtual void calc_metric(const gr_complex *sample, float *metric, trellis_metric_type_t type); + virtual void calc_metric(const gr_complex *sample, float *metric, gr::digital::trellis_metric_type_t type); virtual void calc_euclidean_metric(const gr_complex *sample, float *metric); virtual void calc_hard_symbol_metric(const gr_complex *sample, float *metric); diff --git a/gr-digital/include/digital/costas_loop_cc.h b/gr-digital/include/digital/costas_loop_cc.h index bad6de9363..252f39914a 100644 --- a/gr-digital/include/digital/costas_loop_cc.h +++ b/gr-digital/include/digital/costas_loop_cc.h @@ -24,6 +24,7 @@ #define INCLUDED_DIGITAL_COSTAS_LOOP_CC_H #include <digital/api.h> +#include <blocks/control_loop.h> #include <gr_sync_block.h> namespace gr { @@ -54,7 +55,9 @@ namespace gr { * stream 1 is the baseband I and Q; * stream 2 is the normalized frequency of the loop */ - class DIGITAL_API costas_loop_cc : virtual public gr_sync_block + class DIGITAL_API costas_loop_cc + : virtual public gr_sync_block, + virtual public blocks::control_loop { public: // gr::digital::costas_loop_cc::sptr diff --git a/gr-digital/include/digital/crc32_bb.h b/gr-digital/include/digital/crc32_bb.h new file mode 100644 index 0000000000..4bfac76070 --- /dev/null +++ b/gr-digital/include/digital/crc32_bb.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DIGITAL_CRC32_BB_H +#define INCLUDED_DIGITAL_CRC32_BB_H + +#include <digital/api.h> +#include <gr_tagged_stream_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief Byte-stream CRC block + * \ingroup digital + * + * Input: stream of bytes, which form a packet. The first byte of the packet + * has a tag with key "length" and the value being the number of bytes in the + * packet. + * + * Output: The same bytes as incoming, but trailing a CRC32 of the packet. + * The tag is re-set to the new length. + */ + class DIGITAL_API crc32_bb : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<crc32_bb> sptr; + + /*! + * \param check Set to true if you want to check CRC, false to create CRC. + * \param lengthtagname Length tag key + */ + static sptr make(bool check=false, const std::string& lengthtagname="packet_len"); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_CRC32_BB_H */ + diff --git a/gr-digital/include/digital/fll_band_edge_cc.h b/gr-digital/include/digital/fll_band_edge_cc.h index 1a9fd0bf88..7b823630ed 100644 --- a/gr-digital/include/digital/fll_band_edge_cc.h +++ b/gr-digital/include/digital/fll_band_edge_cc.h @@ -25,7 +25,7 @@ #include <digital/api.h> #include <gr_sync_block.h> -#include <gri_control_loop.h> +#include <blocks/control_loop.h> namespace gr { namespace digital { @@ -84,7 +84,7 @@ namespace gr { */ class DIGITAL_API fll_band_edge_cc : virtual public gr_sync_block, - virtual public gri_control_loop + virtual public blocks::control_loop { public: // gr::digital::fll_band_edge_cc::sptr diff --git a/gr-digital/include/digital/header_payload_demux.h b/gr-digital/include/digital/header_payload_demux.h new file mode 100644 index 0000000000..014e0304a2 --- /dev/null +++ b/gr-digital/include/digital/header_payload_demux.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H +#define INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H + +#include <digital/api.h> +#include <gr_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief Header/Payload demuxer. + * \ingroup digital + * + * This block is designed to handle packets from a bursty transmission. + * Input 0 takes a continuous transmission of samples. + * If used, input 1 is a trigger signal. In this case, a 1 on input 1 + * is a trigger. Otherwise, a tag with the key specified in \p trigger_tag_key + * is used as a trigger (its value is irrelevant). + * + * Until a trigger signal is detected, all samples are dropped onto the floor. + * Once a trigger is detected, a total of \p header_len items are copied to output 0. + * The block then stalls until it receives a message on the message port + * \p header_data. The message must be a PMT dictionary; all key/value pairs are + * copied as tags to the first item of the payload (which is assumed to be the + * first item after the header). + * The value corresponding to the key specified in \p length_tag_key is read + * and taken as the payload length. The payload, together with the header data + * as tags, is then copied to output 1. + * + * If specified, \p guard_interval items are discarded before every symbol. + * This is useful for demuxing bursts of OFDM signals. + * + * Any tags on the input stream are copied to the corresponding output *if* they're + * on an item that is propagated. Note that a tag on the header items is copied to the + * header stream; that means the header-parsing block must handle these tags if they + * should go on the payload. + * A special case are tags on items that make up the guard interval. These are copied + * to the first item of the following symbol. + */ + class DIGITAL_API header_payload_demux : virtual public gr_block + { + public: + typedef boost::shared_ptr<header_payload_demux> sptr; + + /*! + * \param header_len Number of symbols per header + * \param items_per_symbol Number of items per symbol + * \param guard_interval Number of items between two consecutive symbols + * \param length_tag_key Key of the frame length tag + * \param trigger_tag_key Key of the trigger tag + * \param output_symbols Output symbols (true) or items (false)? + * \param itemsize Item size (bytes per item) + */ + static sptr make( + int header_len, + int items_per_symbol, + int guard_interval=0, + const std::string &length_tag_key="frame_len", + const std::string &trigger_tag_key="", + bool output_symbols=false, + size_t itemsize=sizeof(gr_complex) + ); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_H */ + diff --git a/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h b/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h new file mode 100644 index 0000000000..9c743e66b3 --- /dev/null +++ b/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H +#define INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H + +#include <digital/api.h> +#include <gr_tagged_stream_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief Create frequency domain OFDM symbols from complex values, add pilots. + * \ingroup ofdm_blk + * + * This block turns a stream of complex, scalar modulation symbols into vectors + * which are the input for an IFFT in an OFDM transmitter. It also supports the + * possibility of placing pilot symbols onto the carriers. + * + * The carriers can be allocated freely, if a carrier is not allocated, it is set + * to zero. This allows doing OFDMA-style carrier allocations. + * + * Input: A tagged stream of complex scalars. The first item must have a tag + * containing the number of complex symbols in this frame. + * Output: A tagged stream of complex vectors of length fft_len. This can directly + * be connected to an FFT block. Make sure to set this block to 'reverse' + * for the IFFT. If \p output_is_shifted is true, the FFT block must activate + * FFT shifting, otherwise, set shifting to false. If given, sync words are + * prepended to the output. Note that sync words are prepended verbatim, + * make sure they are shifted (or not). + * + * Carrier indexes are always such that index 0 is the DC carrier (note: you should + * not allocate this carrier). The carriers below the DC carrier are either indexed + * with negative numbers, or with indexes larger than \p fft_len/2. Index -1 and index + * \p fft_len-1 both identify the carrier below the DC carrier. + * + */ + class DIGITAL_API ofdm_carrier_allocator_cvc : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<ofdm_carrier_allocator_cvc> sptr; + + virtual std::string len_tag_key() = 0; + virtual const int fft_len() = 0; + virtual std::vector<std::vector<int> > occupied_carriers() = 0; + + /* + * \param fft_len FFT length, is also the maximum width of the OFDM symbols, the + * output vector size and maximum value for elements in + * \p occupied_carriers and \p pilot_carriers. + * \param occupied_carriers A vector of vectors of indexes. Example: if + * occupied_carriers = ((1, 2, 3), (1, 2, 4)), the first + * three input symbols will be mapped to carriers 1, 2 + * and 3. After that, a new OFDM symbol is started. The next + * three input symbols will be placed onto carriers 1, 2 + * and 4 of the second OFDM symbol. The allocation then + * starts from the beginning. + * Order matters! The first input symbol is always mapped + * onto occupied_carriers[0][0]. + * \param pilot_carriers The position of the pilot symbols. Same as occupied_carriers, + * but the actual symbols are taken from pilot_symbols instead + * of the input stream. + * \param pilot_symbols The pilot symbols which are placed onto the pilot carriers. + * pilot_symbols[0][0] is placed onto the first OFDM symbol, on + * carrier index pilot_carriers[0][0] etc. + * \param sync_words OFDM symbols that are prepended to the OFDM frame (usually for + * synchronisation purposes, e.g. OFDM symbols with every second + * sub-carrier being idle). Is a vector of complex vectors of length + * \p fft_len + * \param len_tag_key The key of the tag identifying the length of the input packet. + */ + static sptr make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key = "packet_len", + const bool output_is_shifted=true); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_H */ + diff --git a/gr-digital/include/digital/ofdm_chanest_vcvc.h b/gr-digital/include/digital/ofdm_chanest_vcvc.h new file mode 100644 index 0000000000..0c29d630da --- /dev/null +++ b/gr-digital/include/digital/ofdm_chanest_vcvc.h @@ -0,0 +1,95 @@ +/* -*- 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 sync_blk + * + * Input: OFDM symbols (in frequency domain). The first one (or two) symbols are expected + * to be synchronisation symbols, which are used to estimate the coarse freq offset + * and the initial equalizer taps (these symbols are removed from the stream). + * The following \p n_data_symbols are passed through unmodified (the actual equalisation + * must be done elsewhere). + * Output: The data symbols, without the synchronisation symbols. + * The first data symbol passed through has two tags: + * 'ofdm_sync_carr_offset' (integer), the coarse frequency offset as number of carriers, + * and 'ofdm_sync_eq_taps' (complex vector). + * Any tags attached to the synchronisation symbols are attached to the first data + * symbol. All other tags are propagated normally. + * + * This block assumes the frequency offset is even (i.e. an integer multiple of 2). + * + * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM", + * Communications, IEEE Transactions on, 1997. + * [2] K.D. Kammeyer, "Nachrichtenuebertragung," Chapter. 16.3.2. + */ + class DIGITAL_API 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_cyclic_prefixer.h b/gr-digital/include/digital/ofdm_cyclic_prefixer.h index 551d1ee834..6292d62697 100644 --- a/gr-digital/include/digital/ofdm_cyclic_prefixer.h +++ b/gr-digital/include/digital/ofdm_cyclic_prefixer.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ -/* - * Copyright 2004-2006,2011,2012 Free Software Foundation, Inc. +/* + * Copyright 2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,34 +24,48 @@ #define INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H #include <digital/api.h> -#include <gr_sync_interpolator.h> +#include <gr_tagged_stream_block.h> namespace gr { namespace digital { - + /*! - * \brief adds a cyclic prefix vector to an input size long ofdm - * symbol(vector) and converts vector to a stream output_size - * long. + * \brief Adds a cyclic prefix and performs pulse shaping on OFDM symbols. * \ingroup ofdm_blk + * + * Input: OFDM symbols (in the time domain, i.e. after the IFFT). Optionally, + * entire frames can be processed. In this case, \p len_tag_key must be + * specified which holds the key of the tag that denotes how + * many OFDM symbols are in a frame. + * Output: A stream of (scalar) complex symbols, which include the cyclic prefix + * and the pulse shaping. + * Note: If complete frames are processed, and \p rolloff_len is greater + * than zero, the final OFDM symbol is followed by the delay line of + * the pulse shaping. + * + * The pulse shape is a raised cosine in the time domain. */ - class DIGITAL_API ofdm_cyclic_prefixer : virtual public gr_sync_interpolator + class DIGITAL_API ofdm_cyclic_prefixer : virtual public gr_tagged_stream_block { - public: - // gr::digital::ofdm_cyclic_prefixer::sptr + public: typedef boost::shared_ptr<ofdm_cyclic_prefixer> sptr; /*! - * Make an OFDM cyclic prefix adder block. - * - * \param input_size size of the input symbol - * \param output_size output of the symbol - * (CP len = output_size - input_size) + * \param input_size FFT length (i.e. length of the OFDM symbols) + * \param output_size FFT length + cyclic prefix length (in samples) + * \param rolloff_len Length of the rolloff flank in samples + * \param len_tag_key For framed processing the key of the length tag */ - static sptr make(size_t input_size, size_t output_size); + static sptr make( + size_t input_size, + size_t output_size, + int rolloff_len=0, + const std::string &len_tag_key="" + ); }; - } /* namespace digital */ -} /* namespace gr */ + } // namespace digital +} // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_H */ + diff --git a/gr-digital/include/digital/ofdm_equalizer_base.h b/gr-digital/include/digital/ofdm_equalizer_base.h new file mode 100644 index 0000000000..0e23eb381f --- /dev/null +++ b/gr-digital/include/digital/ofdm_equalizer_base.h @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H +#define INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H + +#include <digital/api.h> +#include <gr_tags.h> +#include <gr_complex.h> +#include <boost/enable_shared_from_this.hpp> + +namespace gr { + namespace digital { + + /* \brief Base class for implementation details of frequency-domain OFDM equalizers. + * \ingroup ofdm_blk + * \ingroup eq_blk + */ + class DIGITAL_API ofdm_equalizer_base + : public boost::enable_shared_from_this<ofdm_equalizer_base> + { + protected: + int d_fft_len; + int d_carr_offset; + + public: + typedef boost::shared_ptr<ofdm_equalizer_base> sptr; + + ofdm_equalizer_base(int fft_len); + ~ofdm_equalizer_base(); + + //! Reset the channel information state knowledge + virtual void reset() = 0; + //! Set the carrier offset in integer multiples + void set_carrier_offset(int offset) { d_carr_offset = offset; }; + virtual void equalize( + gr_complex *frame, + int n_sym, + const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), + const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>()) = 0; + //! Return the current channel state + virtual void get_channel_state(std::vector<gr_complex> &taps) = 0; + int fft_len() { return d_fft_len; }; + sptr base() { return shared_from_this(); }; + }; + + + /* \brief Base class for implementation details of 1-dimensional OFDM FDEs which use pilot tones. + * \ingroup digital + * + */ + class DIGITAL_API ofdm_equalizer_1d_pilots : public ofdm_equalizer_base + { + protected: + //! If \p d_occupied_carriers[k][l] is true, symbol k, carrier l is carrying data. + // (this is a different format than occupied_carriers!) + std::vector<bool> d_occupied_carriers; + //! If \p d_pilot_carriers[k][l] is true, symbol k, carrier l is carrying data. + // (this is a different format than pilot_carriers!) + std::vector<std::vector<bool> > d_pilot_carriers; + //! If \p d_pilot_carriers[k][l] is true, d_pilot_symbols[k][l] is its tx'd value. + // (this is a different format than pilot_symbols!) + std::vector<std::vector<gr_complex> > d_pilot_symbols; + //! In case the frame doesn't begin with OFDM symbol 0, this is the index of the first symbol + int d_symbols_skipped; + //! The current position in the set of pilot symbols + int d_pilot_carr_set; + //! Vector of length d_fft_len saving the current channel state (on the occupied carriers) + std::vector<gr_complex> d_channel_state; + + public: + typedef boost::shared_ptr<ofdm_equalizer_1d_pilots> sptr; + + ofdm_equalizer_1d_pilots( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + bool input_is_shifted); + ~ofdm_equalizer_1d_pilots(); + + void reset(); + void get_channel_state(std::vector<gr_complex> &taps); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_BASE_H */ + diff --git a/gr-digital/include/digital/ofdm_equalizer_simpledfe.h b/gr-digital/include/digital/ofdm_equalizer_simpledfe.h new file mode 100644 index 0000000000..9d286576bc --- /dev/null +++ b/gr-digital/include/digital/ofdm_equalizer_simpledfe.h @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H +#define INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H + +#include <digital/api.h> +#include <digital/constellation.h> +#include <digital/ofdm_equalizer_base.h> + +namespace gr { + namespace digital { + + /* \brief Simple decision feedback equalizer for OFDM. + * \ingroup ofdm_blk + * \ingroup eq_blk + * + * Equalizes an OFDM signal symbol by symbol using knowledge of the + * complex modulations symbols. + * For every symbol, the following steps are performed: + * - On every sub-carrier, decode the modulation symbol + * - Use the difference between the decoded symbol and the received symbol + * to update the channel state on this carrier + * - Whenever a pilot symbol is found, it uses the known pilot symbol to + * update the channel state. + * + * This equalizer makes a lot of assumptions: + * - The initial channel state is good enough to decode the first + * symbol without error (unless the first symbol only consists of pilot + * tones) + * - The channel changes only very slowly, such that the channel state + * from one symbol is enough to decode the next + * - SNR low enough that equalization will always suffice to correctly + * decode a symbol + * If these assumptions are not met, the most common error is that the + * channel state is estimated incorrectly during equalization; after that, + * all subsequent symbols will be completely wrong. + * + * Note that the equalized symbols are *exact points* on the constellation. + * This means soft information of the modulation symbols is lost after the + * equalization, which is suboptimal for channel codes that use soft decision. + * + */ + class DIGITAL_API ofdm_equalizer_simpledfe : public ofdm_equalizer_1d_pilots + { + public: + typedef boost::shared_ptr<ofdm_equalizer_simpledfe> sptr; + + ofdm_equalizer_simpledfe( + int fft_len, + const gr::digital::constellation_sptr &constellation, + const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), + int symbols_skipped = 0, + float alpha = 0.1, + bool input_is_shifted = true); + + ~ofdm_equalizer_simpledfe(); + + void equalize(gr_complex *frame, + int n_sym, + const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), + const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>()); + + /* + * \param fft_len FFT length + * \param constellation The constellation object describing the modulation used + * on the subcarriers (e.g. QPSK). This is used to decode + * the individual symbols. + * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator + * for a description. + * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param alpha Averaging coefficient (in a nutshell, if \f$H_{i,k}\f$ is the channel + * state for carrier i and symbol k, + * \f$H_{i,k+1} = \alpha H_{i,k} + (1 - \alpha) H_{i,k+1}\f$. Make this + * larger if there's more noise, but keep in mind that larger values + * of alpha mean slower response to channel changes). + * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers. + * If the first symbol of the frame was removed (e.g. to decode the + * header), set this make sure the pilot symbols are correctly + * identified. + * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. + * the first input items is on the DC carrier. + * Note that a lot of the OFDM receiver blocks operate on shifted + * signals! + */ + static sptr make( + int fft_len, + const gr::digital::constellation_sptr &constellation, + const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), + int symbols_skipped=0, + float alpha=0.1, + bool input_is_shifted=true + ); + + private: + gr::digital::constellation_sptr d_constellation; + //! Averaging coefficient + float d_alpha; + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_SIMPLEDFE_H */ + diff --git a/gr-digital/include/digital/ofdm_equalizer_static.h b/gr-digital/include/digital/ofdm_equalizer_static.h new file mode 100644 index 0000000000..67586be6fb --- /dev/null +++ b/gr-digital/include/digital/ofdm_equalizer_static.h @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H +#define INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H + +#include <digital/api.h> +#include <digital/constellation.h> +#include <digital/ofdm_equalizer_base.h> + +namespace gr { + namespace digital { + + /* \brief Very simple static equalizer for OFDM. + * \ingroup ofdm_blk + * \ingroup eq_blk + * + * This is an extremely simple equalizer. It will only work for high-SNR, very, very + * slowly changing channels. + * It simply divides the signal with the currently known channel state. Whenever + * a pilot symbol comes around, it updates the channel state on that particular + * carrier by dividing the received symbol with the known pilot symbol. + */ + class DIGITAL_API ofdm_equalizer_static : public ofdm_equalizer_1d_pilots + { + public: + typedef boost::shared_ptr<ofdm_equalizer_static> sptr; + + ofdm_equalizer_static( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), + int symbols_skipped = 0, + bool input_is_shifted = true + ); + ~ofdm_equalizer_static(); + + /*! \brief Divide the input signal with the current channel state. + * + * Does the following (and nothing else): + * - Divide every OFDM symbol with the current channel state + * - If a pilot symbol is found, re-set the channel state by dividing the received + * symbol with the known pilot symbol + */ + void equalize(gr_complex *frame, + int n_sym, + const std::vector<gr_complex> &initial_taps = std::vector<gr_complex>(), + const std::vector<gr_tag_t> &tags = std::vector<gr_tag_t>()); + + /* + * \param fft_len FFT length + * \param occupied_carriers List of occupied carriers, see ofdm_carrier_allocator + * for a description. + * \param pilot_carriers Position of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param pilot_symbols Value of pilot symbols, see ofdm_carrier_allocator + * for a description. + * \param symbols_skipped Starting position within occupied_carriers and pilot_carriers. + * If the first symbol of the frame was removed (e.g. to decode the + * header), set this make sure the pilot symbols are correctly + * identified. + * \param input_is_shifted Set this to false if the input signal is not shifted, i.e. + * the first input items is on the DC carrier. + * Note that a lot of the OFDM receiver blocks operate on shifted + * signals! + */ + static sptr make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<int> > &pilot_carriers = std::vector<std::vector<int> >(), + const std::vector<std::vector<gr_complex> > &pilot_symbols = std::vector<std::vector<gr_complex> >(), + int symbols_skipped = 0, + bool input_is_shifted = true + ); + }; + + } /* namespace digital */ +} /* namespace gr */ + +#endif /* INCLUDED_DIGITAL_OFDM_EQUALIZER_STATIC_H */ + diff --git a/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h new file mode 100644 index 0000000000..de74d325ad --- /dev/null +++ b/gr-digital/include/digital/ofdm_frame_equalizer_vcvc.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H +#define INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H + +#include <digital/api.h> +#include <digital/ofdm_equalizer_base.h> +#include <gr_tagged_stream_block.h> + +namespace gr { + namespace digital { + + /*! + * \brief OFDM frame equalizer + * \ingroup ofdm + * + * Performs equalization in one or two dimensions on a tagged OFDM frame. + * Input: a tagged series of OFDM symbols. + * Output: The same as the input, but equalized. + */ + class DIGITAL_API ofdm_frame_equalizer_vcvc : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<ofdm_frame_equalizer_vcvc> sptr; + + /*! + * \param equalizer The equalizer object that will do the actual work + * \param len_tag_key Length tag key + * \param propagate_channel_state If true, the channel state after the last symbol + * will be added to the first symbol as a tag + */ + static sptr make( + ofdm_equalizer_base::sptr equalizer, + const std::string &len_tag_key = "frame_len", + bool propagate_channel_state=false + ); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_OFDM_FRAME_EQUALIZER_VCVC_H */ + diff --git a/gr-digital/include/digital/ofdm_serializer_vcc.h b/gr-digital/include/digital/ofdm_serializer_vcc.h new file mode 100644 index 0000000000..c4dc36ec06 --- /dev/null +++ b/gr-digital/include/digital/ofdm_serializer_vcc.h @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H +#define INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H + +#include <digital/api.h> +#include <gr_tagged_stream_block.h> +#include <digital/ofdm_carrier_allocator_cvc.h> + +namespace gr { + namespace digital { + + /*! + * \brief Serializes complex modulations symbols from OFDM sub-carriers + * \ingroup ofdm_blk + * + * This is the inverse block to the carrier_allocator_cvc. It outputs the + * complex data symbols as a tagged stream, discarding the pilot symbols. + * + * If given, two different tags are parsed: The first key (\p len_tag_key) + * specifies the number of OFDM symbols in the frame at the input. The + * second key (\p packet_len_tag_key) specifies the number of complex symbols + * that are coded into this frame. If given, this second key is then used + * at the output, otherwise, \p len_tag_key is used. + * If both are given, the packet length specifies the maximum number of + * output items, and the frame length specifies the exact number of + * consumed input items. + * + * Input: Complex vectors of length \p fft_len + * Output: Complex scalars, in the same order as specified in occupied_carriers. + */ + class DIGITAL_API ofdm_serializer_vcc : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<ofdm_serializer_vcc> sptr; + + /*! + * \param fft_len FFT length + * \param occupied_carriers See ofdm_carrier_allocator_cvc. + * \param len_tag_key The key of the tag identifying the length of the input frame in OFDM symbols. + * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet. + * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this + * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false + */ + static sptr make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::string &len_tag_key="frame_len", + const std::string &packet_len_tag_key="", + int symbols_skipped=0, + bool input_is_shifted=true + ); + + /*! + * \param allocator The carrier allocator block of which this shall be the inverse + * \param packet_len_tag_key The key of the tag identifying the number of complex symbols in this packet. + * \param symbols_skipped If the first symbol is not allocated as in \p occupied_carriers[0], set this + * \param input_is_shifted If the input has the DC carrier on index 0 (i.e. it is not FFT shifted), set this to false + */ + static sptr make( + const gr::digital::ofdm_carrier_allocator_cvc::sptr &allocator, + const std::string &packet_len_tag_key="", + int symbols_skipped=0, + bool input_is_shifted=true + ); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_H */ + diff --git a/gr-digital/include/digital/ofdm_sync_sc_cfb.h b/gr-digital/include/digital/ofdm_sync_sc_cfb.h new file mode 100644 index 0000000000..0c5c46f38d --- /dev/null +++ b/gr-digital/include/digital/ofdm_sync_sc_cfb.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_SYNC_SC_CFB_H +#define INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H + +#include <digital/api.h> +#include <gr_hier_block2.h> + +namespace gr { + namespace digital { + + /*! + * \brief Schmidl & Cox synchronisation for OFDM + * \ingroup ofdm_blk + * \ingroup sync_blk + * + * Input: complex samples. + * Output 0: Fine frequency offset, scaled by the OFDM symbol duration. + * This is \f$\hat{\varphi}\f$ in [1]. The normalized frequency + * offset is then 2.0*output0/fft_len. + * Output 1: Beginning of the first OFDM symbol after the first (doubled) OFDM + * symbol. The beginning is marked with a 1 (it's 0 everywhere else). + * + * The evaluation of the coarse frequency offset is *not* done in this block. + * Also, the initial equalizer taps are not calculated here. + * + * Note that we use a different normalization factor in the timing metric than + * the authors do in their original work[1]. If the timing metric (8) is + * \f[ + * M(d) = \frac{|P(d)|^2}{(R(d))^2}, + * \f] + * we calculate the normalization as + * \f[ + * R(d) = \frac{1}{2} \sum_{k=0}^{N-1} |r_{k+d}|^2, + * \f] + * i.e., we estimate the energy from *both* half-symbols. This avoids spurious detects + * at the end of a burst, when the energy level suddenly drops. + * + * [1] Schmidl, T.M. and Cox, D.C., "Robust frequency and timing synchronization for OFDM", + * Communications, IEEE Transactions on, 1997. + */ + class DIGITAL_API ofdm_sync_sc_cfb : virtual public gr_hier_block2 + { + public: + typedef boost::shared_ptr<ofdm_sync_sc_cfb> sptr; + + /*! \param fft_len FFT length + * \param cp_len Length of the guard interval (cyclic prefix) in samples + */ + static sptr make(int fft_len, int cp_len); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_H */ + diff --git a/gr-digital/include/digital/packet_header_default.h b/gr-digital/include/digital/packet_header_default.h new file mode 100644 index 0000000000..d69a0f30a6 --- /dev/null +++ b/gr-digital/include/digital/packet_header_default.h @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H +#define INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H + +#include <gr_tags.h> +#include <digital/api.h> +#include <boost/enable_shared_from_this.hpp> + +namespace gr { + namespace digital { + + /*! + * \brief Default header formatter for digital packet transmission. + * \ingroup digital + * + * For bursty/packetized digital transmission, packets are usually prepended + * with a packet header, containing the number of bytes etc. + * This class is not a block, but a tool to create these packet header. + * + * This is a default packet header (see header_formatter()) for a description + * on the header format). To create other header, derive packet header creator + * classes from this function. + * + * gr::digital::packet_headergenerator_bb uses header generators derived from + * this class to create packet headers from data streams. + */ + class DIGITAL_API packet_header_default : public boost::enable_shared_from_this<gr::digital::packet_header_default> + { + public: + typedef boost::shared_ptr<packet_header_default> sptr; + + packet_header_default( + long header_len, + const std::string &len_tag_key="packet_len", + const std::string &num_tag_key="packet_num", + int bits_per_byte=1); + ~packet_header_default(); + + sptr base() { return shared_from_this(); }; + sptr formatter() { return shared_from_this(); }; + + void set_header_num(unsigned header_num) { d_header_number = header_num; }; + long header_len() { return d_header_len; }; + pmt::pmt_t len_tag_key() { return d_len_tag_key; }; + + /*! + * \brief Encodes the header information in the given tags into bits and places them into \p out + * + * Uses the following header format: + * Bits 0-11: The packet length (what was stored in the tag with key \p len_tag_key) + * Bits 12-27: The header number (counts up everytime this function is called) + * Bit 28: Even parity bit + * All other bits: Are set to zero + * + * If the header length is smaller than 29, bits are simply left out. For this + * reason, they always start with the LSB. + */ + bool header_formatter( + long packet_len, + unsigned char *out, + const std::vector<gr_tag_t> &tags=std::vector<gr_tag_t>() + ); + + /*! + * \brief Inverse function to header_formatter(). + * + * Reads the bit stream in \in and writes a corresponding tag into \p tags. + * + */ + bool header_parser( + const unsigned char *header, + std::vector<gr_tag_t> &tags); + + static sptr make( + long header_len, + const std::string &len_tag_key="packet_len", + const std::string &num_tag_key="packet_num", + int bits_per_byte=1); + + protected: + long d_header_len; + pmt::pmt_t d_len_tag_key; + pmt::pmt_t d_num_tag_key; + int d_bits_per_byte; + unsigned d_header_number; + unsigned d_mask; + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_PACKET_HEADER_DEFAULT_H */ + diff --git a/gr-digital/include/digital/packet_header_ofdm.h b/gr-digital/include/digital/packet_header_ofdm.h new file mode 100644 index 0000000000..9f70900b49 --- /dev/null +++ b/gr-digital/include/digital/packet_header_ofdm.h @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H +#define INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H + +#include <vector> +#include <digital/api.h> +#include <digital/packet_header_default.h> + +namespace gr { + namespace digital { + + /*! + * \brief Header utility for OFDM signals. + * \ingroup ofdm_blk + * + */ + class DIGITAL_API packet_header_ofdm : public packet_header_default + { + public: + typedef boost::shared_ptr<packet_header_ofdm> sptr; + + packet_header_ofdm( + const std::vector<std::vector<int> > &occupied_carriers, + int n_syms, + const std::string &len_tag_key="packet_len", + const std::string &frame_len_tag_key="frame_len", + const std::string &num_tag_key="packet_num", + int bits_per_sym=1); + ~packet_header_ofdm(); + + /*! + * \brief Inverse function to header_formatter(). + * + * Does the same as packet_header_default::header_parser(), but + * adds another tag that stores the number of OFDM symbols in the + * packet. + * Note that there is usually no linear connection between the number + * of OFDM symbols and the packet length, because, a packet might + * finish mid-OFDM-symbol. + */ + bool header_parser( + const unsigned char *header, + std::vector<gr_tag_t> &tags); + + static sptr make( + const std::vector<std::vector<int> > &occupied_carriers, + int n_syms, + const std::string &len_tag_key="packet_len", + const std::string &frame_len_tag_key="frame_len", + const std::string &num_tag_key="packet_num", + int bits_per_sym=1); + + + protected: + pmt::pmt_t d_frame_len_tag_key; + const std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data + int d_syms_per_set; //!< Helper variable: Total number of elements in d_occupied_carriers + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_PACKET_HEADER_OFDM_H */ + diff --git a/gr-digital/include/digital/packet_headergenerator_bb.h b/gr-digital/include/digital/packet_headergenerator_bb.h new file mode 100644 index 0000000000..cec860fd55 --- /dev/null +++ b/gr-digital/include/digital/packet_headergenerator_bb.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_PACKET_HEADERGENERATOR_BB_H +#define INCLUDED_PACKET_HEADERGENERATOR_BB_H + +#include <digital/api.h> +#include <gr_tagged_stream_block.h> +#include <digital/packet_header_default.h> + +namespace gr { + namespace digital { + + /*! + * \brief Generates a header for a tagged, streamed packet. + * \ingroup digital + * + * Input: A tagged stream. This is consumed entirely, it is not appended + * to the output stream. + * Output: An tagged stream containing the header. The details on the header + * are set in a header formatter object (of type packet_header_default + * or a subclass thereof). If only a number of bits is specified, a + * default header is generated (see packet_header_default). + */ + class DIGITAL_API packet_headergenerator_bb : virtual public gr_tagged_stream_block + { + public: + typedef boost::shared_ptr<packet_headergenerator_bb> sptr; + + /* \param header_formatter A header formatter object. + * \param len_tag_key Length tag key. Note that for header generation, + * it is irrelevant which tag names are set in the + * formatter object, only this value is relevant! + */ + static sptr make( + const packet_header_default::sptr &header_formatter, + const std::string &len_tag_key="packet_len" + ); + + /* \param header_len If this value is given, a packet_header_default + * object is used to generate the header. This is + * the number of bits per header. + * \param len_tag_key Length tag key. + */ + static sptr make( + long header_len, + const std::string &len_tag_key = "packet_len"); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_PACKET_HEADERGENERATOR_BB_H */ + diff --git a/gr-digital/include/digital/packet_headerparser_b.h b/gr-digital/include/digital/packet_headerparser_b.h new file mode 100644 index 0000000000..2dc6a80717 --- /dev/null +++ b/gr-digital/include/digital/packet_headerparser_b.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H +#define INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H + +#include <digital/api.h> +#include <gr_sync_block.h> +#include <digital/packet_header_default.h> + +namespace gr { + namespace digital { + + /*! + * \brief Post header metadata as a PMT + * \ingroup digital + * + * In a sense, this is the inverse block to packet_headergenerator_bb. + * The difference is, the parsed header is not output as a stream, + * but as a PMT dictionary, which is published to message port with + * the id "header_data". + * The dictionary consists of the tags created by the header formatter + * object. You should be able to use the exact same formatter object + * as used on the Tx side in the packet_headergenerator_bb. + * + * If only a header length is given, this block uses the default header + * format. + */ + class DIGITAL_API packet_headerparser_b : virtual public gr_sync_block + { + public: + typedef boost::shared_ptr<packet_headerparser_b> sptr; + + /*! + * \param header_formatter Header object. This should be the same as used for + * packet_headergenerator_bb. + */ + static sptr make(const gr::digital::packet_header_default::sptr &header_formatter); + + /*! + * \param header_len Number of bytes per header + * \param len_tag_key Length Tag Key + */ + static sptr make(long header_len, const std::string &len_tag_key); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_H */ + diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index d47e7fb1f3..a17c91a85a 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -26,15 +26,15 @@ include_directories( ${GR_ANALOG_INCLUDE_DIRS} ${GR_FFT_INCLUDE_DIRS} ${GR_FILTER_INCLUDE_DIRS} - ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_BLOCKS_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_INCLUDE_DIRS} ${VOLK_INCLUDE_DIRS} - ${GRUEL_INCLUDE_DIRS} - ${LOG4CXX_INCLUDE_DIRS} + ${LOG4CPP_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) link_directories(${Boost_LIBRARY_DIRS}) -link_directories(${LOG4CXX_LIBRARY_DIRS}) +link_directories(${LOG4CPP_LIBRARY_DIRS}) if(ENABLE_GR_CTRLPORT) ADD_DEFINITIONS(-DGR_CTRLPORT) @@ -50,7 +50,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " #!${PYTHON_EXECUTABLE} import sys, os, re -sys.path.append('${GR_CORE_PYTHONPATH}') +sys.path.append('${GR_RUNTIME_PYTHONPATH}') os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' os.chdir('${CMAKE_CURRENT_BINARY_DIR}') @@ -112,40 +112,54 @@ expand_cc(chunks_to_symbols_XX_impl bf bc sf sc if ic) ######################################################################## list(APPEND digital_sources ${generated_sources} - constellation.cc - crc32.cc - glfsr.cc - mpsk_snr_est.cc additive_scrambler_bb_impl.cc binary_slicer_fb_impl.cc clock_recovery_mm_cc_impl.cc clock_recovery_mm_ff_impl.cc cma_equalizer_cc_impl.cc - constellation_receiver_cb_impl.cc + constellation.cc constellation_decoder_cb_impl.cc + constellation_receiver_cb_impl.cc correlate_access_code_bb_impl.cc correlate_access_code_tag_bb_impl.cc costas_loop_cc_impl.cc cpmmod_bc_impl.cc + crc32.cc + crc32_bb_impl.cc descrambler_bb_impl.cc diff_decoder_bb_impl.cc diff_encoder_bb_impl.cc diff_phasor_cc_impl.cc fll_band_edge_cc_impl.cc framer_sink_1_impl.cc + glfsr.cc glfsr_source_b_impl.cc glfsr_source_f_impl.cc + header_payload_demux_impl.cc kurtotic_equalizer_cc_impl.cc lms_dd_equalizer_cc_impl.cc map_bb_impl.cc mpsk_receiver_cc_impl.cc + mpsk_snr_est.cc mpsk_snr_est_cc_impl.cc + ofdm_carrier_allocator_cvc_impl.cc + ofdm_chanest_vcvc_impl.cc ofdm_cyclic_prefixer_impl.cc + ofdm_equalizer_base.cc + ofdm_equalizer_simpledfe.cc + ofdm_equalizer_static.cc ofdm_frame_acquisition_impl.cc + ofdm_frame_equalizer_vcvc_impl.cc ofdm_frame_sink_impl.cc ofdm_insert_preamble_impl.cc ofdm_mapper_bcv_impl.cc ofdm_sampler_impl.cc + ofdm_serializer_vcc_impl.cc + ofdm_sync_sc_cfb_impl.cc + packet_header_default.cc + packet_header_ofdm.cc + packet_headergenerator_bb_impl.cc + packet_headerparser_b_impl.cc packet_sink_impl.cc pfb_clock_sync_ccf_impl.cc pfb_clock_sync_fff_impl.cc @@ -153,8 +167,9 @@ list(APPEND digital_sources probe_density_b_impl.cc probe_mpsk_snr_est_c_impl.cc scrambler_bb_impl.cc - simple_framer_impl.cc simple_correlator_impl.cc + simple_framer_impl.cc + header_payload_demux_impl.cc ) #Add Windows DLL resource file if using MSVC @@ -173,18 +188,25 @@ ENDIF(MSVC) list(APPEND digital_libs volk - gnuradio-core + gnuradio-runtime gnuradio-filter gnuradio-blocks gnuradio-analog ${Boost_LIBRARIES} - ${LOG4CXX_LIBRARIES} + ${LOG4CPP_LIBRARIES} ) add_library(gnuradio-digital SHARED ${digital_sources}) target_link_libraries(gnuradio-digital ${digital_libs}) GR_LIBRARY_FOO(gnuradio-digital RUNTIME_COMPONENT "digital_runtime" DEVEL_COMPONENT "digital_devel") -add_dependencies(gnuradio-digital - digital_generated_includes digital_generated_swigs - gnuradio-core gnuradio-filter gnuradio-analog) + +add_dependencies( + gnuradio-digital + digital_generated_includes + digital_generated_swigs + gnuradio-runtime + gnuradio-filter + gnuradio-analog + gnuradio-blocks +) diff --git a/gr-digital/lib/constellation_receiver_cb_impl.cc b/gr-digital/lib/constellation_receiver_cb_impl.cc index c3203e9079..30be24aab9 100644 --- a/gr-digital/lib/constellation_receiver_cb_impl.cc +++ b/gr-digital/lib/constellation_receiver_cb_impl.cc @@ -54,7 +54,7 @@ namespace gr { : gr_block("constellation_receiver_cb", gr_make_io_signature(1, 1, sizeof(gr_complex)), gr_make_io_signaturev(1, 5, iosig)), - gri_control_loop(loop_bw, fmax, fmin), + blocks::control_loop(loop_bw, fmax, fmin), d_constellation(constellation), d_current_const_point(0) { diff --git a/gr-digital/lib/constellation_receiver_cb_impl.h b/gr-digital/lib/constellation_receiver_cb_impl.h index 50946840ae..7c34518340 100644 --- a/gr-digital/lib/constellation_receiver_cb_impl.h +++ b/gr-digital/lib/constellation_receiver_cb_impl.h @@ -24,15 +24,15 @@ #define INCLUDED_DIGITAL_CONSTELLATION_RECEIVER_CB_IMPL_H #include <digital/constellation_receiver_cb.h> -#include <gruel/attributes.h> +#include <attributes.h> #include <gr_complex.h> -#include <gri_control_loop.h> +#include <blocks/control_loop.h> namespace gr { namespace digital { class constellation_receiver_cb_impl - : public constellation_receiver_cb, gri_control_loop + : public constellation_receiver_cb, blocks::control_loop { public: constellation_receiver_cb_impl(constellation_sptr constell, diff --git a/gr-digital/lib/costas_loop_cc_impl.cc b/gr-digital/lib/costas_loop_cc_impl.cc index 5afabf4294..fcdd45045b 100644 --- a/gr-digital/lib/costas_loop_cc_impl.cc +++ b/gr-digital/lib/costas_loop_cc_impl.cc @@ -44,7 +44,7 @@ namespace gr { : gr_sync_block("costas_loop_cc", gr_make_io_signature(1, 1, sizeof(gr_complex)), gr_make_io_signature2(1, 2, sizeof(gr_complex), sizeof(float))), - gri_control_loop(loop_bw, 1.0, -1.0), + blocks::control_loop(loop_bw, 1.0, -1.0), d_order(order), d_phase_detector(NULL) { // Set up the phase detector to use based on the constellation order diff --git a/gr-digital/lib/costas_loop_cc_impl.h b/gr-digital/lib/costas_loop_cc_impl.h index 9310368b4d..ecba2cdd4f 100644 --- a/gr-digital/lib/costas_loop_cc_impl.h +++ b/gr-digital/lib/costas_loop_cc_impl.h @@ -25,12 +25,11 @@ #define INCLUDED_DIGITAL_COSTAS_LOOP_CC_IMPL_H #include <digital/costas_loop_cc.h> -#include <gri_control_loop.h> namespace gr { namespace digital { - class costas_loop_cc_impl : public costas_loop_cc, gri_control_loop + class costas_loop_cc_impl : public costas_loop_cc { private: int d_order; diff --git a/gr-digital/lib/crc32_bb_impl.cc b/gr-digital/lib/crc32_bb_impl.cc new file mode 100644 index 0000000000..608c5758ac --- /dev/null +++ b/gr-digital/lib/crc32_bb_impl.cc @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "crc32_bb_impl.h" +#include <digital/crc32.h> + +namespace gr { + namespace digital { + + crc32_bb::sptr + crc32_bb::make(bool check, const std::string& lengthtagname) + { + return gnuradio::get_initial_sptr (new crc32_bb_impl(check, lengthtagname)); + } + + crc32_bb_impl::crc32_bb_impl(bool check, const std::string& lengthtagname) + : gr_tagged_stream_block("crc32_bb", + gr_make_io_signature(1, 1, sizeof (char)), + gr_make_io_signature(1, 1, sizeof (char)), + lengthtagname), + d_check(check) + { + set_tag_propagation_policy(TPP_DONT); + } + + crc32_bb_impl::~crc32_bb_impl() + { + } + + int + crc32_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) + { + if (d_check) { + return ninput_items[0] - 4; + } else { + return ninput_items[0] + 4; + } + } + + int + crc32_bb_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + long packet_length = ninput_items[0]; + int packet_size_diff = d_check ? -4 : 4; + unsigned int crc; + + if (d_check) { + crc = gr::digital::crc32(in, packet_length-4); + if (crc != *(unsigned int *)(in+packet_length-4)) { // Drop package + return 0; + } + memcpy((void *) out, (const void *) in, packet_length-4); + } else { + crc = gr::digital::crc32(in, packet_length); + memcpy((void *) out, (const void *) in, packet_length); + memcpy((void *) (out + packet_length), &crc, 4); // FIXME big-endian/little-endian, this might be wrong + } + + std::vector<gr_tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+packet_length); + for (unsigned i = 0; i < tags.size(); i++) { + tags[i].offset -= nitems_read(0); + if (d_check && tags[i].offset > packet_length+packet_size_diff) { + tags[i].offset = packet_length-5; + } + add_item_tag(0, nitems_written(0) + tags[i].offset, + tags[i].key, + tags[i].value); + } + + return packet_length + packet_size_diff; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/crc32_bb_impl.h b/gr-digital/lib/crc32_bb_impl.h new file mode 100644 index 0000000000..7b9dbb6351 --- /dev/null +++ b/gr-digital/lib/crc32_bb_impl.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_CRC32_BB_IMPL_H +#define INCLUDED_DIGITAL_CRC32_BB_IMPL_H + +#include <digital/crc32_bb.h> + +namespace gr { + namespace digital { + + class crc32_bb_impl : public crc32_bb + { + private: + bool d_check; + + public: + crc32_bb_impl(bool check, const std::string& lengthtagname); + ~crc32_bb_impl(); + + int calculate_output_stream_length(const gr_vector_int &ninput_items); + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_CRC32_BB_IMPL_H */ + diff --git a/gr-digital/lib/fll_band_edge_cc_impl.cc b/gr-digital/lib/fll_band_edge_cc_impl.cc index 980d3ab464..c438b813f4 100644 --- a/gr-digital/lib/fll_band_edge_cc_impl.cc +++ b/gr-digital/lib/fll_band_edge_cc_impl.cc @@ -58,25 +58,25 @@ namespace gr { : gr_sync_block("fll_band_edge_cc", gr_make_io_signature(1, 1, sizeof(gr_complex)), gr_make_io_signaturev(1, 4, iosig)), - gri_control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), - -M_TWOPI*(2.0/samps_per_sym)), + blocks::control_loop(bandwidth, M_TWOPI*(2.0/samps_per_sym), + -M_TWOPI*(2.0/samps_per_sym)), d_updated(false) { // Initialize samples per symbol if(samps_per_sym <= 0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0."); + throw std::out_of_range("fll_band_edge_cc: invalid number of sps. Must be > 0."); } d_sps = samps_per_sym; // Initialize rolloff factor if(rolloff < 0 || rolloff > 1.0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); + throw std::out_of_range("fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); } d_rolloff = rolloff; // Initialize filter length if(filter_size <= 0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0."); + throw std::out_of_range("fll_band_edge_cc: invalid filter size. Must be > 0."); } d_filter_size = filter_size; @@ -97,7 +97,7 @@ namespace gr { fll_band_edge_cc_impl::set_samples_per_symbol(float sps) { if(sps <= 0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid number of sps. Must be > 0."); + throw std::out_of_range("fll_band_edge_cc: invalid number of sps. Must be > 0."); } d_sps = sps; design_filter(d_sps, d_rolloff, d_filter_size); @@ -107,7 +107,7 @@ namespace gr { fll_band_edge_cc_impl::set_rolloff(float rolloff) { if(rolloff < 0 || rolloff > 1.0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); + throw std::out_of_range("fll_band_edge_cc: invalid rolloff factor. Must be in [0,1]."); } d_rolloff = rolloff; design_filter(d_sps, d_rolloff, d_filter_size); @@ -117,7 +117,7 @@ namespace gr { fll_band_edge_cc_impl::set_filter_size(int filter_size) { if(filter_size <= 0) { - throw std::out_of_range("digital_fll_band_edge_cc: invalid filter size. Must be > 0."); + throw std::out_of_range("fll_band_edge_cc: invalid filter size. Must be > 0."); } d_filter_size = filter_size; design_filter(d_sps, d_rolloff, d_filter_size); diff --git a/gr-digital/lib/fll_band_edge_cc_impl.h b/gr-digital/lib/fll_band_edge_cc_impl.h index 55e338b38c..9eb3e6e7ae 100644 --- a/gr-digital/lib/fll_band_edge_cc_impl.h +++ b/gr-digital/lib/fll_band_edge_cc_impl.h @@ -24,7 +24,7 @@ #define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_IMPL_H #include <digital/fll_band_edge_cc.h> -#include <gri_control_loop.h> +#include <blocks/control_loop.h> #include <filter/fir_filter.h> namespace gr { diff --git a/gr-digital/lib/header_payload_demux_impl.cc b/gr-digital/lib/header_payload_demux_impl.cc new file mode 100644 index 0000000000..a2e81c5b8e --- /dev/null +++ b/gr-digital/lib/header_payload_demux_impl.cc @@ -0,0 +1,292 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <climits> +#include <gr_io_signature.h> +#include "header_payload_demux_impl.h" + +namespace gr { + namespace digital { + + enum demux_states_t { + STATE_IDLE, + STATE_HEADER, + STATE_WAIT_FOR_MSG, + STATE_PAYLOAD + }; + +#define msg_port_id pmt::mp("header_data") + + header_payload_demux::sptr + header_payload_demux::make( + int header_len, + int items_per_symbol, + int guard_interval, + const std::string &length_tag_key, + const std::string &trigger_tag_key, + bool output_symbols, + size_t itemsize) + { + return gnuradio::get_initial_sptr ( + new header_payload_demux_impl( + header_len, + items_per_symbol, + guard_interval, + length_tag_key, + trigger_tag_key, + output_symbols, + itemsize + ) + ); + } + + header_payload_demux_impl::header_payload_demux_impl( + int header_len, + int items_per_symbol, + int guard_interval, + const std::string &length_tag_key, + const std::string &trigger_tag_key, + bool output_symbols, + size_t itemsize + ) : gr_block("header_payload_demux", + gr_make_io_signature2(1, 2, itemsize, sizeof(char)), + gr_make_io_signature(2, 2, (output_symbols ? itemsize * items_per_symbol : itemsize))), + d_header_len(header_len), + d_items_per_symbol(items_per_symbol), + d_gi(guard_interval), + d_len_tag_key(pmt::string_to_symbol(length_tag_key)), + d_trigger_tag_key(pmt::string_to_symbol(trigger_tag_key)), + d_output_symbols(output_symbols), + d_itemsize(itemsize), + d_uses_trigger_tag(!trigger_tag_key.empty()), + d_state(STATE_IDLE) + { + if (d_header_len < 1) { + throw std::invalid_argument("Header length must be at least 1 symbol."); + } + if (d_items_per_symbol < 1 || d_gi < 0 || d_itemsize < 1) { + throw std::invalid_argument("Items and symbol sizes must be at least 1."); + } + set_output_multiple(d_items_per_symbol); + message_port_register_in(msg_port_id); + } + + header_payload_demux_impl::~header_payload_demux_impl() + { + } + + void + header_payload_demux_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + // noutput_items is an integer multiple of d_items_per_symbol! + for (unsigned i = 0; i < ninput_items_required.size(); i++) { + ninput_items_required[i] = + noutput_items / d_items_per_symbol * (d_items_per_symbol + d_gi); + } + } + + int + header_payload_demux_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out_header = (unsigned char *) output_items[0]; + unsigned char *out_payload = (unsigned char *) output_items[1]; + + int nread = 0; + bool exit_loop = false; + + int produced_hdr = 0; + int produced_payload = 0; + + while (nread < noutput_items && !exit_loop) { + switch (d_state) { + case STATE_IDLE: + // 1) Search for a trigger signal on input 1 (if present) + // 2) Search for a trigger tag, make sure it's the first one + // The first trigger to be found is used! + // 3) Make sure the right number of items is skipped + // 4) If trigger found, switch to STATE_HEADER + if (find_trigger_signal(nread, noutput_items, input_items)) { + d_remaining_symbols = d_header_len; + d_state = STATE_HEADER; + in += nread * d_itemsize; + } + break; + + case STATE_HEADER: + copy_symbol(in, out_header, 0, nread, produced_hdr); + if (d_remaining_symbols == 0) { + d_state = STATE_WAIT_FOR_MSG; + exit_loop = true; + } + break; + + case STATE_WAIT_FOR_MSG: + // If we're in this state, nread is zero (because previous state exits loop) + // 1) Wait for msg (blocking call) + // 2) set d_remaining_symbols + // 3) Write tags + // 4) fall through to next state + d_remaining_symbols = -1; + if (!parse_header_data_msg()) { + exit_loop = true; + break; + } + d_state = STATE_PAYLOAD; + + case STATE_PAYLOAD: + copy_symbol(in, out_payload, 1, nread, produced_payload); + if (d_remaining_symbols == 0) { + d_state = STATE_IDLE; + exit_loop = true; + } + break; + + default: + throw std::runtime_error("invalid state"); + } /* switch */ + } /* while(nread < noutput_items) */ + + if (!d_output_symbols) { + produced_hdr *= d_items_per_symbol; + produced_payload *= d_items_per_symbol; + } + produce(0, produced_hdr); + produce(1, produced_payload); + consume_each (nread); + return WORK_CALLED_PRODUCE; + } /* general_work() */ + + + bool + header_payload_demux_impl::find_trigger_signal( + int &pos, + int noutput_items, + gr_vector_const_void_star &input_items) + { + if (input_items.size() == 2) { + unsigned char *in_trigger = (unsigned char *) input_items[1]; + for (int i = 0; i < noutput_items; i++) { + if (in_trigger[i]) { + pos = i; + return true; + } + } + } + if (d_uses_trigger_tag) { + std::vector<gr_tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+noutput_items); + uint64_t min_offset = ULLONG_MAX; + int tag_index = -1; + for (unsigned i = 0; i < tags.size(); i++) { + if (tags[i].key == d_trigger_tag_key && tags[i].offset < min_offset) { + tag_index = (int) i; + min_offset = tags[i].offset; + } + } + if (tag_index != -1) { + pos = min_offset - nitems_read(0); + return true; + } + } + pos += noutput_items; + return false; + } + + + bool + header_payload_demux_impl::parse_header_data_msg() + { + pmt::pmt_t msg(delete_head_blocking(msg_port_id)); + if (pmt::is_integer(msg)) { + d_remaining_symbols = pmt::to_long(msg); + add_item_tag(1, nitems_written(1), d_len_tag_key, msg); + } else if (pmt::is_dict(msg)) { + pmt::pmt_t dict_items(pmt::dict_items(msg)); + while (!pmt::is_null(dict_items)) { + pmt::pmt_t this_item(pmt::car(dict_items)); + add_item_tag(1, nitems_written(1), pmt::car(this_item), pmt::cdr(this_item)); + if (pmt::equal(pmt::car(this_item), d_len_tag_key)) { + d_remaining_symbols = pmt::to_long(pmt::cdr(this_item)); + } + dict_items = pmt::cdr(dict_items); + } + if (d_remaining_symbols == -1) { + throw std::runtime_error("no length tag passed from header data"); + } + } else if (pmt::is_null(msg)) { // Blocking call was interrupted + return false; + } else { + throw std::runtime_error("Received illegal header data"); + } + return true; + } + + void + header_payload_demux_impl::copy_symbol(const unsigned char *&in, unsigned char *&out, int port, int &nread, int &nproduced) + { + std::vector<gr_tag_t> tags; + memcpy((void *) out, + (void *) (in + d_gi * d_itemsize), + d_itemsize * d_items_per_symbol + ); + // Tags on GI + get_tags_in_range(tags, 0, + nitems_read(0) + nread, + nitems_read(0) + nread + d_gi + ); + for (unsigned t = 0; t < tags.size(); t++) { + add_item_tag(port, + nitems_written(port)+nproduced, + tags[t].key, + tags[t].value + ); + } + // Tags on symbol + get_tags_in_range( + tags, 0, + nitems_read(port) + nread + d_gi, + nitems_read(port) + nread + d_gi + d_items_per_symbol + ); + for (unsigned t = 0; t < tags.size(); t++) { + add_item_tag(0, + tags[t].offset - nitems_read(0)-nread + nitems_written(port)+nproduced, + tags[t].key, + tags[t].value + ); + } + in += d_itemsize * (d_items_per_symbol + d_gi); + out += d_items_per_symbol * d_itemsize; + nread += d_items_per_symbol + d_gi; + nproduced++; + d_remaining_symbols--; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/header_payload_demux_impl.h b/gr-digital/lib/header_payload_demux_impl.h new file mode 100644 index 0000000000..dc8cc7883a --- /dev/null +++ b/gr-digital/lib/header_payload_demux_impl.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H +#define INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H + +#include <digital/header_payload_demux.h> + +namespace gr { + namespace digital { + + class header_payload_demux_impl : public header_payload_demux + { + private: + int d_header_len; //!< Number of bytes per header + int d_items_per_symbol; //!< Bytes per symbol + int d_gi; //!< Bytes per guard interval + pmt::pmt_t d_len_tag_key; //!< Key of length tag + pmt::pmt_t d_trigger_tag_key; //!< Key of trigger tag (if used) + bool d_output_symbols; //!< If true, output is symbols, not items + size_t d_itemsize; //!< Bytes per item + bool d_uses_trigger_tag; //!< If a trigger tag is used + int d_ninput_items_reqd; //!< Helper for forecast() + int d_state; //!< Current read state + int d_remaining_symbols; //!< When in payload or header state, the number of symbols still to transmit + + // Helpers to make the state machine more readable + + //! Helper function that does the reading from the msg port + bool parse_header_data_msg(); + + //! Helper function that returns true if a trigger signal is detected. + // Searches input 1 (if active), then the tags. Sets \p pos to the position + // of the first tag. + bool find_trigger_signal( + int &pos, + int noutput_items, + gr_vector_const_void_star &input_items); + + //! Helper function, copies one symbol from in to out and updates all pointers and counters + void copy_symbol(const unsigned char *&in, unsigned char *&out, int port, int &nread, int &nproduced); + + public: + + header_payload_demux_impl( + int header_len, + int items_per_symbol, + int guard_interval, + const std::string &length_tag_key, + const std::string &trigger_tag_key, + bool output_symbols, + size_t itemsize); + ~header_payload_demux_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_HEADER_PAYLOAD_DEMUX_IMPL_H */ + diff --git a/gr-digital/lib/map_bb_impl.cc b/gr-digital/lib/map_bb_impl.cc index 3a06394ec4..4ea91835a9 100644 --- a/gr-digital/lib/map_bb_impl.cc +++ b/gr-digital/lib/map_bb_impl.cc @@ -51,7 +51,7 @@ namespace gr { void map_bb_impl::set_map(const std::vector<int> &map) { - gruel::scoped_lock guard(d_mutex); + gr::thread::scoped_lock guard(d_mutex); for(int i = 0; i < 0x100; i++) d_map[i] = i; @@ -75,7 +75,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - gruel::scoped_lock guard(d_mutex); + gr::thread::scoped_lock guard(d_mutex); const unsigned char *in = (const unsigned char*)input_items[0]; unsigned char *out = (unsigned char*)output_items[0]; diff --git a/gr-digital/lib/map_bb_impl.h b/gr-digital/lib/map_bb_impl.h index bce2b9b1b3..59f1e834b7 100644 --- a/gr-digital/lib/map_bb_impl.h +++ b/gr-digital/lib/map_bb_impl.h @@ -24,7 +24,7 @@ #define INCLUDED_GR_MAP_BB_IMPL_H #include <digital/map_bb.h> -#include <gruel/thread.h> +#include <thread/thread.h> namespace gr { namespace digital { @@ -33,7 +33,7 @@ namespace gr { { private: unsigned char d_map[0x100]; - gruel::mutex d_mutex; + gr::thread::mutex d_mutex; public: map_bb_impl(const std::vector<int> &map); diff --git a/gr-digital/lib/mpsk_receiver_cc_impl.cc b/gr-digital/lib/mpsk_receiver_cc_impl.cc index 31355c5653..ea11b7cdaa 100644 --- a/gr-digital/lib/mpsk_receiver_cc_impl.cc +++ b/gr-digital/lib/mpsk_receiver_cc_impl.cc @@ -63,7 +63,7 @@ namespace gr { : gr_block("mpsk_receiver_cc", gr_make_io_signature(1, 1, sizeof(gr_complex)), gr_make_io_signature(1, 1, sizeof(gr_complex))), - gri_control_loop(loop_bw, fmax, fmin), + blocks::control_loop(loop_bw, fmax, fmin), d_M(M), d_theta(theta), d_current_const_point(0), d_mu(mu), d_gain_mu(gain_mu), d_gain_omega(gain_omega), diff --git a/gr-digital/lib/mpsk_receiver_cc_impl.h b/gr-digital/lib/mpsk_receiver_cc_impl.h index 3db6fa8b62..ed53d0f2e4 100644 --- a/gr-digital/lib/mpsk_receiver_cc_impl.h +++ b/gr-digital/lib/mpsk_receiver_cc_impl.h @@ -24,8 +24,8 @@ #define INCLUDED_DIGITAL_MPSK_RECEIVER_CC_IMPL_H #include <digital/mpsk_receiver_cc.h> -#include <gruel/attributes.h> -#include <gri_control_loop.h> +#include <attributes.h> +#include <blocks/control_loop.h> #include <gr_complex.h> #include <fstream> #include <filter/mmse_fir_interpolator_cc.h> @@ -34,7 +34,7 @@ namespace gr { namespace digital { class mpsk_receiver_cc_impl - : public mpsk_receiver_cc, public gri_control_loop + : public mpsk_receiver_cc, public blocks::control_loop { public: mpsk_receiver_cc_impl(unsigned int M, float theta, diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc new file mode 100644 index 0000000000..afeb10e1d5 --- /dev/null +++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc @@ -0,0 +1,193 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "ofdm_carrier_allocator_cvc_impl.h" + +namespace gr { + namespace digital { + + ofdm_carrier_allocator_cvc::sptr + ofdm_carrier_allocator_cvc::make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ) + { + return gnuradio::get_initial_sptr( + new ofdm_carrier_allocator_cvc_impl( + fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, + sync_words, + len_tag_key, + output_is_shifted + ) + ); + } + + ofdm_carrier_allocator_cvc_impl::ofdm_carrier_allocator_cvc_impl( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ) : gr_tagged_stream_block("ofdm_carrier_allocator_cvc", + gr_make_io_signature(1, 1, sizeof (gr_complex)), + gr_make_io_signature(1, 1, sizeof (gr_complex) * fft_len), len_tag_key), + d_fft_len(fft_len), + d_occupied_carriers(occupied_carriers), + d_pilot_carriers(pilot_carriers), + d_pilot_symbols(pilot_symbols), + d_sync_words(sync_words), + d_symbols_per_set(0), + d_output_is_shifted(output_is_shifted) + { + for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { + for (unsigned j = 0; j < d_occupied_carriers[i].size(); j++) { + if (occupied_carriers[i][j] < 0) { + d_occupied_carriers[i][j] += d_fft_len; + } + if (d_occupied_carriers[i][j] > d_fft_len || d_occupied_carriers[i][j] < 0) { + throw std::invalid_argument("data carrier index out of bounds"); + } + if (d_output_is_shifted) { + d_occupied_carriers[i][j] = (d_occupied_carriers[i][j] + fft_len/2) % fft_len; + } + } + } + for (unsigned i = 0; i < d_pilot_carriers.size(); i++) { + if (d_pilot_carriers[i].size() != pilot_symbols[i].size()) { + throw std::invalid_argument("pilot_carriers do not match pilot_symbols"); + } + for (unsigned j = 0; j < d_pilot_carriers[i].size(); j++) { + if (d_pilot_carriers[i][j] < 0) { + d_pilot_carriers[i][j] += d_fft_len; + } + if (d_pilot_carriers[i][j] > d_fft_len || d_pilot_carriers[i][j] < 0) { + throw std::invalid_argument("pilot carrier index out of bounds"); + } + if (d_output_is_shifted) { + d_pilot_carriers[i][j] = (d_pilot_carriers[i][j] + fft_len/2) % fft_len; + } + } + } + for (unsigned i = 0; i < d_sync_words.size(); i++) { + if (d_sync_words[i].size() != (unsigned) d_fft_len) { + throw std::invalid_argument("sync words must be fft length"); + } + } + + for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { + d_symbols_per_set += d_occupied_carriers[i].size(); + } + set_tag_propagation_policy(TPP_DONT); + set_relative_rate((double) d_symbols_per_set / d_occupied_carriers.size()); + } + + ofdm_carrier_allocator_cvc_impl::~ofdm_carrier_allocator_cvc_impl() + { + } + + int + ofdm_carrier_allocator_cvc_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) + { + int nin = ninput_items[0]; + int nout = (nin / d_symbols_per_set) * d_occupied_carriers.size(); + int k = 0; + for (int i = 0; i < nin % d_symbols_per_set; k++) { + nout++; + i += d_occupied_carriers[k % d_occupied_carriers.size()].size(); + } + return nout + d_sync_words.size(); + } + + int + ofdm_carrier_allocator_cvc_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + std::vector<gr_tag_t> tags; + + memset((void *) out, 0x00, sizeof(gr_complex) * d_fft_len * noutput_items); + // Copy Sync word + for (unsigned i = 0; i < d_sync_words.size(); i++) { + memcpy((void *) out, (void *) &d_sync_words[i][0], sizeof(gr_complex) * d_fft_len); + out += d_fft_len; + } + + // Copy data symbols + long n_ofdm_symbols = 0; + int curr_set = 0; + int symbols_to_allocate = d_occupied_carriers[0].size(); + int symbols_allocated = 0; + for (int i = 0; i < ninput_items[0]; i++) { + if (symbols_allocated == 0) { + // Copy all tags associated with these input symbols onto this OFDM symbol + get_tags_in_range(tags, 0, + nitems_read(0)+i, + nitems_read(0)+std::min(i+symbols_to_allocate, (int) ninput_items[0]) + ); + for (unsigned t = 0; t < tags.size(); t++) { + add_item_tag(0, nitems_written(0)+n_ofdm_symbols, + tags[t].key, + tags[t].value); + } + n_ofdm_symbols++; + } + out[(n_ofdm_symbols-1) * d_fft_len + d_occupied_carriers[curr_set][symbols_allocated]] = in[i]; + symbols_allocated++; + if (symbols_allocated == symbols_to_allocate) { + curr_set = (curr_set + 1) % d_occupied_carriers.size(); + symbols_to_allocate = d_occupied_carriers[curr_set].size(); + symbols_allocated = 0; + } + } + // Copy pilot symbols + curr_set = 0; + for (int i = 0; i < n_ofdm_symbols; i++) { + for (unsigned k = 0; k < d_pilot_carriers[curr_set].size(); k++) { + out[i * d_fft_len + d_pilot_carriers[curr_set][k]] = d_pilot_symbols[curr_set][k]; + } + curr_set = (curr_set + 1) % d_pilot_carriers.size(); + } + + return n_ofdm_symbols + d_sync_words.size(); + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h new file mode 100644 index 0000000000..6e478b3389 --- /dev/null +++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H +#define INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H + +#include <digital/ofdm_carrier_allocator_cvc.h> + +namespace gr { + namespace digital { + + class ofdm_carrier_allocator_cvc_impl : public ofdm_carrier_allocator_cvc + { + private: + //! FFT length + const int d_fft_len; + //! Which carriers/symbols carry data + std::vector<std::vector<int> > d_occupied_carriers; + //! Which carriers/symbols carry pilots symbols + std::vector<std::vector<int> > d_pilot_carriers; + //! Value of said pilot symbols + const std::vector<std::vector<gr_complex> > d_pilot_symbols; + //! Synch words + const std::vector<std::vector<gr_complex> > d_sync_words; + int d_symbols_per_set; + const bool d_output_is_shifted; + + protected: + int calculate_output_stream_length(const gr_vector_int &ninput_items); + + public: + ofdm_carrier_allocator_cvc_impl( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ); + ~ofdm_carrier_allocator_cvc_impl(); + + std::string len_tag_key() { return d_length_tag_key_str; }; + + const int fft_len() { return d_fft_len; }; + std::vector<std::vector<int> > occupied_carriers() { return d_occupied_carriers; }; + + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_CARRIER_ALLOCATOR_CVC_IMPL_H */ + diff --git a/gr-digital/lib/ofdm_chanest_vcvc_impl.cc b/gr-digital/lib/ofdm_chanest_vcvc_impl.cc new file mode 100644 index 0000000000..d0d8faba59 --- /dev/null +++ b/gr-digital/lib/ofdm_chanest_vcvc_impl.cc @@ -0,0 +1,273 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "ofdm_chanest_vcvc_impl.h" + +namespace gr { + namespace digital { + + ofdm_chanest_vcvc::sptr + ofdm_chanest_vcvc::make(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol) + { + return gnuradio::get_initial_sptr ( + new ofdm_chanest_vcvc_impl( + sync_symbol1, + sync_symbol2, + n_data_symbols, + eq_noise_red_len, + max_carr_offset, + force_one_sync_symbol + ) + ); + } + + ofdm_chanest_vcvc_impl::ofdm_chanest_vcvc_impl(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol) + : gr_block("ofdm_chanest_vcvc", + gr_make_io_signature(1, 1, sizeof (gr_complex) * sync_symbol1.size()), + gr_make_io_signature(1, 1, sizeof (gr_complex) * sync_symbol1.size())), + d_fft_len(sync_symbol1.size()), + d_n_data_syms(n_data_symbols), + d_n_sync_syms(1), + d_eq_noise_red_len(eq_noise_red_len), + d_ref_sym((sync_symbol2.size() && !force_one_sync_symbol) ? sync_symbol2 : sync_symbol1), + d_corr_v(sync_symbol2), + d_known_symbol_diffs(0, 0), + d_new_symbol_diffs(0, 0), + d_interpolate(false) + { + // Set index of first and last active carrier + for (int i = 0; i < d_fft_len; i++) { + if (d_ref_sym[i] != gr_complex(0, 0)) { + d_first_active_carrier = i; + break; + } + } + for (int i = d_fft_len-1; i >= 0; i--) { + if (d_ref_sym[i] != gr_complex(0, 0)) { + d_last_active_carrier = i; + break; + } + } + + // Sanity checks + if (sync_symbol2.size()) { + if (sync_symbol1.size() != sync_symbol2.size()) { + throw std::invalid_argument("sync symbols must have equal length."); + } + if (!force_one_sync_symbol) { + d_n_sync_syms = 2; + } + } else { + if (sync_symbol1[d_first_active_carrier+1] == gr_complex(0, 0)) { + d_last_active_carrier++; + d_interpolate = true; + } + } + + // Set up coarse freq estimation info + // Allow all possible values: + d_max_neg_carr_offset = -d_first_active_carrier; + d_max_pos_carr_offset = d_fft_len - d_last_active_carrier - 1; + if (max_carr_offset != -1) { + d_max_neg_carr_offset = std::max(-max_carr_offset, d_max_neg_carr_offset); + d_max_pos_carr_offset = std::min(max_carr_offset, d_max_pos_carr_offset); + } + // Carrier offsets must be even + if (d_max_neg_carr_offset % 2) + d_max_neg_carr_offset++; + if (d_max_pos_carr_offset % 2) + d_max_pos_carr_offset--; + + if (d_n_sync_syms == 2) { + for (int i = 0; i < d_fft_len; i++) { + if (sync_symbol1[i] == gr_complex(0, 0)) { + d_corr_v[i] = gr_complex(0, 0); + } else { + d_corr_v[i] /= sync_symbol1[i]; + } + } + } else { + d_corr_v.resize(0, 0); + d_known_symbol_diffs.resize(d_fft_len, 0); + d_new_symbol_diffs.resize(d_fft_len, 0); + for (int i = d_first_active_carrier; i < d_last_active_carrier-2 && i < d_fft_len-2; i += 2) { + d_known_symbol_diffs[i] = std::norm(sync_symbol1[i] - sync_symbol1[i+2]); + } + } + + set_relative_rate((double) n_data_symbols / (n_data_symbols + d_n_sync_syms)); + set_tag_propagation_policy(TPP_DONT); + } + + ofdm_chanest_vcvc_impl::~ofdm_chanest_vcvc_impl() + { + } + + void + ofdm_chanest_vcvc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = (noutput_items/d_n_data_syms) * (d_n_data_syms + d_n_sync_syms); + } + + int + ofdm_chanest_vcvc_impl::get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2) + { + int carr_offset = 0; + if (d_corr_v.size()) { + // Use Schmidl & Cox method + float Bg_max = 0; + // g here is 2g in the paper + for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) { + gr_complex tmp = gr_complex(0, 0); + for (int k = 0; k < d_fft_len; k++) { + if (d_corr_v[k] != gr_complex(0, 0)) { + tmp += std::conj(sync_sym1[k+g]) * std::conj(d_corr_v[k]) * sync_sym2[k+g]; + } + } + if (std::abs(tmp) > Bg_max) { + Bg_max = std::abs(tmp); + carr_offset = g; + } + } + } else { + // Correlate + std::fill(d_new_symbol_diffs.begin(), d_new_symbol_diffs.end(), 0); + for(int i = 0; i < d_fft_len-2; i++) { + d_new_symbol_diffs[i] = std::norm(sync_sym1[i] - sync_sym1[i+2]); + } + + float sum; + float max = 0; + for (int g = d_max_neg_carr_offset; g <= d_max_pos_carr_offset; g += 2) { + sum = 0; + for (int j = 0; j < d_fft_len; j++) { + if (d_known_symbol_diffs[j]) { + sum += (d_known_symbol_diffs[j] * d_new_symbol_diffs[j + g]); + } + if(sum > max) { + max = sum; + carr_offset = g; + } + } + } + } + return carr_offset; + } + + + void + ofdm_chanest_vcvc_impl::get_chan_taps( + const gr_complex *sync_sym1, + const gr_complex *sync_sym2, + int carr_offset, + std::vector<gr_complex> &taps) + { + const gr_complex *sym = ((d_n_sync_syms == 2) ? sync_sym2 : sync_sym1); + std::fill(taps.begin(), taps.end(), gr_complex(0, 0)); + int loop_start = 0; + int loop_end = d_fft_len; + if (carr_offset > 0) { + loop_start = carr_offset; + } else if (carr_offset < 0) { + loop_end = d_fft_len + carr_offset; + } + for (int i = loop_start; i < loop_end; i++) { + if ((d_ref_sym[i-carr_offset] != gr_complex(0, 0))) { + taps[i] = sym[i] / d_ref_sym[i-carr_offset]; + } + } + + if (d_interpolate) { + for (int i = d_first_active_carrier + 1; i < d_last_active_carrier; i += 2) { + taps[i] = (taps[i-1] + taps[i+1]) / gr_complex(2.0, 0); + } + taps[d_last_active_carrier] = taps[d_last_active_carrier-1]; + } + + if (d_eq_noise_red_len) { + // TODO + // 1) IFFT + // 2) Set all elements > d_eq_noise_red_len to zero + // 3) FFT + } + } + + + int + ofdm_chanest_vcvc_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + int n_frames = noutput_items/d_n_data_syms; + const int framesize = d_n_sync_syms + d_n_data_syms; + + for (int i = 0; i < n_frames; i++) { + int carr_offset = 0; + if (d_max_neg_carr_offset || d_max_pos_carr_offset) + carr_offset = get_carr_offset(in, in+d_fft_len); + std::vector<gr_complex> chan_taps(d_fft_len, 0); + get_chan_taps(in, in+d_fft_len, carr_offset, chan_taps); + + memcpy((void *) out, + (void *) &in[d_n_sync_syms * d_fft_len], + sizeof(gr_complex) * d_fft_len * d_n_data_syms); + in += framesize * d_fft_len; + out += d_n_data_syms * d_fft_len; + + std::vector<gr_tag_t> tags; + this->get_tags_in_range(tags, 0, + this->nitems_read(0)+i*framesize, + this->nitems_read(0)+(i+1)*framesize); + for (unsigned t = 0; t < tags.size(); t++) { + int offset = tags[t].offset - (this->nitems_read(0) + i*framesize); + if (offset < d_n_sync_syms) { + offset = 0; + } else { + offset -= d_n_sync_syms; + } + tags[t].offset = offset + this->nitems_written(0) + i*d_n_data_syms; + this->add_item_tag(0, tags[t]); + } + + this->add_item_tag(0, this->nitems_written(0) + i*d_n_data_syms, + pmt::string_to_symbol("ofdm_sync_carr_offset"), + pmt::from_long(carr_offset)); + this->add_item_tag(0, this->nitems_written(0) + i*d_n_data_syms, + pmt::string_to_symbol("ofdm_sync_chan_taps"), + pmt::init_c32vector(d_fft_len, chan_taps)); + } + + consume_each(n_frames * framesize); + return n_frames * d_n_data_syms; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_chanest_vcvc_impl.h b/gr-digital/lib/ofdm_chanest_vcvc_impl.h new file mode 100644 index 0000000000..def8734e64 --- /dev/null +++ b/gr-digital/lib/ofdm_chanest_vcvc_impl.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_IMPL_H +#define INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_IMPL_H + +#include <digital/ofdm_chanest_vcvc.h> + +namespace gr { + namespace digital { + + class ofdm_chanest_vcvc_impl : public ofdm_chanest_vcvc + { + private: + int d_fft_len; //! FFT length + int d_n_data_syms; //! Number of data symbols following the sync symbol(s) + int d_n_sync_syms; //! Number of sync symbols (1 or 2) + //! 0 if no noise reduction is done for the initial channel state estimation. Otherwise, the maximum length of the channel delay in samples. + int d_eq_noise_red_len; + //! Is sync_symbol1 if d_n_sync_syms == 1, otherwise sync_symbol2. Used as a reference symbol to estimate the channel. + std::vector<gr_complex> d_ref_sym; + //! If d_n_sync_syms == 2 this is used as a differential correlation vector (called 'v' in [1]). + std::vector<gr_complex> d_corr_v; + //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset + std::vector<float> d_known_symbol_diffs; + //! If d_n_sync_syms == 1 we use this instead of d_corr_v to estimate the coarse freq. offset (temp. variable) + std::vector<float> d_new_symbol_diffs; + //! The index of the first carrier with data (index 0 is not DC here, but the lowest frequency) + int d_first_active_carrier; + //! The index of the last carrier with data + int d_last_active_carrier; + //! If true, the channel estimation must be interpolated + bool d_interpolate; + //! Maximum carrier offset (negative value!) + int d_max_neg_carr_offset; + //! Maximum carrier offset (positive value!) + int d_max_pos_carr_offset; + + //! Calculate the coarse frequency offset in number of carriers + int get_carr_offset(const gr_complex *sync_sym1, const gr_complex *sync_sym2); + //! Estimate the channel (phase and amplitude offset per carrier) + void get_chan_taps(const gr_complex *sync_sym1, const gr_complex *sync_sym2, int carr_offset, std::vector<gr_complex> &taps); + + public: + ofdm_chanest_vcvc_impl(const std::vector<gr_complex> &sync_symbol1, const std::vector<gr_complex> &sync_symbol2, int n_data_symbols, int eq_noise_red_len, int max_carr_offset, bool force_one_sync_symbol); + ~ofdm_chanest_vcvc_impl(); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_CHANEST_VCVC_IMPL_H */ + diff --git a/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc b/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc index 67cfba615f..d48c5f7e45 100644 --- a/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc +++ b/gr-digital/lib/ofdm_cyclic_prefixer_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010-2012 Free Software Foundation, Inc. +/* + * Copyright 2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,56 +24,142 @@ #include "config.h" #endif -#include "ofdm_cyclic_prefixer_impl.h" #include <gr_io_signature.h> +#include "ofdm_cyclic_prefixer_impl.h" namespace gr { namespace digital { - + ofdm_cyclic_prefixer::sptr - ofdm_cyclic_prefixer::make(size_t input_size, size_t output_size) + ofdm_cyclic_prefixer::make(size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key) { - return gnuradio::get_initial_sptr - (new ofdm_cyclic_prefixer_impl(input_size, output_size)); + return gnuradio::get_initial_sptr (new ofdm_cyclic_prefixer_impl(input_size, output_size, rolloff_len, len_tag_key)); } - ofdm_cyclic_prefixer_impl::ofdm_cyclic_prefixer_impl(size_t input_size, - size_t output_size) - : gr_sync_interpolator("ofdm_cyclic_prefixer", - gr_make_io_signature(1, 1, input_size*sizeof(gr_complex)), - gr_make_io_signature(1, 1, sizeof(gr_complex)), - output_size), - d_input_size(input_size), - d_output_size(output_size) + + ofdm_cyclic_prefixer_impl::ofdm_cyclic_prefixer_impl(size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key) + : gr_tagged_stream_block ("ofdm_cyclic_prefixer", + gr_make_io_signature (1, 1, input_size*sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + len_tag_key), + d_fft_len(input_size), + d_output_size(output_size), + d_cp_size(output_size - input_size), + d_rolloff_len(rolloff_len), + d_up_flank((rolloff_len ? rolloff_len-1 : 0), 0), + d_down_flank((rolloff_len ? rolloff_len-1 : 0), 0), + d_delay_line(0, 0) { + set_relative_rate(d_output_size); + + // Flank of length 1 would just be rectangular + if (d_rolloff_len == 1) { + d_rolloff_len = 0; + } + if (d_rolloff_len) { + d_delay_line.resize(d_rolloff_len-1, 0); + if (rolloff_len > d_cp_size) { + throw std::invalid_argument("cyclic prefixer: rolloff len must smaller than the cyclic prefix."); + } + // The actual flanks are one sample shorter than d_rolloff_len, because the + // first sample of the up- and down flank is always zero and one, respectively + for (int i = 1; i < d_rolloff_len; i++) { + d_up_flank[i-1] = 0.5 * (1 + cos(M_PI * i/rolloff_len - M_PI)); + d_down_flank[i-1] = 0.5 * (1 + cos(M_PI * (rolloff_len-i)/rolloff_len - M_PI)); + } + } + + if (len_tag_key.empty()) { + set_output_multiple(d_output_size); + } else { + set_tag_propagation_policy(TPP_DONT); + } } ofdm_cyclic_prefixer_impl::~ofdm_cyclic_prefixer_impl() { } + int - ofdm_cyclic_prefixer_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + ofdm_cyclic_prefixer_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) { - gr_complex *in = (gr_complex*)input_items[0]; - gr_complex *out = (gr_complex*)output_items[0]; - size_t cp_size = d_output_size - d_input_size; - unsigned int i=0, j=0; - - j = cp_size; - for(i=0; i < d_input_size; i++,j++) { - out[j] = in[i]; + int nout = ninput_items[0] * d_output_size + d_delay_line.size(); + return nout; + } + + + // Operates in two ways: + // - When there's a length tag name specified, operates in packet mode. + // Here, an entire OFDM frame is processed at once. The final OFDM symbol + // is postfixed with the delay line of the pulse shape. + // We manually propagate tags. + // - Otherwise, we're in freewheeling mode. Process as many OFDM symbols as + // are space for in the output buffer. The delay line is never flushed. + // Tags are propagated by the scheduler. + int + ofdm_cyclic_prefixer_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + int symbols_to_read = 0; + + // 1) Figure out if we're in freewheeling or packet mode + if (!d_length_tag_key_str.empty()) { + symbols_to_read = ninput_items[0]; + noutput_items = symbols_to_read * d_output_size + d_delay_line.size(); + } else { + symbols_to_read = std::min(noutput_items / (int) d_output_size, ninput_items[0]); + noutput_items = symbols_to_read * d_output_size; + } + + // 2) Do the cyclic prefixing and, optionally, the pulse shaping + for (int sym_idx = 0; sym_idx < symbols_to_read; sym_idx++) { + memcpy((void *)(out + d_cp_size), (void *) in, d_fft_len * sizeof(gr_complex)); + memcpy((void *) out, (void *) (in + d_fft_len - d_cp_size), d_cp_size * sizeof(gr_complex)); + if (d_rolloff_len) { + for (int i = 0; i < d_rolloff_len-1; i++) { + out[i] = out[i] * d_up_flank[i] + d_delay_line[i]; + d_delay_line[i] = in[i] * d_down_flank[i]; + } + } + in += d_fft_len; + out += d_output_size; } - j = d_input_size - cp_size; - for(i=0; i < cp_size; i++, j++) { - out[i] = in[j]; + // 3) If we're in packet mode: + // - flush the delay line, if applicable + // - Propagate tags + if (!d_length_tag_key_str.empty()) { + if (d_rolloff_len) { + for (unsigned i = 0; i < d_delay_line.size(); i++) { + *out++ = d_delay_line[i]; + } + d_delay_line.assign(d_delay_line.size(), 0); + } + std::vector<gr_tag_t> tags; + get_tags_in_range( + tags, 0, + nitems_read(0), nitems_read(0)+symbols_to_read + ); + for (unsigned i = 0; i < tags.size(); i++) { + tags[i].offset = ((tags[i].offset - nitems_read(0)) * d_output_size) + nitems_written(0); + add_item_tag(0, + tags[i].offset, + tags[i].key, + tags[i].value + ); + } + } else { + consume_each(symbols_to_read); } - return d_output_size; + return noutput_items; } } /* namespace digital */ } /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_cyclic_prefixer_impl.h b/gr-digital/lib/ofdm_cyclic_prefixer_impl.h index 20f0489d7c..5a5766f131 100644 --- a/gr-digital/lib/ofdm_cyclic_prefixer_impl.h +++ b/gr-digital/lib/ofdm_cyclic_prefixer_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ -/* - * Copyright 2004-2006,2011,2012 Free Software Foundation, Inc. +/* + * Copyright 2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,23 +27,38 @@ namespace gr { namespace digital { - + class ofdm_cyclic_prefixer_impl : public ofdm_cyclic_prefixer { - private: - size_t d_input_size; + private: + size_t d_fft_len; + //! FFT length + CP length in samples size_t d_output_size; + //! Length of the cyclic prefix in samples + int d_cp_size; + //! Length of pulse rolloff in samples + int d_rolloff_len; + //! Buffers the up-flank (at the beginning of the cyclic prefix) + std::vector<float> d_up_flank; + //! Buffers the down-flank (which trails the symbol) + std::vector<float> d_down_flank; + std::vector<gr_complex> d_delay_line; // We do this explicitly to avoid outputting zeroes (i.e. no history!) + + protected: + int calculate_output_stream_length(const gr_vector_int &ninput_items); - public: - ofdm_cyclic_prefixer_impl(size_t input_size, size_t output_size); + public: + ofdm_cyclic_prefixer_impl(size_t input_size, size_t output_size, int rolloff_len, const std::string &len_tag_key); ~ofdm_cyclic_prefixer_impl(); int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; - } /* namespace digital */ -} /* namespace gr */ + } // namespace digital +} // namespace gr #endif /* INCLUDED_DIGITAL_OFDM_CYCLIC_PREFIXER_IMPL_H */ + diff --git a/gr-digital/lib/ofdm_equalizer_base.cc b/gr-digital/lib/ofdm_equalizer_base.cc new file mode 100644 index 0000000000..5209b09c29 --- /dev/null +++ b/gr-digital/lib/ofdm_equalizer_base.cc @@ -0,0 +1,121 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital/ofdm_equalizer_base.h> + +namespace gr { + namespace digital { + + // *** Base class **************************************************** + ofdm_equalizer_base::ofdm_equalizer_base(int fft_len) : + d_fft_len(fft_len), + d_carr_offset(0) + { + } + + + ofdm_equalizer_base::~ofdm_equalizer_base() + { + } + + + // *** Sub-Base class for 1D equalizers using pilot tones ************* + ofdm_equalizer_1d_pilots::ofdm_equalizer_1d_pilots( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + bool input_is_shifted) + : ofdm_equalizer_base(fft_len), + d_occupied_carriers(fft_len, false), + d_pilot_carriers(pilot_carriers.size(), std::vector<bool>(fft_len, false)), + d_pilot_symbols(pilot_symbols.size(), std::vector<gr_complex>(fft_len, gr_complex(0, 0))), + d_symbols_skipped(symbols_skipped), + d_pilot_carr_set(symbols_skipped), + d_channel_state(fft_len, gr_complex(1, 0)) + { + int fft_shift_width = 0; + if (input_is_shifted) { + fft_shift_width = fft_len/2; + } + if (!occupied_carriers.size()) { + std::fill(d_occupied_carriers.begin(), d_occupied_carriers.end(), true); + } else { + for (unsigned i = 0; i < occupied_carriers.size(); i++) { + for (unsigned k = 0; k < occupied_carriers[i].size(); k++) { + int carr_index = occupied_carriers[i][k]; + if (occupied_carriers[i][k] < 0) { + carr_index += fft_len; + } + if (carr_index >= fft_len || carr_index < 0) { + throw std::invalid_argument("data carrier index out of bounds."); + } + d_occupied_carriers[(carr_index + fft_shift_width) % fft_len] = true; + } + } + } + if (pilot_carriers.size()) { + for (unsigned i = 0; i < pilot_carriers.size(); i++) { + if (pilot_carriers[i].size() != pilot_symbols[i].size()) { + throw std::invalid_argument("pilot carriers and -symbols do not match."); + } + for (unsigned k = 0; k < pilot_carriers[i].size(); k++) { + int carr_index = pilot_carriers[i][k]; + if (pilot_carriers[i][k] < 0) { + carr_index += fft_len; + } + if (carr_index >= fft_len || carr_index < 0) { + throw std::invalid_argument("pilot carrier index out of bounds."); + } + d_pilot_carriers[i][(carr_index + fft_shift_width) % fft_len] = true; + d_pilot_symbols[i][(carr_index + fft_shift_width) % fft_len] = pilot_symbols[i][k]; + } + } + } + } + + + ofdm_equalizer_1d_pilots::~ofdm_equalizer_1d_pilots() + { + } + + + void + ofdm_equalizer_1d_pilots::reset() + { + std::fill(d_channel_state.begin(), d_channel_state.end(), gr_complex(1, 0)); + d_pilot_carr_set = d_symbols_skipped; + } + + + void ofdm_equalizer_1d_pilots::get_channel_state(std::vector<gr_complex> &taps) + { + taps = d_channel_state; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_equalizer_simpledfe.cc b/gr-digital/lib/ofdm_equalizer_simpledfe.cc new file mode 100644 index 0000000000..fcb0e18cbf --- /dev/null +++ b/gr-digital/lib/ofdm_equalizer_simpledfe.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital/ofdm_equalizer_simpledfe.h> + +namespace gr { + namespace digital { + + ofdm_equalizer_simpledfe::sptr + ofdm_equalizer_simpledfe::make( + int fft_len, + const gr::digital::constellation_sptr &constellation, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + float alpha, + bool input_is_shifted) + { + return ofdm_equalizer_simpledfe::sptr( + new ofdm_equalizer_simpledfe( + fft_len, + constellation, + occupied_carriers, + pilot_carriers, + pilot_symbols, + symbols_skipped, + alpha, + input_is_shifted + ) + ); + } + + ofdm_equalizer_simpledfe::ofdm_equalizer_simpledfe( + int fft_len, + const gr::digital::constellation_sptr &constellation, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + float alpha, + bool input_is_shifted) + : ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted), + d_constellation(constellation), + d_alpha(alpha) + { + } + + + ofdm_equalizer_simpledfe::~ofdm_equalizer_simpledfe() + { + } + + + void + ofdm_equalizer_simpledfe::equalize(gr_complex *frame, + int n_sym, + const std::vector<gr_complex> &initial_taps, + const std::vector<gr_tag_t> &tags) + { + if (!initial_taps.empty()) { + d_channel_state = initial_taps; + } + gr_complex sym_eq, sym_est; + + for (int i = 0; i < n_sym; i++) { + for (int k = 0; k < d_fft_len; k++) { + if (!d_occupied_carriers[k]) { + continue; + } + if (d_pilot_carriers.size() && d_pilot_carriers[d_pilot_carr_set][k-d_carr_offset]) { + d_channel_state[k] = d_alpha * d_channel_state[k] + + (1-d_alpha) * frame[i*d_fft_len + k] / d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset]; + frame[i*d_fft_len+k] = d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset]; + } else { + sym_eq = frame[i*d_fft_len+k] / d_channel_state[k]; + d_constellation->map_to_points(d_constellation->decision_maker(&sym_eq), &sym_est); + d_channel_state[k] = d_alpha * d_channel_state[k] + frame[i*d_fft_len+k] / sym_est; + frame[i*d_fft_len+k] = sym_est; + } + } + d_pilot_carr_set = (d_pilot_carr_set + 1) % d_pilot_carriers.size(); + } + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_equalizer_static.cc b/gr-digital/lib/ofdm_equalizer_static.cc new file mode 100644 index 0000000000..8601eff430 --- /dev/null +++ b/gr-digital/lib/ofdm_equalizer_static.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital/ofdm_equalizer_static.h> + +namespace gr { + namespace digital { + + ofdm_equalizer_static::sptr + ofdm_equalizer_static::make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + bool input_is_shifted) + { + return ofdm_equalizer_static::sptr( + new ofdm_equalizer_static( + fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, + symbols_skipped, + input_is_shifted + ) + ); + } + + ofdm_equalizer_static::ofdm_equalizer_static( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + int symbols_skipped, + bool input_is_shifted) + : ofdm_equalizer_1d_pilots(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, symbols_skipped, input_is_shifted) + { + } + + + ofdm_equalizer_static::~ofdm_equalizer_static() + { + } + + + void + ofdm_equalizer_static::equalize(gr_complex *frame, + int n_sym, + const std::vector<gr_complex> &initial_taps, + const std::vector<gr_tag_t> &tags) + { + d_channel_state = initial_taps; + + for (int i = 0; i < n_sym; i++) { + for (int k = 0; k < d_fft_len; k++) { + if (!d_occupied_carriers[k]) { + continue; + } + if (d_pilot_carriers.size() && d_pilot_carriers[d_pilot_carr_set][k-d_carr_offset]) { + d_channel_state[k] = frame[i*d_fft_len + k] / d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset]; + frame[i*d_fft_len+k] = d_pilot_symbols[d_pilot_carr_set][k-d_carr_offset]; + } else { + frame[i*d_fft_len+k] /= d_channel_state[k]; + } + } + if (!d_pilot_carriers.empty()) { + d_pilot_carr_set = (d_pilot_carr_set + 1) % d_pilot_carriers.size(); + } + } + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc new file mode 100644 index 0000000000..594b2df838 --- /dev/null +++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "ofdm_frame_equalizer_vcvc_impl.h" + +namespace gr { + namespace digital { + + ofdm_frame_equalizer_vcvc::sptr + ofdm_frame_equalizer_vcvc::make(ofdm_equalizer_base::sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state) + { + return gnuradio::get_initial_sptr ( + new ofdm_frame_equalizer_vcvc_impl( + equalizer, len_tag_key, propagate_channel_state + ) + ); + } + + ofdm_frame_equalizer_vcvc_impl::ofdm_frame_equalizer_vcvc_impl(ofdm_equalizer_base::sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state) + : gr_tagged_stream_block("ofdm_frame_equalizer_vcvc", + gr_make_io_signature(1, 1, sizeof (gr_complex) * equalizer->fft_len()), + gr_make_io_signature(1, 1, sizeof (gr_complex) * equalizer->fft_len()), + len_tag_key), + d_fft_len(equalizer->fft_len()), + d_eq(equalizer), + d_propagate_channel_state(propagate_channel_state), + d_channel_state(equalizer->fft_len(), gr_complex(1, 0)) + {} + + ofdm_frame_equalizer_vcvc_impl::~ofdm_frame_equalizer_vcvc_impl() + { + } + + + int + ofdm_frame_equalizer_vcvc_impl::work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + int carrier_offset = 0; + + std::vector<gr_tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + for (unsigned i = 0; i < tags.size(); i++) { + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_chan_taps") { + d_channel_state = pmt::c32vector_elements(tags[i].value); + remove_item_tag(0, tags[i]); + } + } + + memcpy((void *) out, (void *) in, sizeof(gr_complex) * d_fft_len * ninput_items[0]); + d_eq->reset(); + d_eq->set_carrier_offset(carrier_offset); + d_eq->equalize(out, ninput_items[0], d_channel_state); + d_eq->get_channel_state(d_channel_state); + if (d_propagate_channel_state) { + add_item_tag(0, nitems_written(0), + pmt::string_to_symbol("ofdm_sync_chan_taps"), + pmt::init_c32vector(d_fft_len, d_channel_state)); + } + + return ninput_items[0]; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h new file mode 100644 index 0000000000..f86451e839 --- /dev/null +++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H +#define INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H + +#include <digital/ofdm_frame_equalizer_vcvc.h> + +namespace gr { + namespace digital { + + class ofdm_frame_equalizer_vcvc_impl : public ofdm_frame_equalizer_vcvc + { + private: + const int d_fft_len; + ofdm_equalizer_base::sptr d_eq; + bool d_propagate_channel_state; + std::vector<gr_complex> d_channel_state; + + protected: + // These aren't really necessary, so let's override them with nuthin' + void remove_length_tags(const std::vector<std::vector<gr_tag_t> > &tags) {}; + void update_length_tags(int n_produced, int n_ports) {}; + + public: + ofdm_frame_equalizer_vcvc_impl(ofdm_equalizer_base::sptr equalizer, const std::string &len_tag_key, bool propagate_channel_state); + ~ofdm_frame_equalizer_vcvc_impl(); + + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_FRAME_EQUALIZER_VCVC_IMPL_H */ + diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.cc b/gr-digital/lib/ofdm_serializer_vcc_impl.cc new file mode 100644 index 0000000000..09c0039a1c --- /dev/null +++ b/gr-digital/lib/ofdm_serializer_vcc_impl.cc @@ -0,0 +1,205 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "ofdm_serializer_vcc_impl.h" + +namespace gr { + namespace digital { + + ofdm_serializer_vcc::sptr + ofdm_serializer_vcc::make( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::string &len_tag_key, + const std::string &packet_len_tag_key, + int symbols_skipped, + bool input_is_shifted + ) + { + return gnuradio::get_initial_sptr ( + new ofdm_serializer_vcc_impl( + fft_len, occupied_carriers, + len_tag_key, packet_len_tag_key, + symbols_skipped, input_is_shifted + ) + ); + } + + ofdm_serializer_vcc::sptr + ofdm_serializer_vcc::make( + const gr::digital::ofdm_carrier_allocator_cvc::sptr &allocator, + const std::string &packet_len_tag_key, + int symbols_skipped, + bool input_is_shifted + ) + { + return gnuradio::get_initial_sptr( + new ofdm_serializer_vcc_impl( + allocator->fft_len(), + allocator->occupied_carriers(), + allocator->len_tag_key(), + packet_len_tag_key, + symbols_skipped, + input_is_shifted + ) + ); + } + + ofdm_serializer_vcc_impl::ofdm_serializer_vcc_impl ( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::string &len_tag_key, + const std::string &packet_len_tag_key, + int symbols_skipped, + bool input_is_shifted) + : gr_tagged_stream_block ("ofdm_serializer_vcc", + gr_make_io_signature(1, 1, sizeof (gr_complex) * fft_len), + gr_make_io_signature(1, 1, sizeof (gr_complex)), + len_tag_key), + d_fft_len(fft_len), + d_occupied_carriers(occupied_carriers), + d_packet_len_tag_key(pmt::string_to_symbol(packet_len_tag_key)), + d_out_len_tag_key(pmt::string_to_symbol((packet_len_tag_key.empty() ? len_tag_key : packet_len_tag_key))), + d_symbols_skipped(symbols_skipped % occupied_carriers.size()), + d_curr_set(symbols_skipped % occupied_carriers.size()), + d_symbols_per_set(0) + { + for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { + for (unsigned k = 0; k < d_occupied_carriers[i].size(); k++) { + if (d_occupied_carriers[i][k] < 0) { + d_occupied_carriers[i][k] += fft_len; + } + if (d_occupied_carriers[i][k] >= fft_len || d_occupied_carriers[i][k] < 0) { + throw std::invalid_argument("ofdm_serializer_vcc: trying to occupy a carrier outside the fft length."); + } + if (input_is_shifted) { + d_occupied_carriers[i][k] = (d_occupied_carriers[i][k] + fft_len) % fft_len; + } + } + } + + for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { + d_symbols_per_set += d_occupied_carriers[i].size(); + } + set_relative_rate((double) d_symbols_per_set / d_occupied_carriers.size()); + set_tag_propagation_policy(TPP_DONT); + } + + ofdm_serializer_vcc_impl::~ofdm_serializer_vcc_impl() + { + } + + int + ofdm_serializer_vcc_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) + { + int nout = (ninput_items[0] / d_occupied_carriers.size()) * d_symbols_per_set; + for (unsigned i = 0; i < ninput_items[0] % d_occupied_carriers.size(); i++) { + nout += d_occupied_carriers[(i + d_curr_set) % d_occupied_carriers.size()].size(); + } + return nout; + } + + void + ofdm_serializer_vcc_impl::update_length_tags(int n_produced, int n_ports) + { + add_item_tag(0, nitems_written(0), + d_out_len_tag_key, + pmt::from_long(n_produced) + ); + } + + int + ofdm_serializer_vcc_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + long frame_length = ninput_items[0]; // Input frame + long packet_length = 0; // Output frame + int carr_offset = 0; + + std::vector<gr_tag_t> tags; + // Packet mode + if (!d_length_tag_key_str.empty()) { + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+1); + for (unsigned i = 0; i < tags.size(); i++) { + if (pmt::symbol_to_string(tags[i].key) == "ofdm_sync_carr_offset") { + carr_offset = pmt::to_long(tags[i].value); + } + if (tags[i].key == d_packet_len_tag_key) { + packet_length = pmt::to_long(tags[i].value); + remove_item_tag(0, tags[i]); + } + } + } else { + // recalc frame length from noutput_items + frame_length = 0; + int sym_per_frame = 0; + while ((sym_per_frame + d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size()) < noutput_items) { + frame_length++; + sym_per_frame += d_occupied_carriers[(frame_length + 1) % d_occupied_carriers.size()].size(); + } + } + + // Copy symbols + int n_out_symbols = 0; + for (int i = 0; i < frame_length; i++) { + // Copy all tags associated with this input OFDM symbol onto the first output symbol + get_tags_in_range(tags, 0, + nitems_read(0)+i, + nitems_read(0)+i+1 + ); + for (unsigned t = 0; t < tags.size(); t++) { + add_item_tag(0, nitems_written(0)+n_out_symbols, + tags[i].key, + tags[i].value + ); + } + for (unsigned k = 0; k < d_occupied_carriers[d_curr_set].size(); k++) { + out[n_out_symbols++] = in[i * d_fft_len + d_occupied_carriers[d_curr_set][k] + carr_offset]; + } + if (packet_length && n_out_symbols > packet_length) { + n_out_symbols = packet_length; + break; + } + d_curr_set = (d_curr_set + 1) % d_occupied_carriers.size(); + } + + // Housekeeping + if (d_length_tag_key_str.empty()) { + consume_each(frame_length); + } else { + d_curr_set = d_symbols_skipped; + } + + return n_out_symbols; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_serializer_vcc_impl.h b/gr-digital/lib/ofdm_serializer_vcc_impl.h new file mode 100644 index 0000000000..4f750eac71 --- /dev/null +++ b/gr-digital/lib/ofdm_serializer_vcc_impl.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H +#define INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H + +#include <digital/ofdm_serializer_vcc.h> + +namespace gr { + namespace digital { + + class ofdm_serializer_vcc_impl : public ofdm_serializer_vcc + { + private: + int d_fft_len; //!< FFT length + std::vector<std::vector<int> > d_occupied_carriers; //!< Which carriers/symbols carry data + pmt::pmt_t d_packet_len_tag_key; //!< Key of the length tag + pmt::pmt_t d_out_len_tag_key; //!< Key of the length tag + const int d_symbols_skipped; //!< Start position in d_occupied_carriers + int d_curr_set; //!< Current position in d_occupied_carriers + int d_symbols_per_set; + + protected: + /*! + * Calculate the number of scalar complex symbols given a number of + * OFDM symbols. + */ + int calculate_output_stream_length(const gr_vector_int &ninput_items); + void update_length_tags(int n_produced, int n_ports); + + public: + ofdm_serializer_vcc_impl( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::string &len_tag_key, + const std::string &packet_len_tag_key, + int symbols_skipped, + bool input_is_shifted + ); + ~ofdm_serializer_vcc_impl(); + + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_SERIALIZER_VCC_IMPL_H */ + diff --git a/gr-digital/lib/ofdm_sync_sc_cfb_impl.cc b/gr-digital/lib/ofdm_sync_sc_cfb_impl.cc new file mode 100644 index 0000000000..822b9021e2 --- /dev/null +++ b/gr-digital/lib/ofdm_sync_sc_cfb_impl.cc @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "ofdm_sync_sc_cfb_impl.h" + +#include <blocks/plateau_detector_fb.h> +#include <blocks/complex_to_arg.h> +#include <blocks/complex_to_mag_squared.h> +#include <blocks/conjugate_cc.h> +#include <blocks/delay.h> +#include <blocks/divide_ff.h> +#include <blocks/multiply_cc.h> +#include <blocks/multiply_ff.h> +#include <blocks/sample_and_hold_ff.h> +#include <filter/fir_filter_ccf.h> +#include <filter/fir_filter_fff.h> + +namespace gr { + namespace digital { + + ofdm_sync_sc_cfb::sptr + ofdm_sync_sc_cfb::make(int fft_len, int cp_len) + { + return gnuradio::get_initial_sptr (new ofdm_sync_sc_cfb_impl(fft_len, cp_len)); + } + + ofdm_sync_sc_cfb_impl::ofdm_sync_sc_cfb_impl(int fft_len, int cp_len) + : gr_hier_block2 ("ofdm_sync_sc_cfb", + gr_make_io_signature(1, 1, sizeof (gr_complex)), +#ifndef SYNC_ADD_DEBUG_OUTPUT + gr_make_io_signature2(2, 2, sizeof (float), sizeof (unsigned char))) +#else + gr_make_io_signature3(3, 3, sizeof (float), sizeof (unsigned char), sizeof (float))) +#endif + { + std::vector<float> ma_taps(fft_len/2, 1.0); + gr::blocks::delay::sptr delay(gr::blocks::delay::make(sizeof(gr_complex), fft_len/2)); + gr::blocks::conjugate_cc::sptr delay_conjugate(gr::blocks::conjugate_cc::make()); + gr::blocks::multiply_cc::sptr delay_corr(gr::blocks::multiply_cc::make()); + gr::filter::fir_filter_ccf::sptr delay_ma(gr::filter::fir_filter_ccf::make(1, std::vector<float>(fft_len/2, 1.0))); + gr::blocks::complex_to_mag_squared::sptr delay_magsquare(gr::blocks::complex_to_mag_squared::make()); + gr::blocks::divide_ff::sptr delay_normalize(gr::blocks::divide_ff::make()); + + gr::blocks::complex_to_mag_squared::sptr normalizer_magsquare(gr::blocks::complex_to_mag_squared::make()); + gr::filter::fir_filter_fff::sptr normalizer_ma(gr::filter::fir_filter_fff::make(1, std::vector<float>(fft_len, 0.5))); + gr::blocks::multiply_ff::sptr normalizer_square(gr::blocks::multiply_ff::make()); + + gr::blocks::complex_to_arg::sptr peak_to_angle(gr::blocks::complex_to_arg::make()); + gr::blocks::sample_and_hold_ff::sptr sample_and_hold(gr::blocks::sample_and_hold_ff::make()); + + gr::blocks::plateau_detector_fb::sptr plateau_detector(gr::blocks::plateau_detector_fb::make(cp_len)); + + // Delay Path + connect(self(), 0, delay, 0); + connect(delay, 0, delay_conjugate, 0); + connect(delay_conjugate, 0, delay_corr, 1); + connect(self(), 0, delay_corr, 0); + connect(delay_corr, 0, delay_ma, 0); + connect(delay_ma, 0, delay_magsquare, 0); + connect(delay_magsquare, 0, delay_normalize, 0); + // Energy Path + connect(self(), 0, normalizer_magsquare, 0); + connect(normalizer_magsquare, 0, normalizer_ma, 0); + connect(normalizer_ma, 0, normalizer_square, 0); + connect(normalizer_ma, 0, normalizer_square, 1); + connect(normalizer_square, 0, delay_normalize, 1); + // Fine frequency estimate (output 0) + connect(delay_ma, 0, peak_to_angle, 0); + connect(peak_to_angle, 0, sample_and_hold, 0); + connect(sample_and_hold, 0, self(), 0); + // Peak detect (output 1) + connect(delay_normalize, 0, plateau_detector, 0); + connect(plateau_detector, 0, sample_and_hold, 1); + connect(plateau_detector, 0, self(), 1); +#ifdef SYNC_ADD_DEBUG_OUTPUT + // Debugging: timing metric (output 2) + connect(delay_normalize, 0, self(), 2); +#endif + } + + ofdm_sync_sc_cfb_impl::~ofdm_sync_sc_cfb_impl() + { + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/ofdm_sync_sc_cfb_impl.h b/gr-digital/lib/ofdm_sync_sc_cfb_impl.h new file mode 100644 index 0000000000..207ea41ae1 --- /dev/null +++ b/gr-digital/lib/ofdm_sync_sc_cfb_impl.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_IMPL_H +#define INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_IMPL_H + +#include <digital/ofdm_sync_sc_cfb.h> + +namespace gr { + namespace digital { + + class ofdm_sync_sc_cfb_impl : public ofdm_sync_sc_cfb + { + public: + ofdm_sync_sc_cfb_impl(int fft_len, int cp_len); + ~ofdm_sync_sc_cfb_impl(); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_OFDM_SYNC_SC_CFB_IMPL_H */ + diff --git a/gr-digital/lib/packet_header_default.cc b/gr-digital/lib/packet_header_default.cc new file mode 100644 index 0000000000..ef5e44ac8d --- /dev/null +++ b/gr-digital/lib/packet_header_default.cc @@ -0,0 +1,129 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <digital/packet_header_default.h> + +namespace gr { + namespace digital { + + packet_header_default::sptr + packet_header_default::make( + long header_len, + const std::string &len_tag_key, + const std::string &num_tag_key, + int bits_per_byte) + { + return packet_header_default::sptr(new packet_header_default(header_len, len_tag_key, num_tag_key, bits_per_byte)); + } + + const unsigned MASK_LUT[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x2F, 0x7F, 0xFF}; + packet_header_default::packet_header_default( + long header_len, + const std::string &len_tag_key, + const std::string &num_tag_key, + int bits_per_byte) + : d_header_len(header_len), + d_len_tag_key(pmt::string_to_symbol(len_tag_key)), + d_num_tag_key(pmt::string_to_symbol(num_tag_key)), + d_bits_per_byte(bits_per_byte), + d_header_number(0) + { + if (d_bits_per_byte < 1 || d_bits_per_byte > 8) { + throw std::invalid_argument("bits_per_byte must be in [1, 8]"); + } + d_mask = MASK_LUT[d_bits_per_byte]; + } + + packet_header_default::~packet_header_default() + { + } + + bool packet_header_default::header_formatter( + long packet_len, + unsigned char *out, + const std::vector<gr_tag_t> &tags + ) + { + packet_len &= 0x0FFF; + + memset(out, 0x00, d_header_len); + int parity = 0; + int k = 0; // Position in out + for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) { + out[k] = (unsigned char) ((packet_len >> i) & d_mask); + parity += out[k]; + } + for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) { + out[k] = (unsigned char) ((d_header_number >> i) & d_mask); + parity += out[k]; + } + if (k < d_header_len) { + out[k] = (unsigned char) (parity % 2); + } + d_header_number++; + + return true; + } + + + bool packet_header_default::header_parser( + const unsigned char *in, + std::vector<gr_tag_t> &tags) + { + unsigned header_len = 0; + unsigned header_num = 0; + gr_tag_t tag; + + int k = 0; // Position in "in" + for (int i = 0; i < 12 && k < d_header_len; i += d_bits_per_byte, k++) { + header_len |= (((int) in[k]) & d_mask) << i; + } + tag.key = d_len_tag_key; + tag.value = pmt::from_long(header_len); + tags.push_back(tag); + if (k >= d_header_len) { + return true; + } + for (int i = 0; i < 16 && k < d_header_len; i += d_bits_per_byte, k++) { + header_num |= (((int) in[k]) & d_mask) << i; + } + tag.key = d_num_tag_key; + tag.value = pmt::from_long(header_num); + tags.push_back(tag); + if (k >= d_header_len) { + return true; + } + + int parity = in[k]; + for (int i = 0; i < 28; i++) { + parity += in[i]; + } + return !(parity % 2); + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/packet_header_ofdm.cc b/gr-digital/lib/packet_header_ofdm.cc new file mode 100644 index 0000000000..ed3d3586cb --- /dev/null +++ b/gr-digital/lib/packet_header_ofdm.cc @@ -0,0 +1,115 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital/packet_header_ofdm.h> + +namespace gr { + namespace digital { + + int _get_header_len_from_occupied_carriers(const std::vector<std::vector<int> > &occupied_carriers, int n_syms) + { + int header_len = 0; + for (int i = 0; i < n_syms; i++) { + header_len += occupied_carriers[i].size(); + } + + return header_len; + } + + packet_header_ofdm::sptr + packet_header_ofdm::make( + const std::vector<std::vector<int> > &occupied_carriers, + int n_syms, + const std::string &len_tag_key, + const std::string &frame_len_tag_key, + const std::string &num_tag_key, + int bits_per_sym) + { + return packet_header_ofdm::sptr( + new packet_header_ofdm( + occupied_carriers, n_syms, len_tag_key, frame_len_tag_key, num_tag_key, bits_per_sym + ) + ); + } + + packet_header_ofdm::packet_header_ofdm( + const std::vector<std::vector<int> > &occupied_carriers, + int n_syms, + const std::string &len_tag_key, + const std::string &frame_len_tag_key, + const std::string &num_tag_key, + int bits_per_sym) + : packet_header_default( + _get_header_len_from_occupied_carriers(occupied_carriers, n_syms), + len_tag_key, + num_tag_key, + bits_per_sym), + d_frame_len_tag_key(pmt::string_to_symbol(frame_len_tag_key)), + d_occupied_carriers(occupied_carriers), + d_syms_per_set(0) + { + for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { + d_syms_per_set += d_occupied_carriers[i].size(); + } + } + + packet_header_ofdm::~packet_header_ofdm() + { + } + + + bool packet_header_ofdm::header_parser( + const unsigned char *in, + std::vector<gr_tag_t> &tags) + { + if (!packet_header_default::header_parser(in, tags)) { + return false; + } + int packet_len = 0; // # of OFDM symbols + for (unsigned i = 0; i < tags.size(); i++) { + if (pmt::equal(tags[i].key, d_len_tag_key)) { + packet_len = pmt::to_long(tags[i].value); + break; + } + } + + int frame_len = packet_len / d_syms_per_set; + int k = 0; + int i = frame_len * d_syms_per_set; + while (i < packet_len) { + frame_len++; + i += d_occupied_carriers[k].size(); + } + gr_tag_t tag; + tag.key = d_frame_len_tag_key; + tag.value = pmt::from_long(frame_len); + tags.push_back(tag); + + return true; + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/packet_headergenerator_bb_impl.cc b/gr-digital/lib/packet_headergenerator_bb_impl.cc new file mode 100644 index 0000000000..3232858148 --- /dev/null +++ b/gr-digital/lib/packet_headergenerator_bb_impl.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <boost/format.hpp> +#include <gr_io_signature.h> +#include "packet_headergenerator_bb_impl.h" + +namespace gr { + namespace digital { + + packet_headergenerator_bb::sptr + packet_headergenerator_bb::make( + const packet_header_default::sptr &header_formatter, + const std::string &len_tag_key + ) + { + return gnuradio::get_initial_sptr (new packet_headergenerator_bb_impl(header_formatter, len_tag_key)); + } + + + packet_headergenerator_bb::sptr + packet_headergenerator_bb::make( + long header_len, + const std::string &len_tag_key + ) + { + const packet_header_default::sptr header_formatter( + new packet_header_default(header_len, len_tag_key) + ); + return gnuradio::get_initial_sptr (new packet_headergenerator_bb_impl(header_formatter, len_tag_key)); + } + + + packet_headergenerator_bb_impl::packet_headergenerator_bb_impl( + const gr::digital::packet_header_default::sptr &header_formatter, + const std::string &len_tag_key + ) + : gr_tagged_stream_block("packet_headergenerator_bb_impl", + gr_make_io_signature(1, 1, sizeof (char)), + gr_make_io_signature(1, 1, sizeof (char)), + len_tag_key), + d_formatter(header_formatter) + { + set_output_multiple(d_formatter->header_len()); + // This is the worst case rate, because we don't know the true value, of course + set_relative_rate(d_formatter->header_len()); + set_tag_propagation_policy(TPP_DONT); + } + + packet_headergenerator_bb_impl::~packet_headergenerator_bb_impl() + { + } + + int + packet_headergenerator_bb_impl::work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + unsigned char *out = (unsigned char *) output_items[0]; + if (!d_formatter->header_formatter(ninput_items[0], out)) { + GR_LOG_FATAL(d_logger, boost::format("header_formatter() returned false (this shouldn't happen). Offending header started at %1%") % nitems_read(0)); + throw std::runtime_error("header formatter returned false."); + } + + return d_formatter->header_len(); + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/packet_headergenerator_bb_impl.h b/gr-digital/lib/packet_headergenerator_bb_impl.h new file mode 100644 index 0000000000..ce60fdf76c --- /dev/null +++ b/gr-digital/lib/packet_headergenerator_bb_impl.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H +#define INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H + +#include <digital/packet_headergenerator_bb.h> + +namespace gr { + namespace digital { + + class packet_headergenerator_bb_impl : public packet_headergenerator_bb + { + private: + gr::digital::packet_header_default::sptr d_formatter; + + public: + packet_headergenerator_bb_impl( + const packet_header_default::sptr &header_formatter, + const std::string &len_tag_key + ); + ~packet_headergenerator_bb_impl(); + + void remove_length_tags(const std::vector<std::vector<gr_tag_t> > &tags) {}; + int calculate_output_stream_length(const gr_vector_int &ninput_items) { return d_formatter->header_len(); }; + + int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_PACKET_HEADERGENERATOR_BB_IMPL_H */ + diff --git a/gr-digital/lib/packet_headerparser_b_impl.cc b/gr-digital/lib/packet_headerparser_b_impl.cc new file mode 100644 index 0000000000..60e1fdef0b --- /dev/null +++ b/gr-digital/lib/packet_headerparser_b_impl.cc @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <boost/format.hpp> +#include <gr_io_signature.h> +#include "packet_headerparser_b_impl.h" + +#define msg_port_id pmt::mp("header_data") + +namespace gr { + namespace digital { + + packet_headerparser_b::sptr + packet_headerparser_b::make(long header_len, const std::string &len_tag_key) + { + const packet_header_default::sptr header_formatter( + new packet_header_default(header_len, len_tag_key) + ); + return gnuradio::get_initial_sptr (new packet_headerparser_b_impl(header_formatter)); + } + + packet_headerparser_b::sptr + packet_headerparser_b::make(const gr::digital::packet_header_default::sptr &header_formatter) + { + return gnuradio::get_initial_sptr (new packet_headerparser_b_impl(header_formatter)); + } + + packet_headerparser_b_impl::packet_headerparser_b_impl(const gr::digital::packet_header_default::sptr &header_formatter) + : gr_sync_block("packet_headerparser_b", + gr_make_io_signature(1, 1, sizeof (unsigned char)), + gr_make_io_signature(0, 0, 0)), + d_header_formatter(header_formatter) + { + message_port_register_out(msg_port_id); + set_output_multiple(header_formatter->header_len()); + } + + packet_headerparser_b_impl::~packet_headerparser_b_impl() + { + } + + int + packet_headerparser_b_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const unsigned char *in = (const unsigned char *) input_items[0]; + + if (noutput_items < d_header_formatter->header_len()) { + return 0; + } + + std::vector<gr_tag_t> tags; + if (!d_header_formatter->header_parser(in, tags)) { + GR_LOG_INFO(d_logger, boost::format("Detected an invalid packet at item %1%") % nitems_read(0)); + message_port_pub(msg_port_id, pmt::PMT_F); + } else { + pmt::pmt_t dict(pmt::make_dict()); + for (unsigned i = 0; i < tags.size(); i++) { + pmt::dict_add(dict, tags[i].key, tags[i].value); + } + message_port_pub(msg_port_id, dict); + } + + return d_header_formatter->header_len(); + } + + } /* namespace digital */ +} /* namespace gr */ + diff --git a/gr-digital/lib/packet_headerparser_b_impl.h b/gr-digital/lib/packet_headerparser_b_impl.h new file mode 100644 index 0000000000..a7ded1143f --- /dev/null +++ b/gr-digital/lib/packet_headerparser_b_impl.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H +#define INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H + +#include <digital/packet_headerparser_b.h> + +namespace gr { + namespace digital { + + class packet_headerparser_b_impl : public packet_headerparser_b + { + private: + packet_header_default::sptr d_header_formatter; + + public: + packet_headerparser_b_impl(const gr::digital::packet_header_default::sptr &header_formatter); + ~packet_headerparser_b_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace digital +} // namespace gr + +#endif /* INCLUDED_DIGITAL_PACKET_HEADERPARSER_B_IMPL_H */ + diff --git a/gr-digital/python/digital/CMakeLists.txt b/gr-digital/python/digital/CMakeLists.txt index 8162c6fe20..919509f434 100644 --- a/gr-digital/python/digital/CMakeLists.txt +++ b/gr-digital/python/digital/CMakeLists.txt @@ -39,6 +39,7 @@ GR_PYTHON_INSTALL( ofdm_sync_ml.py ofdm_sync_pnac.py ofdm_sync_pn.py + ofdm_txrx.py packet_utils.py pkt.py psk.py @@ -55,6 +56,7 @@ GR_PYTHON_INSTALL( utils/gray_code.py utils/mod_codes.py utils/alignment.py + utils/tagged_streams.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital/utils COMPONENT "digital_python" ) diff --git a/gr-digital/python/digital/__init__.py b/gr-digital/python/digital/__init__.py index d37c900929..5059e4eec8 100644 --- a/gr-digital/python/digital/__init__.py +++ b/gr-digital/python/digital/__init__.py @@ -49,6 +49,7 @@ from ofdm_sync_fixed import * from ofdm_sync_ml import * from ofdm_sync_pnac import * from ofdm_sync_pn import * +from ofdm_txrx import ofdm_tx, ofdm_rx import packet_utils import ofdm_packet_utils diff --git a/gr-digital/python/digital/cpm.py b/gr-digital/python/digital/cpm.py index a9915ba91a..b27fb098f5 100644 --- a/gr-digital/python/digital/cpm.py +++ b/gr-digital/python/digital/cpm.py @@ -26,6 +26,7 @@ from gnuradio import gr, filter from gnuradio import analog +from gnuradio import blocks from math import pi import numpy @@ -195,13 +196,13 @@ class cpm_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.B2s, - gr.file_sink(gr.sizeof_float, "symbols.dat")) + blocks.file_sink(gr.sizeof_float, "symbols.dat")) self.connect(self.pam, - gr.file_sink(gr.sizeof_float, "pam.dat")) + blocks.file_sink(gr.sizeof_float, "pam.dat")) self.connect(self.filter, - gr.file_sink(gr.sizeof_float, "filter.dat")) + blocks.file_sink(gr.sizeof_float, "filter.dat")) self.connect(self.fmmod, - gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) + blocks.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) def add_options(parser): diff --git a/gr-digital/python/digital/digital_voice.py.real b/gr-digital/python/digital/digital_voice.py.real index 4a2ef7721f..241a4a3dc2 100644 --- a/gr-digital/python/digital/digital_voice.py.real +++ b/gr-digital/python/digital/digital_voice.py.real @@ -23,8 +23,7 @@ """ Digital voice Tx and Rx using GSM 13kbit vocoder and GMSK. -Runs channel at 32kbit/sec. Currently uses fake channel coding, -but there's room for a rate 1/2 coder. +Runs channel at 32kbit/sec. """ from gnuradio import gr, gru @@ -66,7 +65,7 @@ class digital_voice_tx(gr.hier_block): f2s = blocks.float_to_short() voice_coder = gsm_full_rate.encode_sp() - channel_coder = gr.fake_channel_encoder_pp(GSM_FRAME_SIZE, AIR_FRAME_SIZE) + channel_coder = gr.multiply_const_b(1) p2s = gr.parallel_to_serial(gr.sizeof_char, AIR_FRAME_SIZE) mod = gmsk_mod(fg, sps=samples_per_symbol, @@ -93,7 +92,7 @@ class digital_voice_rx(gr.hier_block): p_size=AIR_FRAME_SIZE) s2p = gr.serial_to_parallel(gr.sizeof_char, AIR_FRAME_SIZE) - channel_decoder = gr.fake_channel_decoder_pp(AIR_FRAME_SIZE, GSM_FRAME_SIZE) + channel_decoder = gr.multiply_const_b(1) voice_decoder = gsm_full_rate.decode_ps() s2f = blocks.short_to_float () diff --git a/gr-digital/python/digital/generic_mod_demod.py b/gr-digital/python/digital/generic_mod_demod.py index f5b2084766..b812fe1c37 100644 --- a/gr-digital/python/digital/generic_mod_demod.py +++ b/gr-digital/python/digital/generic_mod_demod.py @@ -198,17 +198,17 @@ class generic_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.bytes2chunks, - gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) + blocks.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) if self.pre_diff_code: self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.8b")) + blocks.file_sink(gr.sizeof_char, "tx_symbol_mapper.8b")) if self._differential: self.connect(self.diffenc, - gr.file_sink(gr.sizeof_char, "tx_diffenc.8b")) + blocks.file_sink(gr.sizeof_char, "tx_diffenc.8b")) self.connect(self.chunks2symbols, - gr.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.32fc")) + blocks.file_sink(gr.sizeof_gr_complex, "tx_chunks2symbols.32fc")) self.connect(self.rrc_filter, - gr.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.32fc")) + blocks.file_sink(gr.sizeof_gr_complex, "tx_rrc_filter.32fc")) # ///////////////////////////////////////////////////////////////////////////// @@ -338,39 +338,39 @@ class generic_demod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.agc, - gr.file_sink(gr.sizeof_gr_complex, "rx_agc.32fc")) + blocks.file_sink(gr.sizeof_gr_complex, "rx_agc.32fc")) self.connect((self.freq_recov, 0), - gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.32fc")) + blocks.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.32fc")) self.connect((self.freq_recov, 1), - gr.file_sink(gr.sizeof_float, "rx_freq_recov_freq.32f")) + blocks.file_sink(gr.sizeof_float, "rx_freq_recov_freq.32f")) self.connect((self.freq_recov, 2), - gr.file_sink(gr.sizeof_float, "rx_freq_recov_phase.32f")) + blocks.file_sink(gr.sizeof_float, "rx_freq_recov_phase.32f")) self.connect((self.freq_recov, 3), - gr.file_sink(gr.sizeof_float, "rx_freq_recov_error.32f")) + blocks.file_sink(gr.sizeof_float, "rx_freq_recov_error.32f")) self.connect((self.time_recov, 0), - gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.32fc")) + blocks.file_sink(gr.sizeof_gr_complex, "rx_time_recov.32fc")) self.connect((self.time_recov, 1), - gr.file_sink(gr.sizeof_float, "rx_time_recov_error.32f")) + blocks.file_sink(gr.sizeof_float, "rx_time_recov_error.32f")) self.connect((self.time_recov, 2), - gr.file_sink(gr.sizeof_float, "rx_time_recov_rate.32f")) + blocks.file_sink(gr.sizeof_float, "rx_time_recov_rate.32f")) self.connect((self.time_recov, 3), - gr.file_sink(gr.sizeof_float, "rx_time_recov_phase.32f")) + blocks.file_sink(gr.sizeof_float, "rx_time_recov_phase.32f")) self.connect((self.receiver, 0), - gr.file_sink(gr.sizeof_char, "rx_receiver.8b")) + blocks.file_sink(gr.sizeof_char, "rx_receiver.8b")) self.connect((self.receiver, 1), - gr.file_sink(gr.sizeof_float, "rx_receiver_error.32f")) + blocks.file_sink(gr.sizeof_float, "rx_receiver_error.32f")) self.connect((self.receiver, 2), - gr.file_sink(gr.sizeof_float, "rx_receiver_phase.32f")) + blocks.file_sink(gr.sizeof_float, "rx_receiver_phase.32f")) self.connect((self.receiver, 3), - gr.file_sink(gr.sizeof_float, "rx_receiver_freq.32f")) + blocks.file_sink(gr.sizeof_float, "rx_receiver_freq.32f")) if self._differential: self.connect(self.diffdec, - gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) + blocks.file_sink(gr.sizeof_char, "rx_diffdec.8b")) if self.pre_diff_code: self.connect(self.symbol_mapper, - gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) + blocks.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) self.connect(self.unpack, - gr.file_sink(gr.sizeof_char, "rx_unpack.8b")) + blocks.file_sink(gr.sizeof_char, "rx_unpack.8b")) def add_options(parser): """ diff --git a/gr-digital/python/digital/gfsk.py b/gr-digital/python/digital/gfsk.py index e4aeef8ef9..6ba007ca0f 100644 --- a/gr-digital/python/digital/gfsk.py +++ b/gr-digital/python/digital/gfsk.py @@ -116,7 +116,7 @@ class gfsk_mod(gr.hier_block2): self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) # FM modulation - self.fmmod = frequency.frequency_modulator_fc(sensitivity) + self.fmmod = analog.frequency_modulator_fc(sensitivity) # small amount of output attenuation to prevent clipping USRP sink self.amp = blocks.multiply_const_cc(0.999) @@ -146,11 +146,11 @@ class gfsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.nrz, - gr.file_sink(gr.sizeof_float, "nrz.dat")) + blocks.file_sink(gr.sizeof_float, "nrz.dat")) self.connect(self.gaussian_filter, - gr.file_sink(gr.sizeof_float, "gaussian_filter.dat")) + blocks.file_sink(gr.sizeof_float, "gaussian_filter.dat")) self.connect(self.fmmod, - gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) + blocks.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) def add_options(parser): @@ -272,11 +272,11 @@ class gfsk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." self.connect(self.fmdemod, - gr.file_sink(gr.sizeof_float, "fmdemod.dat")) + blocks.file_sink(gr.sizeof_float, "fmdemod.dat")) self.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_float, "clock_recovery.dat")) + blocks.file_sink(gr.sizeof_float, "clock_recovery.dat")) self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) + blocks.file_sink(gr.sizeof_char, "slicer.dat")) def add_options(parser): """ diff --git a/gr-digital/python/digital/gmsk.py b/gr-digital/python/digital/gmsk.py index 53a5640259..9a44837002 100644 --- a/gr-digital/python/digital/gmsk.py +++ b/gr-digital/python/digital/gmsk.py @@ -136,11 +136,11 @@ class gmsk_mod(gr.hier_block2): def _setup_logging(self): print "Modulation logging turned on." self.connect(self.nrz, - gr.file_sink(gr.sizeof_float, "nrz.dat")) + blocks.file_sink(gr.sizeof_float, "nrz.dat")) self.connect(self.gaussian_filter, - gr.file_sink(gr.sizeof_float, "gaussian_filter.dat")) + blocks.file_sink(gr.sizeof_float, "gaussian_filter.dat")) self.connect(self.fmmod, - gr.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) + blocks.file_sink(gr.sizeof_gr_complex, "fmmod.dat")) def add_options(parser): @@ -256,11 +256,11 @@ class gmsk_demod(gr.hier_block2): def _setup_logging(self): print "Demodulation logging turned on." self.connect(self.fmdemod, - gr.file_sink(gr.sizeof_float, "fmdemod.dat")) + blocks.file_sink(gr.sizeof_float, "fmdemod.dat")) self.connect(self.clock_recovery, - gr.file_sink(gr.sizeof_float, "clock_recovery.dat")) + blocks.file_sink(gr.sizeof_float, "clock_recovery.dat")) self.connect(self.slicer, - gr.file_sink(gr.sizeof_char, "slicer.dat")) + blocks.file_sink(gr.sizeof_char, "slicer.dat")) def add_options(parser): """ diff --git a/gr-digital/python/digital/ofdm.py b/gr-digital/python/digital/ofdm.py index 5bbe111f31..fdb23703f9 100644 --- a/gr-digital/python/digital/ofdm.py +++ b/gr-digital/python/digital/ofdm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2008 Free Software Foundation, Inc. +# Copyright 2006-2008,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -118,13 +118,13 @@ class ofdm_mod(gr.hier_block2): self._print_verbage() if options.log: - self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + self.connect(self._pkt_input, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) - self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + self.connect(self.preambles, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_preambles.dat")) - self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + self.connect(self.ifft, blocks.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_ifft_c.dat")) - self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, + self.connect(self.cp_adder, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat")) def send_pkt(self, payload='', eof=False): @@ -256,11 +256,11 @@ class ofdm_demod(gr.hier_block2): if options.log: self.connect(self.ofdm_demod, - gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones, + blocks.file_sink(gr.sizeof_gr_complex*self._occupied_tones, "ofdm_frame_sink_c.dat")) else: self.connect(self.ofdm_demod, - gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones)) + blocks.null_sink(gr.sizeof_gr_complex*self._occupied_tones)) if options.verbose: self._print_verbage() diff --git a/gr-digital/python/digital/ofdm_receiver.py b/gr-digital/python/digital/ofdm_receiver.py index f4fc5f5ba3..4fbf76251a 100644 --- a/gr-digital/python/digital/ofdm_receiver.py +++ b/gr-digital/python/digital/ofdm_receiver.py @@ -144,11 +144,11 @@ class ofdm_receiver(gr.hier_block2): self.connect((self.ofdm_frame_acq,1), (self,1)) # frame and symbol timing, and equalization if logging: - self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) - self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) + self.connect(self.chan_filt, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) + self.connect(self.fft_demod, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) self.connect(self.ofdm_frame_acq, - gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) - self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat")) - self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) - self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) - self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat")) + blocks.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) + self.connect((self.ofdm_frame_acq,1), blocks.file_sink(1, "ofdm_receiver-found_corr_b.dat")) + self.connect(self.sampler, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) + self.connect(self.sigmix, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) + self.connect(self.nco, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat")) diff --git a/gr-digital/python/digital/ofdm_sync_fixed.py b/gr-digital/python/digital/ofdm_sync_fixed.py index 9bac789bf6..9cbd59b943 100644 --- a/gr-digital/python/digital/ofdm_sync_fixed.py +++ b/gr-digital/python/digital/ofdm_sync_fixed.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2007 Free Software Foundation, Inc. +# Copyright 2007,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,6 +22,7 @@ import math from gnuradio import gr +from gnuradio import blocks class ofdm_sync_fixed(gr.hier_block2): def __init__(self, fft_length, cp_length, nsymbols, freq_offset, logging=False): @@ -35,16 +36,16 @@ class ofdm_sync_fixed(gr.hier_block2): pkt_length = nsymbols*symbol_length data = (pkt_length)*[0,] data[(symbol_length)-1] = 1 - self.peak_trigger = gr.vector_source_b(data, True) + self.peak_trigger = blocks.vector_source_b(data, True) # Use a pre-defined frequency offset foffset = (pkt_length)*[math.pi*freq_offset,] - self.frequency_offset = gr.vector_source_f(foffset, True) + self.frequency_offset = blocks.vector_source_f(foffset, True) - self.connect(self, gr.null_sink(gr.sizeof_gr_complex)) + self.connect(self, blocks.null_sink(gr.sizeof_gr_complex)) self.connect(self.frequency_offset, (self,0)) self.connect(self.peak_trigger, (self,1)) if logging: - self.connect(self.peak_trigger, gr.file_sink(gr.sizeof_char, "ofdm_sync_fixed-peaks_b.dat")) + self.connect(self.peak_trigger, blocks.file_sink(gr.sizeof_char, "ofdm_sync_fixed-peaks_b.dat")) diff --git a/gr-digital/python/digital/ofdm_sync_ml.py b/gr-digital/python/digital/ofdm_sync_ml.py index 76c00f3a54..3afd647098 100644 --- a/gr-digital/python/digital/ofdm_sync_ml.py +++ b/gr-digital/python/digital/ofdm_sync_ml.py @@ -158,18 +158,18 @@ class ofdm_sync_ml(gr.hier_block2): if logging: - self.connect(self.moving_sum_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-energy_f.dat")) - self.connect(self.diff, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat")) - self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat")) - self.connect(self.corrmag, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-corrmag_f.dat")) - self.connect(self.kscorr, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-kscorr_c.dat")) - self.connect(self.div, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-div_f.dat")) - self.connect(self.mul, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-mul_f.dat")) - self.connect(self.slice, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-slice_f.dat")) - self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat")) + self.connect(self.moving_sum_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-energy_f.dat")) + self.connect(self.diff, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat")) + self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat")) + self.connect(self.corrmag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-corrmag_f.dat")) + self.connect(self.kscorr, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-kscorr_c.dat")) + self.connect(self.div, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-div_f.dat")) + self.connect(self.mul, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-mul_f.dat")) + self.connect(self.slice, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-slice_f.dat")) + self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat")) if use_dpll: - self.connect(self.dpll, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat")) + self.connect(self.dpll, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat")) - self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat")) - self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat")) + self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat")) + self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat")) diff --git a/gr-digital/python/digital/ofdm_sync_pn.py b/gr-digital/python/digital/ofdm_sync_pn.py index 63e85135bc..4c6a30f802 100644 --- a/gr-digital/python/digital/ofdm_sync_pn.py +++ b/gr-digital/python/digital/ofdm_sync_pn.py @@ -124,10 +124,10 @@ class ofdm_sync_pn(gr.hier_block2): self.connect(self.pk_detect, (self,1)) if logging: - self.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) - self.connect(self.normalize, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) - self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) - self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) - self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) - self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat")) + self.connect(self.matched_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) + self.connect(self.normalize, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) + self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) + self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) + self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) + self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat")) diff --git a/gr-digital/python/digital/ofdm_sync_pnac.py b/gr-digital/python/digital/ofdm_sync_pnac.py index 547b1e93c0..ee7c82927a 100644 --- a/gr-digital/python/digital/ofdm_sync_pnac.py +++ b/gr-digital/python/digital/ofdm_sync_pnac.py @@ -125,11 +125,11 @@ class ofdm_sync_pnac(gr.hier_block2): self.connect(self.peaks, (self,1)) if logging: - self.connect(self.compare, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-compare_f.dat")) - self.connect(self.c2mag, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-theta_f.dat")) - self.connect(self.power, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-inputpower_f.dat")) - self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-epsilon_f.dat")) - self.connect(self.threshold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-threshold_f.dat")) - self.connect(self.peaks, gr.file_sink(gr.sizeof_char, "ofdm_sync_pnac-peaks_b.dat")) - self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pnac-sample_and_hold_f.dat")) - self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pnac-input_c.dat")) + self.connect(self.compare, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-compare_f.dat")) + self.connect(self.c2mag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-theta_f.dat")) + self.connect(self.power, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-inputpower_f.dat")) + self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-epsilon_f.dat")) + self.connect(self.threshold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-threshold_f.dat")) + self.connect(self.peaks, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pnac-peaks_b.dat")) + self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-sample_and_hold_f.dat")) + self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pnac-input_c.dat")) diff --git a/gr-digital/python/digital/ofdm_txrx.py b/gr-digital/python/digital/ofdm_txrx.py new file mode 100644 index 0000000000..37c4086cc3 --- /dev/null +++ b/gr-digital/python/digital/ofdm_txrx.py @@ -0,0 +1,261 @@ +# +# Copyright 2005-2007,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. +# +""" +OFDM Transmitter / Receiver hier blocks. + +For simple configurations, no need to connect all the relevant OFDM blocks +to form an OFDM Tx/Rx--simply use these. +""" + +import numpy +from gnuradio import gr +import digital_swig as digital +from utils import tagged_streams + +try: + # This will work when feature #505 is added. + from gnuradio import fft + from gnuradio import blocks + from gnuradio import analog +except ImportError: + # Until then this will work. + import fft_swig as fft + import blocks_swig as blocks + import analog_swig as analog + +_def_fft_len = 64 +_def_cp_len = 16 +_def_frame_length_tag_key = "frame_length" +_def_packet_length_tag_key = "frame_length" +_def_packet_num_tag_key = "" +_def_occupied_carriers=(range(1, 27) + range(38, 64),) +_def_pilot_carriers=((0,),) +_def_pilot_symbols=((100,),) +_seq_seed = 42 + +def _make_sync_word(fft_len, occupied_carriers, constellation): + """ Makes a random sync sequence """ + occupied_carriers = list(occupied_carriers[0]) + occupied_carriers = [occupied_carriers[x] + fft_len if occupied_carriers[x] < 0 else occupied_carriers[x] for x in range(len(occupied_carriers))] + numpy.random.seed(_seq_seed) + sync_sequence = [constellation.map_to_points_v(numpy.random.randint(constellation.arity()))[0] * numpy.sqrt(2) if x in occupied_carriers and x % 3 else 0 for x in range(fft_len)] + return sync_sequence + +def _get_constellation(bps): + """ Returns a modulator block for a given number of bits per symbol """ + constellation = { + 1: digital.constellation_bpsk(), + 2: digital.constellation_qpsk(), + 3: digital.constellation_8psk() + } + try: + return constellation[bps] + except KeyError: + print 'Modulation not supported.' + exit(1) + +class ofdm_tx(gr.hier_block2): + """ + Hierarchical block for OFDM modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + Args: + fft_len: The length of FFT (integer). + cp_len: The length of cyclic prefix (integer). + occupied_carriers: ?? + pilot_carriers: ?? + pilot_symbols: ?? + length_tag_key: The name of the tag giving packet length. + """ + def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, + frame_length_tag_key=_def_frame_length_tag_key, + occupied_carriers=_def_occupied_carriers, + pilot_carriers=_def_pilot_carriers, + pilot_symbols=_def_pilot_symbols, + bps_header=1, + bps_payload=1, + sync_word1=None, + sync_word2=None, + rolloff=0 + ): + gr.hier_block2.__init__(self, "ofdm_tx", + gr.io_signature(1, 1, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + self.fft_len = fft_len + self.cp_len = cp_len + self.frame_length_tag_key = frame_length_tag_key + self.occupied_carriers = occupied_carriers + self.pilot_carriers = pilot_carriers + self.pilot_symbols = pilot_symbols + self.bps_header = bps_header + self.bps_payload = bps_payload + n_sync_words = 1 + header_constellation = _get_constellation(bps_header) + header_mod = digital.chunks_to_symbols_bc(header_constellation.points()) + self.sync_word1 = sync_word1 + if sync_word1 is None: + self.sync_word1 = _make_sync_word(fft_len, occupied_carriers, header_constellation) + else: + if len(sync_word1) != self.fft_len: + raise ValueError("Length of sync sequence(s) must be FFT length.") + self.sync_words = [sync_word1,] + self.sync_word2 = () + if sync_word2 is not None: + if len(sync_word2) != fft_len: + raise ValueError("Length of sync sequence(s) must be FFT length.") + self.sync_word2 = sync_word2 + n_sync_words = 2 + self.sync_words.append(self.sync_word2) + crc = digital.crc32_bb(False, self.frame_length_tag_key) + formatter_object = digital.packet_header_ofdm( + occupied_carriers=occupied_carriers, n_syms=1, + bits_per_sym=self.bps_header + ) + header_gen = digital.packet_headergenerator_bb(formatter_object.base(), self.frame_length_tag_key) + header_payload_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*1, self.frame_length_tag_key) + self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) + payload_constellation = _get_constellation(bps_payload) + payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points()) + self.connect( + crc, + blocks.repack_bits_bb(8, bps_payload, frame_length_tag_key), + payload_mod, + (header_payload_mux, 1) + ) + allocator = digital.ofdm_carrier_allocator_cvc( + self.fft_len, + occupied_carriers=self.occupied_carriers, + pilot_carriers=self.pilot_carriers, + pilot_symbols=self.pilot_symbols, + sync_words=self.sync_words, + len_tag_key=self.frame_length_tag_key + ) + ffter = fft.fft_vcc(self.fft_len, False, (), True) + cyclic_prefixer = digital.ofdm_cyclic_prefixer( + self.fft_len, + self.fft_len+self.cp_len, + rolloff, + self.frame_length_tag_key + ) + self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) + + +class ofdm_rx(gr.hier_block2): + """ + Hierarchical block for OFDM demodulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + Args: + fft_len: The length of FFT (integer). + cp_len: The length of cyclic prefix (integer). + occupied_carriers: ?? + pilot_carriers: ?? + pilot_symbols: ?? + length_tag_key: The name of the tag giving packet length. + """ + def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, + frame_length_tag_key=_def_frame_length_tag_key, + packet_length_tag_key=_def_packet_length_tag_key, + packet_num_tag_key=_def_packet_num_tag_key, + occupied_carriers=_def_occupied_carriers, + pilot_carriers=_def_pilot_carriers, + pilot_symbols=_def_pilot_symbols, + bps_header=1, + bps_payload=1, + sync_word1=None, + sync_word2=None + ): + gr.hier_block2.__init__(self, "ofdm_rx", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(1, 1, gr.sizeof_char)) + self.fft_len = fft_len + self.cp_len = cp_len + self.frame_length_tag_key = frame_length_tag_key + self.packet_length_tag_key = packet_length_tag_key + self.occupied_carriers = occupied_carriers + self.bps_header = bps_header + self.bps_payload = bps_payload + n_sync_words = 1 + header_constellation = _get_constellation(bps_header) + if sync_word1 is None: + self.sync_word1 = _make_sync_word(fft_len, occupied_carriers, header_constellation) + else: + if len(sync_word1) != self.fft_len: + raise ValueError("Length of sync sequence(s) must be FFT length.") + self.sync_word1 = sync_word1 + self.sync_word2 = () + if sync_word2 is not None: + if len(sync_word2) != fft_len: + raise ValueError("Length of sync sequence(s) must be FFT length.") + self.sync_word2 = sync_word2 + n_sync_words = 2 + else: + sync_word2 = () + # Receiver path + sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len) + oscillator = analog.frequency_modulator_fc(-2.0 / fft_len) + delay = gr.delay(gr.sizeof_gr_complex, fft_len+cp_len) + mixer = gr.multiply_cc() + hpd = digital.header_payload_demux(n_sync_words, fft_len, cp_len, + frame_length_tag_key, "", True) + self.connect(self, sync_detect) + self.connect((sync_detect, 0), oscillator, (mixer, 0)) + self.connect(self, delay, (mixer, 1)) + self.connect(mixer, (hpd, 0)) + self.connect((sync_detect, 1), (hpd, 1)) + # Header demodulation + header_fft = fft.fft_vcc(self.fft_len, True, (), True) + chanest = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2, 1) + header_equalizer = digital.ofdm_equalizer_simpledfe( + fft_len, header_constellation.base(), + occupied_carriers, pilot_carriers, pilot_symbols + ) + header_eq = digital.ofdm_frame_equalizer_vcvc(header_equalizer.base(), frame_length_tag_key, True) + header_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers) + header_constellation = _get_constellation(bps_header) + header_demod = digital.constellation_decoder_cb(header_constellation.base()) + header_formatter = digital.packet_header_ofdm( + occupied_carriers, 1, + packet_length_tag_key, + frame_length_tag_key, + packet_num_tag_key, + bps_header + ) + header_parser = digital.packet_headerparser_b(header_formatter.formatter()) + self.connect((hpd, 0), header_fft, chanest, header_eq, header_serializer, header_demod, header_parser) + self.msg_connect(header_parser, "header_data", hpd, "header_data") + # Payload demodulation + payload_fft = fft.fft_vcc(self.fft_len, True, (), True) + payload_equalizer = digital.ofdm_equalizer_simpledfe( + fft_len, header_constellation.base(), + occupied_carriers, pilot_carriers, pilot_symbols, 1 + ) + payload_eq = digital.ofdm_frame_equalizer_vcvc(payload_equalizer.base(), frame_length_tag_key) + payload_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers) + payload_constellation = _get_constellation(bps_payload) + payload_demod = digital.constellation_decoder_cb(payload_constellation.base()) + bit_packer = blocks.repack_bits_bb(bps_payload, 8, packet_length_tag_key, True) + self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer, payload_demod, bit_packer, self) + diff --git a/gr-digital/python/digital/qa_binary_slicer_fb.py b/gr-digital/python/digital/qa_binary_slicer_fb.py index 162fd73f8e..93e12dbb8d 100755 --- a/gr-digital/python/digital/qa_binary_slicer_fb.py +++ b/gr-digital/python/digital/qa_binary_slicer_fb.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,9 +20,9 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +import random -import math, random +from gnuradio import gr, gr_unittest, digital, blocks class test_binary_slicer_fb(gr_unittest.TestCase): @@ -36,9 +36,9 @@ class test_binary_slicer_fb(gr_unittest.TestCase): expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) src_data = [s + (1 - random.random()) for s in src_data] # add some noise - src = gr.vector_source_f(src_data) + src = blocks.vector_source_f(src_data) op = digital.binary_slicer_fb() - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op) self.tb.connect(op, dst) diff --git a/gr-digital/python/digital/qa_chunks_to_symbols.py b/gr-digital/python/digital/qa_chunks_to_symbols.py index aab5a5addd..25798f33e5 100755 --- a/gr-digital/python/digital/qa_chunks_to_symbols.py +++ b/gr-digital/python/digital/qa_chunks_to_symbols.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_chunks_to_symbols(gr_unittest.TestCase): @@ -37,10 +37,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (1+0j, 0+1j, -1+0j, 0-1j, 0-1j, -1+0j, 0+1j, 1+0j) - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.chunks_to_symbols_bc(const) - dst = gr.vector_sink_c() + dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() @@ -54,10 +54,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (-3, -1, 1, 3, 3, 1, -1, -3) - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.chunks_to_symbols_bf(const) - dst = gr.vector_sink_f() + dst = blocks.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() @@ -72,10 +72,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (1+0j, 0+1j, -1+0j, 0-1j, 0-1j, -1+0j, 0+1j, 1+0j) - src = gr.vector_source_i(src_data) + src = blocks.vector_source_i(src_data) op = digital.chunks_to_symbols_ic(const) - dst = gr.vector_sink_c() + dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() @@ -89,10 +89,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (-3, -1, 1, 3, 3, 1, -1, -3) - src = gr.vector_source_i(src_data) + src = blocks.vector_source_i(src_data) op = digital.chunks_to_symbols_if(const) - dst = gr.vector_sink_f() + dst = blocks.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() @@ -107,10 +107,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (1+0j, 0+1j, -1+0j, 0-1j, 0-1j, -1+0j, 0+1j, 1+0j) - src = gr.vector_source_s(src_data) + src = blocks.vector_source_s(src_data) op = digital.chunks_to_symbols_sc(const) - dst = gr.vector_sink_c() + dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() @@ -124,10 +124,10 @@ class test_chunks_to_symbols(gr_unittest.TestCase): expected_result = (-3, -1, 1, 3, 3, 1, -1, -3) - src = gr.vector_source_s(src_data) + src = blocks.vector_source_s(src_data) op = digital.chunks_to_symbols_sf(const) - dst = gr.vector_sink_f() + dst = blocks.vector_sink_f() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() diff --git a/gr-digital/python/digital/qa_clock_recovery_mm.py b/gr-digital/python/digital/qa_clock_recovery_mm.py index b9e9121c32..783770d6e9 100755 --- a/gr-digital/python/digital/qa_clock_recovery_mm.py +++ b/gr-digital/python/digital/qa_clock_recovery_mm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,7 +23,7 @@ import random import cmath -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_clock_recovery_mm(gr_unittest.TestCase): @@ -46,8 +46,8 @@ class test_clock_recovery_mm(gr_unittest.TestCase): omega_rel_lim) data = 100*[complex(1, 1),] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -81,8 +81,8 @@ class test_clock_recovery_mm(gr_unittest.TestCase): omega_rel_lim) data = 100*[1,] - self.src = gr.vector_source_f(data, False) - self.snk = gr.vector_sink_f() + self.src = blocks.vector_source_f(data, False) + self.snk = blocks.vector_sink_f() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -116,8 +116,8 @@ class test_clock_recovery_mm(gr_unittest.TestCase): omega_rel_lim) data = 1000*[complex(1, 1), complex(1, 1), complex(-1, -1), complex(-1, -1)] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -151,8 +151,8 @@ class test_clock_recovery_mm(gr_unittest.TestCase): omega_rel_lim) data = 1000*[1, 1, -1, -1] - self.src = gr.vector_source_f(data, False) - self.snk = gr.vector_sink_f() + self.src = blocks.vector_source_f(data, False) + self.snk = blocks.vector_sink_f() self.tb.connect(self.src, self.test, self.snk) self.tb.run() diff --git a/gr-digital/python/digital/qa_cma_equalizer.py b/gr-digital/python/digital/qa_cma_equalizer.py index 7335c0f918..6da391f70c 100755 --- a/gr-digital/python/digital/qa_cma_equalizer.py +++ b/gr-digital/python/digital/qa_cma_equalizer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010,2011 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_cma_equalizer_fir(gr_unittest.TestCase): @@ -31,9 +31,9 @@ class test_cma_equalizer_fir(gr_unittest.TestCase): self.tb = None def transform(self, src_data): - SRC = gr.vector_source_c(src_data, False) + SRC = blocks.vector_source_c(src_data, False) EQU = digital.cma_equalizer_cc(4, 1.0, .001, 1) - DST = gr.vector_sink_c() + DST = blocks.vector_sink_c() self.tb.connect(SRC, EQU, DST) self.tb.run() return DST.data() diff --git a/gr-digital/python/digital/qa_constellation.py b/gr-digital/python/digital/qa_constellation.py index 709debb2b9..9e7e691d5c 100755 --- a/gr-digital/python/digital/qa_constellation.py +++ b/gr-digital/python/digital/qa_constellation.py @@ -174,9 +174,9 @@ class test_constellation(gr_unittest.TestCase): else: rotations = [None] for rotation in rotations: - src = gr.vector_source_b(self.src_data) + src = blocks.vector_source_b(self.src_data) content = mod_demod(constellation, differential, rotation) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb = gr.top_block() self.tb.connect(src, content, dst) self.tb.run() diff --git a/gr-digital/python/digital/qa_constellation_decoder_cb.py b/gr-digital/python/digital/qa_constellation_decoder_cb.py index 1c910feacb..d3fbce91ba 100755 --- a/gr-digital/python/digital/qa_constellation_decoder_cb.py +++ b/gr-digital/python/digital/qa_constellation_decoder_cb.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010-2012 Free Software Foundation, Inc. +# Copyright 2004,2007,2010-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_constellation_decoder(gr_unittest.TestCase): @@ -36,9 +36,9 @@ class test_constellation_decoder(gr_unittest.TestCase): 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) expected_result = ( 1, 1, 0, 0, 1, 0, 1) - src = gr.vector_source_c(src_data) + src = blocks.vector_source_c(src_data) op = digital.constellation_decoder_cb(cnst.base()) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op) self.tb.connect(op, dst) @@ -55,9 +55,9 @@ class test_constellation_decoder(gr_unittest.TestCase): 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) expected_result = ( 3, 1, 0, 2, 3, 2, 1) - src = gr.vector_source_c(src_data) + src = blocks.vector_source_c(src_data) op = digital_swig.constellation_decoder_cb(cnst.base()) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op) self.tb.connect(op, dst) diff --git a/gr-digital/python/digital/qa_constellation_receiver.py b/gr-digital/python/digital/qa_constellation_receiver.py index 914e347d88..e595b585ac 100755 --- a/gr-digital/python/digital/qa_constellation_receiver.py +++ b/gr-digital/python/digital/qa_constellation_receiver.py @@ -152,7 +152,7 @@ class rec_test_tb(gr.top_block): else: self.src_data = src_data packer = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) - src = gr.vector_source_b(self.src_data) + src = blocks.vector_source_b(self.src_data) mod = generic_mod(constellation, differential=differential) # Channel if freq_offset: @@ -167,7 +167,7 @@ class rec_test_tb(gr.top_block): else: demod = generic_demod(constellation, differential=differential, freq_bw=0, phase_bw=0) - self.dst = gr.vector_sink_b() + self.dst = blocks.vector_sink_b() self.connect(src, packer, mod, channel, demod, self.dst) if __name__ == '__main__': diff --git a/gr-digital/python/digital/qa_correlate_access_code.py b/gr-digital/python/digital/qa_correlate_access_code.py index 849ca474a9..198a254da7 100755 --- a/gr-digital/python/digital/qa_correlate_access_code.py +++ b/gr-digital/python/digital/qa_correlate_access_code.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010,2011 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,9 +20,7 @@ # Boston, MA 02110-1301, USA. # -import math - -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -52,9 +50,9 @@ class test_correlate_access_code(gr_unittest.TestCase): # 0 0 0 1 0 0 0 1 src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7 expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6 - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.correlate_access_code_bb("1011", 0) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op, dst) self.tb.run() result_data = dst.data() @@ -69,9 +67,9 @@ class test_correlate_access_code(gr_unittest.TestCase): #print access_code src_data = code + (1, 0, 1, 1) + pad expected_result = pad + code + (3, 0, 1, 1) - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.correlate_access_code_bb(access_code, 0) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op, dst) self.tb.run() result_data = dst.data() @@ -85,9 +83,9 @@ class test_correlate_access_code(gr_unittest.TestCase): #print access_code src_data = code + (1, 0, 1, 1) + pad expected_result = code + (1, 0, 1, 1) + pad - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.correlate_access_code_tag_bb(access_code, 0, "test") - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op, dst) self.tb.run() result_data = dst.data() diff --git a/gr-digital/python/digital/qa_costas_loop_cc.py b/gr-digital/python/digital/qa_costas_loop_cc.py index e920a76e05..9ecb017599 100755 --- a/gr-digital/python/digital/qa_costas_loop_cc.py +++ b/gr-digital/python/digital/qa_costas_loop_cc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,7 +23,7 @@ import random import cmath -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks from gnuradio.digital import psk class test_costas_loop_cc(gr_unittest.TestCase): @@ -41,8 +41,8 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.test = digital.costas_loop_cc(natfreq, order) data = 100*[complex(1,0),] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -58,8 +58,8 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.test = digital.costas_loop_cc(natfreq, order) data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -82,8 +82,8 @@ class test_costas_loop_cc(gr_unittest.TestCase): expected_result = data[N:] data = [rot*d for d in data] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -108,8 +108,8 @@ class test_costas_loop_cc(gr_unittest.TestCase): expected_result = data[N:] data = [rot*d for d in data] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() @@ -137,8 +137,8 @@ class test_costas_loop_cc(gr_unittest.TestCase): rot = cmath.exp(0.1j) # some small rotation data = [rot*d for d in data] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.test, self.snk) self.tb.run() diff --git a/gr-digital/python/digital/qa_cpm.py b/gr-digital/python/digital/qa_cpm.py index 5f7253f5f8..6468ed507b 100755 --- a/gr-digital/python/digital/qa_cpm.py +++ b/gr-digital/python/digital/qa_cpm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2010 Free Software Foundation, Inc. +# Copyright 2010,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -36,10 +36,10 @@ class test_cpm(gr_unittest.TestCase): sps = 2 L = 1 in_bits = (1,) * 20 - src = gr.vector_source_b(in_bits, False) + src = blocks.vector_source_b(in_bits, False) cpm = digital.cpmmod_bc(type, 0.5, sps, L) arg = blocks.complex_to_arg() - sink = gr.vector_sink_f() + sink = blocks.vector_sink_f() self.tb.connect(src, cpm, arg, sink) self.tb.run() @@ -67,10 +67,10 @@ class test_cpm(gr_unittest.TestCase): L = 5 bt = 0.3 in_bits = (1,) * 20 - src = gr.vector_source_b(in_bits, False) + src = blocks.vector_source_b(in_bits, False) gmsk = digital.gmskmod_bc(sps, L, bt) arg = blocks.complex_to_arg() - sink = gr.vector_sink_f() + sink = blocks.vector_sink_f() self.tb.connect(src, gmsk, arg, sink) self.tb.run() diff --git a/gr-digital/python/digital/qa_crc32_bb.py b/gr-digital/python/digital/qa_crc32_bb.py new file mode 100755 index 0000000000..397834ffde --- /dev/null +++ b/gr-digital/python/digital/qa_crc32_bb.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# 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. +# + +from gnuradio import gr, gr_unittest, blocks, digital +import pmt + +class qa_crc32_bb (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_crc_len (self): + """ Make sure the output of a CRC set is 4 bytes longer than the input. """ + data = range(16) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(data)) + src = blocks.vector_source_b(data, False, 1, (tag,)) + crc = digital.crc32_bb(False, tag_name) + sink = blocks.vector_sink_b() + self.tb.connect(src, crc, sink) + self.tb.run() + # Check that the packets before crc_check are 4 bytes longer that the input. + self.assertEqual(len(data)+4, len(sink.data())) + + def test_002_crc_equal (self): + """ Go through CRC set / CRC check and make sure the output + is the same as the input. """ + data = (0, 1, 2, 3, 4, 5, 6, 7, 8) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(data)) + src = blocks.vector_source_b(data, False, 1, (tag,)) + crc = digital.crc32_bb(False, tag_name) + crc_check = digital.crc32_bb(True, tag_name) + sink = blocks.vector_sink_b() + self.tb.connect(src, crc, crc_check, sink) + self.tb.run() + # Check that the packets after crc_check are the same as input. + self.assertEqual(data, sink.data()) + + def test_003_crc_correct_lentag (self): + tag_name = "length" + pack_len = 8 + packets = range(pack_len*2) + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tag_name) + tag1.value = pmt.from_long(pack_len) + tag2 = gr.gr_tag_t() + tag2.offset = pack_len + tag2.key = pmt.string_to_symbol(tag_name) + tag2.value = pmt.from_long(pack_len) + testtag1 = gr.gr_tag_t() + testtag1.offset = 1 + testtag1.key = pmt.string_to_symbol("tag1") + testtag1.value = pmt.from_long(0) + testtag2 = gr.gr_tag_t() + testtag2.offset = pack_len + testtag2.key = pmt.string_to_symbol("tag2") + testtag2.value = pmt.from_long(0) + testtag3 = gr.gr_tag_t() + testtag3.offset = len(packets)-1 + testtag3.key = pmt.string_to_symbol("tag3") + testtag3.value = pmt.from_long(0) + src = blocks.vector_source_b(packets, False, 1, (tag1, tag2, testtag1, testtag2, testtag3)) + crc = digital.crc32_bb(False, tag_name) + sink = blocks.vector_sink_b() + self.tb.connect(src, crc, sink) + self.tb.run() + self.assertEqual(len(sink.data()), 2*(pack_len+4)) + correct_offsets = {'tag1': 1, 'tag2': 12, 'tag3': 19} + tags_found = {'tag1': False, 'tag2': False, 'tag3': False} + for tag in sink.tags(): + key = pmt.symbol_to_string(tag.key) + if key in correct_offsets.keys(): + tags_found[key] = True + self.assertEqual(correct_offsets[key], tag.offset) + if key == tag_name: + self.assertTrue(tag.offset == 0 or tag.offset == pack_len+4) + self.assertTrue(all(tags_found.values())) + + + def test_004_fail (self): + """ Corrupt the data and make sure it fails CRC test. """ + data = (0, 1, 2, 3, 4, 5, 6, 7) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(data)) + src = blocks.vector_source_b(data, False, 1, (tag,)) + crc = digital.crc32_bb(False, tag_name) + crc_check = digital.crc32_bb(True, tag_name) + corruptor = blocks.add_const_bb(1) + sink = blocks.vector_sink_b() + self.tb.connect(src, crc, corruptor, crc_check, sink) + self.tb.run() + # crc_check will drop invalid packets + self.assertEqual(len(sink.data()), 0) + + def test_005_tag_propagation (self): + """ Make sure tags on the CRC aren't lost. """ + data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 230, 166, 39, 8) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(data)) + testtag = gr.gr_tag_t() + testtag.offset = len(data)-1 + testtag.key = pmt.string_to_symbol('tag1') + testtag.value = pmt.from_long(0) + src = blocks.vector_source_b(data, False, 1, (tag, testtag)) + crc_check = digital.crc32_bb(True, tag_name) + sink = blocks.vector_sink_b() + self.tb.connect(src, crc_check, sink) + self.tb.run() + self.assertEqual([len(data)-5,], [tag.offset for tag in sink.tags() if pmt.symbol_to_string(tag.key) == 'tag1']) + +if __name__ == '__main__': + gr_unittest.run(qa_crc32_bb, "qa_crc32_bb.xml") diff --git a/gr-digital/python/digital/qa_diff_encoder.py b/gr-digital/python/digital/qa_diff_encoder.py index 34249760c5..410b937fbc 100755 --- a/gr-digital/python/digital/qa_diff_encoder.py +++ b/gr-digital/python/digital/qa_diff_encoder.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010,2012 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,10 +20,9 @@ # Boston, MA 02110-1301, USA. # -import math import random -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks def make_random_int_tuple(L, min, max): result = [] @@ -45,10 +44,10 @@ class test_diff_encoder(gr_unittest.TestCase): modulus = 2 src_data = make_random_int_tuple(1000, 0, modulus-1) expected_result = src_data - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) enc = digital.diff_encoder_bb(modulus) dec = digital.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, enc, dec, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink @@ -59,10 +58,10 @@ class test_diff_encoder(gr_unittest.TestCase): modulus = 4 src_data = make_random_int_tuple(1000, 0, modulus-1) expected_result = src_data - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) enc = digital.diff_encoder_bb(modulus) dec = digital.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, enc, dec, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink @@ -73,10 +72,10 @@ class test_diff_encoder(gr_unittest.TestCase): modulus = 8 src_data = make_random_int_tuple(40000, 0, modulus-1) expected_result = src_data - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) enc = digital.diff_encoder_bb(modulus) dec = digital.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, enc, dec, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink diff --git a/gr-digital/python/digital/qa_diff_phasor_cc.py b/gr-digital/python/digital/qa_diff_phasor_cc.py index 84e151a630..7cae4870cc 100755 --- a/gr-digital/python/digital/qa_diff_phasor_cc.py +++ b/gr-digital/python/digital/qa_diff_phasor_cc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# Copyright 2004,2007,2010,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,9 +20,7 @@ # Boston, MA 02110-1301, USA. # -import math - -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_diff_phasor(gr_unittest.TestCase): @@ -35,9 +33,9 @@ class test_diff_phasor(gr_unittest.TestCase): def test_diff_phasor_cc(self): src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) - src = gr.vector_source_c(src_data) + src = blocks.vector_source_c(src_data) op = digital.diff_phasor_cc() - dst = gr.vector_sink_c() + dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() # run the graph and wait for it to finish diff --git a/gr-digital/python/digital/qa_fll_band_edge.py b/gr-digital/python/digital/qa_fll_band_edge.py index 02ded4e20c..17c5fa85f8 100755 --- a/gr-digital/python/digital/qa_fll_band_edge.py +++ b/gr-digital/python/digital/qa_fll_band_edge.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -49,7 +49,7 @@ class test_fll_band_edge_cc(gr_unittest.TestCase): # Create a set of 1's and -1's, pulse shape and interpolate to sps random.seed(0) data = [2.0*random.randint(0, 2) - 1.0 for i in xrange(200)] - self.src = gr.vector_source_c(data, False) + self.src = blocks.vector_source_c(data, False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) # Mix symbols with a complex sinusoid to spin them @@ -61,10 +61,10 @@ class test_fll_band_edge_cc(gr_unittest.TestCase): # Create sinks for all outputs of the FLL # we will only care about the freq and error outputs - self.vsnk_frq = gr.vector_sink_f() - self.nsnk_fll = gr.null_sink(gr.sizeof_gr_complex) - self.nsnk_phs = gr.null_sink(gr.sizeof_float) - self.nsnk_err = gr.null_sink(gr.sizeof_float) + self.vsnk_frq = blocks.vector_sink_f() + self.nsnk_fll = blocks.null_sink(gr.sizeof_gr_complex) + self.nsnk_phs = blocks.null_sink(gr.sizeof_float) + self.nsnk_err = blocks.null_sink(gr.sizeof_float) # Connect the blocks self.tb.connect(self.nco, (self.mix,1)) diff --git a/gr-digital/python/digital/qa_framer_sink.py b/gr-digital/python/digital/qa_framer_sink.py index d5c4df1f1e..4b260c14ec 100755 --- a/gr-digital/python/digital/qa_framer_sink.py +++ b/gr-digital/python/digital/qa_framer_sink.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -55,10 +55,10 @@ class test_framker_sink(gr_unittest.TestCase): rcvd_pktq = gr.msg_queue() - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) correlator = digital.correlate_access_code_bb(access_code, 0) framer_sink = digital.framer_sink_1(rcvd_pktq) - vsnk = gr.vector_sink_b() + vsnk = blocks.vector_sink_b() self.tb.connect(src, correlator, framer_sink) self.tb.connect(correlator, vsnk) @@ -79,10 +79,10 @@ class test_framker_sink(gr_unittest.TestCase): rcvd_pktq = gr.msg_queue() - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) correlator = digital.correlate_access_code_bb(access_code, 0) framer_sink = digital.framer_sink_1(rcvd_pktq) - vsnk = gr.vector_sink_b() + vsnk = blocks.vector_sink_b() self.tb.connect(src, correlator, framer_sink) self.tb.connect(correlator, vsnk) diff --git a/gr-digital/python/digital/qa_glfsr_source.py b/gr-digital/python/digital/qa_glfsr_source.py index 155a91c4a0..f39c408198 100755 --- a/gr-digital/python/digital/qa_glfsr_source.py +++ b/gr-digital/python/digital/qa_glfsr_source.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2007,2010,2012 Free Software Foundation, Inc. +# Copyright 2007,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_glfsr_source(gr_unittest.TestCase): @@ -45,7 +45,7 @@ class test_glfsr_source(gr_unittest.TestCase): for degree in range(1,11): # Higher degrees take too long to correlate src = digital.glfsr_source_b(degree, False) b2f = digital.chunks_to_symbols_bf((-1.0,1.0), 1) - dst = gr.vector_sink_f() + dst = blocks.vector_sink_f() del self.tb # Discard existing top block self.tb = gr.top_block() self.tb.connect(src, b2f, dst) @@ -70,7 +70,7 @@ class test_glfsr_source(gr_unittest.TestCase): def test_005_correlation_f(self): for degree in range(1,11): # Higher degrees take too long to correlate src = digital.glfsr_source_f(degree, False) - dst = gr.vector_sink_f() + dst = blocks.vector_sink_f() del self.tb # Discard existing top block self.tb = gr.top_block() self.tb.connect(src, dst) diff --git a/gr-digital/python/digital/qa_header_payload_demux.py b/gr-digital/python/digital/qa_header_payload_demux.py new file mode 100755 index 0000000000..e0ade4e5fa --- /dev/null +++ b/gr-digital/python/digital/qa_header_payload_demux.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import time + +from gnuradio import gr, gr_unittest, digital, blocks +import pmt + +class qa_header_payload_demux (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + """ Simplest possible test: put in zeros, then header, + then payload, trigger signal, try to demux. + The return signal from the header parser is faked via _post() + """ + n_zeros = 100 + header = (1, 2, 3) + payload = tuple(range(17)) + data_signal = (0,) * n_zeros + header + payload + trigger_signal = [0,] * len(data_signal) + trigger_signal[n_zeros] = 1 + + data_src = blocks.vector_source_f(data_signal, False) + trigger_src = blocks.vector_source_b(trigger_signal, False) + hpd = digital.header_payload_demux( + len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float + ) + self.assertEqual(pmt.length(hpd.message_ports_in()), 1) + header_sink = blocks.vector_sink_f() + payload_sink = blocks.vector_sink_f() + + self.tb.connect(data_src, (hpd, 0)) + self.tb.connect(trigger_src, (hpd, 1)) + self.tb.connect((hpd, 0), header_sink) + self.tb.connect((hpd, 1), payload_sink) + self.tb.start() + time.sleep(.2) # Need this, otherwise, the next message is ignored + hpd.to_basic_block()._post( + pmt.intern('header_data'), + pmt.from_long(len(payload)) + ) + while len(payload_sink.data()) < len(payload): + time.sleep(.2) + self.tb.stop() + self.tb.wait() + + self.assertEqual(header_sink.data(), header) + self.assertEqual(payload_sink.data(), payload) + + +if __name__ == '__main__': + gr_unittest.run(qa_header_payload_demux, "qa_header_payload_demux.xml") + diff --git a/gr-digital/python/digital/qa_lms_equalizer.py b/gr-digital/python/digital/qa_lms_equalizer.py index f610eeaaae..7768c1f078 100755 --- a/gr-digital/python/digital/qa_lms_equalizer.py +++ b/gr-digital/python/digital/qa_lms_equalizer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2006,2007,2010,2011 Free Software Foundation, Inc. +# Copyright 2006,2007,2010,2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_lms_dd_equalizer(gr_unittest.TestCase): @@ -31,9 +31,9 @@ class test_lms_dd_equalizer(gr_unittest.TestCase): self.tb = None def transform(self, src_data, gain, const): - SRC = gr.vector_source_c(src_data, False) + SRC = blocks.vector_source_c(src_data, False) EQU = digital.lms_dd_equalizer_cc(4, gain, 1, const.base()) - DST = gr.vector_sink_c() + DST = blocks.vector_sink_c() self.tb.connect(SRC, EQU, DST) self.tb.run() return DST.data() diff --git a/gr-digital/python/digital/qa_map.py b/gr-digital/python/digital/qa_map.py index df906d5e08..604fa084d9 100755 --- a/gr-digital/python/digital/qa_map.py +++ b/gr-digital/python/digital/qa_map.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_map(gr_unittest.TestCase): @@ -33,9 +33,9 @@ class test_map(gr_unittest.TestCase): def helper(self, symbols): src_data = [0, 1, 2, 3, 0, 1, 2, 3] expected_data = map(lambda x: symbols[x], src_data) - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.map_bb(symbols) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op, dst) self.tb.run() diff --git a/gr-digital/python/digital/qa_mpsk_receiver.py b/gr-digital/python/digital/qa_mpsk_receiver.py index d1ae81cef5..1379b52e61 100755 --- a/gr-digital/python/digital/qa_mpsk_receiver.py +++ b/gr-digital/python/digital/qa_mpsk_receiver.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -24,7 +24,7 @@ import random import cmath import time -from gnuradio import gr, gr_unittest, digital, filter +from gnuradio import gr, gr_unittest, digital, filter, blocks class test_mpsk_receiver(gr_unittest.TestCase): @@ -54,8 +54,8 @@ class test_mpsk_receiver(gr_unittest.TestCase): data = 10000*[complex(1,0), complex(-1,0)] #data = [2*random.randint(0,1)-1 for x in xrange(10000)] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() # pulse shaping interpolation filter nfilts = 32 @@ -110,8 +110,8 @@ class test_mpsk_receiver(gr_unittest.TestCase): complex(-0.707, -0.707), complex( 0.707, -0.707)] data = [0.5*d for d in data] - self.src = gr.vector_source_c(data, False) - self.snk = gr.vector_sink_c() + self.src = blocks.vector_source_c(data, False) + self.snk = blocks.vector_sink_c() # pulse shaping interpolation filter nfilts = 32 diff --git a/gr-digital/python/digital/qa_mpsk_snr_est.py b/gr-digital/python/digital/qa_mpsk_snr_est.py index 7991f26a5b..cb3e954141 100755 --- a/gr-digital/python/digital/qa_mpsk_snr_est.py +++ b/gr-digital/python/digital/qa_mpsk_snr_est.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011,2012 Free Software Foundation, Inc. +# Copyright 2011-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,7 +21,7 @@ # import random -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks def get_cplx(): return complex(2*random.randint(0,1) - 1, 0) @@ -45,8 +45,8 @@ class test_mpsk_snr_est(gr_unittest.TestCase): for i in xrange(1,6): src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)] - src = gr.vector_source_c(src_data) - dst = gr.null_sink(gr.sizeof_gr_complex) + src = blocks.vector_source_c(src_data) + dst = blocks.null_sink(gr.sizeof_gr_complex) tb = gr.top_block() tb.connect(src, op) @@ -103,7 +103,7 @@ class test_mpsk_snr_est(gr_unittest.TestCase): for i in xrange(1,6): src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)] - src = gr.vector_source_c(src_data) + src = blocks.vector_source_c(src_data) N = 10000 alpha = 0.001 diff --git a/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py b/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py new file mode 100755 index 0000000000..56cd7a617e --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# 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. +# + +from gnuradio import gr, gr_unittest, digital, blocks +import pmt + +class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + """ + pretty simple (the carrier allocation is not a practical OFDM configuration!) + """ + fft_len = 6 + tx_symbols = (1, 2, 3) + # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 + pilot_symbols = ((1j,),) + occupied_carriers = ((0, 1, 2),) + pilot_carriers = ((3,),) + sync_word = (range(fft_len),) + expected_result = tuple(sync_word[0] + [1j, 0, 0, 1, 2, 3]) + # ^ DC carrier + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_symbols)) + src = blocks.vector_source_c(tx_symbols, False, 1, (tag,)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, sync_word, + tag_name) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, alloc, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + + def test_001_t2 (self): + """ + pretty simple (same as before, but odd fft len) + """ + fft_len = 5 + tx_symbols = (1, 2, 3) + # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 + occupied_carriers = ((0, 1, 2),) + pilot_carriers = ((-2,),) + pilot_symbols = ((1j,),) + expected_result = (1j, 0, 1, 2, 3) + # ^ DC carrier + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_symbols)) + src = blocks.vector_source_c(tx_symbols, False, 1, (tag,)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, (), + tag_name) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, alloc, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + + def test_002_t (self): + """ + same, but using negative carrier indices + """ + fft_len = 6 + tx_symbols = (1, 2, 3) + pilot_symbols = ((1j,),) + occupied_carriers = ((-1, 1, 2),) + pilot_carriers = ((3,),) + expected_result = (1j, 0, 1, 0, 2, 3) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_symbols)) + src = blocks.vector_source_c(tx_symbols, False, 1, (tag,)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, (), + tag_name) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, alloc, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + + def test_003_t (self): + """ + more advanced: + - 6 symbols per carrier + - 2 pilots per carrier + - have enough data for nearly 3 OFDM symbols + - send that twice + - add some random tags + - don't shift + """ + tx_symbols = range(1, 16); # 15 symbols + pilot_symbols = ((1j, 2j), (3j, 4j)) + occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) + pilot_carriers = ((2, 13), (3, 12)) + expected_result = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, + 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, + 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) + fft_len = 16 + tag_name = "len" + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tag_name) + tag1.value = pmt.from_long(len(tx_symbols)) + tag2 = gr.gr_tag_t() + tag2.offset = len(tx_symbols) + tag2.key = pmt.string_to_symbol(tag_name) + tag2.value = pmt.from_long(len(tx_symbols)) + testtag1 = gr.gr_tag_t() + testtag1.offset = 0 + testtag1.key = pmt.string_to_symbol('tag1') + testtag1.value = pmt.from_long(0) + testtag2 = gr.gr_tag_t() + testtag2.offset = 7 # On the 2nd OFDM symbol + testtag2.key = pmt.string_to_symbol('tag2') + testtag2.value = pmt.from_long(0) + testtag3 = gr.gr_tag_t() + testtag3.offset = len(tx_symbols)+1 # First OFDM symbol of packet 2 + testtag3.key = pmt.string_to_symbol('tag3') + testtag3.value = pmt.from_long(0) + testtag4 = gr.gr_tag_t() + testtag4.offset = 2*len(tx_symbols)-1 # Last OFDM symbol of packet 2 + testtag4.key = pmt.string_to_symbol('tag4') + testtag4.value = pmt.from_long(0) + src = blocks.vector_source_c(tx_symbols * 2, False, 1, + (tag1, tag2, testtag1, testtag2, testtag3, testtag4)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, (), + tag_name, + False) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, alloc, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result * 2) + tags_found = {'tag1': False, 'tag2': False, 'tag3': False, 'tag4': False} + correct_offsets = {'tag1': 0, 'tag2': 1, 'tag3': 3, 'tag4': 5} + for tag in sink.tags(): + key = pmt.symbol_to_string(tag.key) + if key in tags_found.keys(): + tags_found[key] = True + self.assertEqual(correct_offsets[key], tag.offset) + if key == tag_name: + self.assertTrue(tag.offset == 0 or tag.offset == 3) + self.assertTrue(pmt.to_long(tag.value) == 3) + self.assertTrue(all(tags_found.values())) + + +if __name__ == '__main__': + gr_unittest.run(qa_digital_carrier_allocator_cvc, "qa_digital_carrier_allocator_cvc.xml") + diff --git a/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py new file mode 100755 index 0000000000..c9e2bacd0d --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python +# 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. +# + +import sys +import random + +import numpy + +from gnuradio import gr, gr_unittest, blocks, analog, digital +import pmt + +def shift_tuple(vec, N): + """ Shifts a vector by N elements. Fills up with zeros. """ + if N > 0: + return (0,) * N + tuple(vec[0:-N]) + else: + N = -N + return tuple(vec[N:]) + (0,) * N + +def rand_range(min_val, max_val): + """ Returns a random value (uniform) from the interval min_val, max_val """ + return random.random() * (max_val - min_val) + min_val + + +class qa_ofdm_sync_eqinit_vcvc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_offset_2sym (self): + """ Add a frequency offset, check if it's correctly detected. + Also add some random tags and see if they come out at the correct + position. """ + fft_len = 16 + carr_offset = -2 + sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + sync_symbol2 = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + tx_data = shift_tuple(sync_symbol1, carr_offset) + \ + shift_tuple(sync_symbol2, carr_offset) + \ + shift_tuple(data_symbol, carr_offset) + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol("test_tag_1") + tag1.value = pmt.from_long(23) + tag2 = gr.gr_tag_t() + tag2.offset = 2 + tag2.key = pmt.string_to_symbol("test_tag_2") + tag2.value = pmt.from_long(42) + src = blocks.vector_source_c(tx_data, False, fft_len, (tag1, tag2)) + chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chanest, sink) + self.tb.run() + self.assertEqual(shift_tuple(sink.data(), -carr_offset), data_symbol) + tags = sink.tags() + detected_tags = { + 'ofdm_sync_carr_offset': False, + 'test_tag_1': False, + 'test_tag_2': False + } + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + carr_offset_hat = pmt.to_long(tag.value) + self.assertEqual(pmt.to_long(tag.value), carr_offset) + if pmt.symbol_to_string(tag.key) == 'test_tag_1': + self.assertEqual(tag.offset, 0) + if pmt.symbol_to_string(tag.key) == 'test_tag_2': + self.assertEqual(tag.offset, 0) + detected_tags[pmt.symbol_to_string(tag.key)] = True + self.assertTrue(all(detected_tags.values())) + + def test_002_offset_1sym (self): + """ Add a frequency offset, check if it's correctly detected. + Difference to previous test is, it only uses one synchronisation symbol. """ + fft_len = 16 + carr_offset = -2 + # This will not correct for +2 because it thinks carrier 14 is used + # (because of interpolation) + sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + tx_data = shift_tuple(sync_symbol, carr_offset) + \ + shift_tuple(data_symbol, carr_offset) + src = blocks.vector_source_c(tx_data, False, fft_len) + # 17 is out of bounds! + chanest = digital.ofdm_chanest_vcvc(sync_symbol, (), 1, 0, 17) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chanest, sink) + self.tb.run() + self.assertEqual(shift_tuple(sink.data(), -carr_offset), data_symbol) + tags = sink.tags() + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + carr_offset_hat = pmt.to_long(tag.value) + self.assertEqual(pmt.to_long(tag.value), carr_offset) + + def test_003_channel_no_carroffset (self): + """ Add a channel, check if it's correctly estimated """ + fft_len = 16 + carr_offset = 0 + sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + sync_symbol2 = (0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + tx_data = sync_symbol1 + sync_symbol2 + data_symbol + channel = (0, 0, 0, 2, -2, 2, 3j, 2, 0, 2, 2, 2, 2, 3, 0, 0) + src = blocks.vector_source_c(tx_data, False, fft_len) + chan = blocks.multiply_const_vcc(channel) + chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chan, chanest, sink) + self.tb.run() + tags = sink.tags() + self.assertEqual(shift_tuple(sink.data(), -carr_offset), tuple(numpy.multiply(data_symbol, channel))) + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + self.assertEqual(pmt.to_long(tag.value), carr_offset) + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps': + self.assertEqual(pmt.c32vector_elements(tag.value), channel) + + def test_004_channel_no_carroffset_1sym (self): + """ Add a channel, check if it's correctly estimated. + Only uses 1 synchronisation symbol. """ + fft_len = 16 + carr_offset = 0 + sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + tx_data = sync_symbol + data_symbol + channel = (0, 0, 0, 2, 2, 2, 2.5, 3, 2.5, 2, 2.5, 3, 2, 1, 1, 0) + src = blocks.vector_source_c(tx_data, False, fft_len) + chan = blocks.multiply_const_vcc(channel) + chanest = digital.ofdm_chanest_vcvc(sync_symbol, (), 1) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chan, chanest, sink) + self.tb.run() + tags = sink.tags() + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + self.assertEqual(pmt.to_long(tag.value), carr_offset) + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps': + self.assertEqual(pmt.c32vector_elements(tag.value), channel) + + def test_005_both_1sym_force (self): + """ Add a channel, check if it's correctly estimated. + Only uses 1 synchronisation symbol. """ + fft_len = 16 + carr_offset = 0 + sync_symbol = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + ref_symbol = (0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + tx_data = sync_symbol + data_symbol + channel = (0, 0, 0, 2, 2, 2, 2.5, 3, 2.5, 2, 2.5, 3, 2, 1, 1, 0) + src = blocks.vector_source_c(tx_data, False, fft_len) + chan = blocks.multiply_const_vcc(channel) + chanest = digital.ofdm_chanest_vcvc(sync_symbol, ref_symbol, 1) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chan, chanest, sink) + self.tb.run() + tags = sink.tags() + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + self.assertEqual(pmt.to_long(tag.value), carr_offset) + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps': + self.assertEqual(pmt.c32vector_elements(tag.value), channel) + + def test_006_channel_and_carroffset (self): + """ Add a channel, check if it's correctly estimated """ + fft_len = 16 + carr_offset = 2 + # Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + sync_symbol1 = (0, 0, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0) + sync_symbol2 = (0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1, 0, 0) + data_symbol = (0, 0, 0, 1, -1, 1, -1, 1, 0, 1, -1, -1, -1, 1, 0, 0) + # Channel 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + # Shifted (0, 0, 0, 0, 0, 1j, -1, 1, -1j, 1j, 0, 1, -1j, -1, -1j, 1) + tx_data = shift_tuple(sync_symbol1, carr_offset) + \ + shift_tuple(sync_symbol2, carr_offset) + \ + shift_tuple(data_symbol, carr_offset) + channel = range(fft_len) + src = blocks.vector_source_c(tx_data, False, fft_len) + chan = blocks.multiply_const_vcc(channel) + chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, chan, chanest, sink) + self.tb.run() + tags = sink.tags() + chan_est = None + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + self.assertEqual(pmt.to_long(tag.value), carr_offset) + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps': + chan_est = pmt.c32vector_elements(tag.value) + for i in range(fft_len): + if shift_tuple(sync_symbol2, carr_offset)[i]: # Only here the channel can be estimated + self.assertEqual(chan_est[i], channel[i]) + self.assertEqual(sink.data(), tuple(numpy.multiply(shift_tuple(data_symbol, carr_offset), channel))) + + + def test_999_all_at_once(self): + """docstring for test_999_all_at_once""" + fft_len = 32 + # 6 carriers empty, 10 carriers full, 1 DC carrier, 10 carriers full, 5 carriers empty + syncsym_mask = (0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0) + carrier_mask = (0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0) + max_offset = 4 + wgn_amplitude = 0.05 + min_chan_ampl = 0.1 + max_chan_ampl = 5 + n_iter = 20 + def run_flow_graph(sync_sym1, sync_sym2, data_sym): + top_block = gr.top_block() + carr_offset = random.randint(-max_offset/2, max_offset/2) * 2 + tx_data = shift_tuple(sync_sym1, carr_offset) + \ + shift_tuple(sync_sym2, carr_offset) + \ + shift_tuple(data_sym, carr_offset) + channel = [rand_range(min_chan_ampl, max_chan_ampl) * numpy.exp(1j * rand_range(0, 2 * numpy.pi)) for x in range(fft_len)] + src = blocks.vector_source_c(tx_data, False, fft_len) + chan = blocks.multiply_const_vcc(channel) + noise = analog.noise_source_c(analog.GR_GAUSSIAN, wgn_amplitude) + add = blocks.add_cc(fft_len) + chanest = digital.ofdm_chanest_vcvc(sync_sym1, sync_sym2, 1) + sink = blocks.vector_sink_c(fft_len) + top_block.connect(src, chan, (add, 0), chanest, sink) + top_block.connect(noise, blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), (add, 1)) + top_block.run() + channel_est = None + carr_offset_hat = 0 + rx_sym_est = [0,] * fft_len + tags = sink.tags() + for tag in tags: + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_carr_offset': + carr_offset_hat = pmt.to_long(tag.value) + self.assertEqual(carr_offset, carr_offset_hat) + if pmt.symbol_to_string(tag.key) == 'ofdm_sync_chan_taps': + channel_est = pmt.c32vector_elements(tag.value) + shifted_carrier_mask = shift_tuple(carrier_mask, carr_offset) + for i in range(fft_len): + if shifted_carrier_mask[i] and channel_est[i]: + self.assertAlmostEqual(channel[i], channel_est[i], places=0) + rx_sym_est[i] = (sink.data()[i] / channel_est[i]).real + return (carr_offset, list(shift_tuple(rx_sym_est, -carr_offset_hat))) + bit_errors = 0 + for k in xrange(n_iter): + sync_sym = [(random.randint(0, 1) * 2 - 1) * syncsym_mask[i] for i in range(fft_len)] + ref_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)] + data_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)] + data_sym[26] = 1 + (carr_offset, rx_sym) = run_flow_graph(sync_sym, ref_sym, data_sym) + rx_sym_est = [0,] * fft_len + for i in xrange(fft_len): + if carrier_mask[i] == 0: + continue + rx_sym_est[i] = {True: 1, False: -1}[rx_sym[i] > 0] + if rx_sym_est[i] != data_sym[i]: + bit_errors += 1 + # This is much more than we could allow + self.assertTrue(bit_errors < n_iter) + + +if __name__ == '__main__': + gr_unittest.run(qa_ofdm_sync_eqinit_vcvc, "qa_ofdm_sync_eqinit_vcvc.xml") + diff --git a/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py b/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py new file mode 100755 index 0000000000..82d4950883 --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# Copyright 2007,2010,2011,2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest, digital, blocks +import pmt + +class test_ofdm_cyclic_prefixer (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_wo_tags_no_rolloff(self): + " The easiest test: make sure the CP is added correctly. " + fft_len = 8 + cp_len = 2 + expected_result = (6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + 6, 7, 0, 1, 2, 3, 4, 5, 6, 7) + src = blocks.vector_source_c(range(fft_len) * 2, False, fft_len) + cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len) + sink = blocks.vector_sink_c() + self.tb.connect(src, cp, sink) + self.tb.run() + self.assertEqual(sink.data(), expected_result) + + def test_wo_tags_2s_rolloff(self): + " No tags, but have a 2-sample rolloff " + fft_len = 8 + cp_len = 2 + rolloff = 2 + expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 + 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8) + src = blocks.vector_source_c(range(1, fft_len+1) * 2, False, fft_len) + cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, rolloff) + sink = blocks.vector_sink_c() + self.tb.connect(src, cp, sink) + self.tb.run() + self.assertEqual(sink.data(), expected_result) + + def test_with_tags_2s_rolloff(self): + " With tags and a 2-sample rolloff " + fft_len = 8 + cp_len = 2 + tag_name = "length" + expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 + 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0/2) + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(2) + tag2 = gr.gr_tag_t() + tag2.offset = 1 + tag2.key = pmt.string_to_symbol("random_tag") + tag2.value = pmt.from_long(42) + src = blocks.vector_source_c(range(1, fft_len+1) * 2, False, fft_len, (tag, tag2)) + cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) + sink = blocks.vector_sink_c() + self.tb.connect(src, cp, sink) + self.tb.run() + self.assertEqual(sink.data(), expected_result) + tags = [gr.tag_to_python(x) for x in sink.tags()] + tags = sorted([(x.offset, x.key, x.value) for x in tags]) + expected_tags = [ + (0, tag_name, len(expected_result)), + (fft_len+cp_len, "random_tag", 42) + ] + self.assertEqual(tags, expected_tags) + + +if __name__ == '__main__': + gr_unittest.run(test_ofdm_cyclic_prefixer, "test_ofdm_cyclic_prefixer.xml") + diff --git a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py new file mode 100755 index 0000000000..ee1e849d92 --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# 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. +# + +import numpy + +from gnuradio import gr, gr_unittest, digital, blocks +import pmt + +class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_simple (self): + """ Very simple functionality testing """ + fft_len = 8 + equalizer = digital.ofdm_equalizer_static(fft_len) + n_syms = 3 + len_tag_key = "frame_len" + tx_data = (1,) * fft_len * n_syms + len_tag = gr.gr_tag_t() + len_tag.offset = 0 + len_tag.key = pmt.string_to_symbol(len_tag_key) + len_tag.value = pmt.from_long(n_syms) + chan_tag = gr.gr_tag_t() + chan_tag.offset = 0 + chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") + chan_tag.value = pmt.init_c32vector(fft_len, (1,) * fft_len) + src = blocks.vector_source_c(tx_data, False, fft_len, (len_tag, chan_tag)) + eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, eq, sink) + self.tb.run () + # Check data + self.assertEqual(tx_data, sink.data()) + for tag in sink.tags(): + self.assertEqual(pmt.symbol_to_string(tag.key), len_tag_key) + self.assertEqual(pmt.to_long(tag.value), n_syms) + + def test_002_static (self): + fft_len = 8 + # 4 5 6 7 0 1 2 3 + tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0 + -1, -1, 0, 2, -1, 2, 0, -1, # 8 + -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols) + -1, -1, 1, 1, -1, 0, 2, -1] # 24 + cnst = digital.constellation_qpsk() + tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data] + occupied_carriers = ((1, 2, 6, 7),) + pilot_carriers = ((), (), (1, 2, 6, 7), ()) + pilot_symbols = ( + [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], [] + ) + equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers, pilot_carriers, pilot_symbols) + channel = [ + 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly... + 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! + 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here. + ] + for idx in range(fft_len, 2*fft_len): + channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5)) + idx2 = idx+2*fft_len + channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5)) + len_tag_key = "frame_len" + len_tag = gr.gr_tag_t() + len_tag.offset = 0 + len_tag.key = pmt.string_to_symbol(len_tag_key) + len_tag.value = pmt.from_long(4) + chan_tag = gr.gr_tag_t() + chan_tag.offset = 0 + chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") + chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len]) + src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (len_tag, chan_tag)) + eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key, True) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, eq, sink) + self.tb.run () + rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()] + self.assertEqual(tx_data, rx_data) + for tag in sink.tags(): + if pmt.symbol_to_string(tag.key) == len_tag_key: + self.assertEqual(pmt.to_long(tag.value), 4) + if pmt.symbol_to_string(tag.key) == "ofdm_sync_chan_taps": + self.assertEqual(list(pmt.c32vector_elements(tag.value)), channel[-fft_len:]) + + def test_002_simpledfe (self): + fft_len = 8 + # 4 5 6 7 0 1 2 3 + tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0 + -1, -1, 0, 2, -1, 2, 0, -1, # 8 + -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols) + -1, -1, 1, 1, -1, 0, 2, -1] # 24 + cnst = digital.constellation_qpsk() + tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data] + occupied_carriers = ((1, 2, 6, 7),) + pilot_carriers = ((), (), (1, 2, 6, 7), ()) + pilot_symbols = ( + [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], [] + ) + equalizer = digital.ofdm_equalizer_simpledfe( + fft_len, cnst.base(), occupied_carriers, pilot_carriers, pilot_symbols, 0, 0.01 + ) + channel = [ + 0, 0, 1, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly... + 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! + 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here. + ] + for idx in range(fft_len, 2*fft_len): + channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5)) + idx2 = idx+2*fft_len + channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5)) + len_tag_key = "frame_len" + len_tag = gr.gr_tag_t() + len_tag.offset = 0 + len_tag.key = pmt.string_to_symbol(len_tag_key) + len_tag.value = pmt.from_long(4) + chan_tag = gr.gr_tag_t() + chan_tag.offset = 0 + chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") + chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len]) + src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (len_tag, chan_tag)) + eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), len_tag_key, True) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, eq, sink) + self.tb.run () + rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()] + self.assertEqual(tx_data, rx_data) + for tag in sink.tags(): + if pmt.symbol_to_string(tag.key) == len_tag_key: + self.assertEqual(pmt.to_long(tag.value), 4) + if pmt.symbol_to_string(tag.key) == "ofdm_sync_chan_taps": + self.assertComplexTuplesAlmostEqual(list(pmt.c32vector_elements(tag.value)), channel[-fft_len:], places=1) + + +if __name__ == '__main__': + gr_unittest.run(qa_ofdm_frame_equalizer_vcvc, "qa_ofdm_frame_equalizer_vcvc.xml") + diff --git a/gr-digital/python/digital/qa_ofdm_insert_preamble.py b/gr-digital/python/digital/qa_ofdm_insert_preamble.py index a9664d6fe6..4edd54c8c6 100755 --- a/gr-digital/python/digital/qa_ofdm_insert_preamble.py +++ b/gr-digital/python/digital/qa_ofdm_insert_preamble.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2007,2010-2012 Free Software Foundation, Inc. +# Copyright 2007,2010-2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -34,8 +34,8 @@ class test_ofdm_insert_preamble(gr_unittest.TestCase): def helper(self, v0, v1, fft_length, preamble): tb = self.tb - src0 = gr.vector_source_c(v0) - src1 = gr.vector_source_b(v1) + src0 = blocks.vector_source_c(v0) + src1 = blocks.vector_source_b(v1) s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, fft_length) @@ -44,8 +44,8 @@ class test_ofdm_insert_preamble(gr_unittest.TestCase): op = digital.ofdm_insert_preamble(fft_length, preamble) v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length) - dst0 = gr.vector_sink_c() - dst1 = gr.vector_sink_b() + dst0 = blocks.vector_sink_c() + dst1 = blocks.vector_sink_b() tb.connect(src0, s2v, (op, 0)) tb.connect(src1, (op, 1)) diff --git a/gr-digital/python/digital/qa_ofdm_serializer_vcc.py b/gr-digital/python/digital/qa_ofdm_serializer_vcc.py new file mode 100755 index 0000000000..fb1f47f2fd --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_serializer_vcc.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# +# 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. +# + +import numpy + +from gnuradio import gr, gr_unittest, blocks. fft, analog, digital +import pmt + +class qa_ofdm_serializer_vcc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_simple (self): + """ Standard test """ + fft_len = 16 + tx_symbols = range(1, 16); + tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, + 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, + 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) + expected_result = tuple(range(1, 16)) + (0, 0, 0) + occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) + n_syms = len(tx_symbols)/fft_len + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(n_syms) + src = blocks.vector_source_c(tx_symbols, False, fft_len, (tag,)) + serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "", 0, False) + sink = blocks.vector_sink_c() + self.tb.connect(src, serializer, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + self.assertEqual(len(sink.tags()), 1) + result_tag = sink.tags()[0] + self.assertEqual(pmt.symbol_to_string(result_tag.key), tag_name) + self.assertEqual(pmt.to_long(result_tag.value), n_syms * len(occupied_carriers[0])) + + def test_002_with_offset (self): + """ Standard test, carrier offset """ + fft_len = 16 + tx_symbols = range(1, 16); + tx_symbols = (0, 0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, + 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, + 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0) + carr_offset = 1 # Compare this with tx_symbols from the previous test + expected_result = tuple(range(1, 16)) + (0, 0, 0) + occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) + n_syms = len(tx_symbols)/fft_len + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(n_syms) + offsettag = gr.gr_tag_t() + offsettag.offset = 0 + offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") + offsettag.value = pmt.from_long(carr_offset) + src = blocks.vector_source_c(tx_symbols, False, fft_len, (tag, offsettag)) + serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "", 0, False) + sink = blocks.vector_sink_c() + self.tb.connect(src, serializer, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + self.assertEqual(len(sink.tags()), 2) + for tag in sink.tags(): + if pmt.symbol_to_string(tag.key) == tag_name: + self.assertEqual(pmt.to_long(tag.value), n_syms * len(occupied_carriers[0])) + + def test_003_connect (self): + """ Connect carrier_allocator to ofdm_serializer, + make sure output==input """ + fft_len = 32 + n_syms = 10 + occupied_carriers = ((1, 2, 6, 7),) + pilot_carriers = ((3,),(5,)) + pilot_symbols = ((1j,),(-1j,)) + sync_word = (range(fft_len),) + tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)]) + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_data)) + src = blocks.vector_source_c(tx_data, False, 1, (tag,)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, sync_word, + tag_name) + serializer = digital.ofdm_serializer_vcc(alloc) + sink = blocks.vector_sink_c() + self.tb.connect(src, alloc, serializer, sink) + self.tb.run () + self.assertEqual(sink.data()[4:], tx_data) + + def test_004_connect (self): + """ + Advanced test: + - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer + - FFT does shift (moves DC to middle) + - Make sure input == output + - Frequency offset is -2 carriers + """ + fft_len = 8 + n_syms = 2 + carr_offset = -2 + freq_offset = 2 * numpy.pi * carr_offset / fft_len # If the sampling rate == 1 + occupied_carriers = ((1, 2, -2, -1),) + pilot_carriers = ((3,),(5,)) + pilot_symbols = ((1j,),(-1j,)) + sync_word = (range(fft_len),) + tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)]) + #tx_data = (1,) * occupied_carriers[0] * n_syms + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_data)) + offsettag = gr.gr_tag_t() + offsettag.offset = 0 + offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") + offsettag.value = pmt.from_long(carr_offset) + src = blocks.vector_source_c(tx_data, False, 1, (tag, offsettag)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, sync_word, + tag_name) + tx_ifft = fft.fft_vcc(fft_len, False, ()) + offset_sig = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0) + mixer = blocks.multiply_cc() + rx_fft = fft.fft_vcc(fft_len, True, (), True) + serializer = digital.ofdm_serializer_vcc(alloc) + sink = blocks.vector_sink_c() + self.tb.connect( + src, alloc, tx_ifft, + blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len), + (mixer, 0), + blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), + rx_fft, serializer, sink + ) + self.tb.connect(offset_sig, (mixer, 1)) + self.tb.run () + # FIXME check this + #self.assertEqual(sink.data(), tx_data) + + def test_005_packet_len_tag (self): + """ Standard test """ + fft_len = 16 + tx_symbols = range(1, 16); + tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, + 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, + 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) + expected_result = tuple(range(1, 16)) + occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) + n_syms = len(tx_symbols)/fft_len + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(n_syms) + tag2 = gr.gr_tag_t() + tag2.offset = 0 + tag2.key = pmt.string_to_symbol("packet_len") + tag2.value = pmt.from_long(len(expected_result)) + src = blocks.vector_source_c(tx_symbols, False, fft_len, (tag, tag2)) + serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, tag_name, "packet_len", 0, False) + sink = blocks.vector_sink_c() + self.tb.connect(src, serializer, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + self.assertEqual(len(sink.tags()), 1) + result_tag = sink.tags()[0] + self.assertEqual(pmt.symbol_to_string(result_tag.key), "packet_len") + self.assertEqual(pmt.to_long(result_tag.value), len(expected_result)) + + def test_099 (self): + """ Make sure it fails if it should """ + fft_len = 16 + occupied_carriers = ((1, 3, 4, 11, 12, 17),) + tag_name = "len" + self.assertRaises(RuntimeError, digital.ofdm_serializer_vcc, fft_len, occupied_carriers, tag_name) + + +if __name__ == '__main__': + #gr_unittest.run(qa_ofdm_serializer_vcc, "qa_ofdm_serializer_vcc.xml") + gr_unittest.run(qa_ofdm_serializer_vcc) + diff --git a/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py new file mode 100755 index 0000000000..ba50240916 --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python +# +# 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. +# + +import numpy +import random + +from gnuradio import gr, gr_unittest, blocks, analog + +try: + # This will work when feature #505 is added. + from gnuradio import digital + from gnuradio.digital.utils import tagged_streams + from gnuradio.digital.ofdm_txrx import ofdm_tx +except ImportError: + # Until then this will work. + import digital_swig as digital + from utils import tagged_streams + from ofdm_txrx import ofdm_tx + + +class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_detect (self): + """ Send two bursts, with zeros in between, and check + they are both detected at the correct position and no + false alarms occur """ + n_zeros = 15 + fft_len = 32 + cp_len = 4 + sig_len = (fft_len + cp_len) * 10 + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + tx_signal = [0,] * n_zeros + \ + sync_symbol[-cp_len:] + \ + sync_symbol + \ + [(random.randint(0, 1)*2)-1 for x in range(sig_len)] + tx_signal = tx_signal * 2 + add = blocks.add_cc() + sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) + sink_freq = blocks.vector_sink_f() + sink_detect = blocks.vector_sink_b() + self.tb.connect(blocks.vector_source_c(tx_signal), (add, 0)) + self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .01), (add, 1)) + self.tb.connect(add, sync) + self.tb.connect((sync, 0), sink_freq) + self.tb.connect((sync, 1), sink_detect) + self.tb.run() + sig1_detect = sink_detect.data()[0:len(tx_signal)/2] + sig2_detect = sink_detect.data()[len(tx_signal)/2:] + self.assertTrue(abs(sig1_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len) + self.assertTrue(abs(sig2_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len) + self.assertEqual(numpy.sum(sig1_detect), 1) + self.assertEqual(numpy.sum(sig2_detect), 1) + + + def test_002_freq (self): + """ Add a fine frequency offset and see if that get's detected properly """ + fft_len = 32 + cp_len = 4 + freq_offset = 0.1 # Must stay < 2*pi/fft_len = 0.196 (otherwise, it's coarse) + sig_len = (fft_len + cp_len) * 10 + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + tx_signal = sync_symbol[-cp_len:] + \ + sync_symbol + \ + [(random.randint(0, 1)*2)-1 for x in range(sig_len)] + mult = blocks.multiply_cc() + add = blocks.add_cc() + sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) + sink_freq = blocks.vector_sink_f() + sink_detect = blocks.vector_sink_b() + self.tb.connect(blocks.vector_source_c(tx_signal), (mult, 0), (add, 0)) + self.tb.connect(analog.sig_source_c(2 * numpy.pi, analog.GR_SIN_WAVE, freq_offset, 1.0), (mult, 1)) + self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .01), (add, 1)) + self.tb.connect(add, sync) + self.tb.connect((sync, 0), sink_freq) + self.tb.connect((sync, 1), sink_detect) + self.tb.run() + phi_hat = sink_freq.data()[sink_detect.data().index(1)] + est_freq_offset = 2 * phi_hat / fft_len + self.assertAlmostEqual(est_freq_offset, freq_offset, places=2) + + + def test_003_multiburst (self): + """ Send several bursts, see if the number of detects is correct. + Burst lengths and content are random. + """ + n_bursts = 42 + fft_len = 32 + cp_len = 4 + tx_signal = [] + for i in xrange(n_bursts): + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + tx_signal += [0,] * random.randint(0, 2*fft_len) + \ + sync_symbol[-cp_len:] + \ + sync_symbol + \ + [(random.randint(0, 1)*2)-1 for x in range(fft_len * random.randint(5,23))] + add = blocks.add_cc() + sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) + sink_freq = blocks.vector_sink_f() + sink_detect = blocks.vector_sink_b() + self.tb.connect(blocks.vector_source_c(tx_signal), (add, 0)) + self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .005), (add, 1)) + self.tb.connect(add, sync) + self.tb.connect((sync, 0), sink_freq) + self.tb.connect((sync, 1), sink_detect) + self.tb.run() + self.assertEqual(numpy.sum(sink_detect.data()), n_bursts, + msg="""Because of statistics, it is possible (though unlikely) +that the number of detected bursts differs slightly. If the number of detects is +off by one or two, run the test again and see what happen. +Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts) + ) + + # FIXME ofdm_mod is currently not working + #def test_004_ofdm_packets (self): + #""" + #Send several bursts, see if the number of detects is correct. + #Burst lengths and content are random. + #""" + #n_bursts = 42 + #fft_len = 64 + #cp_len = 12 + #tx_signal = [] + #packets = [] + #tagname = "length" + #min_packet_length = 100 + #max_packet_length = 100 + #sync_sequence = [random.randint(0, 1)*2-1 for x in range(fft_len/2)] + #for i in xrange(n_bursts): + #packet_length = random.randint(min_packet_length, + #max_packet_length+1) + #packet = [random.randint(0, 255) for i in range(packet_length)] + #packets.append(packet) + #data, tags = tagged_streams.packets_to_vectors( + #packets, tagname, vlen=1) + #total_length = len(data) + + #src = blocks.vector_source_b(data, False, 1, tags) + #mod = ofdm_tx( + #fft_len=fft_len, + #cp_len=cp_len, + #length_tag_name=tagname, + #occupied_carriers=(range(1, 27) + range(38, 64),), + #pilot_carriers=((0,),), + #pilot_symbols=((100,),), + #) + #rate_in = 16000 + #rate_out = 48000 + #ratio = float(rate_out) / rate_in + #throttle1 = gr.throttle(gr.sizeof_gr_complex, rate_in) + #sink_countbursts = gr.vector_sink_c() + #head = gr.head(gr.sizeof_gr_complex, int(total_length * ratio*2)) + #add = gr.add_cc() + #sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) + #sink_freq = blocks.vector_sink_f() + #sink_detect = blocks.vector_sink_b() + #noise_level = 0.01 + #noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_level) + #self.tb.connect(src, mod, blocks.null_sink(gr.sizeof_gr_complex)) + #self.tb.connect(insert_zeros, sink_countbursts) + #self.tb.connect(noise, (add, 1)) + #self.tb.connect(add, sync) + #self.tb.connect((sync, 0), sink_freq) + #self.tb.connect((sync, 1), sink_detect) + #self.tb.run() + #count_data = sink_countbursts.data() + #count_tags = sink_countbursts.tags() + #burstcount = tagged_streams.count_bursts(count_data, count_tags, tagname) + #self.assertEqual(numpy.sum(sink_detect.data()), burstcount) + + +if __name__ == '__main__': + #gr_unittest.run(qa_ofdm_sync_sc_cfb, "qa_ofdm_sync_sc_cfb.xml") + gr_unittest.run(qa_ofdm_sync_sc_cfb) + diff --git a/gr-digital/python/digital/qa_ofdm_txrx.py b/gr-digital/python/digital/qa_ofdm_txrx.py new file mode 100755 index 0000000000..681041d47d --- /dev/null +++ b/gr-digital/python/digital/qa_ofdm_txrx.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# Copyright 2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import random + +import numpy +from gnuradio import gr, gr_unittest, digital, blocks +from gnuradio.digital.ofdm_txrx import ofdm_tx, ofdm_rx +from gnuradio.digital.utils import tagged_streams + +class test_ofdm_txrx (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001 (self): + pass + #len_tag_key = 'frame_len' + #n_bytes = 100 + #test_data = [random.randint(0, 255) for x in range(n_bytes)] + #tx_data, tags = tagged_streams.packets_to_vectors((test_data,), len_tag_key) + #src = blocks.vector_source_b(test_data, False, 1, tags) + #tx = ofdm_tx(frame_length_tag_key=len_tag_key) + #rx = ofdm_rx(frame_length_tag_key=len_tag_key) + #self.assertEqual(tx.sync_word1, rx.sync_word1) + #self.assertEqual(tx.sync_word2, rx.sync_word2) + #delay = blocks.delay(gr.sizeof_gr_complex, 100) + #noise = analog.noise_source_c(analog.GR_GAUSSIAN, 0.05) + #add = blocks.add_cc() + #sink = blocks.vector_sink_b() + ##self.tb.connect(src, tx, add, rx, sink) + ##self.tb.connect(noise, (add, 1)) + #self.tb.connect(src, tx, blocks.null_sink(gr.sizeof_gr_complex)) + #self.tb.run() + + +if __name__ == '__main__': + gr_unittest.run(test_ofdm_txrx, "test_ofdm_txrx.xml") + diff --git a/gr-digital/python/digital/qa_packet_headergenerator_bb.py b/gr-digital/python/digital/qa_packet_headergenerator_bb.py new file mode 100755 index 0000000000..aaf7f89918 --- /dev/null +++ b/gr-digital/python/digital/qa_packet_headergenerator_bb.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest, digital, blocks +import pmt + +class qa_packet_headergenerator_bb (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_12bits (self): + # 3 PDUs: | | | | + data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4) + tagname = "packet_len" + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tagname) + tag1.value = pmt.from_long(4) + tag2 = gr.gr_tag_t() + tag2.offset = 4 + tag2.key = pmt.string_to_symbol(tagname) + tag2.value = pmt.from_long(2) + tag3 = gr.gr_tag_t() + tag3.offset = 6 + tag3.key = pmt.string_to_symbol(tagname) + tag3.value = pmt.from_long(4) + src = blocks.vector_source_b(data, False, 1, (tag1, tag2, tag3)) + header = digital.packet_headergenerator_bb(12, tagname) + sink = blocks.vector_sink_b() + self.tb.connect(src, header, sink) + self.tb.run() + expected_data = ( + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ) + self.assertEqual(sink.data(), expected_data) + + + def test_002_32bits (self): + # 3 PDUs: | | | | + data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4) + tagname = "packet_len" + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tagname) + tag1.value = pmt.from_long(4) + tag2 = gr.gr_tag_t() + tag2.offset = 4 + tag2.key = pmt.string_to_symbol(tagname) + tag2.value = pmt.from_long(2) + tag3 = gr.gr_tag_t() + tag3.offset = 6 + tag3.key = pmt.string_to_symbol(tagname) + tag3.value = pmt.from_long(4) + src = blocks.vector_source_b(data, False, 1, (tag1, tag2, tag3)) + header = digital.packet_headergenerator_bb(32, tagname) + sink = blocks.vector_sink_b() + self.tb.connect(src, header, sink) + self.tb.run() + expected_data = ( + # | Number of symbols | Packet number | Parity + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ) + self.assertEqual(sink.data(), expected_data) + + + def test_003_12bits_formatter_object (self): + # 3 PDUs: | | | | + data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4) + tagname = "packet_len" + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tagname) + tag1.value = pmt.from_long(4) + tag2 = gr.gr_tag_t() + tag2.offset = 4 + tag2.key = pmt.string_to_symbol(tagname) + tag2.value = pmt.from_long(2) + tag3 = gr.gr_tag_t() + tag3.offset = 6 + tag3.key = pmt.string_to_symbol(tagname) + tag3.value = pmt.from_long(4) + src = blocks.vector_source_b(data, False, 1, (tag1, tag2, tag3)) + formatter_object = digital.packet_header_default(12, tagname) + header = digital.packet_headergenerator_bb(formatter_object.formatter(), tagname) + sink = blocks.vector_sink_b() + self.tb.connect(src, header, sink) + self.tb.run() + expected_data = ( + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ) + self.assertEqual(sink.data(), expected_data) + + def test_004_8bits_formatter_ofdm (self): + occupied_carriers = ((1, 2, 3, 5, 6, 7),) + # 3 PDUs: | | | | + data = (1, 2, 3, 4, 1, 2, 1, 2, 3, 4) + tagname = "packet_len" + tag1 = gr.gr_tag_t() + tag1.offset = 0 + tag1.key = pmt.string_to_symbol(tagname) + tag1.value = pmt.from_long(4) + tag2 = gr.gr_tag_t() + tag2.offset = 4 + tag2.key = pmt.string_to_symbol(tagname) + tag2.value = pmt.from_long(2) + tag3 = gr.gr_tag_t() + tag3.offset = 6 + tag3.key = pmt.string_to_symbol(tagname) + tag3.value = pmt.from_long(4) + src = blocks.vector_source_b(data, False, 1, (tag1, tag2, tag3)) + formatter_object = digital.packet_header_ofdm(occupied_carriers, 1, tagname) + self.assertEqual(formatter_object.header_len(), 6) + self.assertEqual(pmt.symbol_to_string(formatter_object.len_tag_key()), tagname) + header = digital.packet_headergenerator_bb(formatter_object.formatter(), tagname) + sink = blocks.vector_sink_b() + self.tb.connect(src, header, sink) + self.tb.run() + expected_data = ( + 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 + ) + self.assertEqual(sink.data(), expected_data) + +if __name__ == '__main__': + gr_unittest.run(qa_packet_headergenerator_bb, "qa_packet_headergenerator_bb.xml") + diff --git a/gr-digital/python/digital/qa_packet_headerparser_b.py b/gr-digital/python/digital/qa_packet_headerparser_b.py new file mode 100755 index 0000000000..b127c86fb1 --- /dev/null +++ b/gr-digital/python/digital/qa_packet_headerparser_b.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import time +from gnuradio import gr, gr_unittest, blocks, digital +import pmt + +class qa_packet_headerparser_b (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + expected_data = ( + # | Number of symbols | Packet number | Parity + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 + ) + tagname = "packet_len" + + src = blocks.vector_source_b(expected_data) + parser = digital.packet_headerparser_b(32, tagname) + sink = blocks.message_debug() + + self.tb.connect(src, parser) + self.tb.msg_connect(parser, "header_data", sink, "store") + self.tb.start () + time.sleep(1) + self.tb.stop() + self.tb.wait() + + self.assertEqual(sink.num_messages(), 3) + msg = sink.get_message(0) + #try: + #self.assertEqual(4, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol(tagname), pmt.PMT_F))) + #self.assertEqual(0, pmt.pmt_to_long(pmt.pmt_dict_ref(msg, pmt.pmt_string_to_symbol("packet_num"), pmt.PMT_F))) + + #except: + #self.fail() + # msg1: length 4, number 0 + # msg2: length 2, number 1 + # msg3: PMT_F because parity fail + + + +if __name__ == '__main__': + gr_unittest.run(qa_packet_headerparser_b, "qa_packet_headerparser_b.xml") diff --git a/gr-digital/python/digital/qa_pfb_clock_sync.py b/gr-digital/python/digital/qa_pfb_clock_sync.py index 77a0c9eadf..286953ab34 100755 --- a/gr-digital/python/digital/qa_pfb_clock_sync.py +++ b/gr-digital/python/digital/qa_pfb_clock_sync.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,7 +23,7 @@ import random import cmath -from gnuradio import gr, gr_unittest, filter, digital +from gnuradio import gr, gr_unittest, filter, digital, blocks class test_pfb_clock_sync(gr_unittest.TestCase): @@ -54,7 +54,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase): osps) data = 10000*[complex(1,0), complex(-1,0)] - self.src = gr.vector_source_c(data, False) + self.src = blocks.vector_source_c(data, False) # pulse shaping interpolation filter rrc_taps = filter.firdes.root_raised_cosine( @@ -65,7 +65,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase): ntaps) self.rrc_filter = filter.pfb_arb_resampler_ccf(sps, rrc_taps) - self.snk = gr.vector_sink_c() + self.snk = blocks.vector_sink_c() self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) self.tb.run() @@ -107,7 +107,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase): osps) data = 10000*[1, -1] - self.src = gr.vector_source_f(data, False) + self.src = blocks.vector_source_f(data, False) # pulse shaping interpolation filter rrc_taps = filter.firdes.root_raised_cosine( @@ -118,7 +118,7 @@ class test_pfb_clock_sync(gr_unittest.TestCase): ntaps) self.rrc_filter = filter.pfb_arb_resampler_fff(sps, rrc_taps) - self.snk = gr.vector_sink_f() + self.snk = blocks.vector_sink_f() self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) self.tb.run() diff --git a/gr-digital/python/digital/qa_pn_correlator_cc.py b/gr-digital/python/digital/qa_pn_correlator_cc.py index f637ee7bd3..92041d9eda 100755 --- a/gr-digital/python/digital/qa_pn_correlator_cc.py +++ b/gr-digital/python/digital/qa_pn_correlator_cc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2007,2010,2012 Free Software Foundation, Inc. +# Copyright 2007,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -37,10 +37,10 @@ class test_pn_correlator_cc(gr_unittest.TestCase): degree = 10 length = 2**degree-1 src = digital.glfsr_source_f(degree) - head = gr.head(gr.sizeof_float, length*length) + head = blocks.head(gr.sizeof_float, length*length) f2c = blocks.float_to_complex() corr = digital.pn_correlator_cc(degree) - dst = gr.vector_sink_c() + dst = blocks.vector_sink_c() self.tb.connect(src, head, f2c, corr, dst) self.tb.run() data = dst.data() diff --git a/gr-digital/python/digital/qa_probe_density.py b/gr-digital/python/digital/qa_probe_density.py index bcf4eeeaf0..752d95da3e 100755 --- a/gr-digital/python/digital/qa_probe_density.py +++ b/gr-digital/python/digital/qa_probe_density.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2012 Free Software Foundation, Inc. +# Copyright 2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_probe_density(gr_unittest.TestCase): @@ -33,7 +33,7 @@ class test_probe_density(gr_unittest.TestCase): def test_001(self): src_data = [0, 1, 0, 1] expected_data = 1 - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.probe_density_b(1) self.tb.connect(src, op) self.tb.run() @@ -45,7 +45,7 @@ class test_probe_density(gr_unittest.TestCase): def test_002(self): src_data = [1, 1, 1, 1] expected_data = 1 - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.probe_density_b(0.01) self.tb.connect(src, op) self.tb.run() @@ -56,7 +56,7 @@ class test_probe_density(gr_unittest.TestCase): def test_003(self): src_data = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] expected_data = 0.95243 - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.probe_density_b(0.01) self.tb.connect(src, op) self.tb.run() diff --git a/gr-digital/python/digital/qa_scrambler.py b/gr-digital/python/digital/qa_scrambler.py index e11958c650..05daebd389 100755 --- a/gr-digital/python/digital/qa_scrambler.py +++ b/gr-digital/python/digital/qa_scrambler.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2010,2012 Free Software Foundation, Inc. +# Copyright 2008,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_scrambler(gr_unittest.TestCase): @@ -32,30 +32,30 @@ class test_scrambler(gr_unittest.TestCase): def test_scrambler_descrambler(self): src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) + src = blocks.vector_source_b(src_data, False) scrambler = digital.scrambler_bb(0x8a, 0x7F, 7) # CCSDS 7-bit scrambler descrambler = digital.descrambler_bb(0x8a, 0x7F, 7) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, scrambler, descrambler, dst) self.tb.run() self.assertEqual(tuple(src_data[:-8]), dst.data()[8:]) # skip garbage during synchronization def test_additive_scrambler(self): src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) + src = blocks.vector_source_b(src_data, False) scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7) descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, scrambler, descrambler, dst) self.tb.run() self.assertEqual(src_data, dst.data()) def test_additive_scrambler_reset(self): src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) + src = blocks.vector_source_b(src_data, False) scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, scrambler, descrambler, dst) self.tb.run() self.assertEqual(src_data, dst.data()) diff --git a/gr-digital/python/digital/qa_simple_correlator.py b/gr-digital/python/digital/qa_simple_correlator.py index 4af1d542c8..f39fb62dda 100755 --- a/gr-digital/python/digital/qa_simple_correlator.py +++ b/gr-digital/python/digital/qa_simple_correlator.py @@ -41,7 +41,7 @@ class test_simple_correlator(gr_unittest.TestCase): # Just using a RRC for some basic filter shape taps = filter.firdes.root_raised_cosine(8, 8, 1.0, 0.5, 21) - src = gr.vector_source_b(expected_result) + src = blocks.vector_source_b(expected_result) frame = digital.simple_framer(4) unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) expand = filter.interp_fir_filter_fff(8, taps) @@ -49,7 +49,7 @@ class test_simple_correlator(gr_unittest.TestCase): mult2 = blocks.multiply_const_ff(2) sub1 = blocks.add_const_ff(-1) op = digital.simple_correlator(4) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, frame, unpack, b2f, mult2, sub1, expand) self.tb.connect(expand, op, dst) self.tb.run() diff --git a/gr-digital/python/digital/qa_simple_framer.py b/gr-digital/python/digital/qa_simple_framer.py index 095d61c5e5..cf9934648b 100755 --- a/gr-digital/python/digital/qa_simple_framer.py +++ b/gr-digital/python/digital/qa_simple_framer.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# Copyright 2004,2007,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,7 +20,7 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, digital +from gnuradio import gr, gr_unittest, digital, blocks class test_simple_framer(gr_unittest.TestCase): @@ -42,9 +42,9 @@ class test_simple_framer(gr_unittest.TestCase): 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) - src = gr.vector_source_b(src_data) + src = blocks.vector_source_b(src_data) op = digital.simple_framer(4) - dst = gr.vector_sink_b() + dst = blocks.vector_sink_b() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() diff --git a/gr-digital/python/digital/utils/tagged_streams.py b/gr-digital/python/digital/utils/tagged_streams.py new file mode 100644 index 0000000000..f2a58ffe1e --- /dev/null +++ b/gr-digital/python/digital/utils/tagged_streams.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# Copyright 2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import pmt + +def make_lengthtags(lengths, offsets, tagname='length', vlen=1): + tags = [] + assert(len(offsets) == len(lengths)) + for offset, length in zip(offsets, lengths): + tag = gr.gr_tag_t() + tag.offset = offset/vlen + tag.key = pmt.string_to_symbol(tagname) + tag.value = pmt.from_long(length/vlen) + tags.append(tag) + return tags + +def string_to_vector(string): + v = [] + for s in string: + v.append(ord(s)) + return v + +def strings_to_vectors(strings, lengthtagname): + vs = [string_to_vector(string) for string in strings] + return packets_to_vectors(vs, lengthtagname) + +def vector_to_string(v): + s = [] + for d in v: + s.append(chr(d)) + return ''.join(s) + +def vectors_to_strings(data, tags, lengthtagname): + packets = vectors_to_packets(data, tags, lengthtagname) + return [vector_to_string(packet) for packet in packets] + +def count_bursts(data, tags, lengthtagname, vlen=1): + lengthtags = [t for t in tags + if pmt.symbol_to_string(t.key) == lengthtagname] + lengths = {} + for tag in lengthtags: + if tag.offset in lengths: + raise ValueError( + "More than one tags with key {0} with the same offset={1}." + .format(lengthtagname, tag.offset)) + lengths[tag.offset] = pmt.to_long(tag.value)*vlen + in_burst = False + in_packet = False + packet_length = None + packet_pos = None + burst_count = 0 + for pos in range(len(data)): + if pos in lengths: + if in_packet: + print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos)) + raise StandardError("Received packet tag while in packet.") + packet_pos = -1 + packet_length = lengths[pos] + in_packet = True + if not in_burst: + burst_count += 1 + in_burst = True + elif not in_packet: + in_burst = False + if in_packet: + packet_pos += 1 + if packet_pos == packet_length-1: + in_packet = False + packet_pos = None + return burst_count + +def vectors_to_packets(data, tags, lengthtagname, vlen=1): + lengthtags = [t for t in tags + if pmt.symbol_to_string(t.key) == lengthtagname] + lengths = {} + for tag in lengthtags: + if tag.offset in lengths: + raise ValueError( + "More than one tags with key {0} with the same offset={1}." + .format(lengthtagname, tag.offset)) + lengths[tag.offset] = pmt.to_long(tag.value)*vlen + if 0 not in lengths: + raise ValueError("There is no tag with key {0} and an offset of 0" + .format(lengthtagname)) + pos = 0 + packets = [] + while pos < len(data): + if pos not in lengths: + raise ValueError("There is no tag with key {0} and an offset of {1}." + "We were expecting one." + .format(lengthtagname, pos)) + length = lengths[pos] + if length == 0: + raise ValueError("Packets cannot have zero length.") + if pos+length > len(data): + raise ValueError("The final packet is incomplete.") + packets.append(data[pos: pos+length]) + pos += length + return packets + +def packets_to_vectors(packets, lengthtagname, vlen=1): + tags = [] + data = [] + offset = 0 + for packet in packets: + data.extend(packet) + tag = gr.gr_tag_t() + tag.offset = offset/vlen + tag.key = pmt.string_to_symbol(lengthtagname) + tag.value = pmt.from_long(len(packet)/vlen) + tags.append(tag) + offset = offset + len(packet) + return data, tags diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt index 6b6eb5e457..76054de3fa 100644 --- a/gr-digital/swig/CMakeLists.txt +++ b/gr-digital/swig/CMakeLists.txt @@ -29,13 +29,10 @@ set(GR_SWIG_INCLUDE_DIRS ${GR_ANALOG_INCLUDE_DIRS} ${GR_FFT_INCLUDE_DIRS} ${GR_FILTER_INCLUDE_DIRS} - ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} - ${GRUEL_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_SWIG_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) -set(GR_SWIG_LIBRARIES gnuradio-digital gnuradio-filter) - if(ENABLE_GR_CTRLPORT) ADD_DEFINITIONS(-DGR_CTRLPORT) list(APPEND GR_SWIG_INCLUDE_DIRS ${ICE_INCLUDE_DIR}) @@ -44,9 +41,11 @@ endif(ENABLE_GR_CTRLPORT) # Setup swig docs to depend on includes and pull in from build directory set(GR_SWIG_TARGET_DEPS digital_generated_includes) set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i) -set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/digital) +set(GR_SWIG_DOCS_TARGET_DEPS runtime_swig_swig_doc) -set(GR_SWIG_LIBRARIES gnuradio-digital gnuradio-filter gnuradio-analog) +set(GR_SWIG_LIBRARIES gnuradio-digital + gnuradio-filter gnuradio-analog gnuradio-blocks) GR_SWIG_MAKE(digital_swig digital_swig.i) @@ -59,6 +58,9 @@ GR_SWIG_INSTALL( install( FILES digital_swig.i + constellation.i + ofdm_equalizer.i + packet_header.i ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "digital_swig" diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index 155efddf75..54f9c64e2d 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -21,8 +21,9 @@ #define DIGITAL_API #define ANALOG_API +#define BLOCKS_API -%include "gnuradio.i" +%include "runtime_swig.i" %include "stdint.i" //load generated python docstrings @@ -30,34 +31,32 @@ %include "analog/cpm.h" -%include "gri_control_loop.h" - -// Used in the constellation objects -%template(unsigned_int_vector) std::vector<unsigned int>; +%{ +#include <blocks/control_loop.h> +%} +%include <blocks/control_loop.h> %{ -#include "digital/metric_type.h" -#include "digital/mpsk_snr_est.h" -#include "digital/lfsr.h" #include "digital/additive_scrambler_bb.h" #include "digital/binary_slicer_fb.h" -#include "digital/chunks_to_symbols_bf.h" #include "digital/chunks_to_symbols_bc.h" -#include "digital/chunks_to_symbols_sf.h" -#include "digital/chunks_to_symbols_sc.h" -#include "digital/chunks_to_symbols_if.h" +#include "digital/chunks_to_symbols_bf.h" #include "digital/chunks_to_symbols_ic.h" +#include "digital/chunks_to_symbols_if.h" +#include "digital/chunks_to_symbols_sc.h" +#include "digital/chunks_to_symbols_sf.h" #include "digital/clock_recovery_mm_cc.h" #include "digital/clock_recovery_mm_ff.h" #include "digital/cma_equalizer_cc.h" #include "digital/constellation.h" -#include "digital/constellation_receiver_cb.h" #include "digital/constellation_decoder_cb.h" +#include "digital/constellation_receiver_cb.h" #include "digital/correlate_access_code_bb.h" #include "digital/correlate_access_code_tag_bb.h" #include "digital/costas_loop_cc.h" #include "digital/cpmmod_bc.h" #include "digital/crc32.h" +#include "digital/crc32_bb.h" #include "digital/descrambler_bb.h" #include "digital/diff_decoder_bb.h" #include "digital/diff_encoder_bb.h" @@ -66,17 +65,33 @@ #include "digital/framer_sink_1.h" #include "digital/glfsr_source_b.h" #include "digital/glfsr_source_f.h" +#include "digital/header_payload_demux.h" #include "digital/kurtotic_equalizer_cc.h" +#include "digital/lfsr.h" #include "digital/lms_dd_equalizer_cc.h" #include "digital/map_bb.h" +#include "digital/metric_type.h" #include "digital/mpsk_receiver_cc.h" +#include "digital/mpsk_snr_est.h" #include "digital/mpsk_snr_est_cc.h" +#include "digital/ofdm_carrier_allocator_cvc.h" +#include "digital/ofdm_chanest_vcvc.h" #include "digital/ofdm_cyclic_prefixer.h" +#include "digital/ofdm_equalizer_base.h" +#include "digital/ofdm_equalizer_simpledfe.h" +#include "digital/ofdm_equalizer_static.h" #include "digital/ofdm_frame_acquisition.h" +#include "digital/ofdm_frame_equalizer_vcvc.h" #include "digital/ofdm_frame_sink.h" #include "digital/ofdm_insert_preamble.h" #include "digital/ofdm_mapper_bcv.h" #include "digital/ofdm_sampler.h" +#include "digital/ofdm_serializer_vcc.h" +#include "digital/ofdm_sync_sc_cfb.h" +#include "digital/packet_header_default.h" +#include "digital/packet_header_ofdm.h" +#include "digital/packet_headergenerator_bb.h" +#include "digital/packet_headerparser_b.h" #include "digital/packet_sink.h" #include "digital/pfb_clock_sync_ccf.h" #include "digital/pfb_clock_sync_fff.h" @@ -84,32 +99,33 @@ #include "digital/probe_density_b.h" #include "digital/probe_mpsk_snr_est_c.h" #include "digital/scrambler_bb.h" -#include "digital/simple_framer.h" #include "digital/simple_correlator.h" +#include "digital/simple_framer.h" +#include "digital/ofdm_serializer_vcc.h" +#include "digital/packet_headerparser_b.h" +#include "digital/header_payload_demux.h" %} -%include "digital/metric_type.h" -%include "digital/mpsk_snr_est.h" -%include "digital/lfsr.h" %include "digital/additive_scrambler_bb.h" %include "digital/binary_slicer_fb.h" -%include "digital/chunks_to_symbols_bf.h" %include "digital/chunks_to_symbols_bc.h" -%include "digital/chunks_to_symbols_sf.h" -%include "digital/chunks_to_symbols_sc.h" -%include "digital/chunks_to_symbols_if.h" +%include "digital/chunks_to_symbols_bf.h" %include "digital/chunks_to_symbols_ic.h" +%include "digital/chunks_to_symbols_if.h" +%include "digital/chunks_to_symbols_sc.h" +%include "digital/chunks_to_symbols_sf.h" %include "digital/clock_recovery_mm_cc.h" %include "digital/clock_recovery_mm_ff.h" %include "digital/cma_equalizer_cc.h" %include "digital/constellation.h" -%include "digital/constellation_receiver_cb.h" %include "digital/constellation_decoder_cb.h" +%include "digital/constellation_receiver_cb.h" %include "digital/correlate_access_code_bb.h" %include "digital/correlate_access_code_tag_bb.h" %include "digital/costas_loop_cc.h" %include "digital/cpmmod_bc.h" %include "digital/crc32.h" +%include "digital/crc32_bb.h" %include "digital/descrambler_bb.h" %include "digital/diff_decoder_bb.h" %include "digital/diff_encoder_bb.h" @@ -118,17 +134,33 @@ %include "digital/framer_sink_1.h" %include "digital/glfsr_source_b.h" %include "digital/glfsr_source_f.h" +%include "digital/header_payload_demux.h" %include "digital/kurtotic_equalizer_cc.h" +%include "digital/lfsr.h" %include "digital/lms_dd_equalizer_cc.h" %include "digital/map_bb.h" +%include "digital/metric_type.h" %include "digital/mpsk_receiver_cc.h" +%include "digital/mpsk_snr_est.h" %include "digital/mpsk_snr_est_cc.h" +%include "digital/ofdm_carrier_allocator_cvc.h" +%include "digital/ofdm_chanest_vcvc.h" %include "digital/ofdm_cyclic_prefixer.h" +%include "digital/ofdm_equalizer_base.h" +%include "digital/ofdm_equalizer_simpledfe.h" +%include "digital/ofdm_equalizer_static.h" %include "digital/ofdm_frame_acquisition.h" +%include "digital/ofdm_frame_equalizer_vcvc.h" %include "digital/ofdm_frame_sink.h" %include "digital/ofdm_insert_preamble.h" %include "digital/ofdm_mapper_bcv.h" %include "digital/ofdm_sampler.h" +%include "digital/ofdm_serializer_vcc.h" +%include "digital/ofdm_sync_sc_cfb.h" +%include "digital/packet_header_default.h" +%include "digital/packet_header_ofdm.h" +%include "digital/packet_headergenerator_bb.h" +%include "digital/packet_headerparser_b.h" %include "digital/packet_sink.h" %include "digital/pfb_clock_sync_ccf.h" %include "digital/pfb_clock_sync_fff.h" @@ -136,25 +168,26 @@ %include "digital/probe_density_b.h" %include "digital/probe_mpsk_snr_est_c.h" %include "digital/scrambler_bb.h" -%include "digital/simple_framer.h" %include "digital/simple_correlator.h" +%include "digital/simple_framer.h" GR_SWIG_BLOCK_MAGIC2(digital, additive_scrambler_bb); GR_SWIG_BLOCK_MAGIC2(digital, binary_slicer_fb); -GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bf); GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bc); -GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sf); -GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sc); -GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_if); +GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bf); GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_ic); +GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_if); +GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sc); +GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_sf); GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_cc); GR_SWIG_BLOCK_MAGIC2(digital, clock_recovery_mm_ff); GR_SWIG_BLOCK_MAGIC2(digital, cma_equalizer_cc); -GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb); GR_SWIG_BLOCK_MAGIC2(digital, constellation_decoder_cb); +GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb); GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_bb); GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_tag_bb); GR_SWIG_BLOCK_MAGIC2(digital, costas_loop_cc); +GR_SWIG_BLOCK_MAGIC2(digital, crc32_bb); GR_SWIG_BLOCK_MAGIC2(digital, cpmmod_bc); GR_SWIG_BLOCK_MAGIC2(digital, descrambler_bb); GR_SWIG_BLOCK_MAGIC2(digital, diff_decoder_bb); @@ -164,17 +197,25 @@ GR_SWIG_BLOCK_MAGIC2(digital, fll_band_edge_cc); GR_SWIG_BLOCK_MAGIC2(digital, framer_sink_1); GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_b); GR_SWIG_BLOCK_MAGIC2(digital, glfsr_source_f); +GR_SWIG_BLOCK_MAGIC2(digital, header_payload_demux); GR_SWIG_BLOCK_MAGIC2(digital, kurtotic_equalizer_cc); GR_SWIG_BLOCK_MAGIC2(digital, lms_dd_equalizer_cc); GR_SWIG_BLOCK_MAGIC2(digital, map_bb); GR_SWIG_BLOCK_MAGIC2(digital, mpsk_receiver_cc); GR_SWIG_BLOCK_MAGIC2(digital, mpsk_snr_est_cc); +GR_SWIG_BLOCK_MAGIC2(digital, ofdm_carrier_allocator_cvc); +GR_SWIG_BLOCK_MAGIC2(digital, ofdm_chanest_vcvc); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_cyclic_prefixer); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_acquisition); +GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_equalizer_vcvc); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_frame_sink); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_insert_preamble); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_mapper_bcv); GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sampler); +GR_SWIG_BLOCK_MAGIC2(digital, ofdm_serializer_vcc); +GR_SWIG_BLOCK_MAGIC2(digital, ofdm_sync_sc_cfb); +GR_SWIG_BLOCK_MAGIC2(digital, packet_headergenerator_bb); +GR_SWIG_BLOCK_MAGIC2(digital, packet_headerparser_b); GR_SWIG_BLOCK_MAGIC2(digital, packet_sink); GR_SWIG_BLOCK_MAGIC2(digital, pfb_clock_sync_ccf); GR_SWIG_BLOCK_MAGIC2(digital, pfb_clock_sync_fff); @@ -182,10 +223,13 @@ GR_SWIG_BLOCK_MAGIC2(digital, pn_correlator_cc); GR_SWIG_BLOCK_MAGIC2(digital, probe_density_b); GR_SWIG_BLOCK_MAGIC2(digital, probe_mpsk_snr_est_c); GR_SWIG_BLOCK_MAGIC2(digital, scrambler_bb); -GR_SWIG_BLOCK_MAGIC2(digital, simple_framer); GR_SWIG_BLOCK_MAGIC2(digital, simple_correlator); +GR_SWIG_BLOCK_MAGIC2(digital, simple_framer); GR_SWIG_BLOCK_MAGIC_FACTORY(digital, cpmmod_bc, gmskmod_bc); -// Properly package up constellation objects +// Properly package up non-block objects %include "constellation.i" +%include "packet_header.i" +%include "ofdm_equalizer.i" + diff --git a/gr-digital/swig/ofdm_equalizer.i b/gr-digital/swig/ofdm_equalizer.i new file mode 100644 index 0000000000..bd97b5bc06 --- /dev/null +++ b/gr-digital/swig/ofdm_equalizer.i @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%template(ofdm_equalizer_base_sptr) boost::shared_ptr<gr::digital::ofdm_equalizer_base>; +%template(ofdm_equalizer_1d_pilots_sptr) boost::shared_ptr<gr::digital::ofdm_equalizer_1d_pilots>; +%pythoncode %{ +ofdm_equalizer_1d_pilots_sptr.__repr__ = lambda self: "<OFDM equalizer 1D base class>" +%} + +%template(ofdm_equalizer_simpledfe_sptr) boost::shared_ptr<gr::digital::ofdm_equalizer_simpledfe>; +%pythoncode %{ +ofdm_equalizer_simpledfe_sptr.__repr__ = lambda self: "<OFDM equalizer simpledfe>" +ofdm_equalizer_simpledfe = ofdm_equalizer_simpledfe.make; +%} +//%rename(ofdm_equalizer_simpledfe) make_ofdm_equalizer_simpledfe; +//%ignore ofdm_equalizer_simpledfe; + +%template(ofdm_equalizer_static_sptr) boost::shared_ptr<gr::digital::ofdm_equalizer_static>; +%pythoncode %{ +ofdm_equalizer_static_sptr.__repr__ = lambda self: "<OFDM equalizer static>" +ofdm_equalizer_static = ofdm_equalizer_static.make; +%} +//%rename(ofdm_equalizer_static) make_ofdm_equalizer_static; +//%ignore ofdm_equalizer_static; + diff --git a/gr-digital/swig/packet_header.i b/gr-digital/swig/packet_header.i new file mode 100644 index 0000000000..7c06d19f71 --- /dev/null +++ b/gr-digital/swig/packet_header.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%template(packet_header_default_sptr) boost::shared_ptr<gr::digital::packet_header_default>; +%pythoncode %{ +packet_header_default_sptr.__repr__ = lambda self: "<packet_header_default>" +packet_header_default = packet_header_default .make; +%} + +%template(packet_header_ofdm_sptr) boost::shared_ptr<gr::digital::packet_header_ofdm>; +%pythoncode %{ +packet_header_ofdm_sptr.__repr__ = lambda self: "<packet_header_ofdm>" +packet_header_ofdm = packet_header_ofdm .make; +%} + |