From c7dbfcc7d78275f76d8c2a8ef21e3100721874be Mon Sep 17 00:00:00 2001 From: trondeau Date: Mon, 4 Jun 2007 16:08:44 +0000 Subject: [PATCH] merge ordm/receiver branch -r5574:5659. Reworks OFDM receiver with refactored OFDM blocks. A few bug fixes for other blocks have also been slipped in. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5661 221aa14e-8319-0410-a670-987f0aec2ac5 --- .../filter/gr_fractional_interpolator_cc.cc | 4 +- gnuradio-core/src/lib/general/Makefile.am | 13 +- gnuradio-core/src/lib/general/general.i | 6 +- .../src/lib/general/gr_conjugate_cc.cc | 27 +- gnuradio-core/src/lib/general/gr_delay.cc | 2 +- .../general/{gr_dpll_ff.cc => gr_dpll_bb.cc} | 30 ++- .../general/{gr_dpll_ff.h => gr_dpll_bb.h} | 18 +- .../{io/gr_frame.h => general/gr_dpll_bb.i} | 20 +- gnuradio-core/src/lib/general/gr_dpll_ff.i | 33 --- .../src/lib/general/gr_ofdm_bpsk_mapper.cc | 168 +++++++------ .../src/lib/general/gr_ofdm_bpsk_mapper.h | 49 ++-- .../src/lib/general/gr_ofdm_bpsk_mapper.i | 29 +-- .../src/lib/general/gr_ofdm_correlator.cc | 54 ++-- .../src/lib/general/gr_ofdm_correlator.h | 34 +-- .../src/lib/general/gr_ofdm_correlator.i | 16 +- .../src/lib/general/gr_ofdm_frame_sink.cc | 235 ++++++++++++++++++ .../src/lib/general/gr_ofdm_frame_sink.h | 105 ++++++++ .../gr_ofdm_frame_sink.i} | 15 +- .../src/lib/general/gr_ofdm_sampler.cc | 6 +- gnuradio-core/src/lib/general/gr_skiphead.cc | 76 +++--- gnuradio-core/src/lib/general/gr_skiphead.h | 26 +- gnuradio-core/src/lib/general/gr_skiphead.i | 14 +- .../src/lib/general/gr_stream_mux.cc | 158 ++++-------- gnuradio-core/src/lib/general/gr_stream_mux.h | 16 +- gnuradio-core/src/lib/gengen/Makefile.gen | 18 +- .../src/lib/gengen/generate_common.py | 2 +- .../src/lib/gengen/gengen_generated.i | 12 +- .../src/lib/gengen/gr_peak_detector_XX.cc.t | 8 +- .../src/lib/gengen/gr_sample_and_hold_XX.cc.t | 6 +- gnuradio-core/src/lib/io/Makefile.am | 7 +- gnuradio-core/src/lib/io/gr_file_sink.cc | 90 +------ gnuradio-core/src/lib/io/gr_file_sink.h | 24 +- gnuradio-core/src/lib/io/gr_file_sink.i | 2 +- gnuradio-core/src/lib/io/gr_file_sink_base.cc | 118 +++++++++ gnuradio-core/src/lib/io/gr_file_sink_base.h | 67 +++++ gnuradio-core/src/lib/io/gr_file_sink_base.i | 46 ++++ .../src/lib/io/gr_message_vector_source.cc | 97 -------- .../src/lib/io/gr_message_vector_source.h | 63 ----- gnuradio-core/src/lib/io/io.i | 3 +- .../src/python/gnuradio/blksimpl/Makefile.am | 3 + .../python/gnuradio/blksimpl/channel_model.py | 50 ++++ .../src/python/gnuradio/blksimpl/ofdm_pkt.py | 151 ++++++++--- .../python/gnuradio/blksimpl/ofdm_receiver.py | 55 ++++ .../src/python/gnuradio/blksimpl/ofdm_sync.py | 90 ++++--- .../src/python/gnuradio/gr/Makefile.am | 2 + .../src/python/gnuradio/gr/qa_delay.py | 65 +++++ .../src/python/gnuradio/gr/qa_skiphead.py | 102 ++++++++ .../src/python/gnuradio/gr/qa_stream_mux.py | 170 +++++++++++++ .../src/python/gnuradio/ofdm_packet_utils.py | 32 ++- gnuradio-examples/python/ofdm/Makefile.am | 2 - .../python/ofdm/benchmark_ofdm.py | 148 +++++------ gnuradio-examples/python/ofdm/ofdm.py | 161 ------------ .../python/ofdm/ofdm_mod_demod_test.py | 179 +++++++++++++ gnuradio-examples/python/ofdm/ofdm_sync.m | 28 +++ gnuradio-examples/python/ofdm/receive_path.py | 35 +-- .../python/ofdm/transmit_path.py | 17 +- usrp/fpga/Makefile.extra | 1 - 57 files changed, 1893 insertions(+), 1115 deletions(-) rename gnuradio-core/src/lib/general/{gr_dpll_ff.cc => gr_dpll_bb.cc} (75%) rename gnuradio-core/src/lib/general/{gr_dpll_ff.h => gr_dpll_bb.h} (75%) rename gnuradio-core/src/lib/{io/gr_frame.h => general/gr_dpll_bb.i} (77%) delete mode 100644 gnuradio-core/src/lib/general/gr_dpll_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc create mode 100644 gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h rename gnuradio-core/src/lib/{io/gr_message_vector_source.i => general/gr_ofdm_frame_sink.i} (67%) create mode 100644 gnuradio-core/src/lib/io/gr_file_sink_base.cc create mode 100644 gnuradio-core/src/lib/io/gr_file_sink_base.h create mode 100644 gnuradio-core/src/lib/io/gr_file_sink_base.i delete mode 100644 gnuradio-core/src/lib/io/gr_message_vector_source.cc delete mode 100644 gnuradio-core/src/lib/io/gr_message_vector_source.h create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/channel_model.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py rename gnuradio-examples/python/ofdm/ofdm_receiver.py => gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync.py (68%) create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_delay.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py delete mode 100644 gnuradio-examples/python/ofdm/ofdm.py create mode 100755 gnuradio-examples/python/ofdm/ofdm_mod_demod_test.py create mode 100644 gnuradio-examples/python/ofdm/ofdm_sync.m diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc index 312626a1..ac3ae46e 100644 --- a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc @@ -37,8 +37,8 @@ gr_fractional_interpolator_cc_sptr gr_make_fractional_interpolator_cc(float phas gr_fractional_interpolator_cc::gr_fractional_interpolator_cc(float phase_shift, float interp_ratio) : gr_block ("fractional_interpolator_cc", - gr_make_io_signature (1, 1, sizeof (float)), - gr_make_io_signature (1, 1, sizeof (float))), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), d_mu (phase_shift), d_mu_inc (interp_ratio), d_interp(new gri_mmse_fir_interpolator_cc()) { if (interp_ratio <= 0) diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am index c7613003..d774baa1 100644 --- a/gnuradio-core/src/lib/general/Makefile.am +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -63,7 +63,7 @@ libgeneral_la_SOURCES = \ gr_diff_decoder_bb.cc \ gr_diff_encoder_bb.cc \ gr_diff_phasor_cc.cc \ - gr_dpll_ff.cc \ + gr_dpll_bb.cc \ gr_fake_channel_coder_pp.cc \ gr_fast_atan2f.cc \ gr_feedforward_agc_cc.cc \ @@ -102,6 +102,7 @@ libgeneral_la_SOURCES = \ gr_ofdm_mapper_bcv.cc \ gr_ofdm_bpsk_demapper.cc \ gr_ofdm_bpsk_mapper.cc \ + gr_ofdm_frame_sink.cc \ gr_ofdm_sampler.cc \ gr_pa_2x2_phase_combiner.cc \ gr_packet_sink.cc \ @@ -197,7 +198,7 @@ grinclude_HEADERS = \ gr_deinterleave.h \ gr_delay.h \ gr_diff_phasor_cc.h \ - gr_dpll_ff.h \ + gr_dpll_bb.h \ gr_expj.h \ gr_fake_channel_coder_pp.h \ gr_feedforward_agc_cc.h \ @@ -240,7 +241,8 @@ grinclude_HEADERS = \ gr_ofdm_mapper_bcv.h \ gr_ofdm_bpsk_mapper.h \ gr_ofdm_bpsk_demapper.h \ - gr_ofdm_sampler.h \ + gr_ofdm_frame_sink.h \ + gr_ofdm_sampler.h \ gr_pa_2x2_phase_combiner.h \ gr_packet_sink.h \ gr_phase_modulator_fc.h \ @@ -342,7 +344,7 @@ swiginclude_HEADERS = \ gr_diff_decoder_bb.i \ gr_diff_encoder_bb.i \ gr_diff_phasor_cc.i \ - gr_dpll_ff.i \ + gr_dpll_bb.i \ gr_deinterleave.i \ gr_delay.i \ gr_fake_channel_coder_pp.i \ @@ -379,7 +381,8 @@ swiginclude_HEADERS = \ gr_ofdm_mapper_bcv.i \ gr_ofdm_bpsk_demapper.i \ gr_ofdm_bpsk_mapper.i \ - gr_ofdm_sampler.i \ + gr_ofdm_frame_sink.i \ + gr_ofdm_sampler.i \ gr_pa_2x2_phase_combiner.i \ gr_packet_sink.i \ gr_phase_modulator_fc.i \ diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index 64144a05..1fdb4239 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -84,7 +84,7 @@ #include #include #include -#include +#include #include #include #include @@ -97,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -186,7 +187,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_dpll_bb.i" %include "gr_pll_freqdet_cf.i" %include "gr_pll_refout_cc.i" %include "gr_pll_carriertracking_cc.i" @@ -199,6 +200,7 @@ %include "gr_ofdm_cyclic_prefixer.i" %include "gr_ofdm_bpsk_demapper.i" %include "gr_ofdm_bpsk_mapper.i" +%include "gr_ofdm_frame_sink.i" %include "gr_ofdm_sampler.i" %include "gr_costas_loop_cc.i" %include "gr_pa_2x2_phase_combiner.i" diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc index 0a5b3790..453c6d33 100644 --- a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc @@ -53,19 +53,24 @@ gr_conjugate_cc::work (int noutput_items, int size = noutput_items; while (size >= 8){ - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + optr[0] = conj(iptr[0]); + optr[1] = conj(iptr[1]); + optr[2] = conj(iptr[2]); + optr[3] = conj(iptr[3]); + optr[4] = conj(iptr[4]); + optr[5] = conj(iptr[5]); + optr[6] = conj(iptr[6]); + optr[7] = conj(iptr[7]); size -= 8; + optr += 8; + iptr += 8; + } + + while (size-- > 0) { + *optr = conj(*iptr); + iptr++; + optr++; } - while (size-- > 0) - *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; - return noutput_items; } diff --git a/gnuradio-core/src/lib/general/gr_delay.cc b/gnuradio-core/src/lib/general/gr_delay.cc index 12c50e4b..89ab3ce0 100644 --- a/gnuradio-core/src/lib/general/gr_delay.cc +++ b/gnuradio-core/src/lib/general/gr_delay.cc @@ -56,7 +56,7 @@ gr_delay::work (int noutput_items, iptr = (const char *) input_items[i]; optr = (char *) output_items[i]; - memcpy(optr, iptr + delay()*d_itemsize, noutput_items*d_itemsize); + memcpy(optr, iptr, noutput_items*d_itemsize); } return noutput_items; diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.cc b/gnuradio-core/src/lib/general/gr_dpll_bb.cc similarity index 75% rename from gnuradio-core/src/lib/general/gr_dpll_ff.cc rename to gnuradio-core/src/lib/general/gr_dpll_bb.cc index ae868fce..d5b72652 100644 --- a/gnuradio-core/src/lib/general/gr_dpll_ff.cc +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.cc @@ -20,25 +20,23 @@ * 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 #include -gr_dpll_ff_sptr -gr_make_dpll_ff (float period, float gain) +gr_dpll_bb_sptr +gr_make_dpll_bb (float period, float gain) { - return gr_dpll_ff_sptr (new gr_dpll_ff (period, gain)); + return gr_dpll_bb_sptr (new gr_dpll_bb (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))), +gr_dpll_bb::gr_dpll_bb (float period, float gain) + : gr_sync_block ("dpll_bb", + gr_make_io_signature (1, 1, sizeof (char)), + gr_make_io_signature (1, 1, sizeof (char))), d_restart(0),d_pulse_phase(0) { d_pulse_frequency = 1.0/period; @@ -55,16 +53,16 @@ gr_dpll_ff::gr_dpll_ff (float period, float gain) } int -gr_dpll_ff::work (int noutput_items, +gr_dpll_bb::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]; + const char *iptr = (const char *) input_items[0]; + char *optr = (char *) output_items[0]; for (int i = 0; i < noutput_items; i++){ - optr[i]= (float)0; - if(iptr[i] ==(float)1) { + optr[i]= 0; + if(iptr[i] == 1) { if (d_restart == 0) { d_pulse_phase = 1; } else { @@ -77,7 +75,7 @@ gr_dpll_ff::work (int noutput_items, d_pulse_phase -= 1.0; if (d_restart > 0) { d_restart -= 1; - optr[i] = (float)1; + optr[i] = 1; } } d_pulse_phase += d_pulse_frequency; diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.h b/gnuradio-core/src/lib/general/gr_dpll_bb.h similarity index 75% rename from gnuradio-core/src/lib/general/gr_dpll_ff.h rename to gnuradio-core/src/lib/general/gr_dpll_bb.h index 1de1efa8..c80612bc 100644 --- a/gnuradio-core/src/lib/general/gr_dpll_ff.h +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.h @@ -20,17 +20,15 @@ * 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 +#ifndef INCLUDED_GR_DPLL_BB_H +#define INCLUDED_GR_DPLL_BB_H #include -class gr_dpll_ff; -typedef boost::shared_ptr gr_dpll_ff_sptr; +class gr_dpll_bb; +typedef boost::shared_ptr gr_dpll_bb_sptr; -gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); +gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); /*! * \brief Detect the peak of a signal @@ -39,11 +37,11 @@ gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); * If a peak is detected, this block outputs a 1, * or it outputs 0's. */ -class gr_dpll_ff : public gr_sync_block +class gr_dpll_bb : public gr_sync_block { - friend gr_dpll_ff_sptr gr_make_dpll_ff (float period, float gain); + friend gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); - gr_dpll_ff (float period, float gain); + gr_dpll_bb (float period, float gain); private: unsigned char d_restart; diff --git a/gnuradio-core/src/lib/io/gr_frame.h b/gnuradio-core/src/lib/general/gr_dpll_bb.i similarity index 77% rename from gnuradio-core/src/lib/io/gr_frame.h rename to gnuradio-core/src/lib/general/gr_dpll_bb.i index 07317e9d..ae95e2df 100644 --- a/gnuradio-core/src/lib/io/gr_frame.h +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.i @@ -20,22 +20,12 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_FRAME_H -#define INCLUDED_GR_FRAME_H +GR_SWIG_BLOCK_MAGIC(gr,dpll_bb) -#include + gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); -class gr_frame +class gr_dpll_bb : public gr_sync_block { - public: - gr_frame(unsigned int mtu) - : mtu(mtu), length(0) - { } - - unsigned int mtu; - unsigned int length; - unsigned char data[]; + private: + gr_dpll_bb (float period, float gain); }; - -#endif - diff --git a/gnuradio-core/src/lib/general/gr_dpll_ff.i b/gnuradio-core/src/lib/general/gr_dpll_ff.i deleted file mode 100644 index 9606fba5..00000000 --- a/gnuradio-core/src/lib/general/gr_dpll_ff.i +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- 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_ofdm_bpsk_mapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc index df463239..f0b52c32 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -29,30 +29,32 @@ #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) +gr_make_ofdm_bpsk_mapper (unsigned int msgq_limit, + unsigned int occupied_carriers, unsigned int fft_length, + const std::vector &known_symbol1, + const std::vector &known_symbol2) { - return gr_ofdm_bpsk_mapper_sptr (new gr_ofdm_bpsk_mapper (mtu, occupied_carriers, vlen, + return gr_ofdm_bpsk_mapper_sptr (new gr_ofdm_bpsk_mapper (msgq_limit, occupied_carriers, fft_length, 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), +// Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet +gr_ofdm_bpsk_mapper::gr_ofdm_bpsk_mapper (unsigned int msgq_limit, + unsigned int occupied_carriers, unsigned int fft_length, + const std::vector &known_symbol1, + const std::vector &known_symbol2) + : gr_sync_block ("ofdm_bpsk_mapper", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))), + d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false), d_occupied_carriers(occupied_carriers), - d_vlen(vlen), - d_packet_offset(0), + d_fft_length(fft_length), 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_fft_length); assert(d_occupied_carriers == d_known_symbol1.size()); assert(d_occupied_carriers == d_known_symbol2.size()); } @@ -61,99 +63,101 @@ gr_ofdm_bpsk_mapper::~gr_ofdm_bpsk_mapper(void) { } -void -gr_ofdm_bpsk_mapper::forecast (int noutput_items, gr_vector_int &ninput_items_required) +float randombit() { - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = 1; + int r = rand()&1; + return (float)(-1 + 2*r); } 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) +gr_ofdm_bpsk_mapper::work(int noutput_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; + unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers; + unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0); //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_eof) { + return -1; } - 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); + if(!d_msg) { + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + d_bit_offset = 0; + d_header_sent = 0; + + if((d_msg->length() == 0) && (d_msg->type() == 1)) { + d_msg.reset(); + return -1; } - 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++; - } + i = 0; + while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) { + unsigned char bit = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01; + out[i + zeros_on_left] = gr_complex(-1+2*(bit)); + i++; + d_bit_offset++; + if(d_bit_offset == 8) { + d_bit_offset = 0; + d_msg_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 data to put in symbol + if (d_msg_offset == d_msg->length()) { + while(i < d_occupied_carriers) { // finish filling out the symbol + out[i + zeros_on_left] = gr_complex(randombit(),0); + i++; } - - // Ran out of space in symbol - out += d_vlen; - num_symbols++; + + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); // finished packet, free message + + assert(d_bit_offset == 0); + return 1; // produced one symbol } - consume_each(0); - return num_symbols; + + return 1; // produced symbol } diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h index 1ae6c75d..41b2f5be 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.h @@ -24,17 +24,19 @@ #define INCLUDED_GR_OFDM_BPSK_MAPPER_H -#include -#include +#include +#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); +gr_make_ofdm_bpsk_mapper (unsigned msgq_limit, + unsigned occupied_carriers, unsigned int fft_length, + const std::vector &known_symbol1, + const std::vector &known_symbol2); /*! * \brief take a stream of bytes in and map to a vector of complex @@ -42,35 +44,40 @@ gr_make_ofdm_bpsk_mapper (unsigned mtu, unsigned occupied_carriers, unsigned int * modulator. Simple BPSK version. */ -class gr_ofdm_bpsk_mapper : public gr_block +class gr_ofdm_bpsk_mapper : public gr_sync_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); + gr_make_ofdm_bpsk_mapper (unsigned msgq_limit, + unsigned occupied_carriers, unsigned int fft_length, + const std::vector &known_symbol1, + const 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); + gr_ofdm_bpsk_mapper (unsigned msgq_limit, + unsigned occupied_carriers, unsigned int fft_length, + const std::vector &known_symbol1, + const std::vector &known_symbol2); private: - unsigned int d_mtu; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + unsigned int d_occupied_carriers; - unsigned int d_vlen; - unsigned int d_packet_offset; + unsigned int d_fft_length; 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); + + 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); }; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i index 12b86dc3..d0094062 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.i @@ -22,27 +22,28 @@ #include -GR_SWIG_BLOCK_MAGIC(gr,ofdm_bpsk_mapper) +GR_SWIG_BLOCK_MAGIC(gr,ofdm_bpsk_mapper); gr_ofdm_bpsk_mapper_sptr -gr_make_ofdm_bpsk_mapper (unsigned int mtu, +gr_make_ofdm_bpsk_mapper (unsigned int msgq_limit, unsigned int bits_per_symbol, - unsigned int vlen, - std::vector known_symbol1, - std::vector known_symbol2); + unsigned int fft_length, + const std::vector &known_symbol1, + const std::vector &known_symbol2); -class gr_ofdm_bpsk_mapper : public gr_block +class gr_ofdm_bpsk_mapper : public gr_sync_block { protected: - gr_ofdm_bpsk_mapper (unsigned int mtu, + gr_ofdm_bpsk_mapper (unsigned int msgq_limit, unsigned int bits_per_symbol, - unsigned int vlen, - std::vector known_symbol1, - std::vector known_symbol2); + unsigned int fft_length, + const std::vector &known_symbol1, + const 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); + gr_msg_queue_sptr msgq(); + + int work(int noutput_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 index 21fbc6b3..3973b837 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006, 2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,29 +26,30 @@ #include #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, +gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2) + const std::vector &known_symbol1, + const std::vector &known_symbol2) { - return gr_ofdm_correlator_sptr (new gr_ofdm_correlator (occupied_carriers, vlen, cplen, + return gr_ofdm_correlator_sptr (new gr_ofdm_correlator (occupied_carriers, fft_length, cplen, known_symbol1, known_symbol2)); } -gr_ofdm_correlator::gr_ofdm_correlator (unsigned occupied_carriers, unsigned int vlen, +gr_ofdm_correlator::gr_ofdm_correlator (unsigned occupied_carriers, unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2) + const std::vector &known_symbol1, + const 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)), + gr_make_io_signature (1, 1, sizeof(gr_complex)*fft_length), + gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char))), d_occupied_carriers(occupied_carriers), - d_vlen(vlen), + d_fft_length(fft_length), d_cplen(cplen), d_freq_shift_len(5), d_known_symbol1(known_symbol1), @@ -84,8 +85,9 @@ gr_ofdm_correlator::forecast (int noutput_items, gr_vector_int &ninput_items_req 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)); + // return gr_complex(cos(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count), + // sin(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count)); + return gr_expj(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count); } bool @@ -99,7 +101,7 @@ gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *curr gr_complex h_sqrd = gr_complex(0.0,0.0); float power = 0.0F; - while(!found && (abs(search_delta) < d_freq_shift_len)) { + while(!found && ((unsigned)abs(search_delta) < d_freq_shift_len)) { h_sqrd = gr_complex(0.0,0.0); power = 0.0F; @@ -115,11 +117,20 @@ gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *curr search_delta, h_sqrd.real(), h_sqrd.imag(), power, h_sqrd.real()/power, arg(h_sqrd)); #endif - if(h_sqrd.real() > 0.75*power) { + // FIXME: Look at h_sqrd.read() > power + if((h_sqrd.real() > 0.82*power) && (h_sqrd.real() < 1.1 * power)) { found = true; d_coarse_freq = search_delta; d_phase_count = 1; - d_snr_est = 10*log10(power/(power-h_sqrd.real())); + //d_snr_est = 10*log10(power/(power-h_sqrd.real())); + + // check for low noise power; sets maximum SNR at 100 dB + if(fabs(h_sqrd.imag()) <= 1e-12) { + d_snr_est = 100.0; + } + else { + d_snr_est = 10*log10(fabs(h_sqrd.real()/h_sqrd.imag())); + } printf("CORR: Found, bin %d\tSNR Est %f dB\tcorr power fraction %f\n", search_delta, d_snr_est, h_sqrd.real()/power); @@ -168,23 +179,30 @@ gr_ofdm_correlator::general_work(int noutput_items, { const gr_complex *in = (const gr_complex *)input_items[0]; const gr_complex *previous = &in[0]; - const gr_complex *current = &in[d_vlen]; + const gr_complex *current = &in[d_fft_length]; gr_complex *out = (gr_complex *) output_items[0]; + char *sig = (char *) output_items[1]; unsigned int i=0; - int unoccupied_carriers = d_vlen - d_occupied_carriers; + int unoccupied_carriers = d_fft_length - 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); + sig[0] = 1; + } + else { + sig[0] = 0; } 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 index 4c44cca3..44a6847a 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006, 2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -31,10 +31,10 @@ 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, +gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2); + const std::vector &known_symbol1, + const std::vector &known_symbol2); /*! * \brief take a vector of complex constellation points in from an FFT @@ -48,7 +48,7 @@ gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, * 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 + * symbols to estimate the channel response over all subcarriers and does a simple * 1-tap equalization on all subcarriers. This corrects for the phase and amplitude * distortion caused by the channel. */ @@ -58,7 +58,7 @@ 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 fft_length 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 @@ -67,16 +67,16 @@ class gr_ofdm_correlator : public gr_block * for phase changes between symbols. */ friend gr_ofdm_correlator_sptr - gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2); + const std::vector &known_symbol1, + const std::vector &known_symbol2); protected: - gr_ofdm_correlator (unsigned int occupied_carriers, unsigned int vlen, + gr_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2); + const std::vector &known_symbol1, + const std::vector &known_symbol2); private: unsigned char slicer(gr_complex x); @@ -86,15 +86,15 @@ class gr_ofdm_correlator : public gr_block 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_fft_length; // !< \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 + 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); diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.i b/gnuradio-core/src/lib/general/gr_ofdm_correlator.i index fbbf6a8a..40f9f83f 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.i +++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2006 Free Software Foundation, Inc. + * Copyright 2006, 2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -22,23 +22,23 @@ #include -GR_SWIG_BLOCK_MAGIC(gr,ofdm_correlator) +GR_SWIG_BLOCK_MAGIC(gr,ofdm_correlator); gr_ofdm_correlator_sptr gr_make_ofdm_correlator (unsigned int occupied_carriers, - unsigned int vlen, + unsigned int fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2); + const std::vector &known_symbol1, + const 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 fft_length, unsigned int cplen, - std::vector known_symbol1, - std::vector known_symbol2); + const std::vector &known_symbol1, + const std::vector &known_symbol2); public: float snr() { return d_snr_est; } diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc new file mode 100644 index 00000000..acaf1258 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc @@ -0,0 +1,235 @@ +/* -*- 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 + +#define VERBOSE 0 + +inline void +gr_ofdm_frame_sink::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + +} + +inline void +gr_ofdm_frame_sink::enter_have_sync() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_sync\n"); + + d_state = STATE_HAVE_SYNC; + + // clear state of demapper + d_byte_offset = 0; + d_partial_byte = 0; + + d_header = 0; + d_headerbytelen_cnt = 0; +} + +inline void +gr_ofdm_frame_sink::enter_have_header() +{ + d_state = STATE_HAVE_HEADER; + + // header consists of two 16-bit shorts in network byte order + // payload length is lower 12 bits + // whitener offset is upper 4 bits + d_packetlen = (d_header >> 16) & 0x0fff; + d_packet_whitener_offset = (d_header >> 28) & 0x000f; + d_packetlen_cnt = 0; + + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", + d_packetlen, d_packet_whitener_offset); +} + +unsigned char gr_ofdm_frame_sink::bpsk_slicer(gr_complex x) +{ + return (unsigned char)(x.real() > 0 ? 1 : 0); +} + +unsigned int gr_ofdm_frame_sink::bpsk_demapper(const gr_complex *in, + unsigned char *out) +{ + 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 |= bpsk_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; + } + } + + return bytes_produced; +} + + + +gr_ofdm_frame_sink_sptr +gr_make_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers) +{ + return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(target_queue, occupied_carriers)); +} + + +gr_ofdm_frame_sink::gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers) + : gr_sync_block ("ofdm_frame_sink", + gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)), + gr_make_io_signature (0, 0, 0)), + d_target_queue(target_queue), d_occupied_carriers(occupied_carriers), + d_byte_offset(0), d_partial_byte(0) +{ + d_bytes_out = new unsigned char[(int)ceil(d_occupied_carriers/8.0)]; + + enter_search(); +} + +gr_ofdm_frame_sink::~gr_ofdm_frame_sink () +{ + delete [] d_bytes_out; +} + +int +gr_ofdm_frame_sink::work (int noutput_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 char *sig = (const char *) input_items[1]; + int count_tones=0, count_items=0; + unsigned int j = 0; + unsigned int bytes=0; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"); + + bytes = bpsk_demapper(&in[0], d_bytes_out); + + switch(d_state) { + + case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt + if (VERBOSE) + fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); + + if (sig[0]) { // Found it, set up for header decode + enter_have_sync(); + } + break; + + case STATE_HAVE_SYNC: + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_SYNC\n"); + if (VERBOSE) + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", + d_headerbytelen_cnt, d_header); + + j = 0; + while(j < bytes) { + d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF); + j++; + + if (++d_headerbytelen_cnt == HEADERBYTELEN) { + + if (VERBOSE) + fprintf(stderr, "got header: 0x%08x\n", d_header); + + // we have a full header, check to see if it has been received properly + if (header_ok()){ + enter_have_header(); + printf("\nPacket Length: %d\n", d_packetlen); + //for(int k=0; k < d_packetlen; k++) + // printf("%02x", d_packet[k]); + //printf("\n"); + + while((j < bytes) && (d_packetlen_cnt < d_packetlen)) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + } + + if(d_packetlen_cnt == d_packetlen) { + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + } + } + else { + enter_search(); // bad header + } + } + } + break; + + case STATE_HAVE_HEADER: + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen); + if (VERBOSE) + fprintf(stderr,"Packet Build\n"); + + j = 0; + while(j < bytes) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + + if (d_packetlen_cnt == d_packetlen){ // packet is filled + // build a message + // NOTE: passing header field as arg1 is not scalable + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + break; + + default: + assert(0); + + } // switch + + return 1; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h new file mode 100644 index 00000000..d77c7674 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + +#ifndef INCLUDED_GR_OFDM_FRAME_SINK_H +#define INCLUDED_GR_OFDM_FRAME_SINK_H + +#include +#include + +class gr_ofdm_frame_sink; +typedef boost::shared_ptr gr_ofdm_frame_sink_sptr; + +gr_ofdm_frame_sink_sptr +gr_make_ofdm_frame_sink (gr_msg_queue_sptr target_queue, unsigned int occupied_tones); + +/*! + * \brief Given a stream of bits and access_code flags, assemble packets. + * \ingroup sink + * + * input: stream of bytes from gr_correlate_access_code_bb + * output: none. Pushes assembled packet into target queue + * + * The framer expects a fixed length header of 2 16-bit shorts + * containing the payload length, followed by the payload. If the + * 2 16-bit shorts are not identical, this packet is ignored. Better + * algs are welcome. + * + * The input data consists of bytes that have two bits used. + * Bit 0, the LSB, contains the data bit. + * Bit 1 if set, indicates that the corresponding bit is the + * the first bit of the packet. That is, this bit is the first + * one after the access code. + */ +class gr_ofdm_frame_sink : public gr_sync_block +{ + friend gr_ofdm_frame_sink_sptr + gr_make_ofdm_frame_sink (gr_msg_queue_sptr target_queue, unsigned int occupied_tones); + + private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + static const int MAX_PKT_LEN = 4096; + static const int HEADERBYTELEN = 4; + + gr_msg_queue_sptr d_target_queue; // where to send the packet when received + state_t d_state; + unsigned int d_header; // header bits + int d_headerbytelen_cnt; // how many so far + + unsigned char *d_bytes_out; // hold the current bytes produced by the demapper + + unsigned int d_occupied_carriers; + unsigned int d_byte_offset; + unsigned int d_partial_byte; + + unsigned char d_packet[MAX_PKT_LEN]; // assembled payload + int d_packetlen; // length of packet + int d_packet_whitener_offset; // offset into whitener string to use + int d_packetlen_cnt; // how many so far + + protected: + gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones); + + void enter_search(); + void enter_have_sync(); + void enter_have_header(); + + bool header_ok() + { + // confirm that two copies of header info are identical + return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; + } + + unsigned char bpsk_slicer(gr_complex x); + unsigned int bpsk_demapper(const gr_complex *in, + unsigned char *out); + + public: + ~gr_ofdm_frame_sink(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_OFDM_FRAME_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_vector_source.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i similarity index 67% rename from gnuradio-core/src/lib/io/gr_message_vector_source.i rename to gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i index ff8bd5de..b05c8b79 100644 --- a/gnuradio-core/src/lib/io/gr_message_vector_source.i +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2004,2006 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,17 +20,16 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,message_vector_source); +GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink); -gr_message_vector_source_sptr gr_make_message_vector_source (size_t max_msg_size, int msgq_limit=0); +gr_ofdm_frame_sink_sptr +gr_make_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones); -class gr_message_vector_source : public gr_sync_block +class gr_ofdm_frame_sink : public gr_sync_block { protected: - gr_message_vector_source (size_t itemsize, int msgq_limit); + gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones); public: - ~gr_message_vector_source (); - - gr_msg_queue_sptr msgq() const; + ~gr_ofdm_frame_sink(); }; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc index 9ac5abdc..5f5a91fd 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc @@ -38,7 +38,7 @@ gr_make_ofdm_sampler (unsigned int fft_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_signature2 (2, 2, sizeof (gr_complex), sizeof(char)), gr_make_io_signature (1, 1, sizeof (gr_complex)*fft_length)), d_fft_length(fft_length), d_symbol_length(symbol_length) { @@ -61,7 +61,7 @@ gr_ofdm_sampler::general_work (int noutput_items, gr_vector_void_star &output_items) { gr_complex *iptr = (gr_complex *) input_items[0]; - gr_complex *trigger = (gr_complex *) input_items[1]; + char *trigger = (char *) input_items[1]; gr_complex *optr = (gr_complex *) output_items[0]; @@ -70,7 +70,7 @@ gr_ofdm_sampler::general_work (int noutput_items, unsigned int i=d_fft_length-1; while(!found && i 0.5) + if(trigger[i]) found = 1; else i++; diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc index 4a1f8751..e395cbf6 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.cc +++ b/gnuradio-core/src/lib/general/gr_skiphead.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,45 +26,57 @@ #include #include -gr_skiphead::gr_skiphead (size_t sizeof_stream_item, int nitems) - : gr_sync_block ("skiphead", - gr_make_io_signature (1, 1, sizeof_stream_item), - gr_make_io_signature (1, 1, sizeof_stream_item)), - d_nitems (nitems), d_nskipped_items (0) +gr_skiphead::gr_skiphead (size_t itemsize, size_t nitems_to_skip) + : gr_block ("skiphead", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_nitems_to_skip(nitems_to_skip), d_nitems(0) { } -gr_block_sptr -gr_make_skiphead (size_t sizeof_stream_item, int nitems) +gr_skiphead_sptr +gr_make_skiphead (size_t itemsize, size_t nitems_to_skip) { - return gr_block_sptr (new gr_skiphead (sizeof_stream_item, nitems)); + return gr_skiphead_sptr (new gr_skiphead (itemsize, nitems_to_skip)); } int -gr_skiphead::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +gr_skiphead::general_work(int noutput_items, + gr_vector_int &ninput_items_ignored, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { - int items_to_skip = d_nitems - d_nskipped_items; - if (items_to_skip <=0) - { - //Done with skipping, copy all input to the output; - memcpy (output_items[0], input_items[0], noutput_items * input_signature()->sizeof_stream_item (0)); - return noutput_items; - } else if (items_to_skip < noutput_items) - { - memcpy (output_items[0], &(((char *)input_items[0])[items_to_skip*input_signature()->sizeof_stream_item (0)]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); - //memcpy (output_items[0], &((input_items[0])[items_to_skip]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); - //memcpy (output_items[0], input_items[0]+items_to_skip*input_signature()->sizeof_stream_item (0), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); - d_nskipped_items += items_to_skip; - consume_each (items_to_skip); - return (noutput_items -items_to_skip); - } else - { - d_nskipped_items += noutput_items; - consume_each (items_to_skip); - return 0; + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + int ninput_items = noutput_items; // we've got at least this many input items + int ii = 0; // input index + + while (ii < ninput_items){ + + long long ni_total = ii + d_nitems; // total items processed so far + if (ni_total < d_nitems_to_skip){ // need to skip some more + + int n_to_skip = (int) std::min(d_nitems_to_skip - ni_total, + (long long)(ninput_items - ii)); + ii += n_to_skip; + } + + else { // nothing left to skip. copy away + + int n_to_copy = ninput_items - ii; + if (n_to_copy > 0){ + size_t itemsize = output_signature()->sizeof_stream_item(0); + memcpy(out, in + (ii*itemsize), n_to_copy*itemsize); + } + + d_nitems += ninput_items; + consume_each(ninput_items); + return n_to_copy; + } } - return -1;//Should never get here + d_nitems += ninput_items; + consume_each(ninput_items); + return 0; } diff --git a/gnuradio-core/src/lib/general/gr_skiphead.h b/gnuradio-core/src/lib/general/gr_skiphead.h index 81898ef4..6e2c7827 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.h +++ b/gnuradio-core/src/lib/general/gr_skiphead.h @@ -26,6 +26,10 @@ #include #include // size_t +class gr_skiphead; +typedef boost::shared_ptr gr_skiphead_sptr; + + /*! * \brief skips the first N items, from then on copies items to the output * \ingroup block @@ -33,22 +37,24 @@ * Useful for building test cases and sources which have metadata or junk at the start */ -class gr_skiphead : public gr_sync_block +class gr_skiphead : public gr_block { - friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); - gr_skiphead (size_t sizeof_stream_item, int nitems); + friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip); + gr_skiphead (size_t itemsize, size_t nitems_to_skip); - int d_nitems; - int d_nskipped_items; + long long d_nitems_to_skip; + long long d_nitems; // total items seen public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; -gr_block_sptr -gr_make_skiphead (size_t sizeof_stream_item, int nitems); +gr_skiphead_sptr +gr_make_skiphead (size_t itemsize, size_t nitems_to_skip); #endif /* INCLUDED_GR_SKIPHEAD_H */ diff --git a/gnuradio-core/src/lib/general/gr_skiphead.i b/gnuradio-core/src/lib/general/gr_skiphead.i index 8942f184..c725e26b 100644 --- a/gnuradio-core/src/lib/general/gr_skiphead.i +++ b/gnuradio-core/src/lib/general/gr_skiphead.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,11 +20,11 @@ * Boston, MA 02110-1301, USA. */ -%ignore gr_skiphead; +GR_SWIG_BLOCK_MAGIC(gr,skiphead); + +gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip); + class gr_skiphead : public gr_block { - friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); - gr_skiphead (size_t sizeof_stream_item, int nitems); + friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip); + gr_skiphead (size_t itemsize, size_t nitems_to_skip); }; - -%rename(skiphead) gr_make_skiphead; -gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.cc b/gnuradio-core/src/lib/general/gr_stream_mux.cc index 1eaad29a..e7e45de7 100644 --- a/gnuradio-core/src/lib/general/gr_stream_mux.cc +++ b/gnuradio-core/src/lib/general/gr_stream_mux.cc @@ -44,6 +44,10 @@ gr_stream_mux::gr_stream_mux (size_t itemsize, const std::vector &lengths) d_residual(0), d_lengths(lengths) { + if(d_lengths[d_stream] == 0) { + increment_stream(); + } + d_residual = d_lengths[d_stream]; } gr_stream_mux::~gr_stream_mux(void) @@ -55,9 +59,17 @@ 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; + ninput_items_required[i] = (d_lengths[i] == 0 ? 0 : 1); } +void gr_stream_mux::increment_stream() +{ + do { + d_stream = (d_stream+1) % d_lengths.size(); + } while(d_lengths[d_stream] == 0); + + d_residual = d_lengths[d_stream]; +} int gr_stream_mux::general_work(int noutput_items, @@ -65,128 +77,46 @@ gr_stream_mux::general_work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - char *out = (char *) output_items[0]; const char *in; + int out_index = 0; + std::vector input_index(d_lengths.size(), 0); - 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(size_t i = 0; i < d_lengths.size(); i++) + printf("\tninput_items[%d]: %d\n", i, ninput_items[i]); + } - #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 + while (1) { + int r = std::min(noutput_items - out_index, + std::min(d_residual, + ninput_items[d_stream] - input_index[d_stream])); + if(VERBOSE) { + printf("mux: r=%d\n", r); + printf("\tnoutput_items - out_index: %d\n", + noutput_items - out_index); + printf("\td_residual: %d\n", + d_residual); + printf("\tninput_items[d_stream] - input_index[d_stream]: %d\n", + ninput_items[d_stream] - input_index[d_stream]); + } - in = (const char *) input_items[d_stream]; + if(r <= 0) { + return out_index; + } - if(d_residual) { - #if VERBOSE - printf("Cleaning up residual bytes (%d) from stream %d\n", d_residual, d_stream); - #endif + in = (const char *) input_items[d_stream] + input_index[d_stream]*d_itemsize; - // 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); + memcpy(&out[out_index*d_itemsize], in, r*d_itemsize); + out_index += r; + input_index[d_stream] += r; + d_residual -= r; - // increment the output accumulator - acc += M; - - // keep track of items consumed - consume_vector[d_stream]=M; + consume(d_stream, r); - // 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; @@ -66,14 +65,15 @@ class gr_stream_mux : public gr_block 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; + size_t d_itemsize; + unsigned int d_stream; // index of currently selected stream + int d_residual; // number if items left to put into current stream + gr_vector_int d_lengths; // number if items to pack per stream + + void increment_stream(); + public: ~gr_stream_mux(void); diff --git a/gnuradio-core/src/lib/gengen/Makefile.gen b/gnuradio-core/src/lib/gengen/Makefile.gen index ceb8692b..238622bd 100644 --- a/gnuradio-core/src/lib/gengen/Makefile.gen +++ b/gnuradio-core/src/lib/gengen/Makefile.gen @@ -62,9 +62,9 @@ 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_peak_detector_fb.h \ + gr_peak_detector_ib.h \ + gr_peak_detector_sb.h \ gr_sample_and_hold_bb.h \ gr_sample_and_hold_ff.h \ gr_sample_and_hold_ii.h \ @@ -152,9 +152,9 @@ 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_peak_detector_fb.i \ + gr_peak_detector_ib.i \ + gr_peak_detector_sb.i \ gr_sample_and_hold_bb.i \ gr_sample_and_hold_ff.i \ gr_sample_and_hold_ii.i \ @@ -242,9 +242,9 @@ 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_peak_detector_fb.cc \ + gr_peak_detector_ib.cc \ + gr_peak_detector_sb.cc \ gr_sample_and_hold_bb.cc \ gr_sample_and_hold_ff.cc \ gr_sample_and_hold_ii.cc \ diff --git a/gnuradio-core/src/lib/gengen/generate_common.py b/gnuradio-core/src/lib/gengen/generate_common.py index aaf15f04..c049438a 100755 --- a/gnuradio-core/src/lib/gengen/generate_common.py +++ b/gnuradio-core/src/lib/gengen/generate_common.py @@ -59,9 +59,9 @@ others = ( ('gr_unpacked_to_packed_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')), ('gr_argmax_XX', ('fs','is','ss')), ('gr_max_XX', ('ff','ii','ss')), + ('gr_peak_detector_XX', ('fb','ib','sb')) ) diff --git a/gnuradio-core/src/lib/gengen/gengen_generated.i b/gnuradio-core/src/lib/gengen/gengen_generated.i index bab1f03e..26dd3f41 100644 --- a/gnuradio-core/src/lib/gengen/gengen_generated.i +++ b/gnuradio-core/src/lib/gengen/gengen_generated.i @@ -62,9 +62,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -152,9 +152,9 @@ %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 index 812ec9fd..19a5b98a 100644 --- a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t @@ -44,7 +44,7 @@ gr_make_@BASE_NAME@ (float threshold_factor_rise, 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@))), + gr_make_io_signature (1, 1, sizeof (char))), 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) @@ -57,9 +57,9 @@ int gr_vector_void_star &output_items) { @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; - @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + char *optr = (char *) output_items[0]; - memset(optr, 0, noutput_items*sizeof(@O_TYPE@)); + memset(optr, 0, noutput_items*sizeof(char)); @I_TYPE@ peak_val = -(@I_TYPE@)INFINITY; int peak_ind = 0; @@ -90,7 +90,7 @@ int i++; } else { - optr[peak_ind] = (@O_TYPE@)1; + optr[peak_ind] = 1; state = 0; peak_val = -(@I_TYPE@)INFINITY; //printf("Leaving State 1: Peak: %f Peak Ind: %d i: %d noutput_items: %d\n", 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 index 3b971557..3f2c5f6f 100644 --- 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 @@ -37,7 +37,7 @@ gr_make_@BASE_NAME@ () @NAME@::@NAME@ () : gr_sync_block ("@BASE_NAME@", - gr_make_io_signature (2, 2, sizeof (@I_TYPE@)), + gr_make_io_signature2 (2, 2, sizeof (@I_TYPE@), sizeof(char)), gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), d_data(0) { @@ -49,11 +49,11 @@ int gr_vector_void_star &output_items) { @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; - @I_TYPE@ *ctrl = (@I_TYPE@ *) input_items[1]; + const char *ctrl = (const char *) input_items[1]; @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; for (int i = 0; i < noutput_items; i++){ - if(ctrl[i] > 0.5) { + if(ctrl[i]) { d_data = iptr[i]; } optr[i] = d_data; diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am index 049e6984..4835c68c 100644 --- a/gnuradio-core/src/lib/io/Makefile.am +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -29,12 +29,12 @@ noinst_LTLIBRARIES = libio.la libio_la_SOURCES = \ gr_file_sink.cc \ + gr_file_sink_base.cc \ gr_file_source.cc \ gr_file_descriptor_sink.cc \ 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 \ @@ -57,13 +57,12 @@ libio_la_SOURCES = \ grinclude_HEADERS = \ gr_file_sink.h \ + gr_file_sink_base.h \ 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 \ @@ -90,12 +89,12 @@ grinclude_HEADERS = \ swiginclude_HEADERS = \ io.i \ gr_file_sink.i \ + gr_file_sink_base.i \ gr_file_source.i \ gr_file_descriptor_sink.i \ 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_file_sink.cc b/gnuradio-core/src/lib/io/gr_file_sink.cc index b7cf6c24..0994fd2b 100644 --- a/gnuradio-core/src/lib/io/gr_file_sink.cc +++ b/gnuradio-core/src/lib/io/gr_file_sink.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2006 Free Software Foundation, Inc. + * Copyright 2004,2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,91 +26,28 @@ #include #include -#include -#include -#include -#include #include -// win32 (mingw/msvc) specific -#ifdef HAVE_IO_H -#include -#endif -#ifdef O_BINARY -#define OUR_O_BINARY O_BINARY -#else -#define OUR_O_BINARY 0 -#endif -// should be handled via configure -#ifdef O_LARGEFILE -#define OUR_O_LARGEFILE O_LARGEFILE -#else -#define OUR_O_LARGEFILE 0 -#endif +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename) +{ + return gr_file_sink_sptr (new gr_file_sink (itemsize, filename)); +} gr_file_sink::gr_file_sink(size_t itemsize, const char *filename) : gr_sync_block ("file_sink", gr_make_io_signature(1, 1, itemsize), gr_make_io_signature(0, 0, 0)), - d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_updated(false) + gr_file_sink_base(filename, true), + d_itemsize(itemsize) { if (!open(filename)) throw std::runtime_error ("can't open file"); } -gr_file_sink_sptr -gr_make_file_sink (size_t itemsize, const char *filename) -{ - return gr_file_sink_sptr (new gr_file_sink (itemsize, filename)); -} - gr_file_sink::~gr_file_sink () { - close(); - if (d_fp){ - fclose((FILE *) d_fp); - d_fp = 0; - } -} - -bool -gr_file_sink::open(const char *filename) -{ - omni_mutex_lock l(d_mutex); // hold mutex for duration of this function - - // we use the open system call to get access to the O_LARGEFILE flag. - int fd; - if ((fd = ::open (filename, - O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, 0664)) < 0){ - perror (filename); - return false; - } - - if (d_new_fp){ // if we've already got a new one open, close it - fclose((FILE *) d_new_fp); - d_new_fp = 0; - } - - if ((d_new_fp = fdopen (fd, "wb")) == NULL){ - perror (filename); - ::close(fd); // don't leak file descriptor if fdopen fails. - } - - d_updated = true; - return d_new_fp != 0; -} - -void -gr_file_sink::close() -{ - omni_mutex_lock l(d_mutex); // hold mutex for duration of this function - - if (d_new_fp){ - fclose((FILE *) d_new_fp); - d_new_fp = 0; - } - d_updated = true; } int @@ -121,20 +58,13 @@ gr_file_sink::work (int noutput_items, char *inbuf = (char *) input_items[0]; int nwritten = 0; - if (d_updated){ - omni_mutex_lock l(d_mutex); // hold mutex for duration of this block - if (d_fp) - fclose((FILE *)d_fp); - d_fp = d_new_fp; // install new file pointer - d_new_fp = 0; - d_updated = false; - } + do_update(); // update d_fp is reqd if (!d_fp) return noutput_items; // drop output on the floor while (nwritten < noutput_items){ - int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, (FILE *) d_fp); + int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, d_fp); if (count == 0) // FIXME add error handling break; nwritten += count; diff --git a/gnuradio-core/src/lib/io/gr_file_sink.h b/gnuradio-core/src/lib/io/gr_file_sink.h index c289a150..fd0cd6f6 100644 --- a/gnuradio-core/src/lib/io/gr_file_sink.h +++ b/gnuradio-core/src/lib/io/gr_file_sink.h @@ -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 * @@ -24,7 +24,7 @@ #define INCLUDED_GR_FILE_SINK_H #include -#include +#include class gr_file_sink; typedef boost::shared_ptr gr_file_sink_sptr; @@ -36,16 +36,12 @@ gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); * \ingroup sink */ -class gr_file_sink : public gr_sync_block +class gr_file_sink : public gr_sync_block, public gr_file_sink_base { friend gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); private: size_t d_itemsize; - void *d_fp; // current FILE pointer - void *d_new_fp; // new FILE pointer - bool d_updated; // is there a new FILE pointer? - omni_mutex d_mutex; protected: gr_file_sink(size_t itemsize, const char *filename); @@ -53,23 +49,9 @@ class gr_file_sink : public gr_sync_block public: ~gr_file_sink(); - /*! - * \brief Open filename and begin output to it. - */ - bool open(const char *filename); - - /*! - * \brief Close current output file. - * - * Closes current output file and ignores any output until - * open is called to connect to another file. - */ - void close(); - int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); }; - #endif /* INCLUDED_GR_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink.i b/gnuradio-core/src/lib/io/gr_file_sink.i index 80f86956..202ab931 100644 --- a/gnuradio-core/src/lib/io/gr_file_sink.i +++ b/gnuradio-core/src/lib/io/gr_file_sink.i @@ -25,7 +25,7 @@ GR_SWIG_BLOCK_MAGIC(gr,file_sink) gr_file_sink_sptr gr_make_file_sink (size_t itemsize, const char *filename); -class gr_file_sink : public gr_sync_block +class gr_file_sink : public gr_sync_block, public gr_file_sink_base { protected: gr_file_sink (size_t itemsize, const char *filename); diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.cc b/gnuradio-core/src/lib/io/gr_file_sink_base.cc new file mode 100644 index 00000000..44d01ba8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.cc @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,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 + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_sink_base::gr_file_sink_base(const char *filename, bool is_binary) + : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary) +{ + if (!open(filename)) + throw std::runtime_error ("can't open file"); +} + +gr_file_sink_base::~gr_file_sink_base () +{ + close(); + if (d_fp){ + fclose(d_fp); + d_fp = 0; + } +} + +bool +gr_file_sink_base::open(const char *filename) +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename); + return false; + } + + if (d_new_fp){ // if we've already got a new one open, close it + fclose(d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){ + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + d_updated = true; + return d_new_fp != 0; +} + +void +gr_file_sink_base::close() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + if (d_new_fp){ + fclose(d_new_fp); + d_new_fp = 0; + } + d_updated = true; +} + +void +gr_file_sink_base::do_update() +{ + if (d_updated){ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this block + if (d_fp) + fclose(d_fp); + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.h b/gnuradio-core/src/lib/io/gr_file_sink_base.h new file mode 100644 index 00000000..98fc7b65 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_FILE_SINK_BASE_H +#define INCLUDED_GR_FILE_SINK_BASE_H + +#include +#include + +/*! + * \brief Common base class for file sinks + */ +class gr_file_sink_base +{ + protected: + FILE *d_fp; // current FILE pointer + FILE *d_new_fp; // new FILE pointer + bool d_updated; // is there a new FILE pointer? + bool d_is_binary; + omni_mutex d_mutex; + + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); +}; + + +#endif /* INCLUDED_GR_FILE_SINK_BASE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.i b/gnuradio-core/src/lib/io/gr_file_sink_base.i new file mode 100644 index 00000000..b83f251e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.i @@ -0,0 +1,46 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +class gr_file_sink_base +{ + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); +}; diff --git a/gnuradio-core/src/lib/io/gr_message_vector_source.cc b/gnuradio-core/src/lib/io/gr_message_vector_source.cc deleted file mode 100644 index 69e2bc8d..00000000 --- a/gnuradio-core/src/lib/io/gr_message_vector_source.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- 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 deleted file mode 100644 index 8b346535..00000000 --- a/gnuradio-core/src/lib/io/gr_message_vector_source.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- 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/io.i b/gnuradio-core/src/lib/io/io.i index 806e83e1..c6344051 100644 --- a/gnuradio-core/src/lib/io/io.i +++ b/gnuradio-core/src/lib/io/io.i @@ -34,12 +34,12 @@ #include #include #include -#include #include #include %} +%include "gr_file_sink_base.i" %include "gr_file_sink.i" %include "gr_file_source.i" %include "gr_file_descriptor_sink.i" @@ -51,7 +51,6 @@ %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/blksimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am index 381340c4..b8c80011 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am @@ -29,6 +29,7 @@ grblkspythondir = $(grpythondir)/blksimpl grblkspython_PYTHON = \ __init__.py \ am_demod.py \ + channel_model.py \ dbpsk.py \ dqpsk.py \ d8psk.py \ @@ -40,6 +41,8 @@ grblkspython_PYTHON = \ nbfm_rx.py \ nbfm_tx.py \ ofdm_pkt.py \ + ofdm_receiver.py \ + ofdm_sync.py \ pkt.py \ psk.py \ qam.py \ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/channel_model.py b/gnuradio-core/src/python/gnuradio/blksimpl/channel_model.py new file mode 100644 index 00000000..c7b3f07b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/channel_model.py @@ -0,0 +1,50 @@ +#!/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. +# + +from gnuradio import gr + +class channel_model(gr.hier_block): + def __init__(self, fg, noise_voltage=0.0, frequency_offset=0.0, epsilon=1.0, taps=[1.0,0.0]): + ''' Creates a channel model that includes: + - AWGN noise power in terms of noise voltage + - A frequency offest in the channel in ratio + - A timing offset ratio to model clock difference (epsilon) + - Multipath taps + ''' + + print epsilon + self.timing_offset = gr.fractional_interpolator_cc(0, epsilon) + + self.multipath = gr.fir_filter_ccc(1, taps) + + self.noise_adder = gr.add_cc() + self.noise = gr.noise_source_c(gr.GR_GAUSSIAN,noise_voltage) + self.freq_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.timing_offset, self.multipath) + fg.connect(self.multipath, (self.mixer_offset,0)) + fg.connect(self.freq_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.timing_offset, self.noise_adder) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py index 355455da..9a98b374 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_pkt.py @@ -1,3 +1,4 @@ + # # Copyright 2005,2006,2007 Free Software Foundation, Inc. # @@ -19,10 +20,13 @@ # Boston, MA 02110-1301, USA. # +import math from math import pi from gnuradio import gr, ofdm_packet_utils import gnuradio.gr.gr_threading as _threading +from gnuradio.blksimpl.ofdm_receiver import ofdm_receiver + # ///////////////////////////////////////////////////////////////////////////// # mod/demod with packets as i/o @@ -34,7 +38,7 @@ class mod_ofdm_pkts(gr.hier_block): Send packets by calling send_pkt """ - def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True): + def __init__(self, fg, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets @@ -43,29 +47,38 @@ class mod_ofdm_pkts(gr.hier_block): @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 + win = [] #[1 for i in range(self._fft_length)] + + # hard-coded known symbol + ks1 = known_symbols_4512_1[0:options.occupied_tones] + #ks1 = known_symbols_4512_impulse[0:options.occupied_tones] + ks2 = known_symbols_4512_2[0:options.occupied_tones] + + symbol_length = options.fft_length + options.cp_length # 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) + self._pkt_input = gr.ofdm_bpsk_mapper(msgq_limit, options.occupied_tones, options.fft_length, ks1, ks2) + self.ifft = gr.fft_vcc(options.fft_length, False, win, True) + self.cp_adder = gr.ofdm_cyclic_prefixer(options.fft_length, symbol_length) + self.scale = gr.multiply_const_cc(1.0 / math.sqrt(options.fft_length)) + + fg.connect(self._pkt_input, self.ifft, self.cp_adder, self.scale) + + if options.verbose: + self._print_verbage() + + if 1: + fg.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) + + gr.hier_block.__init__(self, fg, None, self.scale) def send_pkt(self, payload='', eof=False): """ @@ -79,14 +92,41 @@ class mod_ofdm_pkts(gr.hier_block): 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.samples_per_symbol(), + self.bits_per_symbol(), self._pad_for_usrp) #print "pkt =", string_to_hex_list(pkt) msg = gr.message_from_string(pkt) self._pkt_input.msgq().insert_tail(msg) + def samples_per_symbol(self): + return 2 + + 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 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 demod_ofdm_pkts(gr.hier_block): @@ -97,7 +137,7 @@ class demod_ofdm_pkts(gr.hier_block): app via the callback. """ - def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1): + def __init__(self, fg, options, callback=None): """ Hierarchical block for demodulating and deframing packets. @@ -108,36 +148,54 @@ class demod_ofdm_pkts(gr.hier_block): @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._rcvd_pktq = gr.msg_queue() # holds packets from the PHY - 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 + ks1 = known_symbols_4512_1[0:options.occupied_tones] + #ks1 = known_symbols_4512_impulse[0:options.occupied_tones] + ks2 = known_symbols_4512_2[0:options.occupied_tones] + + symbol_length = options.fft_length + options.cp_length + self.ofdm_recv = ofdm_receiver(fg, options.fft_length, options.cp_length, + options.occupied_tones, options.snr, ks1, ks2) + self.ofdm_demod = gr.ofdm_frame_sink(self._rcvd_pktq, + options.occupied_tones) + + fg.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0)) + fg.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1)) - if threshold == -1: - threshold = 12 # FIXME raise exception + gr.hier_block.__init__(self, fg, self.ofdm_recv, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) - 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) + 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) - 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): @@ -156,3 +214,16 @@ class _queue_watcher_thread(_threading.Thread): ok, payload = ofdm_packet_utils.unmake_packet(msg.to_string()) if self.callback: self.callback(ok, payload) + +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] + + + +known_symbols_4512_1 = [-1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1] + +known_symbols_4512_2 = [1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1] + + +known_symbols_4512_impulse = 4512*[1,] diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py new file mode 100644 index 00000000..e2f59328 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# +# Copyright 2006, 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 math +from gnuradio import gr +from gnuradio.blksimpl.ofdm_sync import ofdm_sync + +class ofdm_receiver(gr.hier_block): + def __init__(self, fg, fft_length, cp_length, occupied_tones, snr, ks1, ks2): + self.fg = fg + + bw = (float(occupied_tones) / float(fft_length)) / 2.0 + tb = bw*0.08 + chan_coeffs = gr.firdes.low_pass (1.0, # gain + 1.0, # sampling rate + bw+tb, # midpoint of trans. band + tb, # width of trans. band + gr.firdes.WIN_HAMMING) # filter type + self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs) + + win = [1 for i in range(fft_length)] + + self.ofdm_sync = ofdm_sync(fg, fft_length, cp_length, snr) + self.fft_demod = gr.fft_vcc(fft_length, True, win, True) + self.ofdm_corr = gr.ofdm_correlator(occupied_tones, fft_length, + cp_length, ks1, ks2) + + self.fg.connect(self.chan_filt, self.ofdm_sync, self.fft_demod, self.ofdm_corr) + + if 1: + self.fg.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "chan_filt_c.dat")) + self.fg.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "fft_out_c.dat")) + self.fg.connect(self.ofdm_corr, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_corr_out_c.dat")) + self.fg.connect((self.ofdm_corr,1), gr.file_sink(1, "found_corr_b.dat")) + + gr.hier_block.__init__(self, fg, self.chan_filt, self.ofdm_corr) diff --git a/gnuradio-examples/python/ofdm/ofdm_receiver.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync.py similarity index 68% rename from gnuradio-examples/python/ofdm/ofdm_receiver.py rename to gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync.py index 467e3af0..271be93d 100644 --- a/gnuradio-examples/python/ofdm/ofdm_receiver.py +++ b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2004,2005,2006 Free Software Foundation, Inc. +# Copyright 2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,29 +22,23 @@ 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 +class ofdm_sync(gr.hier_block): + def __init__(self, fg, fft_length, cp_length, snr): self.fg = fg - - cpsize = symbol_length - fft_length; + + self.input = gr.add_const_cc(0) SNR = 10.0**(snr/10.0) rho = SNR / (SNR + 1.0) + symbol_length = fft_length + cp_length # 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.delay = gr.delay(gr.sizeof_gr_complex, fft_length) self.fg.connect(self.input, self.delay) # magnitude squared blocks @@ -52,7 +46,7 @@ class ofdm_receiver(gr.hier_block): self.magsqrd2 = gr.complex_to_mag_squared() self.adder = gr.add_ff() - moving_sum_taps = [rho/2 for i in range(cpsize)] + moving_sum_taps = [rho/2 for i in range(cp_length)] self.moving_sum_filter = gr.fir_filter_fff(1,moving_sum_taps) self.fg.connect(self.input,self.magsqrd1) @@ -66,10 +60,9 @@ class ofdm_receiver(gr.hier_block): self.conjg = gr.conjugate_cc(); self.mixer = gr.multiply_cc(); - movingsum2_taps = [1.0 for i in range(cpsize)] + movingsum2_taps = [1.0 for i in range(cp_length)] self.movingsum2 = gr.fir_filter_ccf(1,movingsum2_taps) - # Correlator data handler self.c2mag = gr.complex_to_mag() self.angle = gr.complex_to_arg() @@ -77,7 +70,7 @@ class ofdm_receiver(gr.hier_block): 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)) @@ -87,8 +80,7 @@ class ofdm_receiver(gr.hier_block): 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.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005) self.sample_and_hold = gr.sample_and_hold_ff() self.nco = gr.frequency_modulator_fc(nco_sensitivity) self.inv = gr.multiply_const_ff(-1) @@ -99,49 +91,51 @@ class ofdm_receiver(gr.hier_block): 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) + # use the sync loop values to set the sampler and the NCO + # self.diff = theta + # self.angle = epsilon + + self.fg.connect(self.diff, self.pk_detect) + use_dpll = 1 + + fixed_timing = 0 + if fixed_timing: + # Use a fixed trigger point instead of sync block + peak_null = gr.null_sink(gr.sizeof_char) data = 640*[0,] data[639] = 1 - peak_trigger = gr.vector_source_f(data, True) + peak_trigger = gr.vector_source_b(data, True) - self.fg.connect(self.pkt_detect, peak_null) - self.fg.connect(peak_trigger, self.f2c, (self.sampler,1)) + self.fg.connect(self.pk_detect, peak_null) + self.fg.connect(peak_trigger, (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: + else: + self.dpll = gr.dpll_bb(float(symbol_length),0.01) if use_dpll: - self.fg.connect(self.pkt_detect, self.dpll,self.f2c, (self.sampler,1)) + self.fg.connect(self.pk_detect, self.dpll) + self.fg.connect(self.dpll, (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)) + else: + self.fg.connect(self.pk_detect, (self.sampler,1)) + self.fg.connect(self.pk_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: + if 1: 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")) + if fixed_timing: + self.fg.connect(peak_trigger, gr.file_sink(gr.sizeof_char, "peaks_b.dat")) else: - self.fg.connect(self.pkt_detect, gr.file_sink(gr.sizeof_float, "peaks_f.dat")) - + self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "peaks_b.dat")) + if use_dpll: + self.fg.connect(self.dpll, gr.file_sink(gr.sizeof_char, "dpll_b.dat")) + + self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "sigmix_c.dat")) + self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "sampler_c.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-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am index 557bf13f..dc0e4a8a 100644 --- a/gnuradio-core/src/python/gnuradio/gr/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -55,6 +55,7 @@ noinst_PYTHON = \ qa_complex_to_xxx.py \ qa_constellation_decoder_cb.py \ qa_correlate_access_code.py \ + qa_delay.py \ qa_diff_encoder.py \ qa_diff_phasor_cc.py \ qa_feval.py \ @@ -89,6 +90,7 @@ noinst_PYTHON = \ qa_sig_source.py \ qa_single_pole_iir.py \ qa_single_pole_iir_cc.py \ + qa_skiphead.py \ qa_unpack_k_bits.py diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_delay.py b/gnuradio-core/src/python/gnuradio/gr/qa_delay.py new file mode 100755 index 00000000..8bef4635 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_delay.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2004 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, gr_unittest +import math + +class test_delay (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_000 (self): + delta_t = 0 + fg = self.fg + src_data = [float(x) for x in range(0, 100)] + expected_result = tuple(delta_t*[0.0] + src_data) + + src = gr.vector_source_f(src_data) + op = gr.delay(gr.sizeof_float, delta_t) + dst = gr.vector_sink_f () + + fg.connect (src, op, dst) + fg.run () + dst_data = dst.data () + self.assertEqual (expected_result, dst_data) + + def test_010 (self): + delta_t = 10 + fg = self.fg + src_data = [float(x) for x in range(0, 100)] + expected_result = tuple(delta_t*[0.0] + src_data[0:-delta_t]) + + src = gr.vector_source_f(src_data) + op = gr.delay(gr.sizeof_float, delta_t) + dst = gr.vector_sink_f () + + fg.connect (src, op, dst) + fg.run () + dst_data = dst.data () + self.assertEqual (expected_result, dst_data) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py b/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py new file mode 100755 index 00000000..4a25f492 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py @@ -0,0 +1,102 @@ +#!/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. +# + +from gnuradio import gr, gr_unittest + +class test_skiphead (gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + self.src_data = [int(x) for x in range(65536)] + + def tearDown(self): + self.fg = None + + def test_skip_0(self): + skip_cnt = 0 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_1(self): + skip_cnt = 1 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_1023(self): + skip_cnt = 1023 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_6339(self): + skip_cnt = 6339 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_12678(self): + skip_cnt = 12678 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_all(self): + skip_cnt = len(self.src_data) + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py b/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py new file mode 100755 index 00000000..4a79cb62 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def help_stream_2ff(self, N, stream_sizes): + v0 = gr.vector_source_f(N*[1,], False) + v1 = gr.vector_source_f(N*[2,], False) + + mux = gr.stream_mux(gr.sizeof_float, stream_sizes) + + dst = gr.vector_sink_f () + + self.fg.connect (v0, (mux,0)) + self.fg.connect (v1, (mux,1)) + self.fg.connect (mux, dst) + self.fg.run () + + return dst.data () + + def help_stream_ramp_2ff(self, N, stream_sizes): + r1 = range(N) + r2 = range(N) + r2.reverse() + + v0 = gr.vector_source_f(r1, False) + v1 = gr.vector_source_f(r2, False) + + mux = gr.stream_mux(gr.sizeof_float, stream_sizes) + + dst = gr.vector_sink_f () + + self.fg.connect (v0, (mux,0)) + self.fg.connect (v1, (mux,1)) + self.fg.connect (mux, dst) + self.fg.run () + + return dst.data () + + def test_stream_2NN_ff(self): + N = 40 + stream_sizes = [10, 10] + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0) + self.assertEqual (exp_data, result_data) + + def test_stream_ramp_2NN_ff(self): + N = 40 + stream_sizes = [10, 10] + result_data = self.help_stream_ramp_2ff(N, stream_sizes) + + exp_data = ( 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 39.0, 38.0, 37.0, 36.0, 35.0, 34.0, 33.0, 32.0, 31.0, 30.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, + 29.0, 28.0, 27.0, 26.0, 25.0, 24.0, 23.0, 22.0, 21.0, 20.0, + 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, + 19.0, 18.0, 17.0, 16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0, + 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, + 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0) + self.assertEqual (exp_data, result_data) + + + def test_stream_2NM_ff(self): + N = 40 + stream_sizes = [7, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0) + + self.assertEqual (exp_data, result_data) + + + def test_stream_2MN_ff(self): + N = 37 + stream_sizes = [7, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0) + + self.assertEqual (exp_data, result_data) + + def test_stream_2N0_ff(self): + N = 30 + stream_sizes = [7, 0] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0) + + self.assertEqual (exp_data, result_data) + + def test_stream_20N_ff(self): + N = 30 + stream_sizes = [0, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0) + + self.assertEqual (exp_data, result_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py b/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py index e2b26306..006ca6de 100644 --- a/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py +++ b/gnuradio-core/src/python/gnuradio/ofdm_packet_utils.py @@ -68,9 +68,6 @@ def conv_1_0_string_to_packed_binary_string(s): 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 @@ -99,8 +96,7 @@ def make_header(payload_len, whitener_offset=0): 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): + pad_for_usrp=True, whitener_offset=0, dowhiten=1): """ Build a packet, given access code, payload, and whitener offset @@ -109,20 +105,14 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, @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:]) @@ -131,16 +121,18 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, 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_hd = 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) + pkt_dt = pkt_dt + usrp_packing + + if(dowhiten): + pkt = pkt_hd + whiten(pkt_dt, whitener_offset) + else: + pkt = pkt_hd + pkt_dt #print "make_packet: len(pkt) =", len(pkt) @@ -168,13 +160,17 @@ def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol): return byte_modulus - r -def unmake_packet(whitened_payload_with_crc, whitener_offset=0): +def unmake_packet(whitened_payload_with_crc, whitener_offset=0, dodewhiten=1): """ Return (ok, payload) @param whitened_payload_with_crc: string """ - payload_with_crc = dewhiten(whitened_payload_with_crc, whitener_offset) + if dodewhiten: + payload_with_crc = dewhiten(whitened_payload_with_crc, whitener_offset) + else: + payload_with_crc = whitened_payload_with_crc + ok, payload = gru.check_crc32(payload_with_crc) if 0: diff --git a/gnuradio-examples/python/ofdm/Makefile.am b/gnuradio-examples/python/ofdm/Makefile.am index 23df3f9d..cbaa45b5 100644 --- a/gnuradio-examples/python/ofdm/Makefile.am +++ b/gnuradio-examples/python/ofdm/Makefile.am @@ -25,8 +25,6 @@ EXTRA_DIST = \ 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 index 3b4761d5..53f4bd0b 100755 --- a/gnuradio-examples/python/ofdm/benchmark_ofdm.py +++ b/gnuradio-examples/python/ofdm/benchmark_ofdm.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2005, 2006 Free Software Foundation, Inc. +# Copyright 2006, 2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,90 +20,68 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gru, modulation_utils -from gnuradio import usrp +from gnuradio import gr, blks from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser +from gnuradio.blksimpl import ofdm_pkt 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.channel_on: + SNR = 10.0**(options.snr/10.0) + power_in_signal = 1.0 + noise_power_in_channel = power_in_signal/SNR + noise_voltage = math.sqrt(noise_power_in_channel/2.0) + print "Noise voltage: ", noise_voltage - 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")) + frequency_offset = options.frequency_offset / options.fft_length + if options.multipath_on: + taps = [1.0, .2, 0.0, .1, .08, -.4, .12, -.2, 0, 0, 0, .3] 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")) - + taps = [1.0, 0.0] + + else: + noise_voltage = 0.0 + frequency_offset = 0.0 + taps = [1.0, 0.0] + + symbols_per_packet = math.ceil(((4+options.size+4) * 8) / options.occupied_tones) + samples_per_packet = (symbols_per_packet+2) * (options.fft_length+options.cp_length) + print "Symbols per Packet: ", symbols_per_packet + print "Samples per Packet: ", samples_per_packet + if options.discontinuous: + stream_size = [100000, int(options.discontinuous*samples_per_packet)] 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")) + stream_size = [0, 100000] + z = [0,] + self.zeros = gr.vector_source_c(z, True) + self.txpath = transmit_path(self, options) + self.mux = gr.stream_mux(gr.sizeof_gr_complex, stream_size) + self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate) + self.channel = blks.channel_model(self, noise_voltage, frequency_offset, options.clockrate_ratio, taps) + self.rxpath = receive_path(self, callback, options) + + self.connect(self.zeros, (self.mux,0)) + self.connect(self.txpath, (self.mux,1)) + self.connect(self.mux, self.throttle, self.channel, self.rxpath) + + self.connect(self.txpath, gr.file_sink(gr.sizeof_gr_complex, "txpath.dat")) + self.connect(self.mux, gr.file_sink(gr.sizeof_gr_complex, "mux.dat")) + self.connect(self.channel, gr.file_sink(gr.sizeof_gr_complex, "channel.dat")) + # ///////////////////////////////////////////////////////////////////////////// # main # ///////////////////////////////////////////////////////////////////////////// @@ -124,6 +102,17 @@ def main(): 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) + + printlst = list() + for x in payload[2:]: + t = hex(ord(x)).replace('0x', '') + if(len(t) == 1): + t = '0' + t + printlst.append(t) + printable = ''.join(printlst) + + print printable + print "\n" parser = OptionParser(option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") @@ -137,21 +126,22 @@ def main(): 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)") + parser.add_option("", "--clockrate-ratio", type="eng_float", default=1.0, + help="set clock rate ratio (sample rate difference) between two systems [default=%default]") + parser.add_option("","--discontinuous", type="int", default=0, + help="enable discontinous transmission, burst of N packets [Default is continuous]") + parser.add_option("","--channel-on", action="store_true", default=True, + help="Enables AWGN, freq offset") + parser.add_option("","--multipath-on", action="store_true", default=False, + help="enable multipath") 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) + ofdm_pkt.mod_ofdm_pkts.add_options(parser, expert_grp) + ofdm_pkt.demod_ofdm_pkts.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) @@ -167,12 +157,12 @@ def main(): 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 + #r = ''.join([chr(random.randint(0,255)) for i in range(pkt_size-2)]) + #pkt_contents = struct.pack('!H', pktno) + r + + pkt_contents = struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff) + send_pkt(pkt_contents) n += pkt_size #sys.stderr.write('.') diff --git a/gnuradio-examples/python/ofdm/ofdm.py b/gnuradio-examples/python/ofdm/ofdm.py deleted file mode 100644 index 8b1e616f..00000000 --- a/gnuradio-examples/python/ofdm/ofdm.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/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_mod_demod_test.py b/gnuradio-examples/python/ofdm/ofdm_mod_demod_test.py new file mode 100755 index 00000000..5fe81a53 --- /dev/null +++ b/gnuradio-examples/python/ofdm/ofdm_mod_demod_test.py @@ -0,0 +1,179 @@ +#!/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, ofdm_packet_utils +import gnuradio.gr.gr_threading as _threading +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys, math, os + +class my_graph(gr.flow_graph): + def __init__(self, callback, options): + gr.flow_graph.__init__(self) + + # hard-coded known symbol + ks1 = known_symbols_4512_1[0:options.occupied_tones] + ks2 = known_symbols_4512_2[0:options.occupied_tones] + + self._rcvd_pktq = gr.msg_queue() + + # accepts messages from the outside world + self.ofdm_mapper = gr.ofdm_bpsk_mapper(4, options.occupied_tones, options.fft_length, ks1, ks2) + self.ofdm_corr = gr.ofdm_correlator(options.occupied_tones, options.fft_length, 0, ks1, ks2) + self.ofdm_framer = gr.ofdm_frame_sink(self._rcvd_pktq, options.occupied_tones) + + if 0: # set to 1 to put the correlator in the path to take over the signalling + self.connect((self.ofdm_mapper, 0), (self.ofdm_corr, 0)) + self.connect((self.ofdm_corr, 0), (self.ofdm_framer, 0)) + self.connect((self.ofdm_corr, 1), (self.ofdm_framer, 1)) + + self.connect((self.ofdm_mapper,0), gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper.dat")) + self.connect((self.ofdm_corr,0), gr.file_sink(gr.sizeof_gr_complex*options.occupied_tones, "ofdm_corr.dat")) + self.connect((self.ofdm_corr,1), gr.file_sink(gr.sizeof_char, "ofdm_sig.dat")) + + else: + self.connect((self.ofdm_mapper, 0), (self.ofdm_framer, 0)) + self.connect((self.ofdm_mapper, 1), (self.ofdm_framer, 1)) + + self.connect((self.ofdm_mapper,0), gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper.dat")) + self.connect((self.ofdm_mapper,1), gr.file_sink(gr.sizeof_char, "ofdm_sig.dat")) + + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + def send_pkt(self, payload='', eof=False): + if eof: + msg = gr.message(1) + else: + pkt = ofdm_packet_utils.make_packet(payload, 1, 1, False, whiten=False) + msg = gr.message_from_string(pkt) + self.ofdm_mapper.msgq().insert_tail(msg) + +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(), whiten=False) + if self.callback: + self.callback(ok, payload) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + ''' Use this program to tie the OFDM modulators straight into the frame sink, with or without + the correlator in between. This is for testing of the modulators and demodulators only without + receiver and sync functionality.''' + + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def send_pkt(payload='', eof=False): + return fg.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) + + printlst = list() + for x in payload[2:]: + t = hex(ord(x)).replace('0x', '') + if(len(t) == 1): + t = '0' + t + printlst.append(t) + printable = ''.join(printlst) + + print printable + print "\n" + + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + expert = 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]") + 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]") + 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]") + + (options, args) = parser.parse_args () + + # build the graph + fg = my_graph(rx_callback, options) + + 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) + r + + pkt_contents = struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff) + + send_pkt(pkt_contents) + n += pkt_size + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + +known_symbols_4512_1 = [-1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1] + +known_symbols_4512_2 = [1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1] + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-examples/python/ofdm/ofdm_sync.m b/gnuradio-examples/python/ofdm/ofdm_sync.m new file mode 100644 index 00000000..d5df4213 --- /dev/null +++ b/gnuradio-examples/python/ofdm/ofdm_sync.m @@ -0,0 +1,28 @@ +% + +function [theta, g, g1, k, h] = ofdm_sync(signal,SNR,FFTSIZE,CPLEN) + + rho = SNR/(SNR+1); + + d = abs(signal).^2; + g = [ zeros(1,FFTSIZE) signal(1:max(size(signal))-FFTSIZE) ]; + g1 = conj(g); + f = abs(g).^2; + c = d + f; + moving_sum_taps = rho/2 * ones(1,CPLEN); + b = conv(c,moving_sum_taps); + b = b(1:max(size(signal))); + %b = b(CPLEN:max(size(b))); + + k = g1 .* signal; + + moving_sum_taps2 = ones(1, CPLEN); + h = conv(k,moving_sum_taps2); + h = h(1:max(size(signal))); + %h = h(CPLEN:max(size(h))); + + a = abs(h); + + theta = a-b; + +endfunction diff --git a/gnuradio-examples/python/ofdm/receive_path.py b/gnuradio-examples/python/ofdm/receive_path.py index 1c9c2384..0e44ffde 100644 --- a/gnuradio-examples/python/ofdm/receive_path.py +++ b/gnuradio-examples/python/ofdm/receive_path.py @@ -28,7 +28,6 @@ import sys # from current dir from pick_bitrate import pick_rx_bitrate -import ofdm # ///////////////////////////////////////////////////////////////////////////// # receive path @@ -43,40 +42,22 @@ class receive_path(gr.hier_block): 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) + self.ofdm_receiver = \ + blks.demod_ofdm_pkts(fg, options, + callback=self._rx_callback) # 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) + #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) + gr.hier_block.__init__(self, fg, self.ofdm_receiver, None) def carrier_sensed(self): """ diff --git a/gnuradio-examples/python/ofdm/transmit_path.py b/gnuradio-examples/python/ofdm/transmit_path.py index 308ec085..e684c442 100644 --- a/gnuradio-examples/python/ofdm/transmit_path.py +++ b/gnuradio-examples/python/ofdm/transmit_path.py @@ -26,9 +26,6 @@ from gnuradio import eng_notation import copy import sys -# from current dir -import ofdm - # ///////////////////////////////////////////////////////////////////////////// # transmit path # ///////////////////////////////////////////////////////////////////////////// @@ -44,13 +41,11 @@ class transmit_path(gr.hier_block): 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 = \ + self.ofdm_transmitter = \ blks.mod_ofdm_pkts(fg, - self.ofdm_mod, - access_code=None, + options, msgq_limit=4, - pad_for_usrp=True) + pad_for_usrp=False) self.amp = gr.multiply_const_cc(1) self.set_tx_amplitude(self._tx_amplitude) @@ -60,7 +55,7 @@ class transmit_path(gr.hier_block): self._print_verbage() # Create and setup transmit path flow graph - fg.connect(self.packet_transmitter, self.amp) + fg.connect(self.ofdm_transmitter, self.amp) gr.hier_block.__init__(self, fg, None, self.amp) def set_tx_amplitude(self, ampl): @@ -75,7 +70,7 @@ class transmit_path(gr.hier_block): """ Calls the transmitter method to send a packet """ - return self.packet_transmitter.send_pkt(payload, eof) + return self.ofdm_transmitter.send_pkt(payload, eof) def bitrate(self): return self._bitrate @@ -87,7 +82,7 @@ class transmit_path(gr.hier_block): """ Adds transmitter-specific options to the Options Parser """ - normal.add_option("", "--tx-amplitude", type="eng_float", default=12000, metavar="AMPL", + normal.add_option("", "--tx-amplitude", type="eng_float", default=1, 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, diff --git a/usrp/fpga/Makefile.extra b/usrp/fpga/Makefile.extra index 7055447a..dc26413c 100644 --- a/usrp/fpga/Makefile.extra +++ b/usrp/fpga/Makefile.extra @@ -72,7 +72,6 @@ EXTRA_DIST = \ sdr_lib/gen_cordic_consts.py \ sdr_lib/gen_sync.v \ sdr_lib/hb/acc.v \ - sdr_lib/hb/coeff_ram.v \ sdr_lib/hb/coeff_rom.v \ sdr_lib/hb/halfband_decim.v \ sdr_lib/hb/halfband_interp.v \ -- 2.30.2