From 43819f0f33498239970b4479684f12aa080859e6 Mon Sep 17 00:00:00 2001 From: jcorgan Date: Thu, 26 Apr 2007 22:51:48 +0000 Subject: [PATCH] Merged r4518:5130 from developer branch n4hy/ofdm into trunk, passes distcheck. Adds incomplete OFDM implementation, further work to be completed in the features/ofdm branch. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5131 221aa14e-8319-0410-a670-987f0aec2ac5 --- config/grc_gnuradio_examples.m4 | 1 + gnuradio-core/src/lib/general/Makefile.am | 30 ++ gnuradio-core/src/lib/general/general.i | 18 +- gnuradio-core/src/lib/general/gr_delay.cc | 63 +++ gnuradio-core/src/lib/general/gr_delay.h | 54 +++ gnuradio-core/src/lib/general/gr_delay.i | 35 ++ gnuradio-core/src/lib/general/gr_dpll_ff.cc | 86 ++++ gnuradio-core/src/lib/general/gr_dpll_ff.h | 59 +++ gnuradio-core/src/lib/general/gr_dpll_ff.i | 33 ++ gnuradio-core/src/lib/general/gr_fft_vcc.cc | 61 ++- gnuradio-core/src/lib/general/gr_fft_vcc.h | 10 +- gnuradio-core/src/lib/general/gr_fft_vcc.i | 6 +- .../src/lib/general/gr_mpsk_receiver_cc.cc | 2 +- .../src/lib/general/gr_ofdm_bpsk_demapper.cc | 97 ++++ .../src/lib/general/gr_ofdm_bpsk_demapper.h | 68 +++ .../src/lib/general/gr_ofdm_bpsk_demapper.i | 40 ++ .../src/lib/general/gr_ofdm_bpsk_mapper.cc | 159 +++++++ .../src/lib/general/gr_ofdm_bpsk_mapper.h | 78 +++ .../src/lib/general/gr_ofdm_bpsk_mapper.i | 48 ++ .../src/lib/general/gr_ofdm_correlator.cc | 191 ++++++++ .../src/lib/general/gr_ofdm_correlator.h | 115 +++++ .../src/lib/general/gr_ofdm_correlator.i | 49 ++ .../lib/general/gr_ofdm_cyclic_prefixer.cc | 68 +++ .../src/lib/general/gr_ofdm_cyclic_prefixer.h | 58 +++ .../src/lib/general/gr_ofdm_cyclic_prefixer.i | 34 ++ .../src/lib/general/gr_ofdm_demapper_vcb.cc | 41 ++ .../src/lib/general/gr_ofdm_demapper_vcb.h | 55 +++ .../src/lib/general/gr_ofdm_demapper_vcb.i | 36 ++ .../src/lib/general/gr_ofdm_mapper_bcv.cc | 41 ++ .../src/lib/general/gr_ofdm_mapper_bcv.h | 56 +++ .../src/lib/general/gr_ofdm_mapper_bcv.i | 36 ++ .../src/lib/general/gr_ofdm_sampler.cc | 94 ++++ .../src/lib/general/gr_ofdm_sampler.h | 59 +++ .../src/lib/general/gr_ofdm_sampler.i | 31 ++ .../src/lib/general/gr_stream_mux.cc | 192 ++++++++ gnuradio-core/src/lib/general/gr_stream_mux.h | 90 ++++ gnuradio-core/src/lib/general/gr_stream_mux.i | 42 ++ gnuradio-core/src/lib/gengen/Makefile.am | 5 +- gnuradio-core/src/lib/gengen/Makefile.gen | 21 + .../src/lib/gengen/generate_common.py | 8 +- .../src/lib/gengen/gengen_generated.i | 14 + .../src/lib/gengen/gr_peak_detector_XX.cc.t | 110 +++++ .../src/lib/gengen/gr_peak_detector_XX.h.t | 125 +++++ .../src/lib/gengen/gr_peak_detector_XX.i.t | 49 ++ .../src/lib/gengen/gr_sample_and_hold_XX.cc.t | 62 +++ .../src/lib/gengen/gr_sample_and_hold_XX.h.t | 57 +++ .../src/lib/gengen/gr_sample_and_hold_XX.i.t | 33 ++ gnuradio-core/src/lib/io/Makefile.am | 6 +- gnuradio-core/src/lib/io/gr_frame.h | 41 ++ .../src/lib/io/gr_message_vector_source.cc | 97 ++++ .../src/lib/io/gr_message_vector_source.h | 63 +++ .../src/lib/io/gr_message_vector_source.i | 36 ++ gnuradio-core/src/lib/io/io.i | 6 +- gnuradio-core/src/python/gnuradio/Makefile.am | 3 +- .../src/python/gnuradio/blksimpl/Makefile.am | 3 +- .../src/python/gnuradio/blksimpl/ofdm_pkt.py | 160 +++++++ .../src/python/gnuradio/ofdm_packet_utils.py | 448 ++++++++++++++++++ gnuradio-core/src/utils/gr_plot_const.py | 113 +++++ gnuradio-core/src/utils/gr_plot_float.py | 75 +++ gnuradio-core/src/utils/gr_plot_iq.py | 77 +++ gnuradio-core/src/utils/gr_read_binary.py | 61 +++ gnuradio-examples/Makefile.am | 2 +- gnuradio-examples/python/Makefile.am | 4 +- .../python/digital/benchmark_loopback.py | 25 +- gnuradio-examples/python/ofdm/Makefile.am | 32 ++ .../python/ofdm/benchmark_ofdm.py | 193 ++++++++ .../python/ofdm/benchmark_ofdm_rx.py | 204 ++++++++ .../python/ofdm/benchmark_ofdm_tx.py | 229 +++++++++ gnuradio-examples/python/ofdm/fftshift.py | 44 ++ gnuradio-examples/python/ofdm/fusb_options.py | 31 ++ gnuradio-examples/python/ofdm/ofdm.py | 161 +++++++ .../python/ofdm/ofdm_receiver.py | 147 ++++++ gnuradio-examples/python/ofdm/pick_bitrate.py | 143 ++++++ gnuradio-examples/python/ofdm/receive_path.py | 125 +++++ .../python/ofdm/transmit_path.py | 104 ++++ 75 files changed, 5310 insertions(+), 43 deletions(-) create mode 100644 gnuradio-core/src/lib/general/gr_delay.cc create mode 100644 gnuradio-core/src/lib/general/gr_delay.h create mode 100644 gnuradio-core/src/lib/general/gr_delay.i create mode 100644 gnuradio-core/src/lib/general/gr_dpll_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_dpll_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_dpll_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_correlator.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_correlator.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_correlator.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_sampler.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_sampler.h create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_sampler.i create mode 100644 gnuradio-core/src/lib/general/gr_stream_mux.cc create mode 100644 gnuradio-core/src/lib/general/gr_stream_mux.h create mode 100644 gnuradio-core/src/lib/general/gr_stream_mux.i create mode 100644 gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t create mode 100644 gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t create mode 100644 gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t create mode 100644 gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t create mode 100644 gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t create mode 100644 gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t create mode 100644 gnuradio-core/src/lib/io/gr_frame.h create mode 100644 gnuradio-core/src/lib/io/gr_message_vector_source.cc create mode 100644 gnuradio-core/src/lib/io/gr_message_vector_source.h create mode 100644 gnuradio-core/src/lib/io/gr_message_vector_source.i create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py create mode 100644 gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py create mode 100755 gnuradio-core/src/utils/gr_plot_const.py create mode 100755 gnuradio-core/src/utils/gr_plot_float.py create mode 100755 gnuradio-core/src/utils/gr_plot_iq.py create mode 100644 gnuradio-core/src/utils/gr_read_binary.py create mode 100644 gnuradio-examples/python/ofdm/Makefile.am create mode 100755 gnuradio-examples/python/ofdm/benchmark_ofdm.py create mode 100755 gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py create mode 100755 gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py create mode 100755 gnuradio-examples/python/ofdm/fftshift.py create mode 100644 gnuradio-examples/python/ofdm/fusb_options.py create mode 100644 gnuradio-examples/python/ofdm/ofdm.py create mode 100644 gnuradio-examples/python/ofdm/ofdm_receiver.py create mode 100644 gnuradio-examples/python/ofdm/pick_bitrate.py create mode 100644 gnuradio-examples/python/ofdm/receive_path.py create mode 100644 gnuradio-examples/python/ofdm/transmit_path.py diff --git a/config/grc_gnuradio_examples.m4 b/config/grc_gnuradio_examples.m4 index bc27f2a7..13b2a1ff 100644 --- a/config/grc_gnuradio_examples.m4 +++ b/config/grc_gnuradio_examples.m4 @@ -42,6 +42,7 @@ AC_DEFUN([GRC_GNURADIO_EXAMPLES],[ gnuradio-examples/python/multi-antenna/Makefile \ gnuradio-examples/python/multi_usrp/Makefile \ gnuradio-examples/python/networking/Makefile \ + gnuradio-examples/python/ofdm/Makefile \ gnuradio-examples/python/usrp/Makefile \ ]) diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index d72a5a10..87e695a6 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -59,9 +59,11 @@ libgeneral_la_SOURCES = \ gr_ctcss_squelch_ff.cc \ gr_dd_mpsk_sync_cc.cc \ gr_deinterleave.cc \ + gr_delay.cc \ gr_diff_decoder_bb.cc \ gr_diff_encoder_bb.cc \ gr_diff_phasor_cc.cc \ + gr_dpll_ff.cc \ gr_fake_channel_coder_pp.cc \ gr_fast_atan2f.cc \ gr_feedforward_agc_cc.cc \ @@ -94,6 +96,13 @@ libgeneral_la_SOURCES = \ gr_nop.cc \ gr_null_sink.cc \ gr_null_source.cc \ + gr_ofdm_correlator.cc \ + gr_ofdm_cyclic_prefixer.cc \ + gr_ofdm_demapper_vcb.cc \ + gr_ofdm_mapper_bcv.cc \ + gr_ofdm_bpsk_demapper.cc \ + gr_ofdm_bpsk_mapper.cc \ + gr_ofdm_sampler.cc \ gr_pa_2x2_phase_combiner.cc \ gr_packet_sink.cc \ gr_phase_modulator_fc.cc \ @@ -121,6 +130,7 @@ libgeneral_la_SOURCES = \ gr_skiphead.cc \ gr_squelch_base_cc.cc \ gr_squelch_base_ff.cc \ + gr_stream_mux.cc \ gr_stream_to_streams.cc \ gr_stream_to_vector.cc \ gr_streams_to_stream.cc \ @@ -184,7 +194,9 @@ grinclude_HEADERS = \ gr_diff_decoder_bb.h \ gr_diff_encoder_bb.h \ gr_deinterleave.h \ + gr_delay.h \ gr_diff_phasor_cc.h \ + gr_dpll_ff.h \ gr_expj.h \ gr_fake_channel_coder_pp.h \ gr_feedforward_agc_cc.h \ @@ -221,6 +233,13 @@ grinclude_HEADERS = \ gr_nop.h \ gr_null_sink.h \ gr_null_source.h \ + gr_ofdm_correlator.h \ + gr_ofdm_cyclic_prefixer.h \ + gr_ofdm_demapper_vcb.h \ + gr_ofdm_mapper_bcv.h \ + gr_ofdm_bpsk_mapper.h \ + gr_ofdm_bpsk_demapper.h \ + gr_ofdm_sampler.h \ gr_pa_2x2_phase_combiner.h \ gr_packet_sink.h \ gr_phase_modulator_fc.h \ @@ -249,6 +268,7 @@ grinclude_HEADERS = \ gr_skiphead.h \ gr_squelch_base_cc.h \ gr_squelch_base_ff.h \ + gr_stream_mux.h \ gr_stream_to_streams.h \ gr_stream_to_vector.h \ gr_streams_to_stream.h \ @@ -320,7 +340,9 @@ swiginclude_HEADERS = \ gr_diff_decoder_bb.i \ gr_diff_encoder_bb.i \ gr_diff_phasor_cc.i \ + gr_dpll_ff.i \ gr_deinterleave.i \ + gr_delay.i \ gr_fake_channel_coder_pp.i \ gr_feedforward_agc_cc.i \ gr_feval.i \ @@ -349,6 +371,13 @@ swiginclude_HEADERS = \ gr_nop.i \ gr_null_sink.i \ gr_null_source.i \ + gr_ofdm_correlator.i \ + gr_ofdm_cyclic_prefixer.i \ + gr_ofdm_demapper_vcb.i \ + gr_ofdm_mapper_bcv.i \ + gr_ofdm_bpsk_demapper.i \ + gr_ofdm_bpsk_mapper.i \ + gr_ofdm_sampler.i \ gr_pa_2x2_phase_combiner.i \ gr_packet_sink.i \ gr_phase_modulator_fc.i \ @@ -374,6 +403,7 @@ swiginclude_HEADERS = \ gr_skiphead.i \ gr_squelch_base_cc.i \ gr_squelch_base_ff.i \ + gr_stream_mux.i \ gr_stream_to_streams.i \ gr_stream_to_vector.i \ gr_streams_to_stream.i \ diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 2c915b60..c49a0122 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2005,2006 Free Software Foundation, Inc. + * Copyright 2004,2005,2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +92,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -150,6 +158,7 @@ %include "gr_firdes.i" %include "gr_interleave.i" %include "gr_deinterleave.i" +%include "gr_delay.i" %include "gr_simple_squelch_cc.i" %include "gr_agc_ff.i" %include "gr_agc_cc.i" @@ -161,6 +170,7 @@ %include "gr_fake_channel_coder_pp.i" %include "gr_throttle.i" %include "gr_mpsk_receiver_cc.i" +%include "gr_stream_mux.i" %include "gr_stream_to_streams.i" %include "gr_streams_to_stream.i" %include "gr_streams_to_vector.i" @@ -175,6 +185,7 @@ %include "gr_packet_sink.i" %include "gr_lms_dfe_cc.i" %include "gr_lms_dfe_ff.i" +%include "gr_dpll_ff.i" %include "gr_pll_freqdet_cf.i" %include "gr_pll_refout_cc.i" %include "gr_pll_carriertracking_cc.i" @@ -182,6 +193,11 @@ %include "gr_probe_avg_mag_sqrd_c.i" %include "gr_probe_avg_mag_sqrd_f.i" %include "gr_probe_signal_f.i" +%include "gr_ofdm_correlator.i" +%include "gr_ofdm_cyclic_prefixer.i" +%include "gr_ofdm_bpsk_demapper.i" +%include "gr_ofdm_bpsk_mapper.i" +%include "gr_ofdm_sampler.i" %include "gr_costas_loop_cc.i" %include "gr_pa_2x2_phase_combiner.i" %include "gr_kludge_copy.i" diff --git a/gnuradio-core/src/lib/general/gr_delay.cc b/gnuradio-core/src/lib/general/gr_delay.cc new file mode 100644 index 00000000..12c50e4b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.cc @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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 +#include + +gr_delay_sptr +gr_make_delay (size_t itemsize, int delay) +{ + return gr_delay_sptr (new gr_delay (itemsize, delay)); +} + +gr_delay::gr_delay (size_t itemsize, int delay) + : gr_sync_block ("delay", + gr_make_io_signature (1, -1, itemsize), + gr_make_io_signature (1, -1, itemsize)), + d_itemsize(itemsize) +{ + set_delay(delay); +} + +int +gr_delay::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert(input_items.size() == output_items.size()); + + const char *iptr; + char *optr; + + for(int i = 0; i < input_items.size(); i++) { + iptr = (const char *) input_items[i]; + optr = (char *) output_items[i]; + + memcpy(optr, iptr + delay()*d_itemsize, noutput_items*d_itemsize); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_delay.h b/gnuradio-core/src/lib/general/gr_delay.h new file mode 100644 index 00000000..fb4fe55a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_DELAY_H +#define INCLUDED_GR_DELAY_H + +#include + +class gr_delay; +typedef boost::shared_ptr gr_delay_sptr; + +gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + +/*! + * \brief delay the input by a certain number of samples + * \ingroup block + */ +class gr_delay : public gr_sync_block +{ + friend gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + + gr_delay (size_t itemsize, int delay); + + size_t d_itemsize; + + public: + int delay () const { return history()-1; } + void set_delay (int delay) { set_history(delay+1); } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_delay.i b/gnuradio-core/src/lib/general/gr_delay.i new file mode 100644 index 00000000..776c9657 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,delay) + + gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + +class gr_delay : public gr_sync_block +{ + private: + gr_delay (size_t itemsize, int delay); + + public: + int delay() const { return history()-1; } + void set_delay (int delay) { set_history(delay+1); } +}; diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.cc b/gnuradio-core/src/lib/general/gr_dpll_ff.cc new file mode 100644 index 00000000..ae868fce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_ff.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +gr_dpll_ff_sptr +gr_make_dpll_ff (float period, float gain) +{ + return gr_dpll_ff_sptr (new gr_dpll_ff (period, gain)); +} + +gr_dpll_ff::gr_dpll_ff (float period, float gain) + : gr_sync_block ("dpll_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_restart(0),d_pulse_phase(0) +{ + d_pulse_frequency = 1.0/period; + d_gain = gain; + d_decision_threshold = 1.0 - 0.5*d_pulse_frequency; +#if 1 + fprintf(stderr,"frequency = %f period = %f gain = %f threshold = %f\n", + d_pulse_frequency, + period, + d_gain, + d_decision_threshold); +#endif + set_history(1); // so we can look behind us +} + +int +gr_dpll_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *iptr = (float *) input_items[0]; + float *optr = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + optr[i]= (float)0; + if(iptr[i] ==(float)1) { + if (d_restart == 0) { + d_pulse_phase = 1; + } else { + if (d_pulse_phase > 0.5) d_pulse_phase += d_gain*(1.0-d_pulse_phase); + else d_pulse_phase -= d_gain*d_pulse_phase; + } + d_restart = 3; + } + if (d_pulse_phase > d_decision_threshold) { + d_pulse_phase -= 1.0; + if (d_restart > 0) { + d_restart -= 1; + optr[i] = (float)1; + } + } + d_pulse_phase += d_pulse_frequency; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.h b/gnuradio-core/src/lib/general/gr_dpll_ff.h new file mode 100644 index 00000000..1de1efa8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_ff.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifndef INCLUDED_GR_DPLL_FF_H +#define INCLUDED_GR_DPLL_FF_H + +#include + +class gr_dpll_ff; +typedef boost::shared_ptr gr_dpll_ff_sptr; + +gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); + +/*! + * \brief Detect the peak of a signal + * \ingroup block + * + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. + */ +class gr_dpll_ff : public gr_sync_block +{ + friend gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); + + gr_dpll_ff (float period, float gain); + + private: + unsigned char d_restart; + float d_pulse_phase, d_pulse_frequency,d_gain,d_decision_threshold; + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.i b/gnuradio-core/src/lib/general/gr_dpll_ff.i new file mode 100644 index 00000000..9606fba5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_ff.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// WARNING: this file is machine generated. Edits will be over written + +GR_SWIG_BLOCK_MAGIC(gr,dpll_ff) + + gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); + +class gr_dpll_ff : public gr_sync_block +{ + private: + gr_dpll_ff (float period, float gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.cc b/gnuradio-core/src/lib/general/gr_fft_vcc.cc index 9ee9f745..d6961486 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.cc +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -30,16 +30,16 @@ #include gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward,const std::vector window) +gr_make_fft_vcc (int fft_size, bool forward,const std::vector window, bool shift) { - return gr_fft_vcc_sptr (new gr_fft_vcc (fft_size, forward, window)); + return gr_fft_vcc_sptr (new gr_fft_vcc (fft_size, forward, window, shift)); } -gr_fft_vcc::gr_fft_vcc (int fft_size, bool forward, const std::vector window) +gr_fft_vcc::gr_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift) : gr_sync_block ("fft_vcc", gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex)), gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex))), - d_fft_size(fft_size) + d_fft_size(fft_size), d_forward(forward), d_shift(shift) { d_fft = new gri_fft_complex (d_fft_size, forward); @@ -66,27 +66,43 @@ gr_fft_vcc::work (int noutput_items, int count = 0; while (count++ < noutput_items){ - + // copy input into optimally aligned buffer - + if (d_window.size()){ gr_complex *dst = d_fft->get_inbuf(); for (unsigned int i = 0; i < d_fft_size; i++) // apply window dst[i] = in[i] * d_window[i]; } - else - memcpy (d_fft->get_inbuf(), in, input_data_size); - + else { + if(!d_forward && d_shift) { // apply an ifft shift on the data + gr_complex *dst = d_fft->get_inbuf(); + unsigned int len = (unsigned int)(floor(d_fft_size/2.0)); // half length of complex array + memcpy(&dst[0], &in[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex)*len); + } + else { + memcpy (d_fft->get_inbuf(), in, input_data_size); + } + } + // compute the fft d_fft->execute (); - - // cpoy result to our output - memcpy (out, d_fft->get_outbuf (), output_data_size); - + + // copy result to our output + if(d_forward && d_shift) { // apply a fft shift on the data + unsigned int len = (unsigned int)(ceil(d_fft_size/2.0)); + memcpy(&out[0], &d_fft->get_outbuf()[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft->get_outbuf()[0], sizeof(gr_complex)*len); + } + else { + memcpy (out, d_fft->get_outbuf (), output_data_size); + } + in += d_fft_size; out += d_fft_size; } - + return noutput_items; } @@ -100,3 +116,18 @@ gr_fft_vcc::set_window(const std::vector window) else return false; } + +/* +fftshift + + for(i=0; i < ceil(d_occupied_carriers/2.0); i++) { + unsigned int k=ceil(d_occupied_carriers/2.0); + out[i] = gr_complex(-1+2*in[i+k],0); + } + for(; i < d_vlen - ceil(d_occupied_carriers/2.0); i++) { + out[i]=gr_complex(0,0); + } + for(unsigned int j=0;i gr_fft_vcc_sptr; gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); +gr_make_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift=false); /*! * \brief Compute forward or reverse FFT. complex vector in / complex vector out. @@ -41,13 +41,15 @@ gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); class gr_fft_vcc : public gr_sync_block { friend gr_fft_vcc_sptr - gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); + gr_make_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift); unsigned int d_fft_size; std::vector d_window; gri_fft_complex *d_fft; + bool d_forward; + bool d_shift; - gr_fft_vcc (int fft_size, bool forward, const std::vector window); + gr_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift); public: ~gr_fft_vcc (); diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.i b/gnuradio-core/src/lib/general/gr_fft_vcc.i index 039f09a3..8295af65 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.i +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,12 +23,12 @@ GR_SWIG_BLOCK_MAGIC(gr, fft_vcc) gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector window); +gr_make_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift=false); class gr_fft_vcc : public gr_sync_block { protected: - gr_fft_vcc (int fft_size, bool forward, const std::vector window); + gr_fft_vcc (int fft_size, bool forward, const std::vector window, bool shift); public: bool set_window(const std::vector window); diff --git a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc index 87b2f541..6b8cc320 100644 --- a/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc +++ b/gnuradio-core/src/lib/general/gr_mpsk_receiver_cc.cc @@ -319,7 +319,7 @@ gr_mpsk_receiver_cc::general_work (int noutput_items, int i=0, o=0; //while(i < ninput_items[0]) { - while(o < noutput_items) { + while((o < noutput_items) && (i < ninput_items[0])) { while((d_mu > 1) && (i < ninput_items[0])) { mm_sampler(in[i]); // puts symbols into a buffer and adjusts d_mu i++; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc new file mode 100644 index 00000000..53484b96 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 +#include + +gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers) +{ + return gr_ofdm_bpsk_demapper_sptr (new gr_ofdm_bpsk_demapper (occupied_carriers)); +} + +gr_ofdm_bpsk_demapper::gr_ofdm_bpsk_demapper (unsigned occupied_carriers) + : gr_block ("ofdm_bpsk_demapper", + gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers), + gr_make_io_signature (1, 1, sizeof(unsigned char))), + d_occupied_carriers(occupied_carriers), + d_byte_offset(0), d_partial_byte(0) +{ +} + +gr_ofdm_bpsk_demapper::~gr_ofdm_bpsk_demapper(void) +{ +} + +unsigned char gr_ofdm_bpsk_demapper::slicer(gr_complex x) +{ + return (unsigned char)(x.real() > 0 ? 1 : 0); +} + +void +gr_ofdm_bpsk_demapper::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = 1; +} + +int +gr_ofdm_bpsk_demapper::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]; + unsigned char *out = (unsigned char *) output_items[0]; + + unsigned int i=0, bytes_produced=0; + + while(i < d_occupied_carriers) { + + while((d_byte_offset < 8) && (i < d_occupied_carriers)) { + //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag()); + d_partial_byte |= slicer(in[i++]) << (d_byte_offset++); + } + + if(d_byte_offset == 8) { + out[bytes_produced++] = d_partial_byte; + d_byte_offset = 0; + d_partial_byte = 0; + } + } + +#if 0 +printf("demod out: "); + for(i = 0; i < bytes_produced; i++) { + printf("%4x", out[i]); + } + printf(" \tlen: %d\n", i); +#endif + + consume_each(1); + return bytes_produced; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h new file mode 100644 index 00000000..c361c62f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_BPSK_DEMAPPER_H +#define INCLUDED_GR_OFDM_BPSK_DEMAPPER_H + + +#include +#include + +class gr_ofdm_bpsk_demapper; +typedef boost::shared_ptr gr_ofdm_bpsk_demapper_sptr; + +gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + +/*! + * \brief take a vector of complex constellation points in from an FFT + * and demodulate to a stream of bits. Simple BPSK version. + */ + +class gr_ofdm_bpsk_demapper : public gr_block +{ + friend gr_ofdm_bpsk_demapper_sptr + gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + protected: + gr_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + private: + unsigned char slicer(gr_complex x); + + unsigned int d_occupied_carriers; + unsigned int d_byte_offset; + unsigned char d_partial_byte; + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + public: + ~gr_ofdm_bpsk_demapper(void); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i new file mode 100644 index 00000000..1af4430d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, 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. + */ + +#include + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_bpsk_demapper) + +gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + +class gr_ofdm_bpsk_demapper : public gr_sync_decimator +{ + protected: + gr_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + public: + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc new file mode 100644 index 00000000..df463239 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc @@ -0,0 +1,159 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 +#include +#include + +gr_ofdm_bpsk_mapper_sptr +gr_make_ofdm_bpsk_mapper (unsigned int mtu, unsigned int occupied_carriers, unsigned int vlen, + std::vector known_symbol1, std::vector known_symbol2) +{ + return gr_ofdm_bpsk_mapper_sptr (new gr_ofdm_bpsk_mapper (mtu, occupied_carriers, vlen, + known_symbol1, known_symbol2)); +} + +gr_ofdm_bpsk_mapper::gr_ofdm_bpsk_mapper (unsigned int mtu, unsigned int occupied_carriers, unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2) + : gr_block ("ofdm_bpsk_mapper", + gr_make_io_signature (1, 1, 2*sizeof(int) + sizeof(unsigned char)*mtu), + gr_make_io_signature (1, 1, sizeof(gr_complex)*vlen)), + d_mtu(mtu), + d_occupied_carriers(occupied_carriers), + d_vlen(vlen), + d_packet_offset(0), + d_bit_offset(0), + d_header_sent(0), + d_known_symbol1(known_symbol1), + d_known_symbol2(known_symbol2) + +{ + assert(d_occupied_carriers < d_vlen); + assert(d_occupied_carriers == d_known_symbol1.size()); + assert(d_occupied_carriers == d_known_symbol2.size()); +} + +gr_ofdm_bpsk_mapper::~gr_ofdm_bpsk_mapper(void) +{ +} + +void +gr_ofdm_bpsk_mapper::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = 1; +} + +int +gr_ofdm_bpsk_mapper::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_frame *in = (const gr_frame *) input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + unsigned int i=0; + unsigned int num_symbols = 0, pkt_length; + + //printf("OFDM BPSK Mapper: ninput_items: %d noutput_items: %d\n", ninput_items[0], noutput_items); + + pkt_length = in[0].length; + + std::vector::iterator ks_itr; + if(d_header_sent == 0) { + ks_itr = d_known_symbol1.begin(); + } + else if(d_header_sent == 1) { + ks_itr = d_known_symbol2.begin(); + } + + if(d_header_sent < 2) { + // Add training symbols here + for(i=0; i < (ceil((d_vlen - d_occupied_carriers)/2.0)); i++) { + out[i] = gr_complex(0,0); + } + for(;i> (d_bit_offset++)) & 0x01; + out[i++] = gr_complex(-1+2*(bit)); + if(d_bit_offset == 8) { + d_bit_offset = 0; + d_packet_offset++; + } + } + + // Ran out of data to put in symbols + if(d_packet_offset == pkt_length) { + while(i < d_vlen-zeros_on_right) { + out[i++] = gr_complex(0,0); + } + + d_packet_offset = 0; + assert(d_bit_offset == 0); + num_symbols++; + d_header_sent = 0; + consume_each(1); + return num_symbols; + } + + // Ran out of space in symbol + out += d_vlen; + num_symbols++; + } + consume_each(0); + return num_symbols; +} + diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h new file mode 100644 index 00000000..1ae6c75d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_BPSK_MAPPER_H +#define INCLUDED_GR_OFDM_BPSK_MAPPER_H + + +#include +#include +#include + +class gr_ofdm_bpsk_mapper; +typedef boost::shared_ptr gr_ofdm_bpsk_mapper_sptr; + +gr_ofdm_bpsk_mapper_sptr +gr_make_ofdm_bpsk_mapper (unsigned mtu, unsigned occupied_carriers, unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2); + +/*! + * \brief take a stream of bytes in and map to a vector of complex + * constellation points suitable for IFFT input to be used in an ofdm + * modulator. Simple BPSK version. + */ + +class gr_ofdm_bpsk_mapper : public gr_block +{ + friend gr_ofdm_bpsk_mapper_sptr + gr_make_ofdm_bpsk_mapper (unsigned mtu, unsigned occupied_carriers, unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2); + + protected: + gr_ofdm_bpsk_mapper (unsigned mtu, unsigned occupied_carriers, unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2); + + private: + unsigned int d_mtu; + unsigned int d_occupied_carriers; + unsigned int d_vlen; + unsigned int d_packet_offset; + unsigned int d_bit_offset; + unsigned int d_header_sent; + std::vector d_known_symbol1, d_known_symbol2; + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + public: + ~gr_ofdm_bpsk_mapper(void); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i new file mode 100644 index 00000000..12b86dc3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, 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. + */ + +#include + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_bpsk_mapper) + +gr_ofdm_bpsk_mapper_sptr +gr_make_ofdm_bpsk_mapper (unsigned int mtu, + unsigned int bits_per_symbol, + unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2); + +class gr_ofdm_bpsk_mapper : public gr_block +{ + protected: + gr_ofdm_bpsk_mapper (unsigned int mtu, + unsigned int bits_per_symbol, + unsigned int vlen, + std::vector known_symbol1, + std::vector known_symbol2); + + public: + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc new file mode 100644 index 00000000..21fbc6b3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc @@ -0,0 +1,191 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 +#include + +#define VERBOSE 0 +#define M_TWOPI (2*M_PI) + +gr_ofdm_correlator_sptr +gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2) +{ + return gr_ofdm_correlator_sptr (new gr_ofdm_correlator (occupied_carriers, vlen, cplen, + known_symbol1, known_symbol2)); +} + +gr_ofdm_correlator::gr_ofdm_correlator (unsigned occupied_carriers, unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2) + : gr_block ("ofdm_correlator", + gr_make_io_signature (1, 1, sizeof(gr_complex)*vlen), + gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)), + d_occupied_carriers(occupied_carriers), + d_vlen(vlen), + d_cplen(cplen), + d_freq_shift_len(5), + d_known_symbol1(known_symbol1), + d_known_symbol2(known_symbol2), + d_coarse_freq(0), + d_phase_count(0) +{ + d_diff_corr_factor.resize(d_occupied_carriers); + d_hestimate.resize(d_occupied_carriers); + + std::vector::iterator i1, i2; + + int i = 0; + gr_complex one(1.0, 0.0); + for(i1 = d_known_symbol1.begin(), i2 = d_known_symbol2.begin(); i1 != d_known_symbol1.end(); i1++, i2++) { + d_diff_corr_factor[i] = one / ((*i1) * conj(*i2)); + i++; + } +} + +gr_ofdm_correlator::~gr_ofdm_correlator(void) +{ +} + +void +gr_ofdm_correlator::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = 2; +} + +gr_complex +gr_ofdm_correlator::coarse_freq_comp(int freq_delta, int symbol_count) +{ + return gr_complex(cos(-M_TWOPI*freq_delta*d_cplen/d_vlen*symbol_count), + sin(-M_TWOPI*freq_delta*d_cplen/d_vlen*symbol_count)); +} + +bool +gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *current, + int zeros_on_left) +{ + unsigned int i = 0; + int search_delta = 0; + bool found = false; + + gr_complex h_sqrd = gr_complex(0.0,0.0); + float power = 0.0F; + + while(!found && (abs(search_delta) < d_freq_shift_len)) { + h_sqrd = gr_complex(0.0,0.0); + power = 0.0F; + + for(i = 0; i < d_occupied_carriers; i++) { + h_sqrd = h_sqrd + previous[i+zeros_on_left+search_delta] * + conj(coarse_freq_comp(search_delta,1)*current[i+zeros_on_left+search_delta]) * + d_diff_corr_factor[i]; + power = power + norm(current[i+zeros_on_left+search_delta]); // No need to do coarse freq here + } + +#if VERBOSE + printf("bin %d\th_sqrd = ( %f, %f )\t power = %f\t real(h)/p = %f\t angle = %f\n", + search_delta, h_sqrd.real(), h_sqrd.imag(), power, h_sqrd.real()/power, arg(h_sqrd)); +#endif + + if(h_sqrd.real() > 0.75*power) { + found = true; + d_coarse_freq = search_delta; + d_phase_count = 1; + d_snr_est = 10*log10(power/(power-h_sqrd.real())); + + printf("CORR: Found, bin %d\tSNR Est %f dB\tcorr power fraction %f\n", + search_delta, d_snr_est, h_sqrd.real()/power); + // search_delta,10*log10(h_sqrd.real()/fabs(h_sqrd.imag())),h_sqrd.real()/power); + break; + } + else { + if(search_delta <= 0) + search_delta = (-search_delta) + 1; + else + search_delta = -search_delta; + } + } + return found; +} + +void +gr_ofdm_correlator::calculate_equalizer(const gr_complex *previous, const gr_complex *current, + int zeros_on_left) +{ + unsigned int i=0; + + for(i = 0; i < d_occupied_carriers; i++) { + // FIXME possibly add small epsilon in divisor to protect from div 0 + //d_hestimate[i] = 0.5F * (d_known_symbol1[i] / previous[i+zeros_on_left] + + // d_known_symbol2[i] / (coarse_freq_comp(d_coarse_freq,1)* + // current[i+zeros_on_left+d_coarse_freq])); + d_hestimate[i] = 0.5F * (d_known_symbol1[i] / previous[i+zeros_on_left+d_coarse_freq] + + d_known_symbol2[i] / (coarse_freq_comp(d_coarse_freq,1)* + current[i+zeros_on_left+d_coarse_freq])); + +#if VERBOSE + fprintf(stderr, "%f %f ", d_hestimate[i].real(), d_hestimate[i].imag()); +#endif + } +#if VERBOSE + fprintf(stderr, "\n"); +#endif +} + +int +gr_ofdm_correlator::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]; + const gr_complex *previous = &in[0]; + const gr_complex *current = &in[d_vlen]; + + gr_complex *out = (gr_complex *) output_items[0]; + + unsigned int i=0; + + int unoccupied_carriers = d_vlen - d_occupied_carriers; + int zeros_on_left = (int)ceil(unoccupied_carriers/2.0); + + bool corr = correlate(previous, current, zeros_on_left); + if(corr) { + calculate_equalizer(previous, current, zeros_on_left); + } + + for(i = 0; i < d_occupied_carriers; i++) { + out[i] = d_hestimate[i]*coarse_freq_comp(d_coarse_freq,d_phase_count)*current[i+zeros_on_left+d_coarse_freq]; + } + d_phase_count++; + consume_each(1); + return 1; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h b/gnuradio-core/src/lib/general/gr_ofdm_correlator.h new file mode 100644 index 00000000..4c44cca3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.h @@ -0,0 +1,115 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_CORRELATOR_H +#define INCLUDED_GR_OFDM_CORRELATOR_H + + +#include +#include + +class gr_ofdm_correlator; +typedef boost::shared_ptr gr_ofdm_correlator_sptr; + +gr_ofdm_correlator_sptr +gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2); + +/*! + * \brief take a vector of complex constellation points in from an FFT + * and performs a correlation and equalization. + * \inblock blocks + * + * This block takes the output of an FFT of a received OFDM symbol and finds the + * start of a frame based on two known symbols. It also looks at the surrounding + * bins in the FFT output for the correlation in case there is a large frequency + * shift in the data. This block assumes that the fine frequency shift has already + * been corrected and that the samples fall in the middle of one FFT bin. + * + * It then uses one of those known + * symbosl to estimate the channel response overa all subcarriers and does a simple + * 1-tap equalization on all subcarriers. This corrects for the phase and amplitude + * distortion caused by the channel. + */ + +class gr_ofdm_correlator : public gr_block +{ + /*! + * \brief Build an OFDM correlator and equalizer. + * \param occupied_carriers The number of subcarriers with data in the received symbol + * \param vlen The size of the FFT vector (occupied_carriers + unused carriers) + * \param known_symbol1 A vector of complex numbers representing a known symbol at the + * start of a frame (usually a BPSK PN sequence) + * \param known_symbol2 A vector of complex numbers representing a known symbol at the + * start of a frame after known_symbol1 (usually a BPSK PN sequence). + * Both of these start symbols are differentially correlated to compensate + * for phase changes between symbols. + */ + friend gr_ofdm_correlator_sptr + gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2); + + protected: + gr_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2); + + private: + unsigned char slicer(gr_complex x); + bool correlate(const gr_complex *previous, const gr_complex *current, int zeros_on_left); + void calculate_equalizer(const gr_complex *previous, + const gr_complex *current, int zeros_on_left); + gr_complex coarse_freq_comp(int freq_delta, int count); + + unsigned int d_occupied_carriers; // !< \brief number of subcarriers with data + unsigned int d_vlen; // !< \brief length of FFT vector + unsigned int d_cplen; // !< \brief length of cyclic prefix in samples + unsigned int d_freq_shift_len; // !< \brief number of surrounding bins to look at for correlation + std::vector d_known_symbol1, d_known_symbol2; // !< \brief known symbols at start of frame + std::vector d_diff_corr_factor; // !< \brief factor used in correlation + std::vector d_hestimate; // !< channel estimate + signed int d_coarse_freq; // !< \brief search distance in number of bins + unsigned int d_phase_count; // !< \brief accumulator for coarse freq correction + float d_snr_est; // !< an estimation of the signal to noise ratio + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + public: + /*! + * \brief Return an estimate of the SNR of the channel + */ + float snr() { return d_snr_est; } + + ~gr_ofdm_correlator(void); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.i b/gnuradio-core/src/lib/general/gr_ofdm_correlator.i new file mode 100644 index 00000000..fbbf6a8a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.i @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, 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. + */ + +#include + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_correlator) + +gr_ofdm_correlator_sptr +gr_make_ofdm_correlator (unsigned int occupied_carriers, + unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2); + +class gr_ofdm_correlator : public gr_sync_decimator +{ + protected: + gr_ofdm_correlator (unsigned int occupied_carriers, + unsigned int vlen, + unsigned int cplen, + std::vector known_symbol1, + std::vector known_symbol2); + + public: + float snr() { return d_snr_est; } + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.cc b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.cc new file mode 100644 index 00000000..fa9cfac4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.cc @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, 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 +#include + +gr_ofdm_cyclic_prefixer_sptr +gr_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size) +{ + return gr_ofdm_cyclic_prefixer_sptr (new gr_ofdm_cyclic_prefixer (input_size, output_size)); +} + +gr_ofdm_cyclic_prefixer::gr_ofdm_cyclic_prefixer (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) + +{ +} + +int +gr_ofdm_cyclic_prefixer::work (int noutput_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]; + 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]; + } + + j = d_input_size - cp_size; + for(i=0; i < cp_size; i++, j++) { + out[i] = in[j]; + } + + return d_output_size; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.h b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.h new file mode 100644 index 00000000..e4992f87 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_CYCLIC_PREFIXER_H +#define INCLUDED_GR_OFDM_CYCLIC_PREFIXER_H + +#include +#include + +class gr_ofdm_cyclic_prefixer; +typedef boost::shared_ptr gr_ofdm_cyclic_prefixer_sptr; + +gr_ofdm_cyclic_prefixer_sptr +gr_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size); + + +/*! + * \brief adds a cyclic prefix vector to an input size long ofdm + * symbol(vector) and converts vector to a stream output_size long. + * \ingroup block + */ +class gr_ofdm_cyclic_prefixer : public gr_sync_interpolator +{ + friend gr_ofdm_cyclic_prefixer_sptr + gr_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size); + + protected: + gr_ofdm_cyclic_prefixer (size_t input_size, size_t output_size); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + private: + size_t d_input_size; + size_t d_output_size; +}; + +#endif /* INCLUDED_GR_OFDM_CYCLIC_PREFIXER_H */ diff --git a/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.i b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.i new file mode 100644 index 00000000..52a7e6c4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_cyclic_prefixer.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_cyclic_prefixer) + +gr_ofdm_cyclic_prefixer_sptr +gr_make_ofdm_cyclic_prefixer (size_t input_size, size_t output_size); + +class gr_ofdm_cyclic_prefixer : public gr_sync_decimator +{ + protected: + gr_ofdm_cyclic_prefixer (size_t input_size, size_t output_size); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.cc b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.cc new file mode 100644 index 00000000..c355e28c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.cc @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 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 2, 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 +#include + +gr_ofdm_demapper_vcb::~gr_ofdm_demapper_vcb(void) +{ +} + +gr_ofdm_demapper_vcb::gr_ofdm_demapper_vcb (unsigned bits_per_symbol,unsigned int vlen) + : gr_sync_decimator ("ofdm_demapper_vcb", + gr_make_io_signature (1, 1, sizeof(gr_complex)*vlen), + gr_make_io_signature (1, 1, sizeof(unsigned char)), + bits_per_symbol) +{ +} + diff --git a/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.h b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.h new file mode 100644 index 00000000..e0b01c72 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_DEMAPPER_VCB_H +#define INCLUDED_GR_OFDM_DEMAPPER_VCB_H + +#include + +class gr_ofdm_demapper_vcb; +typedef boost::shared_ptr gr_ofdm_demapper_vcb_sptr; + +gr_ofdm_demapper_vcb_sptr +gr_make_ofdm_demapper_vcb (unsigned int bits_per_symbol, unsigned int vlen); + + +/*! + * \brief take a stream of vectors in from an FFT and demodulate to a stream of + * bits. Abstract class must be subclassed with specific mapping. + * + */ + +class gr_ofdm_demapper_vcb : public gr_sync_decimator +{ + friend gr_ofdm_demapper_vcb_sptr + gr_make_ofdm_demapper_vcb (unsigned int bits_per_symbol, unsigned int vlen); + +protected: + gr_ofdm_demapper_vcb (unsigned int bits_per_symbol, unsigned int vlen); + +public: + ~gr_ofdm_demapper_vcb(void); +}; + + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.i b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.i new file mode 100644 index 00000000..8ba0670c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_demapper_vcb.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_mapper_bcv) + +gr_ofdm_mapper_bcv_sptr +gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, + unsigned int vlen); + +class gr_ofdm_mapper_bcv : public gr_sync_decimator +{ + protected: + gr_ofdm_mapper_bcv (unsigned int bits_per_symbol, + unsigned int vlen); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc new file mode 100644 index 00000000..a7b46e00 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 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 2, 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 +#include + +gr_ofdm_mapper_bcv::~gr_ofdm_mapper_bcv(void) +{ +} + +gr_ofdm_mapper_bcv::gr_ofdm_mapper_bcv (unsigned bits_per_symbol,unsigned int vlen) + : gr_sync_decimator ("ofdm_mapper_bcv", + gr_make_io_signature (1, 1, sizeof(unsigned char)), + gr_make_io_signature (1, 1, sizeof(gr_complex)*vlen), + bits_per_symbol) +{ +} + diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h new file mode 100644 index 00000000..b1a74fc0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_MAPPER_BCV_H +#define INCLUDED_GR_OFDM_MAPPER_BCV_H + +#include + +class gr_ofdm_mapper_bcv; +typedef boost::shared_ptr gr_ofdm_mapper_bcv_sptr; + +gr_ofdm_mapper_bcv_sptr +gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen); + + +/*! + * \brief take a stream of bytes in and map to a vector of complex + * constellation points suitable for IFFT input to be used in an ofdm + * modulator. Abstract class must be subclassed with specific mapping. + * + */ + +class gr_ofdm_mapper_bcv : public gr_sync_decimator +{ + friend gr_ofdm_mapper_bcv_sptr + gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen); + +protected: + gr_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen); + +public: + ~gr_ofdm_mapper_bcv(void); +}; + + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i new file mode 100644 index 00000000..8ba0670c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_mapper_bcv) + +gr_ofdm_mapper_bcv_sptr +gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, + unsigned int vlen); + +class gr_ofdm_mapper_bcv : public gr_sync_decimator +{ + protected: + gr_ofdm_mapper_bcv (unsigned int bits_per_symbol, + unsigned int vlen); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc new file mode 100644 index 00000000..9ac5abdc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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 +#include +#include + +gr_ofdm_sampler_sptr +gr_make_ofdm_sampler (unsigned int fft_length, + unsigned int symbol_length) +{ + return gr_ofdm_sampler_sptr (new gr_ofdm_sampler (fft_length, symbol_length)); +} + +gr_ofdm_sampler::gr_ofdm_sampler (unsigned int fft_length, + unsigned int symbol_length) + : gr_block ("ofdm_sampler", + gr_make_io_signature (2, 2, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex)*fft_length)), + d_fft_length(fft_length), d_symbol_length(symbol_length) +{ +} + +void +gr_ofdm_sampler::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + // FIXME do we need more + int nreqd = (noutput_items-1) * d_symbol_length + d_fft_length; + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = nreqd; +} + +int +gr_ofdm_sampler::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *trigger = (gr_complex *) input_items[1]; + + gr_complex *optr = (gr_complex *) output_items[0]; + + int found=0; + + unsigned int i=d_fft_length-1; + + while(!found && i 0.5) + found = 1; + else + i++; + + if(found) { + assert(i-d_fft_length+1 >= 0); + for(unsigned int j=i-d_fft_length+1;j<=i;j++) + *optr++ = iptr[j]; + consume_each(i-d_fft_length+2); + //printf("OFDM Sampler found: ninput_items: %d/%d noutput_items: %d consumed: %d found: %d\n", + // ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+2), found); + } + else { + consume_each(i-d_fft_length+1); + //printf("OFDM Sampler not found: ninput_items: %d/%d noutput_items: %d consumed: %d found: %d\n", + // ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+1), found); + } + + + return found; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.h b/gnuradio-core/src/lib/general/gr_ofdm_sampler.h new file mode 100644 index 00000000..0c3fd75f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_OFDM_SAMPLER_H +#define INCLUDED_GR_OFDM_SAMPLER_H + +#include + +class gr_ofdm_sampler; +typedef boost::shared_ptr gr_ofdm_sampler_sptr; + +gr_ofdm_sampler_sptr gr_make_ofdm_sampler (unsigned int fft_length, + unsigned int symbol_length); + +/*! + * \brief does the rest of the OFDM stuff (fixme) + */ + +class gr_ofdm_sampler : public gr_block +{ + friend gr_ofdm_sampler_sptr gr_make_ofdm_sampler (unsigned int fft_length, + unsigned int symbol_length); + + gr_ofdm_sampler (unsigned int fft_length, + unsigned int symbol_length); + + private: + unsigned int d_fft_length; + unsigned int d_symbol_length; + + public: + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.i b/gnuradio-core/src/lib/general/gr_ofdm_sampler.i new file mode 100644 index 00000000..510636e8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_sampler) + +gr_ofdm_sampler_sptr gr_make_ofdm_sampler (unsigned int fft_length, unsigned int symbol_length); + +class gr_ofdm_sampler : public gr_sync_block +{ + private: + gr_ofdm_sampler (unsigned int fft_length, unsigned int symbol_length); +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.cc b/gnuradio-core/src/lib/general/gr_stream_mux.cc new file mode 100644 index 00000000..1eaad29a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_mux.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 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 2, 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 +#include + +#define VERBOSE 0 + +gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, const std::vector &lengths) +{ + return gr_stream_mux_sptr (new gr_stream_mux (itemsize, lengths)); +} + +gr_stream_mux::gr_stream_mux (size_t itemsize, const std::vector &lengths) + : gr_block ("stream_mux", + gr_make_io_signature (1, -1, itemsize), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), + d_stream(0), + d_residual(0), + d_lengths(lengths) +{ +} + +gr_stream_mux::~gr_stream_mux(void) +{ +} + +void +gr_stream_mux::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = 0; +} + + +int +gr_stream_mux::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + + char *out = (char *) output_items[0]; + const char *in; + + int acc = 0; + int N=0; + int M=0; + std::vector consume_vector(d_lengths.size(), 0); + + #if VERBOSE + printf("mux: nouput_items: %d d_stream: %d\n", noutput_items, d_stream); + for(int i = 0; i < d_lengths.size(); i++) + printf("\tninput_items[%d]: %d\n", i, ninput_items[i]); + #endif + + in = (const char *) input_items[d_stream]; + + if(d_residual) { + #if VERBOSE + printf("Cleaning up residual bytes (%d) from stream %d\n", d_residual, d_stream); + #endif + + // get the number of items available in input stream up to the + // num items required + N=std::min(d_residual, ninput_items[d_stream]); + + // get the number of items we can put into the output buffer + M=std::min(N, noutput_items); + + // copy the items to the output buff + memcpy(out, in, M*d_itemsize); + + // increment the output accumulator + acc += M; + + // keep track of items consumed + consume_vector[d_stream]=M; + + // keep track if there are residual items left from the input stream + d_residual -= M; + + #if VERBOSE + printf("Stream: %d (%x) Wrote: %d bytes Output has: %d bytes residual: %d bytes\n", + d_stream, in, M, acc, d_residual); + #endif + + // if no residual items, we're done with this input stream for + // this round + if (!d_residual) { + if(d_stream == d_lengths.size() - 1) { + d_stream=0; // wrap stream pointer + } + else { + d_stream++; // or increment the stream pointer + } + #if VERBOSE + printf("Going to next stream: %d\n", d_stream); + #endif + in = ((const char *) (input_items[d_stream])) + d_itemsize*consume_vector[d_stream]; + } + } + + if(!d_residual) { + while (acc +#include +#include + +class gr_stream_mux; +typedef boost::shared_ptr gr_stream_mux_sptr; + +/*! + * \brief Creates a stream muxing block to multiplex many streams into + * one with a specified format. + * + * \param itemsize the item size of the stream + * \param length a vector (list/tuple) specifying the number of + * items from each stream the mux together. + * Warning: this requires that at least as many items + * per stream are available or the system will wait + * indefinitely for the items. + * + */ + +gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, const std::vector &lengths); + + +/*! + * \brief Stream muxing block to multiplex many streams into + * one with a specified format. + * + * Muxes N streams together producing an output stream that + * contains N0 items from the first stream, N1 items from the second, + * etc. and repeats: + * + * [N0, N1, N2, ..., Nm, N0, N1, ...] + */ + +class gr_stream_mux : public gr_block +{ + friend gr_stream_mux_sptr + gr_make_stream_mux (size_t itemsize, const std::vector &lengths); + + protected: + gr_stream_mux (size_t itemsize, const std::vector &lengths); + private: + size_t d_itemsize; + unsigned int d_stream; + int d_residual; + int d_times; + int d_unconsume; + //gr_vector_int d_unconsume; + gr_vector_int d_lengths; + public: + ~gr_stream_mux(void); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + + +#endif diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.i b/gnuradio-core/src/lib/general/gr_stream_mux.i new file mode 100644 index 00000000..02213515 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_mux.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 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 2, 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. + */ + +#include + +GR_SWIG_BLOCK_MAGIC(gr,stream_mux) + +gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, + const std::vector &lengths); + +class gr_stream_mux : public gr_block +{ + protected: + gr_make_stream_mux (size_t itemsize, + const std::vector &lengths); + + public: + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/gengen/Makefile.am b/gnuradio-core/src/lib/gengen/Makefile.am index d3fa84cf..c566570e 100644 --- a/gnuradio-core/src/lib/gengen/Makefile.am +++ b/gnuradio-core/src/lib/gengen/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2002,2004,2006 Free Software Foundation, Inc. +# Copyright 2001,2002,2004,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -71,6 +71,9 @@ CODE_GENERATOR = \ gr_packed_to_unpacked_XX.cc.t \ gr_packed_to_unpacked_XX.h.t \ gr_packed_to_unpacked_XX.i.t \ + gr_peak_detector_XX.cc.t \ + gr_peak_detector_XX.h.t \ + gr_peak_detector_XX.i.t \ gr_sig_source_X.cc.t \ gr_sig_source_X.h.t \ gr_sig_source_X.i.t \ diff --git a/gnuradio-core/src/lib/gengen/Makefile.gen b/gnuradio-core/src/lib/gengen/Makefile.gen index f0c477e3..adbceba1 100644 --- a/gnuradio-core/src/lib/gengen/Makefile.gen +++ b/gnuradio-core/src/lib/gengen/Makefile.gen @@ -56,6 +56,13 @@ GENERATED_H = \ gr_packed_to_unpacked_bb.h \ gr_packed_to_unpacked_ii.h \ gr_packed_to_unpacked_ss.h \ + gr_peak_detector_ff.h \ + gr_peak_detector_ii.h \ + gr_peak_detector_ss.h \ + gr_sample_and_hold_bb.h \ + gr_sample_and_hold_ff.h \ + gr_sample_and_hold_ii.h \ + gr_sample_and_hold_ss.h \ gr_sig_source_c.h \ gr_sig_source_f.h \ gr_sig_source_i.h \ @@ -133,6 +140,13 @@ GENERATED_I = \ gr_packed_to_unpacked_bb.i \ gr_packed_to_unpacked_ii.i \ gr_packed_to_unpacked_ss.i \ + gr_peak_detector_ff.i \ + gr_peak_detector_ii.i \ + gr_peak_detector_ss.i \ + gr_sample_and_hold_bb.i \ + gr_sample_and_hold_ff.i \ + gr_sample_and_hold_ii.i \ + gr_sample_and_hold_ss.i \ gr_sig_source_c.i \ gr_sig_source_f.i \ gr_sig_source_i.i \ @@ -210,6 +224,13 @@ GENERATED_CC = \ gr_packed_to_unpacked_bb.cc \ gr_packed_to_unpacked_ii.cc \ gr_packed_to_unpacked_ss.cc \ + gr_peak_detector_ff.cc \ + gr_peak_detector_ii.cc \ + gr_peak_detector_ss.cc \ + gr_sample_and_hold_bb.cc \ + gr_sample_and_hold_ff.cc \ + gr_sample_and_hold_ii.cc \ + gr_sample_and_hold_ss.cc \ gr_sig_source_c.cc \ gr_sig_source_f.cc \ gr_sig_source_i.cc \ diff --git a/gnuradio-core/src/lib/gengen/generate_common.py b/gnuradio-core/src/lib/gengen/generate_common.py index 5abb15ce..2ab0586d 100755 --- a/gnuradio-core/src/lib/gengen/generate_common.py +++ b/gnuradio-core/src/lib/gengen/generate_common.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2006 Free Software Foundation, Inc. +# Copyright 2004,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -50,14 +50,16 @@ reg_roots = [ 'gr_add_vXX', 'gr_multiply_vXX', 'gr_add_const_vXX', - 'gr_multiply_const_vXX' + 'gr_multiply_const_vXX', ] # other blocks others = ( ('gr_chunks_to_symbols_XX', ('bf', 'bc', 'sf', 'sc', 'if', 'ic')), ('gr_unpacked_to_packed_XX', ('bb','ss','ii')), - ('gr_packed_to_unpacked_XX', ('bb','ss','ii')) + ('gr_packed_to_unpacked_XX', ('bb','ss','ii')), + ('gr_sample_and_hold_XX', ('bb','ss','ii','ff')), + ('gr_peak_detector_XX', ('ff','ii','ss')) ) diff --git a/gnuradio-core/src/lib/gengen/gengen_generated.i b/gnuradio-core/src/lib/gengen/gengen_generated.i index a41f30a3..d5f874e6 100644 --- a/gnuradio-core/src/lib/gengen/gengen_generated.i +++ b/gnuradio-core/src/lib/gengen/gengen_generated.i @@ -56,6 +56,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -133,6 +140,13 @@ %include %include %include +%include +%include +%include +%include +%include +%include +%include %include %include %include diff --git a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t new file mode 100644 index 00000000..812ec9fd --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha) +{ + return @SPTR_NAME@ (new @NAME@ (threshold_factor_rise, + threshold_factor_fall, + look_ahead, alpha)); +} + +@NAME@::@NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_threshold_factor_rise(threshold_factor_rise), + d_threshold_factor_fall(threshold_factor_fall), + d_look_ahead(look_ahead), d_avg_alpha(alpha), d_avg(0), d_found(0) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + memset(optr, 0, noutput_items*sizeof(@O_TYPE@)); + + @I_TYPE@ peak_val = -(@I_TYPE@)INFINITY; + int peak_ind = 0; + unsigned char state = 0; + int i = 0; + + //printf("noutput_items %d\n",noutput_items); + while(i < noutput_items) { + if(state == 0) { // below threshold + if(iptr[i] > d_avg*d_threshold_factor_rise) { + state = 1; + } + else { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + } + else if(state == 1) { // above threshold, have not found peak + //printf("Entered State 1: %f i: %d noutput_items: %d\n", iptr[i], i, noutput_items); + if(iptr[i] > peak_val) { + peak_val = iptr[i]; + peak_ind = i; + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else if (iptr[i] > d_avg*d_threshold_factor_fall) { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else { + optr[peak_ind] = (@O_TYPE@)1; + state = 0; + peak_val = -(@I_TYPE@)INFINITY; + //printf("Leaving State 1: Peak: %f Peak Ind: %d i: %d noutput_items: %d\n", + //peak_val, peak_ind, i, noutput_items); + } + } + } + + if(state == 0) { + //printf("Leave in State 0, produced %d\n",noutput_items); + return noutput_items; + } + else { // only return up to passing the threshold + //printf("Leave in State 1, only produced %d of %d\n",peak_ind,noutput_items); + return peak_ind; + } +} diff --git a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t new file mode 100644 index 00000000..487f98ba --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise = 0.25, + float threshold_factor_fall = 0.40, + int look_ahead = 10, + float alpha = 0.001); + +/*! + * \brief Detect the peak of a signal + * \ingroup block + * + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. + * + * \param threshold_factor_rise The threshold factor determins when a peak + * has started. An average of the signal is calculated and when the + * value of the signal goes over threshold_factor_rise*average, we + * start looking for a peak. + * \param threshold_factor_fall The threshold factor determins when a peak + * has ended. An average of the signal is calculated and when the + * value of the signal goes bellow threshold_factor_fall*average, we + * stop looking for a peak. + * \param look_ahead The look-ahead value is used when the threshold is + * found to look if there another peak within this step range. + * If there is a larger value, we set that as the peak and look ahead + * again. This is continued until the highest point is found with + * This look-ahead range. + * \param alpha The gain value of a moving average filter + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + @NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + private: + float d_threshold_factor_rise; + float d_threshold_factor_fall; + int d_look_ahead; + float d_avg_alpha; + float d_avg; + unsigned char d_found; + + public: + + /*! \brief Set the threshold factor value for the rise time + * \param thr new threshold factor + */ + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + + /*! \brief Set the threshold factor value for the fall time + * \param thr new threshold factor + */ + void set_threshold_factor_fall(float thr) { d_threshold_factor_fall = thr; } + + /*! \brief Set the look-ahead factor + * \param look new look-ahead factor + */ + void set_look_ahead(int look) { d_look_ahead = look; } + + /*! \brief Set the running average alpha + * \param alpha new alpha for running average + */ + void set_alpha(int alpha) { d_avg_alpha = alpha; } + + /*! \brief Get the threshold factor value for the rise time + * \return threshold factor + */ + float threshold_factor_rise() { return d_threshold_factor_rise; } + + /*! \brief Get the threshold factor value for the fall time + * \return threshold factor + */ + float threshold_factor_fall() { return d_threshold_factor_fall; } + + /*! \brief Get the look-ahead factor value + * \return look-ahead factor + */ + int look_ahead() { return d_look_ahead; } + + /*! \brief Get the alpha value of the running average + * \return alpha + */ + float alpha() { return d_avg_alpha; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t new file mode 100644 index 00000000..02a55946 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise = 0.25, + float threshold_factor_fall = 0.40, + int look_ahead = 10, + float alpha=0.001); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + public: + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + void set_threshold_factor_fall(float thr) { d_threshold_factor_fall = thr; } + void set_look_ahead(int look) { d_look_ahead = look; } + void set_alpha(int alpha) { d_avg_alpha = alpha; } + + float threshold_factor_rise() { return d_threshold_factor_rise; } + float threshold_factor_fall() { return d_threshold_factor_fall; } + int look_ahead() { return d_look_ahead; } + float alpha() { return d_avg_alpha; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t new file mode 100644 index 00000000..3b971557 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return @SPTR_NAME@ (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (2, 2, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_data(0) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @I_TYPE@ *ctrl = (@I_TYPE@ *) input_items[1]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + if(ctrl[i] > 0.5) { + d_data = iptr[i]; + } + optr[i] = d_data; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t new file mode 100644 index 00000000..9da7e462 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief sample and hold circuit + * \ingroup block + * + * Samples the data stream (input stream 0) and holds the value + * if the control signal is 1 (intput stream 1). + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + private: + @O_TYPE@ d_data; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t new file mode 100644 index 00000000..307bf243 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am index 8320375c..049e6984 100644 --- a/gnuradio-core/src/lib/io/Makefile.am +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2001,2003,2004,2006 Free Software Foundation, Inc. +# Copyright 2001,2003,2004,2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -34,6 +34,7 @@ libio_la_SOURCES = \ gr_file_descriptor_source.cc \ gr_message_sink.cc \ gr_message_source.cc \ + gr_message_vector_source.cc \ gr_oscope_guts.cc \ gr_oscope_sink_f.cc \ gr_oscope_sink_x.cc \ @@ -59,8 +60,10 @@ grinclude_HEADERS = \ gr_file_source.h \ gr_file_descriptor_sink.h \ gr_file_descriptor_source.h \ + gr_frame.h \ gr_message_sink.h \ gr_message_source.h \ + gr_message_vector_source.h \ gr_oscope_guts.h \ gr_oscope_sink_f.h \ gr_oscope_sink_x.h \ @@ -92,6 +95,7 @@ swiginclude_HEADERS = \ gr_file_descriptor_source.i \ gr_message_sink.i \ gr_message_source.i \ + gr_message_vector_source.i \ gr_oscope_sink.i \ microtune_xxxx_eval_board.i \ microtune_4702_eval_board.i \ diff --git a/gnuradio-core/src/lib/io/gr_frame.h b/gnuradio-core/src/lib/io/gr_frame.h new file mode 100644 index 00000000..07317e9d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_frame.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FRAME_H +#define INCLUDED_GR_FRAME_H + +#include + +class gr_frame +{ + public: + gr_frame(unsigned int mtu) + : mtu(mtu), length(0) + { } + + unsigned int mtu; + unsigned int length; + unsigned char data[]; +}; + +#endif + diff --git a/gnuradio-core/src/lib/io/gr_message_vector_source.cc b/gnuradio-core/src/lib/io/gr_message_vector_source.cc new file mode 100644 index 00000000..69e2bc8d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_vector_source.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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 +#include +#include +#include +#include +#include +#include +#include + + +// public constructor that returns a shared_ptr + +gr_message_vector_source_sptr +gr_make_message_vector_source(size_t max_msg_size, int msgq_limit) +{ + return gr_message_vector_source_sptr(new gr_message_vector_source(max_msg_size,msgq_limit)); +} + +gr_message_vector_source::gr_message_vector_source (size_t max_msg_size, int msgq_limit) + : gr_sync_block("message_vector_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, 2*sizeof(int) + max_msg_size * sizeof(char))), // Make room for length fields + d_max_msg_size(max_msg_size), d_msgq(gr_make_msg_queue(msgq_limit)), d_eof(false) +{ +} + +gr_message_vector_source::~gr_message_vector_source() +{ +} + +int +gr_message_vector_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + /* + char *out = (char *) output_items[0]; + + if (d_eof) + return -1; + + gr_message_sptr msg = d_msgq->delete_head(); + + if (msg->type() == 1) { // type == 1 sets EOF + d_eof = true; + } + + assert(msg->length() <= d_max_msg_size); + memset((int*)out, msg->length(), 1); + memcpy (&out[4], (msg->msg()), msg->length()); + */ + + char *out = (char *) output_items[0]; + gr_frame *myframe = (gr_frame*)out; + + if (d_eof) + return -1; + + gr_message_sptr msg = d_msgq->delete_head(); + + if (msg->type() == 1) { // type == 1 sets EOF + d_eof = true; + } + + assert(msg->length() <= d_max_msg_size); + myframe->length = msg->length(); + myframe->mtu = d_max_msg_size; + memcpy (myframe->data, (msg->msg()), msg->length()); + + return 1; +} diff --git a/gnuradio-core/src/lib/io/gr_message_vector_source.h b/gnuradio-core/src/lib/io/gr_message_vector_source.h new file mode 100644 index 00000000..8b346535 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_vector_source.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_VECTOR_SOURCE_H +#define INCLUDED_GR_MESSAGE_VECTOR_SOURCE_H + +#include +#include +#include +#include + +class gr_message_vector_source; +typedef boost::shared_ptr gr_message_vector_source_sptr; + +gr_message_vector_source_sptr gr_make_message_vector_source (size_t max_msg_size, int msgq_limit=0); + +/*! + * \brief Turn received messages into vectors + * \ingroup source + */ +class gr_message_vector_source : public gr_sync_block +{ + private: + size_t d_max_msg_size; + gr_msg_queue_sptr d_msgq; + bool d_eof; + + friend gr_message_vector_source_sptr + gr_make_message_vector_source(size_t max_msg_size, int msgq_limit); + + protected: + gr_message_vector_source (size_t max_msg_size, int msgq_limit); + + public: + ~gr_message_vector_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_VECTOR_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_vector_source.i b/gnuradio-core/src/lib/io/gr_message_vector_source.i new file mode 100644 index 00000000..ff8bd5de --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_vector_source.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_vector_source); + +gr_message_vector_source_sptr gr_make_message_vector_source (size_t max_msg_size, int msgq_limit=0); + +class gr_message_vector_source : public gr_sync_block +{ + protected: + gr_message_vector_source (size_t itemsize, int msgq_limit); + + public: + ~gr_message_vector_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i index 7baf94ef..d80f6636 100644 --- a/gnuradio-core/src/lib/io/io.i +++ b/gnuradio-core/src/lib/io/io.i @@ -34,8 +34,9 @@ #include #include #include -#include -#include +#include +#include +#include %} @@ -50,6 +51,7 @@ %include "gr_oscope_sink.i" %include "ppio.i" %include "gr_message_source.i" +%include "gr_message_vector_source.i" %include "gr_message_sink.i" %include "gr_udp_sink.i" %include "gr_udp_source.i" diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am index 0d53a11c..1bd2a975 100644 --- a/gnuradio-core/src/python/gnuradio/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004 Free Software Foundation, Inc. +# Copyright 2004,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -29,6 +29,7 @@ grpython_PYTHON = \ eng_notation.py \ eng_option.py \ modulation_utils.py \ + ofdm_packet_utils.py \ packet_utils.py \ gr_unittest.py \ optfir.py \ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am index 6bfbfa90..051c03db 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2005,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -38,6 +38,7 @@ grblkspython_PYTHON = \ gmsk.py \ nbfm_rx.py \ nbfm_tx.py \ + ofdm_pkt.py \ pkt.py \ psk.py \ qam.py \ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py new file mode 100644 index 00000000..d72bc14a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py @@ -0,0 +1,160 @@ +# +# Copyright 2005,2006 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 2, 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 math import pi +import Numeric + +from gnuradio import gr, ofdm_packet_utils +import gnuradio.gr.gr_threading as _threading + + +# ///////////////////////////////////////////////////////////////////////////// +# mod/demod with packets as i/o +# ///////////////////////////////////////////////////////////////////////////// + +class mod_ofdm_pkts(gr.hier_block): + """ + Wrap an arbitrary digital modulator in our packet handling framework. + + Send packets by calling send_pkt + """ + def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True): + """ + Hierarchical block for sending packets + + Packets to be sent are enqueued by calling send_pkt. + The output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param modulator: instance of modulator class (gr_block or hier_block) + @type modulator: complex baseband out + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's between 1 and 64 long + @param msgq_limit: maximum number of messages in message queue + @type msgq_limit: int + @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples + + See modulators for remaining parameters + """ + self._modulator = modulator + self._pad_for_usrp = pad_for_usrp + + if access_code is None: + access_code = ofdm_packet_utils.default_access_code + if not ofdm_packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + # accepts messages from the outside world + self._pkt_input = gr.message_vector_source(self._modulator.mtu(), msgq_limit) + fg.connect(self._pkt_input, self._modulator) + gr.hier_block.__init__(self, fg, None, self._modulator) + + def send_pkt(self, payload='', eof=False): + """ + Send the payload. + + @param payload: data to send + @type payload: string + """ + if eof: + msg = gr.message(1) # tell self._pkt_input we're not sending any more packets + else: + # print "original_payload =", string_to_hex_list(payload) + pkt = ofdm_packet_utils.make_packet(payload, + self._modulator.samples_per_symbol(), + self._modulator.bits_per_symbol(), + self._access_code, + self._pad_for_usrp) + #print "pkt =", string_to_hex_list(pkt) + msg = gr.message_from_string(pkt) + self._pkt_input.msgq().insert_tail(msg) + + + +class demod_ofdm_pkts(gr.hier_block): + """ + Wrap an arbitrary digital demodulator in our packet handling framework. + + The input is complex baseband. When packets are demodulated, they are passed to the + app via the callback. + """ + + def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1): + """ + Hierarchical block for demodulating and deframing packets. + + The input is the complex modulated signal at baseband. + Demodulated packets are sent to the handler. + + @param fg: flow graph + @type fg: flow graph + @param demodulator: instance of demodulator class (gr_block or hier_block) + @type demodulator: complex baseband in + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's + @param callback: function of two args: ok, payload + @type callback: ok: bool; payload: string + @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) + @type threshold: int + """ + + self._demodulator = demodulator + if access_code is None: + access_code = ofdm_packet_utils.default_access_code + if not ofdm_packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + if threshold == -1: + threshold = 12 # FIXME raise exception + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY + self.bytes_to_bits = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) + self.correlator = gr.correlate_access_code_bb(access_code, threshold) + + self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + fg.connect(self._demodulator, self.bytes_to_bits, self.correlator, self.framer_sink) + + if 0: + fg.connect(self.bytes_to_bits, gr.file_sink(gr.sizeof_char, "received_bits.out")) + + gr.hier_block.__init__(self, fg, self._demodulator, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + +class _queue_watcher_thread(_threading.Thread): + def __init__(self, rcvd_pktq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.rcvd_pktq = rcvd_pktq + self.callback = callback + self.keep_running = True + self.start() + + + def run(self): + while self.keep_running: + msg = self.rcvd_pktq.delete_head() + ok, payload = ofdm_packet_utils.unmake_packet(msg.to_string()) + if self.callback: + self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py b/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py new file mode 100644 index 00000000..c3700c7e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py @@ -0,0 +1,448 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 struct +import Numeric +from gnuradio import gru + +def conv_packed_binary_string_to_1_0_string(s): + """ + '\xAF' --> '10101111' + """ + r = [] + for ch in s: + x = ord(ch) + for i in range(7,-1,-1): + t = (x >> i) & 0x1 + r.append(t) + + return ''.join(map(lambda x: chr(x + ord('0')), r)) + +def conv_1_0_string_to_packed_binary_string(s): + """ + '10101111' -> ('\xAF', False) + + Basically the inverse of conv_packed_binary_string_to_1_0_string, + but also returns a flag indicating if we had to pad with leading zeros + to get to a multiple of 8. + """ + if not is_1_0_string(s): + raise ValueError, "Input must be a string containing only 0's and 1's" + + # pad to multiple of 8 + padded = False + rem = len(s) % 8 + if rem != 0: + npad = 8 - rem + s = '0' * npad + s + padded = True + + assert len(s) % 8 == 0 + + r = [] + i = 0 + while i < len(s): + t = 0 + for j in range(8): + t = (t << 1) | (ord(s[i + j]) - ord('0')) + r.append(chr(t)) + i += 8 + return (''.join(r), padded) + + +default_access_code = \ + conv_packed_binary_string_to_1_0_string('\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC') + +def is_1_0_string(s): + if not isinstance(s, str): + return False + for ch in s: + if not ch in ('0', '1'): + return False + return True + +def string_to_hex_list(s): + return map(lambda x: hex(ord(x)), s) + + +def whiten(s, o): + sa = Numeric.fromstring(s, Numeric.UnsignedInt8) + z = sa ^ random_mask_vec8[o:len(sa)+o] + return z.tostring() + +def dewhiten(s, o): + return whiten(s, o) # self inverse + + +def make_header(payload_len, whitener_offset=0): + # Upper nibble is offset, lower 12 bits is len + val = ((whitener_offset & 0xf) << 12) | (payload_len & 0x0fff) + #print "offset =", whitener_offset, " len =", payload_len, " val=", val + return struct.pack('!HH', val, val) + +def make_packet(payload, samples_per_symbol, bits_per_symbol, + access_code=default_access_code, pad_for_usrp=True, + whitener_offset=0): + """ + Build a packet, given access code, payload, and whitener offset + + @param payload: packet payload, len [0, 4096] + @param samples_per_symbol: samples per symbol (needed for padding calculation) + @type samples_per_symbol: int + @param bits_per_symbol: (needed for padding calculation) + @type bits_per_symbol: int + @param access_code: string of ascii 0's and 1's + @param whitener_offset offset into whitener string to use [0-16) + + Packet will have access code at the beginning, followed by length, payload + and finally CRC-32. + """ + if not is_1_0_string(access_code): + raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) + + if not whitener_offset >=0 and whitener_offset < 16: + raise ValueError, "whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,) + + (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code) + + payload_with_crc = gru.gen_and_append_crc32(payload) + #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) + + L = len(payload_with_crc) + MAXLEN = len(random_mask_tuple) + if L > MAXLEN: + raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,) + + #pkt = ''.join((packed_access_code, make_header(L, whitener_offset)), + # whiten(payload_with_crc, whitener_offset), '\x55')) + pkt_hd = ''.join((packed_access_code, make_header(L, whitener_offset))) + pkt_dt = ''.join((payload_with_crc, '\x55')) + packet_length = len(pkt_hd) + len(pkt_dt) + + if pad_for_usrp: + usrp_packing = _npadding_bytes(packet_length, samples_per_symbol, bits_per_symbol) * '\x55' + pkt_dt = pkt_dt + usrp_packing + pkt = pkt_hd + whiten(pkt_dt, whitener_offset) + + #print "make_packet: len(pkt) =", len(pkt) + + return pkt + +def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol): + """ + Generate sufficient padding such that each packet ultimately ends + up being a multiple of 512 bytes when sent across the USB. We + send 4-byte samples across the USB (16-bit I and 16-bit Q), thus + we want to pad so that after modulation the resulting packet + is a multiple of 128 samples. + + @param ptk_byte_len: len in bytes of packet, not including padding. + @param samples_per_symbol: samples per bit (1 bit / symbolwith GMSK) + @type samples_per_symbol: int + + @returns number of bytes of padding to append. + """ + modulus = 128 + byte_modulus = gru.lcm(modulus/8, samples_per_symbol) * bits_per_symbol / samples_per_symbol + r = pkt_byte_len % byte_modulus + if r == 0: + return 0 + return byte_modulus - r + + +def unmake_packet(whitened_payload_with_crc, whitener_offset=0): + """ + Return (ok, payload) + + @param whitened_payload_with_crc: string + """ + payload_with_crc = dewhiten(whitened_payload_with_crc, whitener_offset) + ok, payload = gru.check_crc32(payload_with_crc) + + if 0: + print "payload_with_crc =", string_to_hex_list(payload_with_crc) + print "ok = %r, len(payload) = %d" % (ok, len(payload)) + print "payload =", string_to_hex_list(payload) + + return ok, payload + + +# FYI, this PN code is the output of a 15-bit LFSR +random_mask_tuple = ( + 255, 63, 0, 16, 0, 12, 0, 5, 192, 3, 16, 1, 204, 0, 85, 192, + 63, 16, 16, 12, 12, 5, 197, 195, 19, 17, 205, 204, 85, 149, 255, 47, + 0, 28, 0, 9, 192, 6, 208, 2, 220, 1, 153, 192, 106, 208, 47, 28, + 28, 9, 201, 198, 214, 210, 222, 221, 152, 89, 170, 186, 255, 51, 0, 21, + 192, 15, 16, 4, 12, 3, 69, 193, 243, 16, 69, 204, 51, 21, 213, 207, + 31, 20, 8, 15, 70, 132, 50, 227, 85, 137, 255, 38, 192, 26, 208, 11, + 28, 7, 73, 194, 182, 209, 182, 220, 118, 217, 230, 218, 202, 219, 23, 27, + 78, 139, 116, 103, 103, 106, 170, 175, 63, 60, 16, 17, 204, 12, 85, 197, + 255, 19, 0, 13, 192, 5, 144, 3, 44, 1, 221, 192, 89, 144, 58, 236, + 19, 13, 205, 197, 149, 147, 47, 45, 220, 29, 153, 201, 170, 214, 255, 30, + 192, 8, 80, 6, 188, 2, 241, 193, 132, 80, 99, 124, 41, 225, 222, 200, + 88, 86, 186, 190, 243, 48, 69, 212, 51, 31, 85, 200, 63, 22, 144, 14, + 236, 4, 77, 195, 117, 145, 231, 44, 74, 157, 247, 41, 134, 158, 226, 232, + 73, 142, 182, 228, 118, 203, 102, 215, 106, 222, 175, 24, 124, 10, 161, 199, + 56, 82, 146, 189, 173, 177, 189, 180, 113, 183, 100, 118, 171, 102, 255, 106, + 192, 47, 16, 28, 12, 9, 197, 198, 211, 18, 221, 205, 153, 149, 170, 239, + 63, 12, 16, 5, 204, 3, 21, 193, 207, 16, 84, 12, 63, 69, 208, 51, + 28, 21, 201, 207, 22, 212, 14, 223, 68, 88, 51, 122, 149, 227, 47, 9, + 220, 6, 217, 194, 218, 209, 155, 28, 107, 73, 239, 118, 204, 38, 213, 218, + 223, 27, 24, 11, 74, 135, 119, 34, 166, 153, 186, 234, 243, 15, 5, 196, + 3, 19, 65, 205, 240, 85, 132, 63, 35, 80, 25, 252, 10, 193, 199, 16, + 82, 140, 61, 165, 209, 187, 28, 115, 73, 229, 246, 203, 6, 215, 66, 222, + 177, 152, 116, 106, 167, 111, 58, 172, 19, 61, 205, 209, 149, 156, 111, 41, + 236, 30, 205, 200, 85, 150, 191, 46, 240, 28, 68, 9, 243, 70, 197, 242, + 211, 5, 157, 195, 41, 145, 222, 236, 88, 77, 250, 181, 131, 55, 33, 214, + 152, 94, 234, 184, 79, 50, 180, 21, 183, 79, 54, 180, 22, 247, 78, 198, + 180, 82, 247, 125, 134, 161, 162, 248, 121, 130, 162, 225, 185, 136, 114, 230, + 165, 138, 251, 39, 3, 90, 129, 251, 32, 67, 88, 49, 250, 148, 67, 47, + 113, 220, 36, 89, 219, 122, 219, 99, 27, 105, 203, 110, 215, 108, 94, 173, + 248, 125, 130, 161, 161, 184, 120, 114, 162, 165, 185, 187, 50, 243, 85, 133, + 255, 35, 0, 25, 192, 10, 208, 7, 28, 2, 137, 193, 166, 208, 122, 220, + 35, 25, 217, 202, 218, 215, 27, 30, 139, 72, 103, 118, 170, 166, 255, 58, + 192, 19, 16, 13, 204, 5, 149, 195, 47, 17, 220, 12, 89, 197, 250, 211, + 3, 29, 193, 201, 144, 86, 236, 62, 205, 208, 85, 156, 63, 41, 208, 30, + 220, 8, 89, 198, 186, 210, 243, 29, 133, 201, 163, 22, 249, 206, 194, 212, + 81, 159, 124, 104, 33, 238, 152, 76, 106, 181, 239, 55, 12, 22, 133, 206, + 227, 20, 73, 207, 118, 212, 38, 223, 90, 216, 59, 26, 147, 75, 45, 247, + 93, 134, 185, 162, 242, 249, 133, 130, 227, 33, 137, 216, 102, 218, 170, 219, + 63, 27, 80, 11, 124, 7, 97, 194, 168, 81, 190, 188, 112, 113, 228, 36, + 75, 91, 119, 123, 102, 163, 106, 249, 239, 2, 204, 1, 149, 192, 111, 16, + 44, 12, 29, 197, 201, 147, 22, 237, 206, 205, 148, 85, 175, 127, 60, 32, + 17, 216, 12, 90, 133, 251, 35, 3, 89, 193, 250, 208, 67, 28, 49, 201, + 212, 86, 223, 126, 216, 32, 90, 152, 59, 42, 147, 95, 45, 248, 29, 130, + 137, 161, 166, 248, 122, 194, 163, 17, 185, 204, 114, 213, 229, 159, 11, 40, + 7, 94, 130, 184, 97, 178, 168, 117, 190, 167, 48, 122, 148, 35, 47, 89, + 220, 58, 217, 211, 26, 221, 203, 25, 151, 74, 238, 183, 12, 118, 133, 230, + 227, 10, 201, 199, 22, 210, 142, 221, 164, 89, 187, 122, 243, 99, 5, 233, + 195, 14, 209, 196, 92, 83, 121, 253, 226, 193, 137, 144, 102, 236, 42, 205, + 223, 21, 152, 15, 42, 132, 31, 35, 72, 25, 246, 138, 198, 231, 18, 202, + 141, 151, 37, 174, 155, 60, 107, 81, 239, 124, 76, 33, 245, 216, 71, 26, + 178, 139, 53, 167, 87, 58, 190, 147, 48, 109, 212, 45, 159, 93, 168, 57, + 190, 146, 240, 109, 132, 45, 163, 93, 185, 249, 178, 194, 245, 145, 135, 44, + 98, 157, 233, 169, 142, 254, 228, 64, 75, 112, 55, 100, 22, 171, 78, 255, + 116, 64, 39, 112, 26, 164, 11, 59, 71, 83, 114, 189, 229, 177, 139, 52, + 103, 87, 106, 190, 175, 48, 124, 20, 33, 207, 88, 84, 58, 191, 83, 48, + 61, 212, 17, 159, 76, 104, 53, 238, 151, 12, 110, 133, 236, 99, 13, 233, + 197, 142, 211, 36, 93, 219, 121, 155, 98, 235, 105, 143, 110, 228, 44, 75, + 93, 247, 121, 134, 162, 226, 249, 137, 130, 230, 225, 138, 200, 103, 22, 170, + 142, 255, 36, 64, 27, 112, 11, 100, 7, 107, 66, 175, 113, 188, 36, 113, + 219, 100, 91, 107, 123, 111, 99, 108, 41, 237, 222, 205, 152, 85, 170, 191, + 63, 48, 16, 20, 12, 15, 69, 196, 51, 19, 85, 205, 255, 21, 128, 15, + 32, 4, 24, 3, 74, 129, 247, 32, 70, 152, 50, 234, 149, 143, 47, 36, + 28, 27, 73, 203, 118, 215, 102, 222, 170, 216, 127, 26, 160, 11, 56, 7, + 82, 130, 189, 161, 177, 184, 116, 114, 167, 101, 186, 171, 51, 63, 85, 208, + 63, 28, 16, 9, 204, 6, 213, 194, 223, 17, 152, 12, 106, 133, 239, 35, + 12, 25, 197, 202, 211, 23, 29, 206, 137, 148, 102, 239, 106, 204, 47, 21, + 220, 15, 25, 196, 10, 211, 71, 29, 242, 137, 133, 166, 227, 58, 201, 211, + 22, 221, 206, 217, 148, 90, 239, 123, 12, 35, 69, 217, 243, 26, 197, 203, + 19, 23, 77, 206, 181, 148, 119, 47, 102, 156, 42, 233, 223, 14, 216, 4, + 90, 131, 123, 33, 227, 88, 73, 250, 182, 195, 54, 209, 214, 220, 94, 217, + 248, 90, 194, 187, 17, 179, 76, 117, 245, 231, 7, 10, 130, 135, 33, 162, + 152, 121, 170, 162, 255, 57, 128, 18, 224, 13, 136, 5, 166, 131, 58, 225, + 211, 8, 93, 198, 185, 146, 242, 237, 133, 141, 163, 37, 185, 219, 50, 219, + 85, 155, 127, 43, 96, 31, 104, 8, 46, 134, 156, 98, 233, 233, 142, 206, + 228, 84, 75, 127, 119, 96, 38, 168, 26, 254, 139, 0, 103, 64, 42, 176, + 31, 52, 8, 23, 70, 142, 178, 228, 117, 139, 103, 39, 106, 154, 175, 43, + 60, 31, 81, 200, 60, 86, 145, 254, 236, 64, 77, 240, 53, 132, 23, 35, + 78, 153, 244, 106, 199, 111, 18, 172, 13, 189, 197, 177, 147, 52, 109, 215, + 109, 158, 173, 168, 125, 190, 161, 176, 120, 116, 34, 167, 89, 186, 186, 243, + 51, 5, 213, 195, 31, 17, 200, 12, 86, 133, 254, 227, 0, 73, 192, 54, + 208, 22, 220, 14, 217, 196, 90, 211, 123, 29, 227, 73, 137, 246, 230, 198, + 202, 210, 215, 29, 158, 137, 168, 102, 254, 170, 192, 127, 16, 32, 12, 24, + 5, 202, 131, 23, 33, 206, 152, 84, 106, 191, 111, 48, 44, 20, 29, 207, + 73, 148, 54, 239, 86, 204, 62, 213, 208, 95, 28, 56, 9, 210, 134, 221, + 162, 217, 185, 154, 242, 235, 5, 143, 67, 36, 49, 219, 84, 91, 127, 123, + 96, 35, 104, 25, 238, 138, 204, 103, 21, 234, 143, 15, 36, 4, 27, 67, + 75, 113, 247, 100, 70, 171, 114, 255, 101, 128, 43, 32, 31, 88, 8, 58, + 134, 147, 34, 237, 217, 141, 154, 229, 171, 11, 63, 71, 80, 50, 188, 21, + 177, 207, 52, 84, 23, 127, 78, 160, 52, 120, 23, 98, 142, 169, 164, 126, + 251, 96, 67, 104, 49, 238, 148, 76, 111, 117, 236, 39, 13, 218, 133, 155, + 35, 43, 89, 223, 122, 216, 35, 26, 153, 203, 42, 215, 95, 30, 184, 8, + 114, 134, 165, 162, 251, 57, 131, 82, 225, 253, 136, 65, 166, 176, 122, 244, + 35, 7, 89, 194, 186, 209, 179, 28, 117, 201, 231, 22, 202, 142, 215, 36, + 94, 155, 120, 107, 98, 175, 105, 188, 46, 241, 220, 68, 89, 243, 122, 197, + 227, 19, 9, 205, 198, 213, 146, 223, 45, 152, 29, 170, 137, 191, 38, 240, + 26, 196, 11, 19, 71, 77, 242, 181, 133, 183, 35, 54, 153, 214, 234, 222, + 207, 24, 84, 10, 191, 71, 48, 50, 148, 21, 175, 79, 60, 52, 17, 215, + 76, 94, 181, 248, 119, 2, 166, 129, 186, 224, 115, 8, 37, 198, 155, 18, + 235, 77, 143, 117, 164, 39, 59, 90, 147, 123, 45, 227, 93, 137, 249, 166, + 194, 250, 209, 131, 28, 97, 201, 232, 86, 206, 190, 212, 112, 95, 100, 56, + 43, 82, 159, 125, 168, 33, 190, 152, 112, 106, 164, 47, 59, 92, 19, 121, + 205, 226, 213, 137, 159, 38, 232, 26, 206, 139, 20, 103, 79, 106, 180, 47, + 55, 92, 22, 185, 206, 242, 212, 69, 159, 115, 40, 37, 222, 155, 24, 107, + 74, 175, 119, 60, 38, 145, 218, 236, 91, 13, 251, 69, 131, 115, 33, 229, + 216, 75, 26, 183, 75, 54, 183, 86, 246, 190, 198, 240, 82, 196, 61, 147, + 81, 173, 252, 125, 129, 225, 160, 72, 120, 54, 162, 150, 249, 174, 194, 252, + 81, 129, 252, 96, 65, 232, 48, 78, 148, 52, 111, 87, 108, 62, 173, 208, + 125, 156, 33, 169, 216, 126, 218, 160, 91, 56, 59, 82, 147, 125, 173, 225, + 189, 136, 113, 166, 164, 122, 251, 99, 3, 105, 193, 238, 208, 76, 92, 53, + 249, 215, 2, 222, 129, 152, 96, 106, 168, 47, 62, 156, 16, 105, 204, 46, + 213, 220, 95, 25, 248, 10, 194, 135, 17, 162, 140, 121, 165, 226, 251, 9, + 131, 70, 225, 242, 200, 69, 150, 179, 46, 245, 220, 71, 25, 242, 138, 197, + 167, 19, 58, 141, 211, 37, 157, 219, 41, 155, 94, 235, 120, 79, 98, 180, + 41, 183, 94, 246, 184, 70, 242, 178, 197, 181, 147, 55, 45, 214, 157, 158, + 233, 168, 78, 254, 180, 64, 119, 112, 38, 164, 26, 251, 75, 3, 119, 65, + 230, 176, 74, 244, 55, 7, 86, 130, 190, 225, 176, 72, 116, 54, 167, 86, + 250, 190, 195, 48, 81, 212, 60, 95, 81, 248, 60, 66, 145, 241, 172, 68, + 125, 243, 97, 133, 232, 99, 14, 169, 196, 126, 211, 96, 93, 232, 57, 142, + 146, 228, 109, 139, 109, 167, 109, 186, 173, 179, 61, 181, 209, 183, 28, 118, + 137, 230, 230, 202, 202, 215, 23, 30, 142, 136, 100, 102, 171, 106, 255, 111, + 0, 44, 0, 29, 192, 9, 144, 6, 236, 2, 205, 193, 149, 144, 111, 44, + 44, 29, 221, 201, 153, 150, 234, 238, 207, 12, 84, 5, 255, 67, 0, 49, + 192, 20, 80, 15, 124, 4, 33, 195, 88, 81, 250, 188, 67, 49, 241, 212, + 68, 95, 115, 120, 37, 226, 155, 9, 171, 70, 255, 114, 192, 37, 144, 27, + 44, 11, 93, 199, 121, 146, 162, 237, 185, 141, 178, 229, 181, 139, 55, 39, + 86, 154, 190, 235, 48, 79, 84, 52, 63, 87, 80, 62, 188, 16, 113, 204, + 36, 85, 219, 127, 27, 96, 11, 104, 7, 110, 130, 172, 97, 189, 232, 113, + 142, 164, 100, 123, 107, 99, 111, 105, 236, 46, 205, 220, 85, 153, 255, 42, + 192, 31, 16, 8, 12, 6, 133, 194, 227, 17, 137, 204, 102, 213, 234, 223, + 15, 24, 4, 10, 131, 71, 33, 242, 152, 69, 170, 179, 63, 53, 208, 23, + 28, 14, 137, 196, 102, 211, 106, 221, 239, 25, 140, 10, 229, 199, 11, 18, + 135, 77, 162, 181, 185, 183, 50, 246, 149, 134, 239, 34, 204, 25, 149, 202, + 239, 23, 12, 14, 133, 196, 99, 19, 105, 205, 238, 213, 140, 95, 37, 248, + 27, 2, 139, 65, 167, 112, 122, 164, 35, 59, 89, 211, 122, 221, 227, 25, + 137, 202, 230, 215, 10, 222, 135, 24, 98, 138, 169, 167, 62, 250, 144, 67, + 44, 49, 221, 212, 89, 159, 122, 232, 35, 14, 153, 196, 106, 211, 111, 29, + 236, 9, 141, 198, 229, 146, 203, 45, 151, 93, 174, 185, 188, 114, 241, 229, + 132, 75, 35, 119, 89, 230, 186, 202, 243, 23, 5, 206, 131, 20, 97, 207, + 104, 84, 46, 191, 92, 112, 57, 228, 18, 203, 77, 151, 117, 174, 167, 60, + 122, 145, 227, 44, 73, 221, 246, 217, 134, 218, 226, 219, 9, 155, 70, 235, + 114, 207, 101, 148, 43, 47, 95, 92, 56, 57, 210, 146, 221, 173, 153, 189, + 170, 241, 191, 4, 112, 3, 100, 1, 235, 64, 79, 112, 52, 36, 23, 91, + 78, 187, 116, 115, 103, 101, 234, 171, 15, 63, 68, 16, 51, 76, 21, 245, + 207, 7, 20, 2, 143, 65, 164, 48, 123, 84, 35, 127, 89, 224, 58, 200, + 19, 22, 141, 206, 229, 148, 75, 47, 119, 92, 38, 185, 218, 242, 219, 5, + 155, 67, 43, 113, 223, 100, 88, 43, 122, 159, 99, 40, 41, 222, 158, 216, + 104, 90, 174, 187, 60, 115, 81, 229, 252, 75, 1, 247, 64, 70, 176, 50, + 244, 21, 135, 79, 34, 180, 25, 183, 74, 246, 183, 6, 246, 130, 198, 225, + 146, 200, 109, 150, 173, 174, 253, 188, 65, 177, 240, 116, 68, 39, 115, 90, + 165, 251, 59, 3, 83, 65, 253, 240, 65, 132, 48, 99, 84, 41, 255, 94, + 192, 56, 80, 18, 188, 13, 177, 197, 180, 83, 55, 125, 214, 161, 158, 248, + 104, 66, 174, 177, 188, 116, 113, 231, 100, 74, 171, 119, 63, 102, 144, 42, + 236, 31, 13, 200, 5, 150, 131, 46, 225, 220, 72, 89, 246, 186, 198, 243, + 18, 197, 205, 147, 21, 173, 207, 61, 148, 17, 175, 76, 124, 53, 225, 215, + 8, 94, 134, 184, 98, 242, 169, 133, 190, 227, 48, 73, 212, 54, 223, 86, + 216, 62, 218, 144, 91, 44, 59, 93, 211, 121, 157, 226, 233, 137, 142, 230, + 228, 74, 203, 119, 23, 102, 142, 170, 228, 127, 11, 96, 7, 104, 2, 174, + 129, 188, 96, 113, 232, 36, 78, 155, 116, 107, 103, 111, 106, 172, 47, 61, + 220, 17, 153, 204, 106, 213, 239, 31, 12, 8, 5, 198, 131, 18, 225, 205, + 136, 85, 166, 191, 58, 240, 19, 4, 13, 195, 69, 145, 243, 44, 69, 221, + 243, 25, 133, 202, 227, 23, 9, 206, 134, 212, 98, 223, 105, 152, 46, 234, + 156, 79, 41, 244, 30, 199, 72, 82, 182, 189, 182, 241, 182, 196, 118, 211, + 102, 221, 234, 217, 143, 26, 228, 11, 11, 71, 71, 114, 178, 165, 181, 187, + 55, 51, 86, 149, 254, 239, 0, 76, 0, 53, 192, 23, 16, 14, 140, 4, + 101, 195, 107, 17, 239, 76, 76, 53, 245, 215, 7, 30, 130, 136, 97, 166, + 168, 122, 254, 163, 0, 121, 192, 34, 208, 25, 156, 10, 233, 199, 14, 210, + 132, 93, 163, 121, 185, 226, 242, 201, 133, 150, 227, 46, 201, 220, 86, 217, + 254, 218, 192, 91, 16, 59, 76, 19, 117, 205, 231, 21, 138, 143, 39, 36, + 26, 155, 75, 43, 119, 95, 102, 184, 42, 242, 159, 5, 168, 3, 62, 129, + 208, 96, 92, 40, 57, 222, 146, 216, 109, 154, 173, 171, 61, 191, 81, 176, + 60, 116, 17, 231, 76, 74, 181, 247, 55, 6, 150, 130, 238, 225, 140, 72, + 101, 246, 171, 6, 255, 66, 192, 49, 144, 20, 108, 15, 109, 196, 45, 147, + 93, 173, 249, 189, 130, 241, 161, 132, 120, 99, 98, 169, 233, 190, 206, 240, + 84, 68, 63, 115, 80, 37, 252, 27, 1, 203, 64, 87, 112, 62, 164, 16, + 123, 76, 35, 117, 217, 231, 26, 202, 139, 23, 39, 78, 154, 180, 107, 55, + 111, 86, 172, 62, 253, 208, 65, 156, 48, 105, 212, 46, 223, 92, 88, 57, + 250, 146, 195, 45, 145, 221, 172, 89, 189, 250, 241, 131, 4, 97, 195, 104, + 81, 238, 188, 76, 113, 245, 228, 71, 11, 114, 135, 101, 162, 171, 57, 191, + 82, 240, 61, 132, 17, 163, 76, 121, 245, 226, 199, 9, 146, 134, 237, 162, + 205, 185, 149, 178, 239, 53, 140, 23, 37, 206, 155, 20, 107, 79, 111, 116, + 44, 39, 93, 218, 185, 155, 50, 235, 85, 143, 127, 36, 32, 27, 88, 11, + 122, 135, 99, 34, 169, 217, 190, 218, 240, 91, 4, 59, 67, 83, 113, 253, + 228, 65, 139, 112, 103, 100, 42, 171, 95, 63, 120, 16, 34, 140, 25, 165, + 202, 251, 23, 3, 78, 129, 244, 96, 71, 104, 50, 174, 149, 188, 111, 49, + 236, 20, 77, 207, 117, 148, 39, 47, 90, 156, 59, 41, 211, 94, 221, 248, + 89, 130, 186, 225, 179, 8, 117, 198, 167, 18, 250, 141, 131, 37, 161, 219, + 56, 91, 82, 187, 125, 179, 97, 181, 232, 119, 14, 166, 132, 122, 227, 99, + 9, 233, 198, 206, 210, 212, 93, 159, 121, 168, 34, 254, 153, 128, 106, 224, + 47, 8, 28, 6, 137, 194, 230, 209, 138, 220, 103, 25, 234, 138, 207, 39, + 20, 26, 143, 75, 36, 55, 91, 86, 187, 126, 243, 96, 69, 232, 51, 14, + 149, 196, 111, 19, 108, 13, 237, 197, 141, 147, 37, 173, 219, 61, 155, 81, + 171, 124, 127, 97, 224, 40, 72, 30, 182, 136, 118, 230, 166, 202, 250, 215, + 3, 30, 129, 200, 96, 86, 168, 62, 254, 144, 64, 108, 48, 45, 212, 29, + 159, 73, 168, 54, 254, 150, 192, 110, 208, 44, 92, 29, 249, 201, 130, 214, + 225, 158, 200, 104, 86, 174, 190, 252, 112, 65, 228, 48, 75, 84, 55, 127, + 86, 160, 62, 248, 16, 66, 140, 49, 165, 212, 123, 31, 99, 72, 41, 246, + 158, 198, 232, 82, 206, 189, 148, 113, 175, 100, 124, 43, 97, 223, 104, 88, + 46, 186, 156, 115, 41, 229, 222, 203, 24, 87, 74, 190, 183, 48, 118, 148, + 38, 239, 90, 204, 59, 21, 211, 79, 29, 244, 9, 135, 70, 226, 178, 201, + 181, 150, 247, 46, 198, 156, 82, 233, 253, 142, 193, 164, 80, 123, 124, 35, + 97, 217, 232, 90, 206, 187, 20, 115, 79, 101, 244, 43, 7, 95, 66, 184, + 49, 178, 148, 117, 175, 103, 60, 42, 145, 223, 44, 88, 29, 250, 137, 131, + 38, 225, 218, 200, 91, 22, 187, 78, 243, 116, 69, 231, 115, 10, 165, 199, + 59, 18, 147, 77, 173, 245, 189, 135, 49, 162, 148, 121, 175, 98, 252, 41, + 129, 222, 224, 88, 72, 58, 182, 147, 54, 237, 214, 205, 158, 213, 168, 95, + 62, 184, 16, 114, 140, 37, 165, 219, 59, 27, 83, 75, 125, 247, 97, 134, + 168, 98, 254, 169, 128, 126, 224, 32, 72, 24, 54, 138, 150, 231, 46, 202, + 156, 87, 41, 254, 158, 192, 104, 80, 46, 188, 28, 113, 201, 228, 86, 203, + 126, 215, 96, 94, 168, 56, 126, 146, 160, 109, 184, 45, 178, 157, 181, 169, + 183, 62, 246, 144, 70, 236, 50, 205, 213, 149, 159, 47, 40, 28, 30, 137, + 200, 102, 214, 170, 222, 255, 24, 64, 10, 176, 7, 52, 2, 151, 65, 174, + 176, 124, 116, 33, 231, 88, 74, 186, 183, 51, 54, 149, 214, 239, 30, 204, + 8, 85, 198, 191, 18, 240, 13, 132, 5, 163, 67, 57, 241, 210, 196, 93, + 147, 121, 173, 226, 253, 137, 129, 166, 224, 122, 200, 35, 22, 153, 206, 234, + 212, 79, 31, 116, 8, 39, 70, 154, 178, 235, 53, 143, 87, 36, 62, 155, + 80, 107, 124, 47, 97, 220, 40, 89, 222, 186, 216, 115, 26, 165, 203, 59, + 23, 83, 78, 189, 244, 113, 135, 100, 98, 171, 105, 191, 110, 240, 44, 68, + 29, 243, 73, 133, 246, 227, 6, 201, 194, 214, 209, 158, 220, 104, 89, 238, + 186, 204, 115, 21, 229, 207, 11, 20, 7, 79, 66, 180, 49, 183, 84, 118, + 191, 102, 240, 42, 196, 31, 19, 72, 13, 246, 133, 134, 227, 34, 201, 217, + 150, 218, 238, 219, 12, 91, 69, 251, 115, 3, 101, 193, 235, 16, 79, 76, + 52, 53, 215, 87, 30, 190, 136, 112, 102, 164, 42, 251, 95, 3, 120, 1, + 226, 128, 73, 160, 54, 248, 22, 194, 142, 209, 164, 92, 123, 121, 227, 98, + 201, 233, 150, 206, 238, 212, 76, 95, 117, 248, 39, 2, 154, 129, 171, 32, + 127, 88, 32, 58, 152, 19, 42, 141, 223, 37, 152, 27, 42, 139, 95, 39, + 120, 26, 162, 139, 57, 167, 82, 250, 189, 131, 49, 161, 212, 120, 95, 98, + 184, 41, 178, 158, 245, 168, 71, 62, 178, 144, 117, 172, 39, 61, 218, 145, + 155, 44, 107, 93, 239, 121, 140, 34, 229, 217, 139, 26, 231, 75, 10, 183, + 71, 54, 178, 150, 245, 174, 199, 60, 82, 145, 253, 172, 65, 189, 240, 113, + 132, 36, 99, 91, 105, 251, 110, 195, 108, 81, 237, 252, 77, 129, 245, 160, + 71, 56, 50, 146, 149, 173, 175, 61, 188, 17, 177, 204, 116, 85, 231, 127, + 10, 160, 7, 56, 2, 146, 129, 173, 160, 125, 184, 33, 178, 152, 117, 170, + 167, 63, 58, 144, 19, 44, 13, 221, 197, 153, 147, 42, 237, 223, 13, 152, + 5, 170, 131, 63, 33, 208, 24, 92, 10, 185, 199, 50, 210, 149, 157, 175, + 41, 188, 30, 241, 200, 68, 86, 179, 126, 245, 224, 71, 8, 50, 134, 149, + 162, 239, 57, 140, 18, 229, 205, 139, 21, 167, 79, 58, 180, 19, 55, 77, + 214, 181, 158, 247, 40, 70, 158, 178, 232, 117, 142, 167, 36, 122, 155, 99, + 43, 105, 223, 110, 216, 44, 90, 157, 251, 41, 131, 94, 225, 248, 72, 66, + 182, 177, 182, 244, 118, 199, 102, 210, 170, 221, 191, 25, 176, 10, 244, 7, + 7, 66, 130, 177, 161, 180, 120, 119, 98, 166, 169, 186, 254, 243, 0, 69, + 192, 51, 16, 21, 204, 15, 21, 196, 15, 19, 68, 13, 243, 69, 133, 243, + 35, 5, 217, 195, 26, 209, 203, 28, 87, 73, 254, 182, 192, 118, 208, 38, + 220, 26, 217, 203, 26, 215, 75, 30, 183, 72, 118, 182, 166, 246, 250, 198, + 195, 18, 209, 205, 156, 85, 169, 255, 62, 192, 16, 80, 12, 60, 5, 209, + 195, 28, 81, 201, 252, 86, 193, 254, 208, 64, 92, 48, 57, 212, 18, 223, + 77, 152, 53, 170, 151, 63, 46, 144, 28, 108, 9, 237, 198, 205, 146, 213, + 173, 159, 61, 168, 17, 190, 140, 112, 101, 228, 43, 11, 95, 71, 120, 50, + 162, 149, 185, 175, 50, 252, 21, 129, 207, 32, 84, 24, 63, 74, 144, 55, + 44, 22, 157, 206, 233, 148, 78, 239, 116, 76, 39, 117, 218, 167, 27, 58, + 139, 83, 39, 125, 218, 161, 155, 56, 107, 82, 175, 125, 188, 33, 177, 216, + 116, 90, 167, 123, 58, 163, 83, 57, 253, 210, 193, 157, 144, 105, 172, 46, + 253, 220, 65, 153, 240, 106, 196, 47, 19, 92, 13, 249, 197, 130, 211, 33, + 157, 216, 105, 154, 174, 235, 60, 79, 81, 244, 60, 71, 81, 242, 188, 69, + 177, 243, 52, 69, 215, 115, 30, 165, 200, 123, 22, 163, 78, 249, 244, 66, + 199, 113, 146, 164, 109, 187, 109, 179, 109, 181, 237, 183, 13, 182, 133, 182, + 227, 54, 201, 214, 214, 222, 222, 216, 88, 90, 186, 187, 51, 51, 255, 63 ) + +random_mask_vec8 = Numeric.array(random_mask_tuple, Numeric.UnsignedInt8) + diff --git a/gnuradio-core/src/utils/gr_plot_const.py b/gnuradio-core/src/utils/gr_plot_const.py new file mode 100755 index 00000000..7e03db1c --- /dev/null +++ b/gnuradio-core/src/utils/gr_plot_const.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 pylab, math +from pylab import * +import struct, sys +from optparse import OptionParser + +import gr_read_binary + +class zoom: + def __init__(self, xdata, reals, imags, sp_iq, sp_const, plot_const, manager): + self.sp_iq = sp_iq + self.sp_const = sp_const + self.xaxis = xdata + self.reals = reals + self.imags = imags + self.plot_const = plot_const + self.manager = manager + + self.xlim = self.sp_iq.get_xlim() + + def __call__(self, event): + newxlim = self.sp_iq.get_xlim() + + if(newxlim != self.xlim): + self.xlim = newxlim + r = self.reals[int(self.xlim[0]) : int(self.xlim[1])] + i = self.imags[int(self.xlim[0]) : int(self.xlim[1])] + + self.plot_const[0].set_data(r, i) + self.sp_const.axis([-2, 2, -2, 2]) + self.manager.canvas.draw() + +def main(): + usage="%prog: [options] output_filename" + parser = OptionParser(conflict_handler="resolve", usage=usage) + parser.add_option("-s", "--size", type="int", default=None, + help="Specify the number of points to plot [default=%default]") + parser.add_option("", "--skip", type="int", default=None, + help="Specify the number of points to skip [default=%default]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + iq = gr_read_binary.read_complex_binary(filename) + + if(options.skip is None): + options.skip = 0 + + if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): + options.size = len(iq[0]) - options.skip + + reals = iq[0][options.skip : options.skip + options.size] + imags = iq[1][options.skip : options.skip + options.size] + x = range(options.skip, options.skip + options.size) + + # PLOT + f = figure(1, figsize=(16, 12), facecolor='w') + rcParams['xtick.labelsize'] = 16 + rcParams['ytick.labelsize'] = 16 + + # Subplot for real and imaginary parts of signal + sp1 = f.add_subplot(2,1,1) + sp1.set_title(("I&Q"), fontsize=26, fontweight="bold") + sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") + sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") + plot(x, reals, 'bo-', x, imags, 'ro-') + + # Subplot for constellation plot + sp2 = f.add_subplot(2,1,2) + sp2.set_title(("Constellation"), fontsize=26, fontweight="bold") + sp2.set_xlabel("Inphase", fontsize=20, fontweight="bold") + sp2.set_ylabel("Qaudrature", fontsize=20, fontweight="bold") + p2 = plot(reals, imags, 'bo') + sp2.axis([-2, 2, -2, 2]) + + manager = get_current_fig_manager() + zm = zoom(x, reals, imags, sp1, sp2, p2, manager) + connect('draw_event', zm) + + show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + + + diff --git a/gnuradio-core/src/utils/gr_plot_float.py b/gnuradio-core/src/utils/gr_plot_float.py new file mode 100755 index 00000000..12e0c280 --- /dev/null +++ b/gnuradio-core/src/utils/gr_plot_float.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 pylab, math +from pylab import * +import struct, sys +from optparse import OptionParser + +import gr_read_binary + +def main(): + usage="%prog: [options] output_filename" + parser = OptionParser(conflict_handler="resolve", usage=usage) + parser.add_option("-s", "--size", type="int", default=None, + help="Specify the number of points to plot [default=%default]") + parser.add_option("", "--skip", type="int", default=None, + help="Specify the number of points to skip [default=%default]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + fl = gr_read_binary.read_float_binary(filename) + + if(options.skip is None): + options.skip = 0 + + if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): + options.size = len(fl) - options.skip + + x = range(options.skip, options.skip + options.size) + + # PLOT REAL AND IMAGINARY PARTS + + f = figure(1, figsize=(16, 12), facecolor='w') + rcParams['xtick.labelsize'] = 16 + rcParams['ytick.labelsize'] = 16 + + sp1 = f.add_subplot(1,1,1) + sp1.set_title(("GNU Radio Float"), fontsize=26, fontweight="bold") + sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") + sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") + plot(x, fl, 'bo-') + + show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + + + diff --git a/gnuradio-core/src/utils/gr_plot_iq.py b/gnuradio-core/src/utils/gr_plot_iq.py new file mode 100755 index 00000000..259b3fb3 --- /dev/null +++ b/gnuradio-core/src/utils/gr_plot_iq.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 pylab, math +from pylab import * +import struct, sys +from optparse import OptionParser + +import gr_read_binary + +def main(): + usage="%prog: [options] output_filename" + parser = OptionParser(conflict_handler="resolve", usage=usage) + parser.add_option("-s", "--size", type="int", default=None, + help="Specify the number of points to plot [default=%default]") + parser.add_option("", "--skip", type="int", default=None, + help="Specify the number of points to skip [default=%default]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + iq = gr_read_binary.read_complex_binary(filename) + + if(options.skip is None): + options.skip = 0 + + if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): + options.size = len(iq[0]) - options.skip + + reals = iq[0][options.skip : options.skip + options.size] + imags = iq[1][options.skip : options.skip + options.size] + x = range(options.skip, options.skip + options.size) + + # PLOT REAL AND IMAGINARY PARTS + + f = figure(1, figsize=(16, 12), facecolor='w') + rcParams['xtick.labelsize'] = 16 + rcParams['ytick.labelsize'] = 16 + + sp1 = f.add_subplot(1,1,1) + sp1.set_title(("I&Q"), fontsize=26, fontweight="bold") + sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") + sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") + plot(x, reals, 'bo-', x, imags, 'ro-') + + show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + + + diff --git a/gnuradio-core/src/utils/gr_read_binary.py b/gnuradio-core/src/utils/gr_read_binary.py new file mode 100644 index 00000000..4216b4eb --- /dev/null +++ b/gnuradio-core/src/utils/gr_read_binary.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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 struct + +def read_binary(filename, type): + n = struct.calcsize(type) + f = open(filename, 'rb') + out = list() + lin = f.read(n) + while(len(lin) == n): + cp = struct.unpack(type, lin) + out.append(cp) + lin = f.read(n) + return out + +def read_char_binary(filename): + return read_binary(filename, 'c') + +def read_float_binary(filename): + return read_binary(filename, 'f') + +def read_int_binary(filename): + return read_binary(filename, 'i') + +def read_short_binary(filename): + return read_binary(filename, 'h') + +def read_complex_binary(filename): + n = struct.calcsize('ff') + f = open(filename, 'rb') + re = list() + im = list() + lin = f.read(n) + while(len(lin) == n): + cp = struct.unpack('ff', lin) + re.append(cp[0]) + im.append(cp[1]) + lin = f.read(n) + return (re, im) + + diff --git a/gnuradio-examples/Makefile.am b/gnuradio-examples/Makefile.am index ad8ca5b1..d0e388e9 100644 --- a/gnuradio-examples/Makefile.am +++ b/gnuradio-examples/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004 Free Software Foundation, Inc. +# Copyright 2004,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am index 0ebffb64..e3aca7ef 100644 --- a/gnuradio-examples/python/Makefile.am +++ b/gnuradio-examples/python/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004 Free Software Foundation, Inc. +# Copyright 2004,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,4 +20,4 @@ # SUBDIRS = apps audio channel-coding digital_voice digital multi-antenna \ - multi_usrp networking usrp hier + multi_usrp networking usrp hier ofdm diff --git a/gnuradio-examples/python/digital/benchmark_loopback.py b/gnuradio-examples/python/digital/benchmark_loopback.py index d036f63a..2b1e965f 100755 --- a/gnuradio-examples/python/digital/benchmark_loopback.py +++ b/gnuradio-examples/python/digital/benchmark_loopback.py @@ -1,7 +1,6 @@ #!/usr/bin/env python -#!/usr/bin/env python # -# Copyright 2005, 2006 Free Software Foundation, Inc. +# Copyright 2005, 2006, 2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -77,10 +76,23 @@ class my_graph(gr.flow_graph): self.rxpath = receive_path(self, demod_class, rx_callback, options) if channelon: - self.channel = awgn_channel(self, options.sample_rate, noise_voltage, frequency_offset, options.seed) + self.channel = awgn_channel(self, options.sample_rate, noise_voltage, + frequency_offset, options.seed) + + if options.discontinuous: + z = 20000*[0,] + self.zeros = gr.vector_source_c(z, True) + packet_size = 5*((4+8+4+1500+4) * 8) + self.mux = gr.stream_mux(gr.sizeof_gr_complex, [packet_size-0, int(9e5)]) + + # Connect components + self.connect(self.txpath, (self.mux,0)) + self.connect(self.zeros, (self.mux,1)) + self.connect(self.mux, self.channel, self.rxpath) + + else: + self.connect(self.txpath, self.channel, self.rxpath) - # Connect components - self.connect(self.txpath, self.throttle, self.channel, self.rxpath) else: # Connect components self.connect(self.txpath, self.throttle, self.rxpath) @@ -106,6 +118,7 @@ def main(): print "ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( ok, pktno, n_rcvd, n_right) + # print payload[2:len(payload)] def send_pkt(payload='', eof=False): return fg.txpath.send_pkt(payload, eof) @@ -170,8 +183,6 @@ def main(): while n < nbytes: send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) n += pkt_size - if options.discontinuous and pktno % 5 == 4: - time.sleep(1) pktno += 1 send_pkt(eof=True) diff --git a/gnuradio-examples/python/ofdm/Makefile.am b/gnuradio-examples/python/ofdm/Makefile.am new file mode 100644 index 00000000..23df3f9d --- /dev/null +++ b/gnuradio-examples/python/ofdm/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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. +# + +EXTRA_DIST = \ + benchmark_ofdm.py \ + benchmark_ofdm_rx.py \ + benchmark_ofdm_tx.py \ + fftshift.py \ + fusb_options.py \ + ofdm.py \ + ofdm_receiver.py \ + pick_bitrate.py \ + receive_path.py \ + transmit_path.py diff --git a/gnuradio-examples/python/ofdm/benchmark_ofdm.py b/gnuradio-examples/python/ofdm/benchmark_ofdm.py new file mode 100755 index 00000000..3b4761d5 --- /dev/null +++ b/gnuradio-examples/python/ofdm/benchmark_ofdm.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# +# Copyright 2005, 2006 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 2, 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, gru, modulation_utils +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys, math, os + +# from current dir +from transmit_path import transmit_path +from receive_path import receive_path +import ofdm + +class awgn_channel(gr.hier_block): + def __init__(self, fg, sample_rate, noise_voltage, frequency_offset): + + self.input = gr.add_const_cc(0) + + self.noise_adder = gr.add_cc() + self.noise = gr.noise_source_c(gr.GR_GAUSSIAN,noise_voltage) + self.offset = gr.sig_source_c(1, gr.GR_SIN_WAVE, frequency_offset, 1.0, 0.0) + self.mixer_offset = gr.multiply_cc() + + fg.connect(self.input, (self.mixer_offset,0)) + fg.connect(self.offset,(self.mixer_offset,1)) + fg.connect(self.mixer_offset, (self.noise_adder,1)) + fg.connect(self.noise, (self.noise_adder,0)) + + gr.hier_block.__init__(self, fg, self.input, self.noise_adder) + +class multipath_channel(gr.hier_block): + def __init__(self, fg): + + self.taps = [1.0, .2, 0.0, .1, .08, -.4, .12, -.2, 0, 0, 0, .3] + self.chan = gr.fir_filter_ccc(1, self.taps) + + gr.hier_block.__init__(self, fg, self.chan, self.chan) + +class my_graph(gr.flow_graph): + def __init__(self, callback, options): + gr.flow_graph.__init__(self) + + channel_on = True + + SNR = 10.0**(options.snr/10.0) + frequency_offset = options.frequency_offset / options.fft_length + + power_in_signal = options.occupied_tones + noise_power_in_channel = power_in_signal/SNR + noise_power_required = noise_power_in_channel * options.fft_length / options.occupied_tones + noise_voltage = math.sqrt(noise_power_required) + + self.txpath = transmit_path(self, options) + self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate) + self.rxpath = receive_path(self, callback, options) + + if channel_on: + self.channel = awgn_channel(self, options.sample_rate, noise_voltage, frequency_offset) + self.multipath = multipath_channel(self) + + if options.discontinuous: + z = 20000*[0,] + self.zeros = gr.vector_source_c(z, True) + packet_size = 15*((4+8+4+1500+4) * 8) + self.mux = gr.stream_mux(gr.sizeof_gr_complex, [packet_size-0, int(10e5)]) + + # Connect components + self.connect(self.txpath, (self.mux,0)) + self.connect(self.zeros, (self.mux,1)) + self.connect(self.mux, self.throttle, self.channel, self.rxpath) + self.connect(self.mux, gr.file_sink(gr.sizeof_gr_complex, "tx_ofdm.dat")) + + else: + #self.connect(self.txpath, self.throttle, self.multipath, self.channel) + self.connect(self.txpath, self.throttle, self.channel) + self.connect(self.channel, self.rxpath) + self.connect(self.txpath, gr.file_sink(gr.sizeof_gr_complex, "tx_ofdm.dat")) + + else: + self.connect(self.txpath, self.throttle, self.rxpath) + self.connect(self.txpath, gr.file_sink(gr.sizeof_gr_complex, "tx")) + self.connect(self.rxpath.ofdm_demod.ofdm_rx, gr.file_sink(options.fft_length*gr.sizeof_gr_complex, "rx")) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + global n_rcvd, n_right + n_rcvd += 1 + (pktno,) = struct.unpack('!H', payload[0:2]) + if ok: + n_right += 1 + print "ok: %r \t pktno: %d \t n_rcvd: %d \t n_right: %d" % (ok, pktno, n_rcvd, n_right) + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + parser.add_option("-s", "--size", type="eng_float", default=1450, + help="set packet size [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1e5, + help="set sample rate to RATE (%default)") + parser.add_option("", "--snr", type="eng_float", default=30, + help="set the SNR of the channel in dB [default=%default]") + parser.add_option("", "--frequency-offset", type="eng_float", default=0, + help="set frequency offset introduced by channel [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + + transmit_path.add_options(parser, expert_grp) + receive_path.add_options(parser, expert_grp) + ofdm.ofdm_mod.add_options(parser, expert_grp) + ofdm.ofdm_demod.add_options(parser, expert_grp) + + (options, args) = parser.parse_args () + + if(options.mtu < options.size): + sys.stderr.write("MTU (%.0f) must be larger than the packet size (%.0f)\n" + % (options.mtu, options.size)) + sys.exit(1) + + # build the graph + fg = my_graph(rx_callback, options) + + r = gr.enable_realtime_scheduling() + # if r != gr.RT_OK: + # print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + pkt_size = int(options.size) + + + + while n < nbytes: + r = ''.join([chr(random.randint(0,255)) for i in range(pkt_size-2)]) + #pkt_contents = struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff) + pkt_contents = struct.pack('!H', pktno) + r + send_pkt(pkt_contents) + n += pkt_size + #sys.stderr.write('.') + #if options.discontinuous and pktno % 5 == 4: + # time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass + + diff --git a/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py b/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py new file mode 100755 index 00000000..f8ebb820 --- /dev/null +++ b/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# +# Copyright 2005, 2006 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 2, 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, gru, modulation_utils +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys, math + +# from current dir +from receive_path import receive_path +import ofdm, fusb_options + +class usrp_graph(gr.flow_graph): + def __init__(self, callback, options): + gr.flow_graph.__init__(self) + + self._rx_freq = options.rx_freq # receiver's center frequency + self._rx_gain = options.rx_gain # receiver's gain + self._rx_subdev_spec = options.rx_subdev_spec # daughterboard to use + self._decim = options.decim # Decimating rate for the USRP (prelim) + self._fusb_block_size = options.fusb_block_size # usb info for USRP + self._fusb_nblocks = options.fusb_nblocks # usb info for USRP + + if self._rx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n") + raise SystemExit + + # Set up USRP source + self._setup_usrp_source() + ok = self.set_freq(self._rx_freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(self._rx_freq)) + raise ValueError, eng_notation.num_to_str(self._rx_freq) + g = self.subdev.gain_range() + if options.show_rx_gain_range: + print "Rx Gain Range: minimum = %g, maximum = %g, step size = %g" \ + % (g[0], g[1], g[2]) + self.set_gain(options.rx_gain) + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + # Set up receive path + self.rxpath = receive_path(self, callback, options) + + self.connect(self.u, self.rxpath) + + def _setup_usrp_source(self): + self.u = usrp.source_c (fusb_block_size=self._fusb_block_size, + fusb_nblocks=self._fusb_nblocks) + adc_rate = self.u.adc_rate() + + self.u.set_decim_rate(self._decim) + + # determine the daughterboard subdevice we're using + if self._rx_subdev_spec is None: + self._rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, self._rx_subdev_spec) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, self._rx_subdev_spec)) + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + """ + Sets the analog gain in the USRP + """ + if gain is None: + r = self.subdev.gain_range() + gain = (r[0] + r[1])/2 # set gain to midpoint + self.gain = gain + return self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def decim(self): + return self._decim + + def add_options(normal, expert): + """ + Adds usrp-specific options to the Options Parser + """ + add_freq_option(normal) + if not normal.has_option("--bitrate"): + normal.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. samples-per-symbol and interp/decim will be derived.") + normal.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + normal.add_option("", "--rx-gain", type="eng_float", default=None, metavar="GAIN", + help="set receiver gain in dB [default=midpoint]. See also --show-rx-gain-range") + normal.add_option("", "--show-rx-gain-range", action="store_true", default=False, + help="print min and max Rx gain available on selected daughterboard") + normal.add_option("-v", "--verbose", action="store_true", default=False) + + expert.add_option("-S", "--samples-per-symbol", type="int", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--rx-freq", type="eng_float", default=None, + help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") + expert.add_option("-d", "--decim", type="intx", default=32, + help="set fpga decimation rate to DECIM [default=%default]") + expert.add_option("", "--snr", type="eng_float", default=30, + help="set the SNR of the channel in dB [default=%default]") + + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + n_rcvd += 1 + (pktno,) = struct.unpack('!H', payload[0:2]) + if ok: + n_right += 1 + print "ok: %r \t pktno: %d \t n_rcvd: %d \t n_right: %d" % (ok, pktno, n_rcvd, n_right) + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1e5, + help="set sample rate to RATE (%default)") + + usrp_graph.add_options(parser, expert_grp) + receive_path.add_options(parser, expert_grp) + ofdm.ofdm_mod.add_options(parser, expert_grp) + fusb_options.add_options(expert_grp) + + (options, args) = parser.parse_args () + + # build the graph + fg = usrp_graph(rx_callback, options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py b/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py new file mode 100755 index 00000000..bda63805 --- /dev/null +++ b/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python +# +# Copyright 2005, 2006 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 2, 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, gru, modulation_utils +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys, math + +# from current dir +from transmit_path import transmit_path +from pick_bitrate import pick_tx_bitrate +import ofdm, fusb_options + +class usrp_graph(gr.flow_graph): + def __init__(self, options): + gr.flow_graph.__init__(self) + + self._tx_freq = options.tx_freq # tranmitter's center frequency + self._tx_subdev_spec = options.tx_subdev_spec # daughterboard to use + self._bitrate = options.bitrate # desired bit rate + self._interp = options.interp # interpolating rate for the USRP (prelim) + self._fusb_block_size = options.fusb_block_size # usb info for USRP + self._fusb_nblocks = options.fusb_nblocks # usb info for USRP + + if self._tx_freq is None: + sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n") + raise SystemExit + + # Set up USRP sink; also adjusts interp, and bitrate + self._setup_usrp_sink() + + # copy the final answers back into options for use by modulator + #options.bitrate = self._bitrate + + self.txpath = transmit_path(self, options) + + self.connect(self.txpath, self.u) + + def _setup_usrp_sink(self): + """ + Creates a USRP sink, determines the settings for best bitrate, + and attaches to the transmitter's subdevice. + """ + self.u = usrp.sink_c(fusb_block_size=self._fusb_block_size, + fusb_nblocks=self._fusb_nblocks) + + self.u.set_interp_rate(self._interp) + + # determine the daughterboard subdevice we're using + if self._tx_subdev_spec is None: + self._tx_subdev_spec = usrp.pick_tx_subdevice(self.u) + self.u.set_mux(usrp.determine_tx_mux_value(self.u, self._tx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, self._tx_subdev_spec) + + # Set center frequency of USRP + ok = self.set_freq(self._tx_freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(self._tx_freq),) + raise ValueError + + # Set the USRP for maximum transmit gain + # (Note that on the RFX cards this is a nop.) + self.set_gain(self.subdev.gain_range()[0]) + + # enable Auto Transmit/Receive switching + self.set_auto_tr(True) + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + """ + Sets the analog gain in the USRP + """ + self.gain = gain + self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + """ + Turns on auto transmit/receive of USRP daughterboard (if exits; else ignored) + """ + return self.subdev.set_auto_tr(enable) + + def interp(self): + return self._interp + + def add_options(normal, expert): + """ + Adds usrp-specific options to the Options Parser + """ + add_freq_option(normal) + if not normal.has_option('--bitrate'): + normal.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. samples-per-symbol and interp/decim will be derived.") + normal.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + normal.add_option("-v", "--verbose", action="store_true", default=False) + + expert.add_option("-S", "--samples-per-symbol", type="int", default=None, + help="set samples/symbol [default=%default]") + expert.add_option("", "--tx-freq", type="eng_float", default=None, + help="set transmit frequency to FREQ [default=%default]", metavar="FREQ") + expert.add_option("-i", "--interp", type="intx", default=64, + help="set fpga interpolation rate to INTERP [default=%default]") + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the transmit path + """ + print "Using TX d'board %s" % (self.subdev.side_and_name(),) + print "modulation: %s" % (self._modulator_class.__name__) + print "interp: %3d" % (self._interp) + print "Tx Frequency: %s" % (eng_notation.num_to_str(self._tx_freq)) + + +def add_freq_option(parser): + """ + Hackery that has the -f / --freq option set both tx_freq and rx_freq + """ + def freq_callback(option, opt_str, value, parser): + parser.values.rx_freq = value + parser.values.tx_freq = value + + if not parser.has_option('--freq'): + parser.add_option('-f', '--freq', type="eng_float", + action="callback", callback=freq_callback, + help="set Tx and/or Rx frequency to FREQ [default=%default]", + metavar="FREQ") + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert_grp = parser.add_option_group("Expert") + parser.add_option("-s", "--size", type="eng_float", default=1450, + help="set packet size [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("-r", "--sample-rate", type="eng_float", default=1e5, + help="set sample rate to RATE (%default)") + + usrp_graph.add_options(parser, expert_grp) + transmit_path.add_options(parser, expert_grp) + ofdm.ofdm_mod.add_options(parser, expert_grp) + fusb_options.add_options(expert_grp) + + (options, args) = parser.parse_args () + + if(options.mtu < options.size): + sys.stderr.write("MTU (%.0f) must be larger than the packet size (%.0f)\n" + % (options.mtu, options.size)) + sys.exit(1) + + # build the graph + fg = usrp_graph(options) + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + pkt_size = int(options.size) + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + #if options.discontinuous and pktno % 5 == 4: + # time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/ofdm/fftshift.py b/gnuradio-examples/python/ofdm/fftshift.py new file mode 100755 index 00000000..6b355326 --- /dev/null +++ b/gnuradio-examples/python/ofdm/fftshift.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +from gnuradio import gr + +class my_graph(gr.flow_graph): + def __init__(self): + gr.flow_graph.__init__(self) + + length = 101 + + data_r = range(length) + data_i = range(length,2*length) + src_r = gr.vector_source_s(data_r, False) + src_i = gr.vector_source_s(data_i, False) + s2f_r = gr.short_to_float() + s2f_i = gr.short_to_float() + f2c = gr.float_to_complex() + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, length) + + shift = True + ifft = gr.fft_vcc(length, False, [], shift) + fft = gr.fft_vcc(length, True, [], shift) + + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, length) + snk_in = gr.file_sink(gr.sizeof_gr_complex, "fftshift.in") + snk_out = gr.file_sink(gr.sizeof_gr_complex, "fftshift.out") + + self.connect(src_r, s2f_r, (f2c,0)) + self.connect(src_i, s2f_i, (f2c,1)) + self.connect(f2c, snk_in) + self.connect(f2c, s2v, ifft, fft, v2s, snk_out) + + +def main(): + fg = my_graph() + fg.start() + fg.wait() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-examples/python/ofdm/fusb_options.py b/gnuradio-examples/python/ofdm/fusb_options.py new file mode 100644 index 00000000..cdb15d72 --- /dev/null +++ b/gnuradio-examples/python/ofdm/fusb_options.py @@ -0,0 +1,31 @@ +# +# Copyright 2006 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 2, 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. +# + +def add_options(parser): + """ + Add Fast USB specifc options to command line parser. + + @param parser: instance of OptionParser + """ + parser.add_option("-B", "--fusb-block-size", type="int", default=0, + help="specify fast usb block size [default=%default]") + parser.add_option("-N", "--fusb-nblocks", type="int", default=0, + help="specify number of fast usb blocks [default=%default]") diff --git a/gnuradio-examples/python/ofdm/ofdm.py b/gnuradio-examples/python/ofdm/ofdm.py new file mode 100644 index 00000000..8b1e616f --- /dev/null +++ b/gnuradio-examples/python/ofdm/ofdm.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2006 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 2, 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 +from optparse import OptionParser +from ofdm_receiver import ofdm_receiver + +class ofdm_mod(gr.hier_block): + def __init__(self, fg, options): + self.fg = fg + self._occupied_tones = options.occupied_tones + self._fft_length = options.fft_length + self._cp_length = options.cp_length + self._mtu = options.mtu + + symbol_length = self._fft_length + self._cp_length + + if self._fft_length < self._occupied_tones: + sys.stderr.write("occupied tones must be less than FFT length\n") + raise SystemExit + if self._fft_length < self._cp_length: + sys.stderr.write("cyclic prefix length must be less than FFT length\n") + raise SystemExit + + win = [] #[1 for i in range(self._fft_length)] + + # hard-coded known symbol + #ks = self._occupied_tones*[1,] + ks1 = known_symbols_200_1 + ks2 = known_symbols_200_2 + + self.ofdm = gr.ofdm_bpsk_mapper(self._mtu, self._occupied_tones, self._fft_length, ks1, ks2) + self.ifft = gr.fft_vcc(self._fft_length, False, win, True) + self.cp_adder = gr.ofdm_cyclic_prefixer(self._fft_length, symbol_length) + + if options.verbose: + self._print_verbage() + + self.fg.connect(self.ofdm, self.ifft, self.cp_adder) + gr.hier_block.__init__(self, self.fg, self.ofdm, self.cp_adder) + + def samples_per_symbol(self): + return 2 + + def mtu(self): + return self._mtu + + def bits_per_symbol(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM + + def add_options(normal, expert): + """ + Adds OFDM-specific options to the Options Parser + """ + expert.add_option("", "--mtu", type="int", default=1500, + help="set maximum transmit unit [default=%default]") + expert.add_option("", "--fft-length", type="intx", default=512, + help="set the number of FFT bins [default=%default]") + expert.add_option("", "--occupied-tones", type="intx", default=200, + help="set the number of occupied FFT bins [default=%default]") + expert.add_option("", "--cp-length", type="intx", default=128, + help="set the number of bits in the cyclic prefix [default=%default]") + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the OFDM modulator + """ + print "\nOFDM Modulator:" + print "FFT length: %3d" % (self._fft_length) + print "Occupied Tones: %3d" % (self._occupied_tones) + print "CP length: %3d" % (self._cp_length) + + +class ofdm_demod(gr.hier_block): + def __init__(self, fg, options): + self.fg = fg + self._occupied_tones = options.occupied_tones + self._fft_length = options.fft_length + self._cp_length = options.cp_length + self._snr = options.snr + + symbol_length = self._fft_length + self._cp_length + + win = [1 for i in range(self._fft_length)] + + # hard-coded known symbol + ks1 = known_symbols_200_1 + ks2 = known_symbols_200_2 + + # ML Sync + self.ofdm_sync = ofdm_receiver(self.fg, self._fft_length, symbol_length, self._snr) + + # OFDM Demod + self.fft_demod = gr.fft_vcc(self._fft_length, True, win, True) + self.ofdm_corr = gr.ofdm_correlator(self._occupied_tones, self._fft_length, + self._cp_length, ks1, ks2) + self.ofdm_demod = gr.ofdm_bpsk_demapper(self._occupied_tones) + + + if options.verbose: + self._print_verbage() + + self.fg.connect(self.ofdm_sync, self.fft_demod, self.ofdm_corr, self.ofdm_demod) + gr.hier_block.__init__(self, self.fg, self.ofdm_sync, self.ofdm_demod) + + def bits_per_symbol(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_symbol = staticmethod(bits_per_symbol) # make it a static method. RTFM + + def add_options(normal, expert): + """ + Adds OFDM-specific options to the Options Parser + """ + expert.add_option("", "--fft-length", type="intx", default=512, + help="set the number of FFT bins [default=%default]") + expert.add_option("", "--occupied-tones", type="intx", default=200, + help="set the number of occupied FFT bins [default=%default]") + expert.add_option("", "--cp-length", type="intx", default=128, + help="set the number of bits in the cyclic prefix [default=%default]") + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the OFDM demodulator + """ + print "\nOFDM Demodulator:" + print "FFT length: %3d" % (self._fft_length) + print "Occupied Tones: %3d" % (self._occupied_tones) + print "CP length: %3d" % (self._cp_length) + + +# generated in python using: +# import random +# pn = [2.0*random.randint(0,1)-1.0 for i in range(self._occupied_tones)] + +known_symbols_200_1 = [1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0] + +known_symbols_200_2 = [-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0] diff --git a/gnuradio-examples/python/ofdm/ofdm_receiver.py b/gnuradio-examples/python/ofdm/ofdm_receiver.py new file mode 100644 index 00000000..467e3af0 --- /dev/null +++ b/gnuradio-examples/python/ofdm/ofdm_receiver.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2006 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 2, 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 math +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class ofdm_receiver(gr.hier_block): + def __init__(self, fg, fft_length, symbol_length, snr): + self.input = gr.add_const_cc(0) # Kluge that goes away with hier_block2 + + self.fg = fg + + cpsize = symbol_length - fft_length; + + SNR = 10.0**(snr/10.0) + rho = SNR / (SNR + 1.0) + + # ML Sync + + # Energy Detection from ML Sync + + # Create a delay line + delayline = [0.0 for i in range(fft_length+1)] + delayline[fft_length] = 1.0 + self.delay = gr.fir_filter_ccf(1,delayline) + self.fg.connect(self.input, self.delay) + + # magnitude squared blocks + self.magsqrd1 = gr.complex_to_mag_squared() + self.magsqrd2 = gr.complex_to_mag_squared() + self.adder = gr.add_ff() + + moving_sum_taps = [rho/2 for i in range(cpsize)] + self.moving_sum_filter = gr.fir_filter_fff(1,moving_sum_taps) + + self.fg.connect(self.input,self.magsqrd1) + self.fg.connect(self.delay,self.magsqrd2) + self.fg.connect(self.magsqrd1,(self.adder,0)) + self.fg.connect(self.magsqrd2,(self.adder,1)) + self.fg.connect(self.adder,self.moving_sum_filter) + + + # Correlation from ML Sync + self.conjg = gr.conjugate_cc(); + self.mixer = gr.multiply_cc(); + + movingsum2_taps = [1.0 for i in range(cpsize)] + self.movingsum2 = gr.fir_filter_ccf(1,movingsum2_taps) + + + # Correlator data handler + self.c2mag = gr.complex_to_mag() + self.angle = gr.complex_to_arg() + self.fg.connect(self.input,(self.mixer,1)) + self.fg.connect(self.delay,self.conjg,(self.mixer,0)) + self.fg.connect(self.mixer,self.movingsum2,self.c2mag) + self.fg.connect(self.movingsum2,self.angle) + + # ML Sync output arg, need to find maximum point of this + self.diff = gr.sub_ff() + self.fg.connect(self.c2mag,(self.diff,0)) + self.fg.connect(self.moving_sum_filter,(self.diff,1)) + + #ML measurements input to sampler block and detect + nco_sensitivity = 1.0/fft_length + self.f2c = gr.float_to_complex() + self.sampler = gr.ofdm_sampler(fft_length,symbol_length) + self.pkt_detect = gr.peak_detector_ff(0.2, 0.25, 30, 0.0001) + self.dpll = gr.dpll_ff(float(symbol_length),0.01) + self.sample_and_hold = gr.sample_and_hold_ff() + self.nco = gr.frequency_modulator_fc(nco_sensitivity) + self.inv = gr.multiply_const_ff(-1) + self.sigmix = gr.multiply_cc() + + # Mix the signal with an NCO controlled by the sync loop + self.fg.connect(self.input, (self.sigmix,0)) + self.fg.connect(self.nco, (self.sigmix,1)) + self.fg.connect(self.sigmix, (self.sampler,0)) + + sample_trigger = 0 + if sample_trigger: + # for testing + peak_null = gr.null_sink(gr.sizeof_float) + data = 640*[0,] + data[639] = 1 + peak_trigger = gr.vector_source_f(data, True) + + self.fg.connect(self.pkt_detect, peak_null) + self.fg.connect(peak_trigger, self.f2c, (self.sampler,1)) + self.fg.connect(peak_trigger, (self.sample_and_hold,1)) + + # use the sync loop values to set the sampler and the NCO + # self.diff = theta + # self.angle = epsilon + + self.fg.connect(self.diff, self.pkt_detect) + use_dpll = 1 + if not sample_trigger: + if use_dpll: + self.fg.connect(self.pkt_detect, self.dpll,self.f2c, (self.sampler,1)) + self.fg.connect(self.dpll, (self.sample_and_hold,1)) + if not use_dpll: + self.fg.connect(self.pkt_detect, self.f2c, (self.sampler,1)) + self.fg.connect(self.pkt_detect, (self.sample_and_hold,1)) + + self.fg.connect(self.angle, (self.sample_and_hold,0)) + self.fg.connect(self.sample_and_hold, self.inv, self.nco) + + + if 0: + self.fg.connect(self.diff, gr.file_sink(gr.sizeof_float, "theta_f.dat")) + self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, "epsilon_f.dat")) + if use_dpll: + self.fg.connect(self.dpll, gr.file_sink(gr.sizeof_float, "dpll_pulses.dat")) + if sample_trigger: + self.fg.connect(peak_trigger, gr.file_sink(gr.sizeof_float, "peaks_f.dat")) + else: + self.fg.connect(self.pkt_detect, gr.file_sink(gr.sizeof_float, "peaks_f.dat")) + + self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "sample_and_hold_f.dat")) + self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "nco_c.dat")) + self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "input_c.dat")) + self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "output_c.dat")) + + gr.hier_block.__init__(self, fg, self.input, self.sampler) diff --git a/gnuradio-examples/python/ofdm/pick_bitrate.py b/gnuradio-examples/python/ofdm/pick_bitrate.py new file mode 100644 index 00000000..42aefa94 --- /dev/null +++ b/gnuradio-examples/python/ofdm/pick_bitrate.py @@ -0,0 +1,143 @@ +# +# Copyright 2005,2006 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 2, 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. +# + +_default_bitrate = 500e3 + +_valid_samples_per_symbol = (2,3,4,5,6,7) + +def _gen_tx_info(converter_rate): + results = [] + for samples_per_symbol in _valid_samples_per_symbol: + for interp in range(16, 512 + 1, 4): + bitrate = converter_rate / interp / samples_per_symbol + results.append((bitrate, samples_per_symbol, interp)) + results.sort() + return results + +def _gen_rx_info(converter_rate): + results = [] + for samples_per_symbol in _valid_samples_per_symbol: + for decim in range(8, 256 + 1, 2): + bitrate = converter_rate / decim / samples_per_symbol + results.append((bitrate, samples_per_symbol, decim)) + results.sort() + return results + +def _filter_info(info, samples_per_symbol, xrate): + if samples_per_symbol is not None: + info = [x for x in info if x[1] == samples_per_symbol] + if xrate is not None: + info = [x for x in info if x[2] == xrate] + return info + +def _pick_best(target_bitrate, bits_per_symbol, info): + """ + @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate) + """ + if len(info) == 0: + raise RuntimeError, "info is zero length!" + + if target_bitrate is None: # return the fastest one + return info[-1] + + # convert bit rate to symbol rate + target_symbolrate = target_bitrate / bits_per_symbol + + # Find the closest matching symbol rate. + # In the event of a tie, the one with the lowest samples_per_symbol wins. + # (We already sorted them, so the first one is the one we take) + + best = info[0] + best_delta = abs(target_symbolrate - best[0]) + for x in info[1:]: + delta = abs(target_symbolrate - x[0]) + if delta < best_delta: + best_delta = delta + best = x + + # convert symbol rate back to bit rate + return ((best[0] * bits_per_symbol),) + best[1:] + +def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + xrate, converter_rate, gen_info): + """ + @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate) + """ + if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1: + raise ValueError, "bits_per_symbol must be an int >= 1" + + if samples_per_symbol is not None and xrate is not None: # completely determined + return (float(converter_rate) / xrate / samples_per_symbol, + samples_per_symbol, xrate) + + if bitrate is None and samples_per_symbol is None and xrate is None: + bitrate = _default_bitrate + + # now we have a target bitrate and possibly an xrate or + # samples_per_symbol constraint, but not both of them. + + return _pick_best(bitrate, bits_per_symbol, + _filter_info(gen_info(converter_rate), samples_per_symbol, xrate)) + +# --------------------------------------------------------------------------------------- + +def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + interp_rate, converter_rate=128e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None + @param interp_rate: USRP interpolation factor + @type interp_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_symbol, interp_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + interp_rate, converter_rate, _gen_tx_info) + + +def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + decim_rate, converter_rate=64e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_symbol: samples/baud (aka samples/symbol) + @type samples_per_symbol: number or None + @param decim_rate: USRP decimation factor + @type decim_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_symbol, decim_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol, + decim_rate, converter_rate, _gen_rx_info) diff --git a/gnuradio-examples/python/ofdm/receive_path.py b/gnuradio-examples/python/ofdm/receive_path.py new file mode 100644 index 00000000..1c9c2384 --- /dev/null +++ b/gnuradio-examples/python/ofdm/receive_path.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 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 2, 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, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +import copy +import sys + +# from current dir +from pick_bitrate import pick_rx_bitrate +import ofdm + +# ///////////////////////////////////////////////////////////////////////////// +# receive path +# ///////////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block): + def __init__(self, fg, rx_callback, options): + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._log = options.log + self._rx_callback = rx_callback # this callback is fired when there's a packet available + + if 0: + + chan_coeffs = gr.firdes.low_pass (1.0, # gain + 2.0, # sampling rate + bw, # midpoint of trans. band + 1*bw, # width of trans. band + gr.firdes.WIN_KAISER) # filter type + else: + chan_coeffs = [ 1.0, 0.0, 0 ] + self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs) + + self.ofdm_demod = ofdm.ofdm_demod(fg, options) + + # receiver + self.packet_receiver = \ + blks.demod_ofdm_pkts(fg, + self.ofdm_demod, + access_code=None, + callback=self._rx_callback, + threshold=-1) + + # Carrier Sensing Blocks + alpha = 0.001 + thresh = 30 # in dB, will have to adjust + self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) + fg.connect(self.chan_filt, self.probe) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + fg.connect(self.chan_filt, self.packet_receiver) + #fg.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdmrx_chflt.dat")) + gr.hier_block.__init__(self, fg, self.chan_filt, None) + + def carrier_sensed(self): + """ + Return True if we think carrier is present. + """ + #return self.probe.level() > X + return self.probe.unmuted() + + def carrier_threshold(self): + """ + Return current setting in dB. + """ + return self.probe.threshold() + + def set_carrier_threshold(self, threshold_in_db): + """ + Set carrier threshold. + + @param threshold_in_db: set detection threshold + @type threshold_in_db: float (dB) + """ + self.probe.set_threshold(threshold_in_db) + + + def add_options(normal, expert): + """ + Adds receiver-specific options to the Options Parser + """ + normal.add_option("-v", "--verbose", action="store_true", default=False) + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to files (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + + def _print_verbage(self): + """ + Prints information about the receive path + """ + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + print "Rx gain: %g" % (self.gain,) + print "modulation: %s" % (self._demod_class.__name__) + print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) + print "samples/symbol: %3d" % (self._samples_per_symbol) + print "decim: %3d" % (self._decim) diff --git a/gnuradio-examples/python/ofdm/transmit_path.py b/gnuradio-examples/python/ofdm/transmit_path.py new file mode 100644 index 00000000..308ec085 --- /dev/null +++ b/gnuradio-examples/python/ofdm/transmit_path.py @@ -0,0 +1,104 @@ +# +# Copyright 2005,2006 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 2, 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, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation + +import copy +import sys + +# from current dir +import ofdm + +# ///////////////////////////////////////////////////////////////////////////// +# transmit path +# ///////////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block): + def __init__(self, fg, options): + ''' + See below for what options should hold + ''' + + options = copy.copy(options) # make a copy so we can destructively modify + + self._verbose = options.verbose + self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP + + self.ofdm_mod = ofdm.ofdm_mod(fg, options) + self.packet_transmitter = \ + blks.mod_ofdm_pkts(fg, + self.ofdm_mod, + access_code=None, + msgq_limit=4, + pad_for_usrp=True) + + self.amp = gr.multiply_const_cc(1) + self.set_tx_amplitude(self._tx_amplitude) + + # Display some information about the setup + if self._verbose: + self._print_verbage() + + # Create and setup transmit path flow graph + fg.connect(self.packet_transmitter, self.amp) + gr.hier_block.__init__(self, fg, None, self.amp) + + def set_tx_amplitude(self, ampl): + """ + Sets the transmit amplitude sent to the USRP + @param: ampl 0 <= ampl < 32768. Try 8000 + """ + self._tx_amplitude = max(0.0, min(ampl, 32767.0)) + self.amp.set_k(self._tx_amplitude) + + def send_pkt(self, payload='', eof=False): + """ + Calls the transmitter method to send a packet + """ + return self.packet_transmitter.send_pkt(payload, eof) + + def bitrate(self): + return self._bitrate + + def samples_per_symbol(self): + return self._samples_per_symbol + + def add_options(normal, expert): + """ + Adds transmitter-specific options to the Options Parser + """ + normal.add_option("", "--tx-amplitude", type="eng_float", default=12000, metavar="AMPL", + help="set transmitter digital amplitude: 0 <= AMPL < 32768 [default=%default]") + normal.add_option("-v", "--verbose", action="store_true", default=False) + expert.add_option("", "--log", action="store_true", default=False, + help="Log all parts of flow graph to file (CAUTION: lots of data)") + + # Make a static method to call before instantiation + add_options = staticmethod(add_options) + + def _print_verbage(self): + """ + Prints information about the transmit path + """ + print "Tx amplitude %s" % (self._tx_amplitude) + -- 2.30.2