commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r7324 - in gnuradio/trunk: . gnuradio-core/src/lib/gen


From: trondeau
Subject: [Commit-gnuradio] r7324 - in gnuradio/trunk: . gnuradio-core/src/lib/general gnuradio-core/src/python/gnuradio/blks2impl gnuradio-core/src/python/gnuradio/blksimpl gnuradio-core/src/utils gnuradio-examples/python/ofdm
Date: Wed, 2 Jan 2008 10:35:36 -0700 (MST)

Author: trondeau
Date: 2008-01-02 10:35:35 -0700 (Wed, 02 Jan 2008)
New Revision: 7324

Added:
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py
   gnuradio/trunk/gnuradio-core/src/utils/README
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_char.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_c.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_f.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_int.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_short.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/gr_plot_ofdm.py
Removed:
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.h
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.i
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_ml.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pn.py
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_read_binary.py
Modified:
   gnuradio/trunk/AUTHORS
   gnuradio/trunk/gnuradio-core/src/lib/general/Makefile.am
   gnuradio/trunk/gnuradio-core/src/lib/general/general.i
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_math.h
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
   gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_const.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_float.py
   gnuradio/trunk/gnuradio-core/src/utils/gr_plot_iq.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/plot_ofdm.m
   gnuradio/trunk/gnuradio-examples/python/ofdm/receive_path.py
   gnuradio/trunk/gnuradio-examples/python/ofdm/transmit_path.py
Log:
Merging ofdm2 branch -r7047:7321 into trunk. This updates the OFDM code to 
hier_block2 in blks2impl and removed from blksimpl. The new code 
implements a decision feedback sync loop to lock the phase/freq, removes two 
unnecessary premables and performs frame sync and equalization off 
single preamble symbol. Also adds/updates Python plotting tools and a 
branchless clip algorithm in gr_math.h.



Modified: gnuradio/trunk/AUTHORS
===================================================================
--- gnuradio/trunk/AUTHORS      2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/AUTHORS      2008-01-02 17:35:35 UTC (rev 7324)
@@ -11,3 +11,4 @@
 Joshua Lackey <address@hidden> Original GMSK implementation.
 Johnathan Corgan <address@hidden>  Build system, ongoing stuff, release manager
 Bdale Garbee <address@hidden>           Debian release packages
+Tom Rondeau <address@hidden>          Mostly digital waveforms and a little 
bit of trouble

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/Makefile.am
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/Makefile.am    2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/Makefile.am    2008-01-02 
17:35:35 UTC (rev 7324)
@@ -96,7 +96,7 @@
        gr_nop.cc                       \
        gr_null_sink.cc                 \
        gr_null_source.cc               \
-       gr_ofdm_correlator.cc           \
+       gr_ofdm_frame_acquisition.cc    \
         gr_ofdm_cyclic_prefixer.cc      \
         gr_ofdm_demapper_vcb.cc         \
         gr_ofdm_mapper_bcv.cc           \
@@ -109,6 +109,7 @@
         gr_ofdm_sampler.cc              \
        gr_pa_2x2_phase_combiner.cc     \
        gr_packet_sink.cc               \
+       gr_peak_detector2_fb.cc         \
        gr_phase_modulator_fc.cc        \
        gr_pll_carriertracking_cc.cc    \
        gr_pll_freqdet_cf.cc            \
@@ -239,7 +240,7 @@
        gr_nop.h                        \
        gr_null_sink.h                  \
        gr_null_source.h                \
-       gr_ofdm_correlator.h            \
+       gr_ofdm_frame_acquisition.h     \
         gr_ofdm_cyclic_prefixer.h       \
         gr_ofdm_demapper_vcb.h          \
         gr_ofdm_mapper_bcv.h            \
@@ -252,6 +253,7 @@
        gr_ofdm_sampler.h               \
        gr_pa_2x2_phase_combiner.h      \
        gr_packet_sink.h                \
+       gr_peak_detector2_fb.h          \
        gr_phase_modulator_fc.h         \
        gr_pll_carriertracking_cc.h     \
        gr_pll_freqdet_cf.h             \
@@ -383,7 +385,7 @@
        gr_nop.i                        \
        gr_null_sink.i                  \
        gr_null_source.i                \
-       gr_ofdm_correlator.i            \
+       gr_ofdm_frame_acquisition.i     \
         gr_ofdm_cyclic_prefixer.i       \
         gr_ofdm_demapper_vcb.i          \
         gr_ofdm_mapper_bcv.i            \
@@ -396,6 +398,7 @@
        gr_ofdm_sampler.i               \
        gr_pa_2x2_phase_combiner.i      \
        gr_packet_sink.i                \
+       gr_peak_detector2_fb.i          \
        gr_phase_modulator_fc.i         \
        gr_pll_carriertracking_cc.i     \
        gr_pll_freqdet_cf.i             \

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/general.i
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/general.i      2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/general.i      2008-01-02 
17:35:35 UTC (rev 7324)
@@ -93,7 +93,7 @@
 #include <gr_probe_avg_mag_sqrd_cf.h>
 #include <gr_probe_avg_mag_sqrd_f.h>
 #include <gr_probe_signal_f.h>
-#include <gr_ofdm_correlator.h>
+#include <gr_ofdm_frame_acquisition.h>
 #include <gr_ofdm_cyclic_prefixer.h>
 #include <gr_ofdm_bpsk_demapper.h>
 #include <gr_ofdm_mapper_bcv.h>
@@ -128,6 +128,7 @@
 #include <gr_bin_statistics_f.h>
 #include <gr_glfsr_source_b.h>
 #include <gr_glfsr_source_f.h>
+#include <gr_peak_detector2_fb.h>
 %}
 
 %include "gr_nop.i"
@@ -201,7 +202,7 @@
 %include "gr_probe_avg_mag_sqrd_cf.i"
 %include "gr_probe_avg_mag_sqrd_f.i"
 %include "gr_probe_signal_f.i"
-%include "gr_ofdm_correlator.i"
+%include "gr_ofdm_frame_acquisition.i"
 %include "gr_ofdm_cyclic_prefixer.i"
 %include "gr_ofdm_bpsk_demapper.i"
 %include "gr_ofdm_mapper_bcv.i"
@@ -236,3 +237,4 @@
 %include "gr_bin_statistics_f.i"
 %include "gr_glfsr_source_b.i"
 %include "gr_glfsr_source_f.i"
+%include "gr_peak_detector2_fb.i"

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_math.h
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_math.h      2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_math.h      2008-01-02 
17:35:35 UTC (rev 7324)
@@ -64,4 +64,17 @@
   return gr_fast_atan2f(z.imag(), z.real()); 
 }
 
+
+/* This bounds x by +/- clip without a branch */
+
+static inline float gr_branchless_clip(float x, float clip)
+{
+  float x1 = fabsf(x+clip);
+  float x2 = fabsf(x-clip);
+  x1 -= x2;
+  return 0.5*x1;
+}
+
+
+
 #endif /* _GR_MATH_H_ */

Deleted: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc

Deleted: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.h

Deleted: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_correlator.i

Copied: 
gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc (from 
rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc   
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc   
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,223 @@
+/* -*- c++ -*- */
+/*
+ * 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_ofdm_frame_acquisition.h>
+#include <gr_io_signature.h>
+#include <gr_expj.h>
+#include <gr_math.h>
+
+#define VERBOSE 0
+#define M_TWOPI (2*M_PI)
+#define MAX_NUM_SYMBOLS 1000
+
+gr_ofdm_frame_acquisition_sptr
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int 
fft_length, 
+                               unsigned int cplen,
+                               const std::vector<gr_complex> &known_symbol,
+                               unsigned int max_fft_shift_len)
+{
+  return gr_ofdm_frame_acquisition_sptr (new gr_ofdm_frame_acquisition 
(occupied_carriers, fft_length, cplen,
+                                                                       
known_symbol, max_fft_shift_len));
+}
+
+gr_ofdm_frame_acquisition::gr_ofdm_frame_acquisition (unsigned 
occupied_carriers, unsigned int fft_length, 
+                                                     unsigned int cplen,
+                                                     const 
std::vector<gr_complex> &known_symbol,
+                                                     unsigned int 
max_fft_shift_len)
+  : gr_block ("ofdm_frame_acquisition",
+             gr_make_io_signature2 (2, 2, sizeof(gr_complex)*fft_length, 
sizeof(char)),
+             gr_make_io_signature2 (2, 2, 
sizeof(gr_complex)*occupied_carriers, sizeof(char))),
+    d_occupied_carriers(occupied_carriers),
+    d_fft_length(fft_length),
+    d_cplen(cplen),
+    d_freq_shift_len(max_fft_shift_len),
+    d_known_symbol(known_symbol),
+    d_coarse_freq(0),
+    d_phase_count(0)
+{
+  d_symbol_phase_diff.resize(d_fft_length);
+  d_known_phase_diff.resize(d_occupied_carriers);
+  d_hestimate.resize(d_occupied_carriers);
+
+  unsigned int i = 0, j = 0;
+
+  std::fill(d_known_phase_diff.begin(), d_known_phase_diff.end(), 0);
+  for(i = 0; i < d_known_symbol.size()-2; i+=2) {
+    d_known_phase_diff[i] = fabs(gr_fast_atan2f(d_known_symbol[i]) - 
gr_fast_atan2f(d_known_symbol[i+2]));
+  }
+  
+  d_phase_lut = new gr_complex[(2*d_freq_shift_len+1) * MAX_NUM_SYMBOLS];
+  for(i = 0; i <= 2*d_freq_shift_len; i++) {
+    for(j = 0; j < MAX_NUM_SYMBOLS; j++) {
+      d_phase_lut[j + i*MAX_NUM_SYMBOLS] =  
gr_expj(-M_TWOPI*d_cplen/d_fft_length*(i-d_freq_shift_len)*j);
+    }
+  }
+}
+
+gr_ofdm_frame_acquisition::~gr_ofdm_frame_acquisition(void)
+{
+  delete [] d_phase_lut;
+}
+
+void
+gr_ofdm_frame_acquisition::forecast (int noutput_items, gr_vector_int 
&ninput_items_required)
+{
+  unsigned ninputs = ninput_items_required.size ();
+  for (unsigned i = 0; i < ninputs; i++)
+    ninput_items_required[i] = 1;
+}
+
+gr_complex
+gr_ofdm_frame_acquisition::coarse_freq_comp(int freq_delta, int 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);
+
+  //return d_phase_lut[MAX_NUM_SYMBOLS * (d_freq_shift_len + freq_delta) + 
symbol_count];
+}
+
+
+
+bool
+gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int 
zeros_on_left)
+{
+  unsigned int i = 0, j = 0;
+
+  std::fill(d_symbol_phase_diff.begin(), d_symbol_phase_diff.end(), 0);
+  for(i = 0; i < d_fft_length-2; i++) {
+    d_symbol_phase_diff[i] = fabs(gr_fast_atan2f(symbol[i]) - 
gr_fast_atan2f(symbol[i+2]));
+  }
+
+  int index = 0;
+  float max = 0, sum=0;
+  for(i =  zeros_on_left - d_freq_shift_len; i < zeros_on_left + 
d_freq_shift_len; i+=2) {
+    sum = 0;
+    for(j = 0; j < d_occupied_carriers; j++) {
+      sum += (d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
+    }
+    if(fabs(sum) > max) {
+      max = sum;
+      index = i;
+    }
+  }
+
+  d_coarse_freq = index - zeros_on_left;
+
+  if(VERBOSE) {
+    fprintf(stderr, "Coarse Freq Offset: %d\n", d_coarse_freq);
+    for(i = 0; i < 40; i++) {
+      fprintf(stderr, "%+.4f   %+.4f\n", d_known_phase_diff[i], 
+             d_symbol_phase_diff[zeros_on_left+d_coarse_freq+i]);
+    }
+  }
+
+  return true;  //FIXME: don't need ot return anything now
+}
+
+void
+gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, int 
zeros_on_left)
+{
+  unsigned int i=0;
+
+  // Set first tap of equalizer
+  d_hestimate[0] = d_known_symbol[0] / 
+    (coarse_freq_comp(d_coarse_freq,1)*symbol[zeros_on_left+d_coarse_freq]);
+
+  // set every even tap based on known symbol
+  // linearly interpolate between set carriers to set zero-filled carriers
+  // FIXME: is this the best way to set this?
+  for(i = 2; i < d_occupied_carriers; i+=2) {
+    d_hestimate[i] = d_known_symbol[i] / 
+      
(coarse_freq_comp(d_coarse_freq,1)*(symbol[i+zeros_on_left+d_coarse_freq]));
+    d_hestimate[i-1] = (d_hestimate[i] + d_hestimate[i-2]) / gr_complex(2.0, 
0.0);    
+  }
+
+  // with even number of carriers; last equalizer tap is wrong
+  if(!(d_occupied_carriers & 1)) {
+    d_hestimate[d_occupied_carriers-1] = d_hestimate[d_occupied_carriers-2];
+  }
+
+  if(VERBOSE) {
+    fprintf(stderr, "Equalizer setting:\n");
+    for(i = 0; i < d_occupied_carriers; i++) {
+      gr_complex sym = 
coarse_freq_comp(d_coarse_freq,1)*symbol[i+zeros_on_left+d_coarse_freq];
+      gr_complex output = sym * d_hestimate[i];
+      fprintf(stderr, "sym: %+.4f + j%+.4f  ks: %+.4f + j%+.4f  eq: %+.4f + 
j%+.4f  ==>  %+.4f + j%+.4f\n", 
+             sym .real(), sym.imag(),
+             d_known_symbol[i].real(), d_known_symbol[i].imag(),
+             d_hestimate[i].real(), d_hestimate[i].imag(),
+             output.real(), output.imag());
+    }
+    fprintf(stderr, "\n");
+  }
+}
+
+int
+gr_ofdm_frame_acquisition::general_work(int noutput_items,
+                                       gr_vector_int &ninput_items,
+                                       gr_vector_const_void_star &input_items,
+                                       gr_vector_void_star &output_items)
+{
+  const gr_complex *symbol = (const gr_complex *)input_items[0];
+  const char *trigger = (const char *)input_items[1];
+
+  gr_complex *out = (gr_complex *) output_items[0];
+  char *sig = (char *) output_items[1];
+  
+  int unoccupied_carriers = d_fft_length - d_occupied_carriers;
+  int zeros_on_left = (int)ceil(unoccupied_carriers/2.0);
+
+  int found = 0;
+  for(int i = 0; i < ninput_items[1]; i++) {
+    found += trigger[i];
+  }
+
+  if(found) {
+    d_phase_count = 1;
+    correlate(symbol, zeros_on_left);
+    calculate_equalizer(symbol, zeros_on_left);
+    sig[0] = 1;
+  }
+  else {
+    sig[0] = 0;
+  }
+
+  for(unsigned int i = 0; i < d_occupied_carriers; i++) {
+    out[i] = d_hestimate[i]*coarse_freq_comp(d_coarse_freq,d_phase_count)
+      *symbol[i+zeros_on_left+d_coarse_freq];
+  }
+  
+  d_phase_count++;
+  if(d_phase_count == MAX_NUM_SYMBOLS) {
+    d_phase_count = 1;
+  }
+
+  consume(0,1);
+  consume(1,ninput_items[1]);
+  return 1;
+}

Copied: 
gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h (from 
rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h    
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h    
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/*
+ * 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_OFDM_FRAME_ACQUISITION_H
+#define INCLUDED_GR_OFDM_FRAME_ACQUISITION_H
+
+
+#include <gr_block.h>
+#include <vector>
+
+class gr_ofdm_frame_acquisition;
+typedef boost::shared_ptr<gr_ofdm_frame_acquisition> 
gr_ofdm_frame_acquisition_sptr;
+
+gr_ofdm_frame_acquisition_sptr 
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int 
fft_length,
+                               unsigned int cplen,
+                               const std::vector<gr_complex> &known_symbol, 
+                               unsigned int max_fft_shift_len=10);
+
+/*!
+ * \brief take a vector of complex constellation points in from an FFT
+ * and performs a correlation and equalization.
+ * \inblock blocks
+ *
+ * This block takes the output of an FFT of a received OFDM symbol and finds 
the 
+ * start of a frame based on two known symbols. It also looks at the 
surrounding
+ * bins in the FFT output for the correlation in case there is a large 
frequency
+ * shift in the data. This block assumes that the fine frequency shift has 
already
+ * been corrected and that the samples fall in the middle of one FFT bin.
+ *
+ * It then uses one of those known
+ * 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.
+ */
+
+class gr_ofdm_frame_acquisition : public gr_block
+{
+  /*! 
+   * \brief Build an OFDM correlator and equalizer.
+   * \param occupied_carriers   The number of subcarriers with data in the 
received symbol
+   * \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
+   *                            start of a frame after known_symbol1 (usually 
a BPSK PN sequence). 
+   *                            Both of these start symbols are differentially 
correlated to compensate
+   *                            for phase changes between symbols. 
+   * \param max_fft_shift_len   Set's the maximum distance you can look 
between bins for correlation
+   */
+  friend gr_ofdm_frame_acquisition_sptr
+  gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int 
fft_length,
+                                 unsigned int cplen,
+                                 const std::vector<gr_complex> &known_symbol, 
+                                 unsigned int max_fft_shift_len);
+  
+protected:
+  gr_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int 
fft_length,
+                            unsigned int cplen,
+                            const std::vector<gr_complex> &known_symbol, 
+                            unsigned int max_fft_shift_len);
+  
+ private:
+  unsigned char slicer(gr_complex x);
+  bool correlate(const gr_complex *symbol, int zeros_on_left);
+  void calculate_equalizer(const gr_complex *symbol, int zeros_on_left);
+  gr_complex coarse_freq_comp(int freq_delta, int count);
+  
+  unsigned int d_occupied_carriers;  // !< \brief number of subcarriers with 
data
+  unsigned int d_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<gr_complex> d_known_symbol; // !< \brief known symbols at start 
of frame
+  std::vector<float> d_known_phase_diff; // !< \brief factor used in 
correlation from known symbol
+  std::vector<float> d_symbol_phase_diff; // !< \brief factor used in 
correlation from received symbol
+  std::vector<gr_complex> d_hestimate;  // !< channel estimate
+  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
+
+  gr_complex *d_phase_lut;  // !< look-up table for coarse frequency 
compensation
+
+  void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ public:
+  /*!
+   * \brief Return an estimate of the SNR of the channel
+   */
+  float snr() { return d_snr_est; }
+
+  ~gr_ofdm_frame_acquisition(void);
+  int general_work(int noutput_items,
+                  gr_vector_int &ninput_items,
+                  gr_vector_const_void_star &input_items,
+                  gr_vector_void_star &output_items);
+};
+
+
+#endif

Copied: 
gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i (from 
rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i    
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i    
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <vector>
+
+GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_acquisition);
+
+gr_ofdm_frame_acquisition_sptr 
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, 
+                               unsigned int fft_length,
+                               unsigned int cplen,
+                               const std::vector<gr_complex> &known_symbol, 
+                               unsigned int max_fft_shift_len=4);
+
+class gr_ofdm_frame_acquisition : public gr_sync_decimator
+{
+ protected:
+  gr_ofdm_frame_acquisition (unsigned int occupied_carriers,
+                            unsigned int fft_length,
+                            unsigned int cplen,
+                            const std::vector<gr_complex> &known_symbol, 
+                            unsigned int max_fft_shift_len);
+
+ public:
+  float snr() { return d_snr_est; }
+  int general_work(int noutput_items,
+                  gr_vector_int &ninput_items,
+                  gr_vector_const_void_star &input_items,
+                  gr_vector_void_star &output_items);
+};

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc  
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc  
2008-01-02 17:35:35 UTC (rev 7324)
@@ -26,8 +26,12 @@
 
 #include <gr_ofdm_frame_sink.h>
 #include <gr_io_signature.h>
+#include <gr_expj.h>
+#include <gr_math.h>
+#include <math.h>
 #include <cstdio>
 #include <stdexcept>
+#include <iostream>
 
 #define VERBOSE 0
 
@@ -55,6 +59,11 @@
 
   d_header = 0;
   d_headerbytelen_cnt = 0;
+
+  // Resetting PLL
+  d_freq = 0.0;
+  d_phase = 0.0;
+  fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
 }
 
 inline void
@@ -96,7 +105,11 @@
                                          unsigned char *out)
 {
   unsigned int i=0, bytes_produced=0;
+  gr_complex carrier;
 
+  carrier=gr_expj(d_phase);
+
+  gr_complex accum_error = 0.0;
   while(i < d_occupied_carriers) {
     if(d_nresid > 0) {
       d_partial_byte |= d_resid;
@@ -106,8 +119,23 @@
     }
 
     while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
-      //fprintf(stderr, "%f+j%f  = %d\n", in[i].real(), in[i].imag(), 
slicer(in[i])); 
-      unsigned char bits = slicer(in[i++]);
+      gr_complex sigrot = in[i]*carrier*d_dfe[i];
+      
+      if(d_derotated_output != NULL){
+       d_derotated_output[i] = sigrot;
+      }
+      
+      unsigned char bits = slicer(sigrot);
+
+      gr_complex closest_sym = d_sym_position[bits];
+      
+      accum_error += sigrot * conj(closest_sym);
+
+      // FIX THE FOLLOWING STATEMENT
+      if (norm(sigrot)> 0.001) d_dfe[i] +=  
d_eq_gain*(closest_sym/sigrot-d_dfe[i]);
+      
+      i++;
+
       if((8 - d_byte_offset) >= d_nbits) {
        d_partial_byte |= bits << (d_byte_offset);
        d_byte_offset += d_nbits;
@@ -130,7 +158,18 @@
       d_partial_byte = 0;
     }
   }
+  //std::cerr << "accum_error " << accum_error << std::endl;
 
+  float angle = arg(accum_error);
+
+  d_freq = d_freq - d_freq_gain*angle;
+  d_phase = d_phase + d_freq - d_phase_gain*angle;
+  if (d_phase >= 2*M_PI) d_phase -= 2*M_PI;
+  if (d_phase <0) d_phase += 2*M_PI;
+    
+  //if(VERBOSE)
+  //  std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << 
std::endl;
+  
   return bytes_produced;
 }
 
@@ -138,24 +177,30 @@
 gr_ofdm_frame_sink_sptr
 gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position, 
                        const std::vector<unsigned char> &sym_value_out,
-                       gr_msg_queue_sptr target_queue, unsigned int 
occupied_carriers)
+                       gr_msg_queue_sptr target_queue, unsigned int 
occupied_carriers,
+                       float phase_gain, float freq_gain)
 {
   return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(sym_position, 
sym_value_out,
-                                                       target_queue, 
occupied_carriers));
+                                                       target_queue, 
occupied_carriers,
+                                                       phase_gain, freq_gain));
 }
 
 
 gr_ofdm_frame_sink::gr_ofdm_frame_sink(const std::vector<gr_complex> 
&sym_position, 
                                       const std::vector<unsigned char> 
&sym_value_out,
-                                      gr_msg_queue_sptr target_queue, unsigned 
int occupied_carriers)
+                                      gr_msg_queue_sptr target_queue, unsigned 
int occupied_carriers,
+                                      float phase_gain, float freq_gain)
   : 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)),
+                  gr_make_io_signature (1, 1, 
sizeof(gr_complex)*occupied_carriers)),
     d_target_queue(target_queue), d_occupied_carriers(occupied_carriers), 
     d_byte_offset(0), d_partial_byte(0),
-    d_resid(0), d_nresid(0)
+    d_resid(0), 
d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain),
+    d_eq_gain(0.05)
 {
   d_bytes_out = new unsigned char[d_occupied_carriers];
+  d_dfe.resize(occupied_carriers);
+  fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
 
   set_sym_value_out(sym_position, sym_value_out);
   
@@ -179,7 +224,7 @@
 
   d_sym_position  = sym_position;
   d_sym_value_out = sym_value_out;
-  d_nbits = (unsigned long)(log10(d_sym_value_out.size()) / log10(2));
+  d_nbits = (unsigned long)ceil(log10(d_sym_value_out.size()) / log10(2.0));
 
   return true;
 }
@@ -194,12 +239,16 @@
   const char *sig = (const char *) input_items[1];
   unsigned int j = 0;
   unsigned int bytes=0;
+
+  // If the output is connected, send it the derotated symbols
+  if(output_items.size() >= 1)
+    d_derotated_output = (gr_complex *)output_items[0];
+  else
+    d_derotated_output = NULL;
   
   if (VERBOSE)
     fprintf(stderr,">>> Entering state machine\n");
-  
-  bytes = demapper(&in[0], d_bytes_out);
-  
+
   switch(d_state) {
       
   case STATE_SYNC_SEARCH:    // Look for flag indicating beginning of pkt
@@ -212,6 +261,10 @@
     break;
 
   case STATE_HAVE_SYNC:
+    // only demod after getting the preamble signal; otherwise, the 
+    // equalizer taps will screw with the PLL performance
+    bytes = demapper(&in[0], d_bytes_out);
+    
     if (VERBOSE) {
       if(sig[0])
        printf("ERROR -- Found SYNC in HAVE_SYNC\n");
@@ -258,6 +311,8 @@
     break;
       
   case STATE_HAVE_HEADER:
+    bytes = demapper(&in[0], d_bytes_out);
+
     if (VERBOSE) {
       if(sig[0])
        printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", 
d_packetlen_cnt, d_packetlen);
@@ -288,6 +343,6 @@
     assert(0);
     
   } // switch
-  
+
   return 1;
 }

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h   
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h   
2008-01-02 17:35:35 UTC (rev 7324)
@@ -32,7 +32,8 @@
 gr_ofdm_frame_sink_sptr 
 gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position, 
                         const std::vector<unsigned char> &sym_value_out,
-                        gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones);
+                        gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones,
+                        float phase_gain=0.25, float freq_gain=0.25*0.25/4.0);
 
 /*!
  * \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs
@@ -47,7 +48,8 @@
   friend gr_ofdm_frame_sink_sptr 
   gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position, 
                           const std::vector<unsigned char> &sym_value_out,
-                          gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones);
+                          gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones,
+                          float phase_gain, float freq_gain);
 
  private:
   enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER};
@@ -71,17 +73,26 @@
   int                d_packet_whitener_offset;  // offset into whitener string 
to use
   int               d_packetlen_cnt;           // how many so far
 
+  gr_complex * d_derotated_output;  // Pointer to output stream to send 
deroated symbols out
+
   std::vector<gr_complex>    d_sym_position;
   std::vector<unsigned char> d_sym_value_out;
+  std::vector<gr_complex>    d_dfe;
   unsigned int d_nbits;
 
   unsigned char d_resid;
   unsigned int d_nresid;
+  float d_phase;
+  float d_freq;
+  float d_phase_gain;
+  float d_freq_gain;
+  float d_eq_gain;
 
  protected:
   gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position, 
                     const std::vector<unsigned char> &sym_value_out,
-                    gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones);
+                    gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones,
+                    float phase_gain, float freq_gain);
 
   void enter_search();
   void enter_have_sync();

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i   
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i   
2008-01-02 17:35:35 UTC (rev 7324)
@@ -25,14 +25,16 @@
 gr_ofdm_frame_sink_sptr 
 gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position, 
                        const std::vector<unsigned char> &sym_value_out,
-                       gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones);
+                       gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones,
+                       float phase_gain=0.25, float freq_gain=0.25*0.25/4);
 
 class gr_ofdm_frame_sink : public gr_sync_block
 {
  protected:
   gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position, 
                     const std::vector<unsigned char> &sym_value_out,
-                    gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones);
+                    gr_msg_queue_sptr target_queue, unsigned int 
occupied_tones,
+                    float phase_gain, float freq_gain);
 
  public:
   ~gr_ofdm_frame_sink();

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc  
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc  
2008-01-02 17:35:35 UTC (rev 7324)
@@ -54,8 +54,8 @@
 {
   if (!(d_occupied_carriers <= d_fft_length))
     throw std::invalid_argument("gr_ofdm_mapper_bcv: occupied carriers must be 
<= fft_length");
-
-  d_nbits = (unsigned long)(log10(d_constellation.size()) / log10(2));
+  
+  d_nbits = (unsigned long)ceil(log10(d_constellation.size()) / log10(2.0));
 }
 
 gr_ofdm_mapper_bcv::~gr_ofdm_mapper_bcv(void)

Modified: gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc     
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc     
2008-01-02 17:35:35 UTC (rev 7324)
@@ -65,22 +65,26 @@
 
   gr_complex *optr = (gr_complex *) output_items[0];
 
-  int found=0;
+  int found=0, index=0;
 
   int i=d_fft_length-1;
 
-  while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
-    if(trigger[i])
+  // FIXME: This is where we miss if the regeneration happens too soon.
+  //while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
+  while(i<std::min(ninput_items[0],ninput_items[1]) ) {
+    if(trigger[i]) {
       found = 1;
+      index = i++;
+    }
     else
       i++;
   }
-
+  
   if(found) {
-    assert(i-d_fft_length+1 >= 0);
-    for(int j=i-d_fft_length+1;j<=i;j++)
+    assert(index-d_fft_length+1 >= 0);
+    for(int j=index - d_fft_length + 1; j <= index; j++)
       *optr++ = iptr[j];
-    consume_each(i-d_fft_length+2);
+    consume_each(index - d_fft_length + 2);
     //printf("OFDM Sampler found:  ninput_items: %d/%d   noutput_items: %d  
consumed: %d   found: %d\n", 
     //   ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+2), 
found);
   }

Copied: gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc        
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc        
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,106 @@
+/* -*- 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_peak_detector2_fb.h>
+#include <gr_io_signature.h>
+
+gr_peak_detector2_fb_sptr
+gr_make_peak_detector2_fb (float threshold_factor_rise,
+                          int look_ahead, float alpha)
+{
+  return gr_peak_detector2_fb_sptr (new gr_peak_detector2_fb 
(threshold_factor_rise, 
+                                 look_ahead, alpha));
+}
+
+gr_peak_detector2_fb::gr_peak_detector2_fb (float threshold_factor_rise, 
+                                           int look_ahead, float alpha)
+  : gr_sync_block ("peak_detector2_fb",
+                  gr_make_io_signature (1, 1, sizeof(float)),
+                  gr_make_io_signature2 (1, 2, sizeof(char), sizeof(float))),
+    d_threshold_factor_rise(threshold_factor_rise), 
+    d_look_ahead(look_ahead), d_alpha(alpha), d_avg(0.0f), d_found(false)
+{
+}
+
+int
+gr_peak_detector2_fb::work (int noutput_items,
+                           gr_vector_const_void_star &input_items,
+                           gr_vector_void_star &output_items) {
+  float *iptr = (float *) input_items[0];
+  char *optr = (char *) output_items[0];
+  
+  assert(noutput_items >= 2);
+
+  memset(optr, 0, noutput_items*sizeof(char));
+
+  for (int i = 0; i < noutput_items; i++) {
+
+    if (!d_found) {
+      // Have not yet detected presence of peak
+      if (iptr[i] > d_avg * (1.0f + d_threshold_factor_rise)) {
+       d_found = true;
+       d_look_ahead_remaining = d_look_ahead;
+        d_peak_val = -(float)INFINITY;
+      } 
+      else {
+       d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg;
+      }
+    } 
+    else {
+      // Detected presence of peak
+      if (iptr[i] > d_peak_val) {
+        d_peak_val = iptr[i];
+        d_peak_ind = i;
+      } 
+      else if (d_look_ahead_remaining <= 0) {
+        optr[d_peak_ind] = 1;
+        d_found = false;
+        d_avg = iptr[i];
+      }
+      
+      // Have not yet located peak, loop and keep searching.
+      d_look_ahead_remaining--;
+    }
+    
+    // Every iteration of the loop, write debugging signal out if
+    // connected:
+    if (output_items.size() == 2) {
+      float *sigout = (float *) output_items[1];
+      sigout[i] = d_avg;
+    }
+  } // loop
+  
+  if (!d_found) 
+    return noutput_items;
+  
+  // else if detected presence, keep searching during the next call to work.
+  int tmp = d_peak_ind;
+  d_peak_ind = 1;
+  
+  return tmp - 1; 
+}
+
+

Copied: gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h         
                (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h 
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,108 @@
+/* -*- 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_gr_peak_detector2_FB_H
+#define INCLUDED_gr_peak_detector2_FB_H
+
+#include <gr_sync_block.h>
+
+class gr_peak_detector2_fb;
+typedef boost::shared_ptr<gr_peak_detector2_fb> gr_peak_detector2_fb_sptr;
+
+gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float 
threshold_factor_rise = 7,
+                                                    int look_ahead = 1000,
+                                                    float alpha = 0.001);
+
+/*!
+ * \brief Detect the peak of a signal
+ * \ingroup block
+ *
+ * If a peak is detected, this block outputs a 1, 
+ * or it outputs 0's.  A separate debug output may be connected, to
+ * view the internal EWMA described below.
+ *
+ * \param threshold_factor_rise The threshold factor determins when a peak
+ *        is present. An EWMA average of the signal is calculated and when the 
+ *        value of the signal goes over threshold_factor_rise*average, we
+ *        call the peak.
+ * \param look_ahead The look-ahead value is used when the threshold is
+ *        found to locate the peak within this range.
+ * \param alpha The gain value of a single-pole moving average filter
+ */
+
+class gr_peak_detector2_fb : public gr_sync_block
+{
+  friend gr_peak_detector2_fb_sptr 
+  gr_make_peak_detector2_fb (float threshold_factor_rise, int look_ahead, 
float alpha);
+  
+  gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float 
alpha);
+  
+private:
+  float d_threshold_factor_rise;
+  int d_look_ahead;
+  int d_look_ahead_remaining;
+  int d_peak_ind;
+  float d_peak_val;
+  float d_alpha;
+  float d_avg;
+  bool d_found;
+  
+public:
+  
+  /*! \brief Set the threshold factor value for the rise time
+   *  \param thr new threshold factor
+   */
+  void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; }
+  
+  /*! \brief Set the look-ahead factor
+   *  \param look new look-ahead factor
+   */
+  void set_look_ahead(int look) { d_look_ahead = look; }
+  
+  /*! \brief Set the running average alpha
+   *  \param alpha new alpha for running average
+   */
+  void set_alpha(int alpha) { d_alpha = alpha; }
+  
+  /*! \brief Get the threshold factor value for the rise time
+   *  \return threshold factor
+   */
+  float threshold_factor_rise() { return d_threshold_factor_rise; }
+  
+  /*! \brief Get the look-ahead factor value
+   *  \return look-ahead factor
+   */
+  int look_ahead() { return d_look_ahead; }
+  
+  /*! \brief Get the alpha value of the running average
+   *  \return alpha
+   */
+  float alpha() { return d_alpha; }
+  
+  int work (int noutput_items,
+           gr_vector_const_void_star &input_items,
+           gr_vector_void_star &output_items);
+};
+
+#endif
+
+

Copied: gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i         
                (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i 
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,45 @@
+/* -*- 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 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+GR_SWIG_BLOCK_MAGIC(gr,peak_detector2_fb)
+  
+  gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float 
threshold_factor_rise = 7,
+                                                      int look_ahead = 1000,
+                                                      float alpha=0.001);
+
+class gr_peak_detector2_fb : public gr_sync_block
+{
+private:
+  gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float 
alpha);
+  
+public:
+  void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; }
+  void set_look_ahead(int look) { d_look_ahead = look; }
+  void set_alpha(int alpha) { d_avg_alpha = alpha; }
+  
+  float threshold_factor_rise() { return d_threshold_factor_rise; } 
+  int look_ahead() { return d_look_ahead; }
+  float alpha() { return d_avg_alpha; }
+};
+
+

Modified: gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am      
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am      
2008-01-02 17:35:35 UTC (rev 7324)
@@ -40,6 +40,12 @@
        cpm.py                  \
        nbfm_rx.py              \
        nbfm_tx.py              \
+       ofdm.py                 \
+       ofdm_receiver.py        \
+       ofdm_sync_fixed.py      \
+       ofdm_sync_pn.py         \
+       ofdm_sync_pnac.py       \
+       ofdm_sync_ml.py         \
        pkt.py                  \
        psk.py                  \
        qam.py                  \

Copied: gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py          
                (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py  
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,311 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from gnuradio import gr, ofdm_packet_utils
+import gnuradio.gr.gr_threading as _threading
+import psk, qam
+
+from gnuradio.blks2impl.ofdm_receiver import ofdm_receiver
+
+
+# /////////////////////////////////////////////////////////////////////////////
+#                   mod/demod with packets as i/o
+# /////////////////////////////////////////////////////////////////////////////
+
+class ofdm_mod(gr.hier_block2):
+    """
+    Modulates an OFDM stream. Based on the options fft_length, occupied_tones, 
and
+    cp_length, this block creates OFDM symbols using a specified modulation 
option.
+    
+    Send packets by calling send_pkt
+    """
+    def __init__(self, options, msgq_limit=2, pad_for_usrp=True):
+        """
+       Hierarchical block for sending packets
+
+        Packets to be sent are enqueued by calling send_pkt.
+        The output is the complex modulated signal at baseband.
+
+        @param options: pass modulation options from higher layers (fft 
length, occupied tones, etc.)
+        @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
+        """
+
+       gr.hier_block2.__init__(self, "ofdm_mod",
+                               gr.io_signature(0, 0, 0),       # Input 
signature
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex)) # 
Output signature
+
+        self._pad_for_usrp = pad_for_usrp
+        self._modulation = options.modulation
+        self._fft_length = options.fft_length
+        self._occupied_tones = options.occupied_tones
+        self._cp_length = options.cp_length
+
+        win = [] #[1 for i in range(self._fft_length)]
+
+        # Use freq domain to get doubled-up known symbol for correlation in 
time domain
+        zeros_on_left = int(math.ceil((self._fft_length - 
self._occupied_tones)/2.0))
+        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
+        for i in range(len(ksfreq)):
+            if((zeros_on_left + i) & 1):
+                ksfreq[i] = 0
+
+        # hard-coded known symbols
+        preambles = (ksfreq,)
+#                     known_symbols_4512_1[0:self._occupied_tones],
+#                     known_symbols_4512_2[0:self._occupied_tones])
+                
+        padded_preambles = list()
+        for pre in preambles:
+            padded = self._fft_length*[0,]
+            padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre
+            padded_preambles.append(padded)
+            
+        symbol_length = options.fft_length + options.cp_length
+        
+        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, 
"qam64": 64, "qam256": 256}
+        arity = mods[self._modulation]
+        
+        rot = 1
+        if self._modulation == "qpsk":
+            rot = (0.707+0.707j)
+            
+        if(self._modulation.find("psk") >= 0):
+            rotated_const = map(lambda pt: pt * rot, 
psk.gray_constellation[arity])
+        elif(self._modulation.find("qam") >= 0):
+            rotated_const = map(lambda pt: pt * rot, qam.constellation[arity])
+        #print rotated_const
+        self._pkt_input = gr.ofdm_mapper_bcv(rotated_const, msgq_limit,
+                                             options.occupied_tones, 
options.fft_length)
+        
+        self.preambles = gr.ofdm_insert_preamble(self._fft_length, 
padded_preambles)
+        self.ifft = gr.fft_vcc(self._fft_length, False, win, True)
+        self.cp_adder = gr.ofdm_cyclic_prefixer(self._fft_length, 
symbol_length)
+        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))
+        
+        self.connect((self._pkt_input, 0), (self.preambles, 0))
+        self.connect((self._pkt_input, 1), (self.preambles, 1))
+        self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, 
self)
+        
+        if options.verbose:
+            self._print_verbage()
+
+        if options.log:
+            self.connect(self._pkt_input, 
gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
+                                                       "ofdm_mapper_c.dat"))
+            self.connect(self.preambles, 
gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
+                                                      "ofdm_preambles.dat"))
+            self.connect(self.ifft, 
gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
+                                                 "ofdm_ifft_c.dat"))
+            self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex,
+                                                     "ofdm_cp_adder_c.dat"))
+
+    def send_pkt(self, payload='', eof=False):
+        """
+        Send the payload.
+
+        @param payload: data to send
+        @type payload: string
+        """
+        if eof:
+            msg = gr.message(1) # tell self._pkt_input we're not sending any 
more packets
+        else:
+            # print "original_payload =", string_to_hex_list(payload)
+            pkt = ofdm_packet_utils.make_packet(payload, 1, 1, 
self._pad_for_usrp, whitening=True)
+            
+            #print "pkt =", string_to_hex_list(pkt)
+            msg = gr.message_from_string(pkt)
+        self._pkt_input.msgq().insert_tail(msg)
+
+    def add_options(normal, expert):
+        """
+        Adds OFDM-specific options to the Options Parser
+        """
+        normal.add_option("-m", "--modulation", type="string", default="bpsk",
+                          help="set modulation type (bpsk, qpsk, 8psk, 
qam{16,64}) [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 "Modulation Type: %s"    % (self._modulation)
+        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_block2):
+    """
+    Demodulates a received OFDM stream. Based on the options fft_length, 
occupied_tones, and
+    cp_length, this block performs synchronization, FFT, and demodulation of 
incoming OFDM
+    symbols and passes packets up the a higher layer.
+
+    The input is complex baseband.  When packets are demodulated, they are 
passed to the
+    app via the callback.
+    """
+
+    def __init__(self, options, callback=None):
+        """
+       Hierarchical block for demodulating and deframing packets.
+
+       The input is the complex modulated signal at baseband.
+        Demodulated packets are sent to the handler.
+
+        @param options: pass modulation options from higher layers (fft 
length, occupied tones, etc.)
+        @param callback:  function of two args: ok, payload
+        @type callback: ok: bool; payload: string
+       """
+       gr.hier_block2.__init__(self, "ofdm_demod",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex)) # 
Output signature
+
+
+        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY
+
+        self._modulation = options.modulation
+        self._fft_length = options.fft_length
+        self._occupied_tones = options.occupied_tones
+        self._cp_length = options.cp_length
+        self._snr = options.snr
+
+        # Use freq domain to get doubled-up known symbol for correlation in 
time domain
+        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
+        for i in range(len(ksfreq)):
+            if(i&1):
+                ksfreq[i] = 0        
+
+        # hard-coded known symbols
+        preambles = (ksfreq,)
+                     #known_symbols_4512_1[0:self._occupied_tones],
+                     #known_symbols_4512_2[0:self._occupied_tones])
+        
+        symbol_length = self._fft_length + self._cp_length
+        self.ofdm_recv = ofdm_receiver(self._fft_length, self._cp_length,
+                                       self._occupied_tones, self._snr, 
preambles,
+                                       options.log)
+
+        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, 
"qam64": 64, "qam256": 256}
+        arity = mods[self._modulation]
+        
+        rot = 1
+        if self._modulation == "qpsk":
+            rot = (0.707+0.707j)
+
+        if(self._modulation.find("psk") >= 0):
+            rotated_const = map(lambda pt: pt * rot, 
psk.gray_constellation[arity])
+        elif(self._modulation.find("qam") >= 0):
+            rotated_const = map(lambda pt: pt * rot, qam.constellation[arity])
+        #print rotated_const
+        self.ofdm_demod = gr.ofdm_frame_sink(rotated_const, range(arity),
+                                             self._rcvd_pktq,
+                                             self._occupied_tones,
+                                             0.25, 0.25*.25/4.0)
+
+        self.connect(self, self.ofdm_recv)
+        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
+        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))
+
+        # added output signature to work around bug, though it might not be a 
bad
+        # thing to export, anyway
+        self.connect(self.ofdm_recv.chan_filt, self)
+
+        if options.log:
+            self.connect(self.ofdm_demod, 
gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones, 
"ofdm_frame_sink_c.dat"))
+        else:
+            self.connect(self.ofdm_demod, 
gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones))
+
+        if options.verbose:
+            self._print_verbage()
+            
+        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
+
+    def add_options(normal, expert):
+        """
+        Adds OFDM-specific options to the Options Parser
+        """
+        normal.add_option("-m", "--modulation", type="string", default="bpsk",
+                          help="set modulation type (bpsk or qpsk) 
[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 demodulator
+        """
+        print "\nOFDM Demodulator:"
+        print "Modulation Type: %s"    % (self._modulation)
+        print "FFT length:      %3d"   % (self._fft_length)
+        print "Occupied Tones:  %3d"   % (self._occupied_tones)
+        print "CP length:       %3d"   % (self._cp_length)
+
+
+
+class _queue_watcher_thread(_threading.Thread):
+    def __init__(self, rcvd_pktq, callback):
+        _threading.Thread.__init__(self)
+        self.setDaemon(1)
+        self.rcvd_pktq = rcvd_pktq
+        self.callback = callback
+        self.keep_running = True
+        self.start()
+
+
+    def run(self):
+        while self.keep_running:
+            msg = self.rcvd_pktq.delete_head()
+            ok, payload = ofdm_packet_utils.unmake_packet(msg.to_string())
+            if self.callback:
+                self.callback(ok, payload)
+
+# Generating known symbols with:
+# i = [2*random.randint(0,1)-1 for i in range(4512)]
+
+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,]
+
+known_symbols_4512_3 = [-1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 
-1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 
-1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 
-1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 
-1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 
-1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 
1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 
-1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 
1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 
1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 
1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 
-1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 
1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 
1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 
1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 
-1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 
-1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 
-1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 
-1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 
1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 
1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 
-1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 
-1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 
1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 
1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 
1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 
1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 
1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 
1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 
-1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 
-1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 
-1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 
-1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 
-1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 
-1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 
1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 
1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 
1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 
1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 
-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 
-1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 
1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 
-1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 
-1, -1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 
-1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 
1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 
-1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 
1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 
1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 
1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 
1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 
1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 
-1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 
1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 
-1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 
-1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 
1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 
-1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 
1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, 
1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 
-1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 
1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 
-1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 
1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 
-1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 
1, -1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 
-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 
1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 
1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 
-1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 
-1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 
-1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 
1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 
1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 
-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 
-1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 
-1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 
-1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 
1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 
-1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 
1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 
1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 
1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, 
-1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 
1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 
-1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 
-1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, 
1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 
1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 
-1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 
1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 
1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 
-1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 
-1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 
-1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 
1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 
1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 
-1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 
-1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, -1, 
-1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 
1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 
-1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 
1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 
-1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 
1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 
-1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 
1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 
1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 
1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 
-1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 
1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 
1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 
-1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 
-1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 
1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, 
-1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 
-1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 
-1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 
-1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 
1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 
-1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 
1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 
-1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 
-1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 
1, -1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 
-1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 
1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 
1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 
-1, -1, -1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 
1, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 
-1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 
1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 
-1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 
-1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 
-1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 
-1, 1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 
-1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 
-1, 1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 
1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 
1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 
1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 
1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 
1, 1, -1, 1, -1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 
-1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 
-1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
-1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 
-1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 
1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 
1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 
-1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 
1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 
1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 
-1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 
-1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 
-1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 
1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 
1, 1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 
-1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 
-1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 
1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 
-1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 
1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 
-1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 
-1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 
-1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 
-1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 
-1, -1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 
-1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 
1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, 
-1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 
1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 
-1, -1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 
1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 
1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 
1, 1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 
1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 
-1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 
1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 
-1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, 
-1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 
1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 
-1, -1, 1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 
1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 
-1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, 
-1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 
1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, 
-1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 
-1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 
-1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, 1, 
1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 
-1, 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 
-1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, -1, 
-1, 1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 
1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 
1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 
1, -1, 1, -1]

Copied: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py 
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py 
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,112 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from numpy import fft
+from gnuradio import gr
+from gnuradio.blks2impl.ofdm_sync_ml import ofdm_sync_ml
+from gnuradio.blks2impl.ofdm_sync_pn import ofdm_sync_pn
+from gnuradio.blks2impl.ofdm_sync_pnac import ofdm_sync_pnac
+from gnuradio.blks2impl.ofdm_sync_fixed import ofdm_sync_fixed
+
+class ofdm_receiver(gr.hier_block2):
+    """
+    Performs receiver synchronization on OFDM symbols.
+
+    The receiver performs channel filtering as well as symbol, frequency, and 
phase synchronization.
+    The synchronization routines are available in three flavors: preamble 
correlator (Schmidl and Cox),
+    modifid preamble correlator with autocorrelation (not yet working), and 
cyclic prefix correlator
+    (Van de Beeks).
+    """
+
+    def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, 
logging=False):
+        """
+       Hierarchical block for receiving OFDM symbols.
+
+       The input is the complex modulated signal at baseband.
+        Synchronized packets are sent back to the demodulator.
+
+        @param fft_length: total number of subcarriers
+        @type  fft_length: int
+        @param cp_length: length of cyclic prefix as specified in subcarriers 
(<= fft_length)
+        @type  cp_length: int
+        @param occupied_tones: number of subcarriers used for data
+        @type  occupied_tones: int
+        @param snr: estimated signal to noise ratio used to guide cyclic 
prefix synchronizer
+        @type  snr: float
+        @param ks: known symbols used as preambles to each packet
+        @type  ks: list of lists
+        @param logging: turn file logging on or off
+        @type  logging: bool
+       """
+
+       gr.hier_block2.__init__(self, "ofdm_receiver",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                                gr.io_signature2(2, 2, 
gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature
+
+        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)]
+
+        zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0))
+        zeros_on_right = fft_length - occupied_tones - zeros_on_left
+        ks0 = zeros_on_left*[0.0,]
+        ks0.extend(ks[0])
+        ks0.extend(zeros_on_right*[0.0,])
+        
+        ks0time = fft.ifft(ks0)
+        # ADD SCALING FACTOR
+        ks0time = ks0time.tolist()
+        
+        SYNC = "pn"
+        if SYNC == "ml":
+            self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, logging)
+        elif SYNC == "pn":
+            self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging)
+        elif SYNC == "pnac":
+            self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time)
+        elif SYNC == "fixed":
+            self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, logging)
+                        
+        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
+        self.ofdm_frame_acq = gr.ofdm_frame_acquisition(occupied_tones, 
fft_length,
+                                                        cp_length, ks[0])
+
+        self.connect(self, self.chan_filt)
+        self.connect(self.chan_filt, self.ofdm_sync, self.fft_demod, 
(self.ofdm_frame_acq,0))
+        self.connect((self.ofdm_sync,1), (self.ofdm_frame_acq,1))
+        self.connect((self.ofdm_frame_acq,0), (self,0))
+        self.connect((self.ofdm_frame_acq,1), (self,1))
+
+        if logging:
+            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, 
"chan_filt_c.dat"))
+            self.connect(self.fft_demod, 
gr.file_sink(gr.sizeof_gr_complex*fft_length, "fft_out_c.dat"))
+            self.connect(self.ofdm_frame_acq,
+                         gr.file_sink(gr.sizeof_gr_complex*occupied_tones, 
"ofdm_frame_acq_c.dat"))
+            self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, 
"found_corr_b.dat"))

Copied: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py)
===================================================================
--- 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py   
                            (rev 0)
+++ 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py   
    2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,49 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from gnuradio import gr
+
+class ofdm_sync_fixed(gr.hier_block2):
+    def __init__(self, fft_length, cp_length, logging=False):
+
+        gr.hier_block2.__init__(self, "ofdm_sync_fixed",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature2(2, 2, 
gr.sizeof_gr_complex*fft_length, gr.sizeof_char)) # Output signature
+
+        # Use a fixed trigger point instead of sync block
+        symbol_length = fft_length + cp_length
+        data = (symbol_length)*[0,]
+        data[(symbol_length)-1] = 1
+        self.peak_trigger = gr.vector_source_b(data, True)
+        self.sampler = gr.ofdm_sampler(fft_length, symbol_length)
+
+        self.connect(self, (self.sampler,0))
+        self.connect(self.peak_trigger, (self.sampler,1))
+        self.connect(self.sampler, (self,0))
+        self.connect(self.peak_trigger, (self,1))
+
+        if logging:
+            self.connect(self.peak_trigger, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_fixed-peaks_b.dat"))
+            self.connect(self.sampler, 
gr.file_sink(gr.sizeof_gr_complex*fft_length,
+                                                    
"ofdm_sync_fixed-sampler_c.dat"))
+

Copied: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py  
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py  
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,142 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from gnuradio import gr
+
+class ofdm_sync_ml(gr.hier_block2):
+    def __init__(self, fft_length, cp_length, snr, logging):
+        ''' Maximum Likelihood OFDM synchronizer:
+        J. van de Beek, M. Sandell, and P. O. Borjesson, "ML Estimation
+        of Time and Frequency Offset in OFDM Systems," IEEE Trans.
+        Signal Processing, vol. 45, no. 7, pp. 1800-1805, 1997.
+        '''
+
+        # FIXME: change the output signature
+        # should be the output of the divider (the normalized peaks) and
+        # the angle value out of the sample and hold block
+        # move sampler out of this block
+
+       gr.hier_block2.__init__(self, "ofdm_sync_ml",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature(1, 1, 
gr.sizeof_gr_complex*fft_length)) # Output signature
+
+        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
+
+        self.connect(self, self.input)
+
+        # Create a delay line
+        self.delay = gr.delay(gr.sizeof_gr_complex, fft_length)
+        self.connect(self.input, self.delay)
+
+        # magnitude squared blocks
+        self.magsqrd1 = gr.complex_to_mag_squared()
+        self.magsqrd2 = gr.complex_to_mag_squared()
+        self.adder = gr.add_ff()
+
+        moving_sum_taps = [rho/2 for i in range(cp_length)]
+        self.moving_sum_filter = gr.fir_filter_fff(1,moving_sum_taps)
+        
+        self.connect(self.input,self.magsqrd1)
+        self.connect(self.delay,self.magsqrd2)
+        self.connect(self.magsqrd1,(self.adder,0))
+        self.connect(self.magsqrd2,(self.adder,1))
+        self.connect(self.adder,self.moving_sum_filter)
+        
+
+        # Correlation from ML Sync
+        self.conjg = gr.conjugate_cc();
+        self.mixer = gr.multiply_cc();
+
+        movingsum2_taps = [1.0 for i in range(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()
+        self.connect(self.input,(self.mixer,1))
+        self.connect(self.delay,self.conjg,(self.mixer,0))
+        self.connect(self.mixer,self.movingsum2,self.c2mag)
+        self.connect(self.movingsum2,self.angle)
+
+        # ML Sync output arg, need to find maximum point of this
+        self.diff = gr.sub_ff()
+        self.connect(self.c2mag,(self.diff,0))
+        self.connect(self.moving_sum_filter,(self.diff,1))
+
+        #ML measurements input to sampler block and detect
+        nco_sensitivity = -1.0/fft_length
+        self.f2c = gr.float_to_complex()
+        self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+        self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005)
+        #self.pk_detect = gr.peak_detector2_fb()
+        self.sample_and_hold = gr.sample_and_hold_ff()
+        self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+        self.sigmix = gr.multiply_cc()
+
+        # Mix the signal with an NCO controlled by the sync loop
+        self.connect(self.input, (self.sigmix,0))
+        self.connect(self.nco, (self.sigmix,1))
+        self.connect(self.sigmix, (self.sampler,0))
+
+        # use the sync loop values to set the sampler and the NCO
+        #     self.diff = theta
+        #     self.angle = epsilon
+                          
+        self.connect(self.diff, self.pk_detect)
+
+        use_dpll = 1
+        if use_dpll:
+            self.dpll = gr.dpll_bb(float(symbol_length),0.01)
+            self.connect(self.pk_detect, self.dpll)
+            self.connect(self.dpll, (self.sampler,1))
+            self.connect(self.dpll, (self.sample_and_hold,1))
+        else:
+            self.connect(self.pk_detect, (self.sampler,1))
+            self.connect(self.pk_detect, (self.sample_and_hold,1))
+            
+        self.connect(self.angle, (self.sample_and_hold,0))
+        self.connect(self.sample_and_hold, self.nco)
+
+        self.connect(self.sampler, self)
+
+        if logging:
+            self.connect(self.diff, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_ml-theta_f.dat"))
+            self.connect(self.angle, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_ml-epsilon_f.dat"))
+            self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_ml-peaks_b.dat"))
+            if use_dpll:
+                self.connect(self.dpll, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_ml-dpll_b.dat"))
+
+            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_ml-sigmix_c.dat"))
+            self.connect(self.sampler, 
gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_ml-sampler_c.dat"))
+            self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_ml-sample_and_hold_f.dat"))
+            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_ml-nco_c.dat"))
+            self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_ml-input_c.dat"))
+

Copied: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py  
                        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py  
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,146 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from numpy import fft
+from gnuradio import gr
+
+class ofdm_sync_pn(gr.hier_block2):
+    def __init__(self, fft_length, cp_length, logging=False):
+        """
+        OFDM synchronization using PN Correlation:
+        T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing
+        Synchonization for OFDM," IEEE Trans. Communications, vol. 45,
+        no. 12, 1997.
+        """
+        
+       gr.hier_block2.__init__(self, "ofdm_sync_pn",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature2(2, 2, 
gr.sizeof_gr_complex*fft_length, gr.sizeof_char)) # Output signature
+
+        # FIXME: when converting to hier_block2's, the output signature
+        # should be the output of the divider (the normalized peaks) and
+        # the angle value out of the sample and hold block
+            
+        self.input = gr.add_const_cc(0)
+
+        symbol_length = fft_length + cp_length
+
+        # PN Sync
+
+        # Create a delay line
+        self.delay = gr.delay(gr.sizeof_gr_complex, fft_length/2)
+
+        # Correlation from ML Sync
+        self.conjg = gr.conjugate_cc();
+        self.corr = gr.multiply_cc();
+
+        # Create a moving sum filter for the corr output
+        if 1:
+            moving_sum_taps = [1.0 for i in range(fft_length//2)]
+            self.moving_sum_filter = gr.fir_filter_ccf(1,moving_sum_taps)
+        else:
+            moving_sum_taps = [complex(1.0,0.0) for i in range(fft_length//2)]
+            self.moving_sum_filter = gr.fft_filter_ccc(1,moving_sum_taps)
+
+        # Create a moving sum filter for the input
+        self.inputmag2 = gr.complex_to_mag_squared()
+        movingsum2_taps = [1.0 for i in range(fft_length//2)]
+
+        if 1:
+            self.inputmovingsum = gr.fir_filter_fff(1,movingsum2_taps)
+        else:
+            self.inputmovingsum = gr.fft_filter_fff(1,movingsum2_taps)
+
+        self.square = gr.multiply_ff()
+        self.normalize = gr.divide_ff()
+     
+        # Get magnitude (peaks) and angle (phase/freq error)
+        self.c2mag = gr.complex_to_mag_squared()
+        self.angle = gr.complex_to_arg()
+
+        self.sample_and_hold = gr.sample_and_hold_ff()
+
+        # Mix the signal with an NCO controlled by the sync loop
+        nco_sensitivity = -2.0/fft_length
+        self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+        self.sigmix = gr.multiply_cc()
+
+        #ML measurements input to sampler block and detect
+        self.sub1 = gr.add_const_ff(-1)
+        self.pk_detect = gr.peak_detector_fb(0.20, 0.20, 30, 0.001)
+        #self.pk_detect = gr.peak_detector2_fb()
+        #self.pk_detect = gr.threshold_detector_fb(0.5)
+        self.regen = gr.regenerate_bb(symbol_length)
+
+        # FIXME: If sampler doesn't get proper input, it can completely
+        # stall the flowgraph.
+        self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+
+        self.connect(self, self.input)
+        
+        self.connect(self.input, self.delay)
+        self.connect(self.input, (self.corr,0))
+        self.connect(self.delay, self.conjg)
+        self.connect(self.conjg, (self.corr,1))
+        self.connect(self.corr, self.moving_sum_filter)
+        self.connect(self.moving_sum_filter, self.c2mag)
+        self.connect(self.moving_sum_filter, self.angle)
+        self.connect(self.angle, (self.sample_and_hold,0))
+        self.connect(self.sample_and_hold, self.nco)
+
+        self.connect(self.input, (self.sigmix,0))
+        self.connect(self.nco, (self.sigmix,1))
+        self.connect(self.sigmix, (self.sampler,0))
+
+        self.connect(self.input, self.inputmag2, self.inputmovingsum)
+        self.connect(self.inputmovingsum, (self.square,0))
+        self.connect(self.inputmovingsum, (self.square,1))
+        self.connect(self.square, (self.normalize,1))
+        self.connect(self.c2mag, (self.normalize,0))
+
+        # Create a moving sum filter for the corr output
+        matched_filter_taps = [1.0/cp_length for i in range(cp_length)]
+        self.matched_filter = gr.fir_filter_fff(1,matched_filter_taps)
+        self.connect(self.normalize, self.matched_filter)
+        
+        self.connect(self.matched_filter, self.sub1, self.pk_detect)
+        self.connect(self.pk_detect, self.regen)
+        self.connect(self.regen, (self.sampler,1))
+        self.connect(self.pk_detect, (self.sample_and_hold,1))
+
+        # Set output from sampler
+        self.connect(self.sampler, (self,0))
+        self.connect(self.pk_detect, (self,1))
+
+        if logging:
+            self.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pn-mf_f.dat"))
+            self.connect(self.normalize, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pn-theta_f.dat"))
+            self.connect(self.angle, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pn-epsilon_f.dat"))
+            self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_pn-peaks_b.dat"))
+            self.connect(self.regen, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_pn-regen_b.dat"))
+            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_pn-sigmix_c.dat"))
+            self.connect(self.sampler, 
gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_pn-sampler_c.dat"))
+            self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pn-sample_and_hold_f.dat"))
+            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_pn-nco_c.dat"))
+            self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_pn-input_c.dat"))
+

Copied: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py 
(from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py)
===================================================================
--- 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py    
                            (rev 0)
+++ 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py    
    2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,131 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import math
+from numpy import fft
+from gnuradio import gr
+
+class ofdm_sync_pnac(gr.hier_block2):
+    def __init__(self, fft_length, cp_length, ks):
+        
+        # FIXME: change the output signature
+        # should be the output of the divider (the normalized peaks) and
+        # the angle value out of the sample and hold block
+        # move sampler out of this block
+
+       gr.hier_block2.__init__(self, "ofdm_sync_pnac",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature(1, 1, 
gr.sizeof_gr_complex*fft_length)) # Output signature
+
+            
+        self.input = gr.add_const_cc(0)
+
+        symbol_length = fft_length + cp_length
+
+        # PN Sync
+
+        # autocorrelate with the known symbol
+        ks = ks[0:fft_length//2]
+        ks.reverse()
+        self.crosscorr_filter = gr.fir_filter_ccc(1, ks)
+        self.connect(self.crosscorr_filter, gr.file_sink(gr.sizeof_gr_complex, 
"crosscorr.dat"))
+        
+        # Create a delay line
+        self.delay = gr.delay(gr.sizeof_gr_complex, fft_length/2)
+
+        # Correlation from ML Sync
+        self.conjg = gr.conjugate_cc();
+        self.corr = gr.multiply_cc();
+
+        # Create a moving sum filter for the corr output
+        moving_sum_taps = [1.0 for i in range(fft_length//2)]
+        self.moving_sum_filter = gr.fir_filter_ccf(1,moving_sum_taps)
+
+        # Create a moving sum filter for the input
+        self.inputmag2 = gr.complex_to_mag_squared()
+        movingsum2_taps = [1.0 for i in range(fft_length/2)]
+        self.inputmovingsum = gr.fir_filter_fff(1,movingsum2_taps)
+        self.square = gr.multiply_ff()
+        self.normalize = gr.divide_ff()
+     
+        # Get magnitude (peaks) and angle (phase/freq error)
+        self.c2mag = gr.complex_to_mag_squared()
+        self.angle = gr.complex_to_arg()
+
+        self.sample_and_hold = gr.sample_and_hold_ff()
+
+        # Mix the signal with an NCO controlled by the sync loop
+        nco_sensitivity = -1.0/fft_length
+        self.nco = gr.frequency_modulator_fc(nco_sensitivity)
+        self.sigmix = gr.multiply_cc()
+
+        #ML measurements input to sampler block and detect
+        self.sub1 = gr.add_const_ff(-1)
+        self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005)
+
+        self.sampler = gr.ofdm_sampler(fft_length,symbol_length)
+
+        self.connect(self, self.input)
+        self.connect(self.input, self.crosscorr_filter)
+        self.connect(self.crosscorr_filter, self.delay)
+        self.connect(self.crosscorr_filter, (self.corr,0))
+        self.connect(self.delay, self.conjg)
+        self.connect(self.conjg, (self.corr,1))
+        self.connect(self.corr, self.moving_sum_filter)
+        self.connect(self.moving_sum_filter, self.c2mag)
+        self.connect(self.moving_sum_filter, self.angle)
+        self.connect(self.angle, (self.sample_and_hold,0))
+        self.connect(self.sample_and_hold, self.nco)
+
+        self.connect(self.input, (self.sigmix,0))
+        self.connect(self.nco, (self.sigmix,1))
+        self.connect(self.sigmix, (self.sampler,0))
+
+        self.connect(self.input, self.inputmag2, self.inputmovingsum)
+        self.connect(self.inputmovingsum, (self.square,0))
+        self.connect(self.inputmovingsum, (self.square,1))
+        self.connect(self.square, (self.normalize,1))
+        self.connect(self.c2mag, (self.normalize,0))
+        self.connect(self.normalize, self.sub1, self.pk_detect)
+
+        self.connect(self.pk_detect, (self.sampler,1))
+        self.connect(self.pk_detect, (self.sample_and_hold,1))
+            
+        self.connect(self.sampler, self)
+
+        if 1:
+            self.connect(self.normalize, gr.file_sink(gr.sizeof_float,
+                                                      
"ofdm_sync_pnac-theta_f.dat"))
+            self.connect(self.angle, gr.file_sink(gr.sizeof_float,
+                                                  
"ofdm_sync_pnac-epsilon_f.dat"))
+            self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char,
+                                                      
"ofdm_sync_pnac-peaks_b.dat"))
+            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex,
+                                                   
"ofdm_sync_pnac-sigmix_c.dat"))
+            self.connect(self.sampler, 
gr.file_sink(gr.sizeof_gr_complex*fft_length,
+                                                    
"ofdm_sync_pnac-sampler_c.dat"))
+            self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float,
+                                                            
"ofdm_sync_pnac-sample_and_hold_f.dat"))
+            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex,
+                                                "ofdm_sync_pnac-nco_c.dat"))
+            self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex,
+                                                  
"ofdm_sync_pnac-input_c.dat"))

Modified: gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am
===================================================================
--- gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am       
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am       
2008-01-02 17:35:35 UTC (rev 7324)
@@ -40,12 +40,6 @@
        cpm.py                  \
        nbfm_rx.py              \
        nbfm_tx.py              \
-       ofdm.py                 \
-       ofdm_receiver.py        \
-       ofdm_sync_fixed.py      \
-       ofdm_sync_ml.py         \
-       ofdm_sync_pnac.py       \
-       ofdm_sync_pn.py         \
        pkt.py                  \
        psk.py                  \
        qam.py                  \

Deleted: gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py

Deleted: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py

Deleted: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py

Deleted: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_ml.py

Deleted: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pn.py

Deleted: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py

Copied: gnuradio/trunk/gnuradio-core/src/utils/README (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/README)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/README                               
(rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/README       2008-01-02 17:35:35 UTC 
(rev 7324)
@@ -0,0 +1,40 @@
+* gr_plot_*.py:
+These are a collection of Python scripts to enable viewing and analysis of 
files produced by GNU Radio flow graphs. Most of them work off complex data 
produced by digital waveforms.
+
+
+** gr_plot_float.py:
+Takes a GNU Radio floating point binary file and displays the samples versus 
time. You can set the block size to specify how many points to read in at a 
time and the start position in the file.
+
+By default, the system assumes a sample rate of 1, so in time, each sample is 
plotted versus the sample number. To set a true time axis, set the sample rate 
(-R or --sample-rate) to the sample rate used when capturing the samples.
+
+
+
+** gr_plot_iq.py:
+Takes a GNU Radio complex binary file and displays the I&Q data versus time. 
You can set the block size to specify how many points to read in at a time and 
the start position in the file.
+
+By default, the system assumes a sample rate of 1, so in time, each sample is 
plotted versus the sample number. To set a true time axis, set the sample rate 
(-R or --sample-rate) to the sample rate used when capturing the samples.
+
+
+
+** gr_plot_const.py:
+Takes a GNU Radio complex binary file and displays the I&Q data versus time 
and the constellation plot (I vs. Q). You can set the block size to specify how 
many points to read in at a time and the start position in the file.
+
+By default, the system assumes a sample rate of 1, so in time, each sample is 
plotted versus the sample number. To set a true time axis, set the sample rate 
(-R or --sample-rate) to the sample rate used when capturing the samples.
+
+
+
+** gr_plot_fft_c.py:
+Takes a GNU Radio complex binary file and displays the I&Q data versus time as 
well as the frequency domain (FFT) plot. The y-axis values are plotted assuming 
volts as the amplitude of the I&Q streams and converted into dBm in the 
frequency domain (the 1/N power adjustment out of the FFT is performed 
internally).
+
+The script plots a certain block of data at a time, specified on the command 
line as -B or --block. This value defaults to 1000. The start position in the 
file can be set by specifying -s or --start and defaults to 0 (the start of the 
file).
+
+By default, the system assumes a sample rate of 1, so in time, each sample is 
plotted versus the sample number. To set a true time and frequency axis, set 
the sample rate (-R or --sample-rate) to the sample rate used when capturing 
the samples.
+
+
+
+** gr_plot_fft_f.py:
+Takes a GNU Radio floating point binary file and displays the samples versus 
time as well as the frequency domain (FFT) plot. The y-axis values are plotted 
assuming volts as the amplitude of the I&Q streams and converted into dBm in 
the frequency domain (the 1/N power adjustment out of the FFT is performed 
internally).
+
+The script plots a certain block of data at a time, specified on the command 
line as -B or --block. This value defaults to 1000. The start position in the 
file can be set by specifying -s or --start and defaults to 0 (the start of the 
file).
+
+By default, the system assumes a sample rate of 1, so in time, each sample is 
plotted versus the sample number. To set a true time and frequency axis, set 
the sample rate (-R or --sample-rate) to the sample rate used when capturing 
the samples.

Copied: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_char.py (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/gr_plot_char.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_char.py                      
        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_char.py      2008-01-02 
17:35:35 UTC (rev 7324)
@@ -0,0 +1,165 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy
+from pylab import *
+from optparse import OptionParser
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_fft_c:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_f.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()))
+        f = scipy.fromfile(self.hfile, dtype=scipy.int8, 
count=self.block_length)
+        #print "Read in %d items" % len(self.f)
+        if(len(f) == 0):
+            print "End of File"
+        else:
+            self.f = f
+            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))]
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(8*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 
0.6])
+        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_f = plot(self.time, self.f, 'bo-')
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+
+        draw()
+
+    def update_plots(self):
+        self.plot_f[0].set_data([self.time, self.f])
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+        draw()
+        
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 2*self.block_length ):
+            self.hfile.seek(-2*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio floating point binary file and displays 
the samples versus time. You can set the block size to specify how many points 
to read in at a time and the start position in the file. By default, the system 
assumes a sample rate of 1, so in time, each sample is plotted versus the 
sample number. To set a true time axis, set the sample rate (-R or 
--sample-rate) to the sample rate used when capturing the samples."
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit, 1
+    filename = args[0]
+
+    dc = draw_fft_c(filename, options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    

Modified: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_const.py
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_const.py     2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_const.py     2008-01-02 
17:35:35 UTC (rev 7324)
@@ -20,89 +20,172 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-import pylab, math
+import scipy
 from pylab import *
-import struct, sys
+from matplotlib.font_manager import fontManager, FontProperties
 from optparse import OptionParser
 
-import gr_read_binary
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
 
-class zoom:
-    def __init__(self, xdata, reals, imags, sp_iq, sp_const, plot_const, 
manager):
-        self.sp_iq = sp_iq
-        self.sp_const = sp_const
-        self.xaxis = xdata
-        self.reals = reals
-        self.imags = imags
-        self.plot_const = plot_const
-        self.manager = manager
+class draw_constellation:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
 
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.95, ("File: %s" % filename), 
weight="heavy", size=16)
+        self.text_file_pos = figtext(0.10, 0.90, "File Position: ", 
weight="heavy", size=16)
+        self.text_block    = figtext(0.40, 0.90, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=16)        
+        self.text_sr       = figtext(0.60, 0.90, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=16)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
         self.xlim = self.sp_iq.get_xlim()
-           
-    def __call__(self, event):
+
+        self.manager = get_current_fig_manager()
+        connect('draw_event', self.zoom)
+        connect('key_press_event', self.click)
+        show()
+
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//8))
+        iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, 
count=self.block_length)
+        #print "Read in %d items" % len(iq)
+        if(len(iq) == 0):
+            print "End of File"
+        else:
+            self.reals = [r.real for r in iq]
+            self.imags = [i.imag for i in iq]
+
+            self.time = [i*(1/self.sample_rate) for i in 
range(len(self.reals))]
+            
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(16*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 
0.6])
+        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, 
self.imags, 'ro-')
+        self.sp_iq.axis([min(self.time), max(self.time),
+                         1.5*min([min(self.reals), min(self.imags)]),
+                         1.5*max([max(self.reals), max(self.imags)])])
+
+        # Subplot for constellation plot
+        self.sp_const = self.fig.add_subplot(2,2,1, position=[0.575, 0.2, 0.4, 
0.6])
+        self.sp_const.set_title(("Constellation"), 
fontsize=self.title_font_size, fontweight="bold")
+        self.sp_const.set_xlabel("Inphase", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_const.set_ylabel("Qaudrature", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_const = plot(self.reals, self.imags, 'bo')
+        self.sp_const.axis([-2, 2, -2, 2])
+
+        draw()
+
+    def update_plots(self):
+        self.plot_iq[0].set_data([self.time, self.reals])
+        self.plot_iq[1].set_data([self.time, self.imags])
+        self.sp_iq.axis([min(self.time), max(self.time),
+                         1.5*min([min(self.reals), min(self.imags)]),
+                         1.5*max([max(self.reals), max(self.imags)])])
+
+        self.plot_const[0].set_data([self.reals, self.imags])
+        self.sp_const.axis([-2, 2, -2, 2])
+        draw()
+        
+    def zoom(self, event):
         newxlim = self.sp_iq.get_xlim()
-
         if(newxlim != self.xlim):
             self.xlim = newxlim
-            r = self.reals[int(self.xlim[0]) : int(self.xlim[1])]
-            i = self.imags[int(self.xlim[0]) : int(self.xlim[1])]
+            r = self.reals[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
+            i = self.imags[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
 
             self.plot_const[0].set_data(r, i)
             self.sp_const.axis([-2, 2, -2, 2])
             self.manager.canvas.draw()
+            draw()
+
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
             
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 16*self.block_length ):
+            self.hfile.seek(-16*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
 def main():
-    usage="%prog: [options] output_filename"
-    parser = OptionParser(conflict_handler="resolve", usage=usage)
-    parser.add_option("-s", "--size", type="int", default=None,
-                      help="Specify the number of points to plot 
[default=%default]")
-    parser.add_option("", "--skip", type="int", default=None,
-                      help="Specify the number of points to skip 
[default=%default]")
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio complex binary file and displays the I&Q 
data versus time and the constellation plot (I vs. Q). You can set the block 
size to specify how many points to read in at a time and the start position in 
the file. By default, the system assumes a sample rate of 1, so in time, each 
sample is plotted versus the sample number. To set a true time axis, set the 
sample rate (-R or --sample-rate) to the sample rate used when capturing the 
samples."
 
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
     (options, args) = parser.parse_args ()
     if len(args) != 1:
         parser.print_help()
         raise SystemExit, 1
     filename = args[0]
 
-    iq = gr_read_binary.read_complex_binary(filename)
+    dc = draw_constellation(filename, options)
 
-    if(options.skip is None):
-        options.skip = 0
-    
-    if((options.size is None) or ((options.skip+options.size) > len(iq[0]))):
-        options.size = len(iq[0]) - options.skip
-
-    reals = iq[0][options.skip : options.skip + options.size]
-    imags = iq[1][options.skip : options.skip + options.size]
-    x = range(options.skip, options.skip + options.size)
-    
-    # PLOT
-    f = figure(1, figsize=(16, 12), facecolor='w')
-    rcParams['xtick.labelsize'] = 16
-    rcParams['ytick.labelsize'] = 16
-
-    # Subplot for real and imaginary parts of signal
-    sp1 = f.add_subplot(2,1,1)
-    sp1.set_title(("I&Q"), fontsize=26, fontweight="bold")
-    sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold")
-    sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold")
-    plot(x, reals, 'bo-', x, imags, 'ro-')
-
-    # Subplot for constellation plot
-    sp2 = f.add_subplot(2,1,2)
-    sp2.set_title(("Constellation"), fontsize=26, fontweight="bold")
-    sp2.set_xlabel("Inphase", fontsize=20, fontweight="bold")
-    sp2.set_ylabel("Qaudrature", fontsize=20, fontweight="bold")
-    p2 = plot(reals, imags, 'bo')
-    sp2.axis([-2, 2, -2, 2])
-    
-    manager = get_current_fig_manager()
-    zm = zoom(x, reals, imags, sp1, sp2, p2, manager)
-    connect('draw_event', zm)
-    
-    show()
-
 if __name__ == "__main__":
     try:
         main()

Copied: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_c.py (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/gr_plot_fft_c.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_c.py                     
        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_c.py     2008-01-02 
17:35:35 UTC (rev 7324)
@@ -0,0 +1,221 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy
+from pylab import *
+from optparse import OptionParser
+from scipy import fftpack
+from math import log10
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_fft_c:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_iq.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('draw_event', self.zoom)
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//8))
+        self.iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, 
count=self.block_length)
+        #print "Read in %d items" % len(self.iq)
+        if(len(self.iq) == 0):
+            print "End of File"
+        else:
+            self.reals = [r.real for r in self.iq]
+            self.imags = [i.imag for i in self.iq]
+
+            self.iq_fft = self.dofft(self.iq)
+
+            self.time = [i*(1/self.sample_rate) for i in 
range(len(self.reals))]
+            self.freq = self.calc_freq(self.time, self.sample_rate)
+
+            
+    def dofft(self, iq):
+        N = len(iq)
+        iq_fft = fftpack.fftshift(scipy.fft(iq))       # fft and shift axis
+        iq_fft = [20*log10(abs(i/N)) for i in iq_fft]  # convert to decibels, 
adjust power
+        return iq_fft
+
+    def calc_freq(self, time, sample_rate):
+        N = len(time)
+        Fs = 1.0 / (max(time) - min(time))
+        Fn = 0.5 * sample_rate
+        freq = [-Fn + i*Fs for i in range(N)]
+        return freq
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(16*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 
0.6])
+        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, 
self.imags, 'ro-')
+        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]),
+                             1.5*max([max(self.reals), max(self.imags)])])
+
+        # Subplot for constellation plot
+        self.sp_fft = self.fig.add_subplot(2,2,1, position=[0.575, 0.2, 0.4, 
0.6])
+        self.sp_fft.set_title(("FFT"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_fft.set_xlabel("Frequency (Hz)", 
fontsize=self.label_font_size, fontweight="bold")
+        self.sp_fft.set_ylabel("Power (dBm)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_fft = plot(self.freq, self.iq_fft, '-bo')
+        self.sp_fft.set_ylim([min(self.iq_fft)-10, max(self.iq_fft)+10])
+        
+        draw()
+
+    def update_plots(self):
+        self.plot_iq[0].set_data([self.time, self.reals])
+        self.plot_iq[1].set_data([self.time, self.imags])
+        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]),
+                             1.5*max([max(self.reals), max(self.imags)])])
+
+        self.plot_fft[0].set_data([self.freq, self.iq_fft])
+        self.sp_fft.set_ylim([min(self.iq_fft)-10, max(self.iq_fft)+10])
+
+        draw()
+        
+    def zoom(self, event):
+        newxlim = self.sp_iq.get_xlim()
+        if(newxlim != self.xlim):
+            self.xlim = newxlim
+            xmin = max(0, int(ceil(self.sample_rate*self.xlim[0])))
+            xmax = min(int(ceil(self.sample_rate*self.xlim[1])), len(self.iq))
+
+            iq = self.iq[xmin : xmax]
+            time = self.time[xmin : xmax]
+            
+            iq_fft = self.dofft(iq)
+            freq = self.calc_freq(time, self.sample_rate)
+            
+            self.plot_fft[0].set_data(freq, iq_fft)
+            self.sp_fft.axis([min(freq), max(freq),
+                              min(iq_fft)-10, max(iq_fft)+10])
+
+            draw()
+
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 16*self.block_length ):
+            self.hfile.seek(-16*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio complex binary file and displays the I&Q 
data versus time as well as the frequency domain (FFT) plot. The y-axis values 
are plotted assuming volts as the amplitude of the I&Q streams and converted 
into dBm in the frequency domain (the 1/N power adjustment out of the FFT is 
performed internally). The script plots a certain block of data at a time, 
specified on the command line as -B or --block. This value defaults to 1000. 
The start position in the file can be set by specifying -s or --start and 
defaults to 0 (the start of the file). By default, the system assumes a sample 
rate of 1, so in time, each sample is plotted versus the sample number. To set 
a true time and frequency axis, set the sample rate (-R or --sample-rate) to 
the sample rate used when capturing the samples."
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit, 1
+    filename = args[0]
+
+    dc = draw_fft_c(filename, options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    
+
+

Copied: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_f.py (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/gr_plot_fft_f.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_f.py                     
        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_fft_f.py     2008-01-02 
17:35:35 UTC (rev 7324)
@@ -0,0 +1,223 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy
+from pylab import *
+from optparse import OptionParser
+from scipy import fftpack
+from math import log10
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_fft_f:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_f.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('draw_event', self.zoom)
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//4))
+        self.floats = scipy.fromfile(self.hfile, dtype=scipy.float32, 
count=self.block_length)
+        #print "Read in %d items" % len(self.floats)
+        if(len(self.floats) == 0):
+            print "End of File"
+        else:
+            self.f_fft = self.dofft(self.floats)
+
+            self.time = [i*(1/self.sample_rate) for i in 
range(len(self.floats))]
+            self.freq = self.calc_freq(self.time, self.sample_rate)
+            
+    def dofft(self, f):
+        N = len(f)
+        f_fft = fftpack.fftshift(scipy.fft(f))       # fft and shift axis
+        f_dB = list()
+        for f in f_fft:
+            try:
+                f_dB.append(20*log10(abs(f/N)))  # convert to decibels, adjust 
power
+            except OverflowError:                # protect against taking 
log(0)
+                f = 1e-14                        # not sure if this is the 
best way to do this
+                f_dB.append(20*log10(abs(f/N)))
+                
+        return f_dB
+
+    def calc_freq(self, time, sample_rate):
+        N = len(time)
+        Fs = 1.0 / (max(time) - min(time))
+        Fn = 0.5 * sample_rate
+        freq = [-Fn + i*Fs for i in range(N)]
+        return freq
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(16*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 
0.6])
+        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_f = plot(self.time, self.floats, 'bo-')
+        self.sp_f.set_ylim([1.5*min(self.floats),
+                            1.5*max(self.floats)])
+
+        # Subplot for constellation plot
+        self.sp_fft = self.fig.add_subplot(2,2,1, position=[0.575, 0.2, 0.4, 
0.6])
+        self.sp_fft.set_title(("FFT"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_fft.set_xlabel("Frequency (Hz)", 
fontsize=self.label_font_size, fontweight="bold")
+        self.sp_fft.set_ylabel("Power (dBm)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_fft = plot(self.freq, self.f_fft, '-bo')
+        self.sp_fft.set_ylim([min(self.f_fft)-10, max(self.f_fft)+10])
+        
+        draw()
+
+    def update_plots(self):
+        self.plot_f[0].set_data([self.time, self.floats])
+        self.sp_f.set_ylim([1.5*min(self.floats),
+                            1.5*max(self.floats)])
+
+        self.plot_fft[0].set_data([self.freq, self.f_fft])
+        self.sp_fft.set_ylim([min(self.f_fft)-10, max(self.f_fft)+10])
+
+        draw()
+        
+    def zoom(self, event):
+        newxlim = self.sp_f.get_xlim()
+        if(newxlim != self.xlim):
+            self.xlim = newxlim
+            xmin = max(0, int(ceil(self.sample_rate*self.xlim[0])))
+            xmax = min(int(ceil(self.sample_rate*self.xlim[1])), 
len(self.floats))
+
+            f = self.floats[xmin : xmax]
+            time = self.time[xmin : xmax]
+            
+            f_fft = self.dofft(f)
+            freq = self.calc_freq(time, self.sample_rate)
+                        
+            self.plot_fft[0].set_data(freq, f_fft)
+            self.sp_fft.axis([min(freq), max(freq),
+                              min(f_fft)-10, max(f_fft)+10])
+
+            draw()
+
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 8*self.block_length ):
+            self.hfile.seek(-8*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio floating point binary file and displays 
the sample data versus time as well as the frequency domain (FFT) plot. The 
y-axis values are plotted assuming volts as the amplitude of the I&Q streams 
and converted into dBm in the frequency domain (the 1/N power adjustment out of 
the FFT is performed internally). The script plots a certain block of data at a 
time, specified on the command line as -B or --block. This value defaults to 
1000. The start position in the file can be set by specifying -s or --start and 
defaults to 0 (the start of the file). By default, the system assumes a sample 
rate of 1, so in time, each sample is plotted versus the sample number. To set 
a true time and frequency axis, set the sample rate (-R or --sample-rate) to 
the sample rate used when capturing the samples."
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit, 1
+    filename = args[0]
+
+    dc = draw_fft_f(filename, options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    
+
+

Modified: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_float.py
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_float.py     2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_float.py     2008-01-02 
17:35:35 UTC (rev 7324)
@@ -20,56 +20,146 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-import pylab, math
+import scipy
 from pylab import *
-import struct, sys
 from optparse import OptionParser
 
-import gr_read_binary
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
 
+class draw_fft_c:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_f.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//4))
+        f = scipy.fromfile(self.hfile, dtype=scipy.float32, 
count=self.block_length)
+        #print "Read in %d items" % len(self.f)
+        if(len(f) == 0):
+            print "End of File"
+        else:
+            self.f = f
+            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))]
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(8*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 
0.6])
+        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_f = plot(self.time, self.f, 'bo-')
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+
+        draw()
+
+    def update_plots(self):
+        self.plot_f[0].set_data([self.time, self.f])
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+        draw()
+        
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 8*self.block_length ):
+            self.hfile.seek(-8*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
 def main():
-    usage="%prog: [options] output_filename"
-    parser = OptionParser(conflict_handler="resolve", usage=usage)
-    parser.add_option("-s", "--size", type="int", default=None,
-                      help="Specify the number of points to plot 
[default=%default]")
-    parser.add_option("", "--skip", type="int", default=None,
-                      help="Specify the number of points to skip 
[default=%default]")
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio floating point binary file and displays 
the samples versus time. You can set the block size to specify how many points 
to read in at a time and the start position in the file. By default, the system 
assumes a sample rate of 1, so in time, each sample is plotted versus the 
sample number. To set a true time axis, set the sample rate (-R or 
--sample-rate) to the sample rate used when capturing the samples."
 
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
     (options, args) = parser.parse_args ()
     if len(args) != 1:
         parser.print_help()
         raise SystemExit, 1
     filename = args[0]
 
-    fl = gr_read_binary.read_float_binary(filename)
+    dc = draw_fft_c(filename, options)
 
-    if(options.skip is None):
-        options.skip = 0
-    
-    if((options.size is None) or ((options.skip+options.size) > len(iq[0]))):
-        options.size = len(fl) - options.skip
-
-    x = range(options.skip, options.skip + options.size)
-    
-    # PLOT REAL AND IMAGINARY PARTS
-    
-    f = figure(1, figsize=(16, 12), facecolor='w')
-    rcParams['xtick.labelsize'] = 16
-    rcParams['ytick.labelsize'] = 16
-
-    sp1 = f.add_subplot(1,1,1)
-    sp1.set_title(("GNU Radio Float"), fontsize=26, fontweight="bold")
-    sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold")
-    sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold")
-    plot(x, fl, 'bo-')
-
-    show()
-
 if __name__ == "__main__":
     try:
         main()
     except KeyboardInterrupt:
         pass
     
-
-

Copied: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_int.py (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/gr_plot_int.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_int.py                       
        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_int.py       2008-01-02 
17:35:35 UTC (rev 7324)
@@ -0,0 +1,165 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy
+from pylab import *
+from optparse import OptionParser
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_fft_c:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_f.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//4))
+        f = scipy.fromfile(self.hfile, dtype=scipy.int32, 
count=self.block_length)
+        #print "Read in %d items" % len(self.f)
+        if(len(f) == 0):
+            print "End of File"
+        else:
+            self.f = f
+            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))]
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(8*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 
0.6])
+        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_f = plot(self.time, self.f, 'bo-')
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+
+        draw()
+
+    def update_plots(self):
+        self.plot_f[0].set_data([self.time, self.f])
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+        draw()
+        
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 8*self.block_length ):
+            self.hfile.seek(-8*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio floating point binary file and displays 
the samples versus time. You can set the block size to specify how many points 
to read in at a time and the start position in the file. By default, the system 
assumes a sample rate of 1, so in time, each sample is plotted versus the 
sample number. To set a true time axis, set the sample rate (-R or 
--sample-rate) to the sample rate used when capturing the samples."
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit, 1
+    filename = args[0]
+
+    dc = draw_fft_c(filename, options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    

Modified: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_iq.py
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_iq.py        2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_iq.py        2008-01-02 
17:35:35 UTC (rev 7324)
@@ -20,53 +20,145 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-import pylab, math
+import scipy
 from pylab import *
-import struct, sys
 from optparse import OptionParser
 
-import gr_read_binary
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
 
+class draw_fft:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_iq.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('key_press_event', self.click)
+        show()
+
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//8))
+        self.iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, 
count=self.block_length)
+        #print "Read in %d items" % len(self.iq)
+        if(len(self.iq) == 0):
+            print "End of File"
+        else:
+            self.reals = [r.real for r in self.iq]
+            self.imags = [i.imag for i in self.iq]
+            self.time = [i*(1/self.sample_rate) for i in 
range(len(self.reals))]
+            
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(16*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.14, 0.85, 
0.67])
+        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, 
self.imags, 'ro-')
+        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]),
+                             1.5*max([max(self.reals), max(self.imags)])])
+        
+        draw()
+
+    def update_plots(self):
+        self.plot_iq[0].set_data([self.time, self.reals])
+        self.plot_iq[1].set_data([self.time, self.imags])
+        self.sp_iq.set_ylim([1.5*min([min(self.reals), min(self.imags)]),
+                             1.5*max([max(self.reals), max(self.imags)])])
+        draw()
+        
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 16*self.block_length ):
+            self.hfile.seek(-16*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
 def main():
-    usage="%prog: [options] output_filename"
-    parser = OptionParser(conflict_handler="resolve", usage=usage)
-    parser.add_option("-s", "--size", type="int", default=None,
-                      help="Specify the number of points to plot 
[default=%default]")
-    parser.add_option("", "--skip", type="int", default=None,
-                      help="Specify the number of points to skip 
[default=%default]")
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio complex binary file and displays the I&Q 
data versus time. You can set the block size to specify how many points to read 
in at a time and the start position in the file. By default, the system assumes 
a sample rate of 1, so in time, each sample is plotted versus the sample 
number. To set a true time axis, set the sample rate (-R or --sample-rate) to 
the sample rate used when capturing the samples."
 
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
     (options, args) = parser.parse_args ()
     if len(args) != 1:
         parser.print_help()
         raise SystemExit, 1
     filename = args[0]
 
-    iq = gr_read_binary.read_complex_binary(filename)
+    dc = draw_fft(filename, options)
 
-    if(options.skip is None):
-        options.skip = 0
-    
-    if((options.size is None) or ((options.skip+options.size) > len(iq[0]))):
-        options.size = len(iq[0]) - options.skip
-
-    reals = iq[0][options.skip : options.skip + options.size]
-    imags = iq[1][options.skip : options.skip + options.size]
-    x = range(options.skip, options.skip + options.size)
-    
-    # PLOT REAL AND IMAGINARY PARTS
-    
-    f = figure(1, figsize=(16, 12), facecolor='w')
-    rcParams['xtick.labelsize'] = 16
-    rcParams['ytick.labelsize'] = 16
-
-    sp1 = f.add_subplot(1,1,1)
-    sp1.set_title(("I&Q"), fontsize=26, fontweight="bold")
-    sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold")
-    sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold")
-    plot(x, reals, 'bo-', x, imags, 'ro-')
-
-    show()
-
 if __name__ == "__main__":
     try:
         main()

Copied: gnuradio/trunk/gnuradio-core/src/utils/gr_plot_short.py (from rev 7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/utils/gr_plot_short.py)
===================================================================
--- gnuradio/trunk/gnuradio-core/src/utils/gr_plot_short.py                     
        (rev 0)
+++ gnuradio/trunk/gnuradio-core/src/utils/gr_plot_short.py     2008-01-02 
17:35:35 UTC (rev 7324)
@@ -0,0 +1,165 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy
+from pylab import *
+from optparse import OptionParser
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_fft_c:
+    def __init__(self, filename, options):
+        self.hfile = open(filename, "r")
+        self.block_length = options.block
+        self.start = options.start
+        self.sample_rate = options.sample_rate
+
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+
+        # Setup PLOT
+        self.fig = figure(1, figsize=(16, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+        
+        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), 
weight="heavy", size=self.text_size)
+        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", 
weight="heavy", size=self.text_size)
+        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % 
self.block_length),
+                                     weight="heavy", size=self.text_size)
+        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % 
self.sample_rate),
+                                     weight="heavy", size=self.text_size)
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_f.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        connect('key_press_event', self.click)
+        show()
+        
+    def get_data(self):
+        self.text_file_pos.set_text("File Position: %d" % 
(self.hfile.tell()//2))
+        f = scipy.fromfile(self.hfile, dtype=scipy.int16, 
count=self.block_length)
+        #print "Read in %d items" % len(self.f)
+        if(len(f) == 0):
+            print "End of File"
+        else:
+            self.f = f
+            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))]
+        
+    def make_plots(self):
+        # if specified on the command-line, set file pointer
+        self.hfile.seek(8*self.start, 1)
+
+        self.get_data()
+        
+        # Subplot for real and imaginary parts of signal
+        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 
0.6])
+        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_f = plot(self.time, self.f, 'bo-')
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+
+        draw()
+
+    def update_plots(self):
+        self.plot_f[0].set_data([self.time, self.f])
+        self.sp_f.set_ylim([1.5*min(self.f),
+                            1.5*max(self.f)])
+        draw()
+        
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        if(self.hfile.tell() >= 4*self.block_length ):
+            self.hfile.seek(-4*self.block_length, 1)
+        else:
+            self.hfile.seek(-self.hfile.tell(),1)
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options] input_filename"
+    description = "Takes a GNU Radio floating point binary file and displays 
the samples versus time. You can set the block size to specify how many points 
to read in at a time and the start position in the file. By default, the system 
assumes a sample rate of 1, so in time, each sample is plotted versus the 
sample number. To set a true time axis, set the sample rate (-R or 
--sample-rate) to the sample rate used when capturing the samples."
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage, 
description=description)
+    parser.add_option("-B", "--block", type="int", default=1000,
+                      help="Specify the block size [default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify where to start in the file 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit, 1
+    filename = args[0]
+
+    dc = draw_fft_c(filename, options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    

Deleted: gnuradio/trunk/gnuradio-core/src/utils/gr_read_binary.py

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm.py
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm.py      
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm.py      
2008-01-02 17:35:35 UTC (rev 7324)
@@ -20,7 +20,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
@@ -32,9 +32,9 @@
 from receive_path import receive_path
 
 
-class my_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
     def __init__(self, callback, options):
-        gr.flow_graph.__init__(self)
+        gr.top_block.__init__(self)
 
         if not options.channel_off:
             SNR = 10.0**(options.snr/10.0)
@@ -67,22 +67,24 @@
 
         z = [0,]
         self.zeros = gr.vector_source_c(z, True)
-        self.txpath = transmit_path(self, options)
+        self.txpath = transmit_path(options)
 
-        self.mux = gr.stream_mux(gr.sizeof_gr_complex, stream_size)
+        #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.channel = blks2.channel_model(noise_voltage, frequency_offset,
+                                           options.clockrate_ratio, taps)
+        self.rxpath = receive_path(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.zeros, (self.mux,0))
+        #self.connect(self.txpath, (self.mux,1))
+        #self.connect(self.mux, self.throttle, self.channel, self.rxpath)
+        #self.connect(self.mux, self.throttle, self.rxpath)
+        self.connect(self.txpath, self.throttle, self.channel, self.rxpath)
+        
         if options.log:
             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"))
+            #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
@@ -95,7 +97,7 @@
     n_right = 0
         
     def send_pkt(payload='', eof=False):
-        return fg.txpath.send_pkt(payload, eof)
+        return tb.txpath.send_pkt(payload, eof)
         
     def rx_callback(ok, payload):
         global n_rcvd, n_right
@@ -139,20 +141,20 @@
 
     transmit_path.add_options(parser, expert_grp)
     receive_path.add_options(parser, expert_grp)
-    blks.ofdm_mod.add_options(parser, expert_grp)
-    blks.ofdm_demod.add_options(parser, expert_grp)
+    blks2.ofdm_mod.add_options(parser, expert_grp)
+    blks2.ofdm_demod.add_options(parser, expert_grp)
     
     (options, args) = parser.parse_args ()
        
     # build the graph
-    fg = my_graph(rx_callback, options)
+    tb = my_top_block(rx_callback, options)
     
     r = gr.enable_realtime_scheduling()
     #    if r != gr.RT_OK:
     #        print "Warning: failed to enable realtime scheduling"
-        
-    fg.start()                       # start flow graph
     
+    tb.start()                       # start flow graph
+    
     # generate and send packets
     nbytes = int(1e6 * options.megabytes)
     n = 0
@@ -173,7 +175,7 @@
         pktno += 1
         
     send_pkt(eof=True)
-    fg.wait()                       # wait for it to finish
+    tb.wait()                       # wait for it to finish
 
 
 if __name__ == '__main__':

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py   
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_rx.py   
2008-01-02 17:35:35 UTC (rev 7324)
@@ -20,21 +20,21 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
 from gnuradio import usrp
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
 
-import random, time, struct, sys
+import struct, sys
 
 # from current dir
 from receive_path import receive_path
 import fusb_options
 
-class usrp_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
     def __init__(self, callback, options):
-        gr.flow_graph.__init__(self)
+        gr.top_block.__init__(self)
 
         self._rx_freq            = options.rx_freq         # receiver's center 
frequency
         self._rx_gain            = options.rx_gain         # receiver's gain
@@ -61,10 +61,10 @@
         self.set_auto_tr(True)                 # enable Auto Transmit/Receive 
switching
 
         # Set up receive path
-        self.rxpath = receive_path(self, callback, options)
+        self.rxpath = receive_path(callback, options)
 
         self.connect(self.u, self.rxpath)
-
+        
     def _setup_usrp_source(self):
         self.u = usrp.source_c (fusb_block_size=self._fusb_block_size,
                                 fusb_nblocks=self._fusb_nblocks)
@@ -187,23 +187,23 @@
     parser.add_option("","--discontinuous", action="store_true", default=False,
                       help="enable discontinuous")
 
-    usrp_graph.add_options(parser, expert_grp)
+    my_top_block.add_options(parser, expert_grp)
     receive_path.add_options(parser, expert_grp)
-    blks.ofdm_mod.add_options(parser, expert_grp)
-    blks.ofdm_demod.add_options(parser, expert_grp)
+    blks2.ofdm_mod.add_options(parser, expert_grp)
+    blks2.ofdm_demod.add_options(parser, expert_grp)
     fusb_options.add_options(expert_grp)
 
     (options, args) = parser.parse_args ()
 
     # build the graph
-    fg = usrp_graph(rx_callback, options)
+    tb = my_top_block(rx_callback, options)
 
     r = gr.enable_realtime_scheduling()
     if r != gr.RT_OK:
         print "Warning: failed to enable realtime scheduling"
 
-    fg.start()                      # start flow graph
-    fg.wait()                       # wait for it to finish
+    tb.start()                      # start flow graph
+    tb.wait()                       # wait for it to finish
 
 if __name__ == '__main__':
     try:

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py   
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/benchmark_ofdm_tx.py   
2008-01-02 17:35:35 UTC (rev 7324)
@@ -20,7 +20,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, blks
+from gnuradio import gr, blks2
 from gnuradio import usrp
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
@@ -33,9 +33,9 @@
 from pick_bitrate import pick_tx_bitrate
 import fusb_options
 
-class usrp_graph(gr.flow_graph):
+class my_top_block(gr.top_block):
     def __init__(self, options):
-        gr.flow_graph.__init__(self)
+        gr.top_block.__init__(self)
 
         self._tx_freq            = options.tx_freq         # tranmitter's 
center frequency
         self._tx_subdev_spec     = options.tx_subdev_spec  # daughterboard to 
use
@@ -53,10 +53,10 @@
         # copy the final answers back into options for use by modulator
         #options.bitrate = self._bitrate
 
-        self.txpath = transmit_path(self, options)
+        self.txpath = transmit_path(options)
 
         self.connect(self.txpath, self.u)
-
+        
     def _setup_usrp_sink(self):
         """
         Creates a USRP sink, determines the settings for best bitrate,
@@ -167,7 +167,7 @@
 def main():
 
     def send_pkt(payload='', eof=False):
-        return fg.txpath.send_pkt(payload, eof)
+        return tb.txpath.send_pkt(payload, eof)
 
     parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
     expert_grp = parser.add_option_group("Expert")
@@ -178,23 +178,23 @@
     parser.add_option("","--discontinuous", action="store_true", default=False,
                       help="enable discontinuous mode")
 
-    usrp_graph.add_options(parser, expert_grp)
+    my_top_block.add_options(parser, expert_grp)
     transmit_path.add_options(parser, expert_grp)
-    blks.ofdm_mod.add_options(parser, expert_grp)
-    blks.ofdm_demod.add_options(parser, expert_grp)
+    blks2.ofdm_mod.add_options(parser, expert_grp)
+    blks2.ofdm_demod.add_options(parser, expert_grp)
     fusb_options.add_options(expert_grp)
 
     (options, args) = parser.parse_args ()
 
     # build the graph
-    fg = usrp_graph(options)
-
+    tb = my_top_block(options)
+    
     r = gr.enable_realtime_scheduling()
     if r != gr.RT_OK:
         print "Warning: failed to enable realtime scheduling"
 
-    fg.start()                       # start flow graph
-
+    tb.start()                       # start flow graph
+    
     # generate and send packets
     nbytes = int(1e6 * options.megabytes)
     n = 0
@@ -210,7 +210,7 @@
         pktno += 1
         
     send_pkt(eof=True)
-    fg.wait()                       # wait for it to finish
+    tb.wait()                       # wait for it to finish
 
 if __name__ == '__main__':
     try:

Copied: gnuradio/trunk/gnuradio-examples/python/ofdm/gr_plot_ofdm.py (from rev 
7320, 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-examples/python/ofdm/gr_plot_ofdm.py)
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/gr_plot_ofdm.py                
                (rev 0)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/gr_plot_ofdm.py        
2008-01-02 17:35:35 UTC (rev 7324)
@@ -0,0 +1,268 @@
+#!/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 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+import scipy, pylab, math
+import struct, sys
+from pylab import *
+from matplotlib.font_manager import fontManager, FontProperties
+from optparse import OptionParser
+from scipy import fftpack
+from math import log10
+
+matplotlib.interactive(True)
+matplotlib.use('TkAgg')
+
+class draw_constellation:
+    def __init__(self, options):
+        derot_file = "ofdm_frame_sink_c.dat"
+        acq_file = "ofdm_frame_acq_c.dat"
+        fft_file = "fft_out_c.dat"
+
+        self.h_derot_file = open(derot_file, "r")
+        self.h_acq_file = open(acq_file, "r")
+        self.h_fft_file = open(fft_file, "r")
+
+        self.occ_tones = options.occ_tones
+        self.fft_size  = options.fft_size
+        self.symbol = options.start
+        self.sample_rate = options.sample_rate
+        
+        self.axis_font_size = 16
+        self.label_font_size = 18
+        self.title_font_size = 20
+        self.text_size = 22
+        
+        # Setup PLOT
+        self.fig = figure(1, figsize=(14, 9), facecolor='w')
+        rcParams['xtick.labelsize'] = self.axis_font_size
+        rcParams['ytick.labelsize'] = self.axis_font_size
+
+        self.text_sym = figtext(0.05, 0.95, ("Symbol: %s" % self.symbol), 
weight="heavy", size=self.text_size)
+
+        self.make_plots()
+
+        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_left = Button(self.button_left_axes, "<")
+        self.button_left_callback = 
self.button_left.on_clicked(self.button_left_click)
+
+        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], 
frameon=True)
+        self.button_right = Button(self.button_right_axes, ">")
+        self.button_right_callback = 
self.button_right.on_clicked(self.button_right_click)
+
+        self.xlim = self.sp_eq.get_xlim()
+
+        self.manager = get_current_fig_manager()
+        #connect('draw_event', self.zoom)
+        connect('key_press_event', self.click)
+        show()
+
+    def get_data(self):
+        self.text_sym.set_text("Symbol: %d" % (self.symbol))
+
+        derot_data = scipy.fromfile(self.h_derot_file, dtype=scipy.complex64, 
count=self.occ_tones)
+        acq_data = scipy.fromfile(self.h_acq_file, dtype=scipy.complex64, 
count=self.occ_tones)
+        fft_data = scipy.fromfile(self.h_fft_file, dtype=scipy.complex64, 
count=self.fft_size)
+        if(len(acq_data) == 0):
+            print "End of File"
+        else:
+            self.acq_data_reals = [r.real for r in acq_data]
+            self.acq_data_imags = [i.imag for i in acq_data]
+            self.derot_data_reals = [r.real for r in derot_data]
+            self.derot_data_imags = [i.imag for i in derot_data]
+
+            self.unequalized_angle = [math.atan2(x.imag, x.real) for x in 
fft_data]
+            self.equalized_angle = [math.atan2(x.imag, x.real) for x in 
acq_data]
+            self.derot_equalized_angle = [math.atan2(x.imag, x.real) for x in 
derot_data]
+
+            self.time = [i*(1/self.sample_rate) for i in range(len(acq_data))]
+            ffttime = [i*(1/self.sample_rate) for i in range(len(fft_data))]
+
+            self.freq = self.get_freq(ffttime, self.sample_rate)
+
+            for i in range(len(fft_data)):
+                if(abs(fft_data[i]) == 0.0):
+                    fft_data[i] = complex(1e-6,1e-6)
+            self.fft_data = [20*log10(abs(f)) for f in fft_data]
+              
+    def get_freq(self, time, sample_rate, T=1):
+        N = len(time)
+        Fs = 1.0 / (max(time) - min(time))
+        Fn = 0.5 * sample_rate
+        freq = [-Fn + i*Fs for i in range(N)]
+        return freq
+
+    def make_plots(self):
+        self.h_acq_file.seek(8*self.symbol*self.occ_tones, 0)
+        self.h_fft_file.seek(8*self.symbol*self.fft_size, 0)
+        self.h_derot_file.seek(8*self.symbol*self.occ_tones, 0)
+
+        self.get_data()
+        
+        # Subplot:  constellation of rotated symbols
+        self.sp_const = self.fig.add_subplot(4,1,1, position=[0.15, 0.55, 0.3, 
0.35])
+        self.sp_const.set_title(("Constellation"), 
fontsize=self.title_font_size, fontweight="bold")
+        self.sp_const.set_xlabel("Inphase", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_const.set_ylabel("Qaudrature", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_const = plot(self.acq_data_reals, self.acq_data_imags, 'bo')
+        self.plot_const += plot(self.derot_data_reals, self.derot_data_imags, 
'ro')
+        self.sp_const.axis([-2, 2, -2, 2])
+
+        # Subplot: unequalized angle
+        self.sp_uneq = self.fig.add_subplot(4,2,1, position=[0.575, 0.55, 0.3, 
0.35])
+        self.sp_uneq.set_title(("Unequalized Angle"), 
fontsize=self.title_font_size, fontweight="bold")
+        self.sp_uneq.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_uneq.set_ylabel("Angle", fontsize=self.label_font_size, 
fontweight="bold")
+        uneqscale = range(len(self.unequalized_angle))
+        self.plot_uneq = plot(uneqscale, self.unequalized_angle, 'bo')
+
+        # Subplot: equalized angle
+        self.sp_eq = self.fig.add_subplot(4,1,2, position=[0.15, 0.1, 0.3, 
0.35])
+        self.sp_eq.set_title(("Equalized Angle"), 
fontsize=self.title_font_size, fontweight="bold")
+        self.sp_eq.set_xlabel("Time (s)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.sp_eq.set_ylabel("Angle", fontsize=self.label_font_size, 
fontweight="bold")
+        eqscale = range(len(self.equalized_angle))
+        self.plot_eq = plot(eqscale, self.equalized_angle, 'bo')
+        self.plot_eq += plot(eqscale, self.derot_equalized_angle, 'ro', 
markersize=4)
+
+        # Subplot: FFT
+        self.sp_fft = self.fig.add_subplot(4,2,2, position=[0.575, 0.1, 0.3, 
0.35])
+        self.sp_fft.set_title(("FFT"), fontsize=self.title_font_size, 
fontweight="bold")
+        self.sp_fft.set_xlabel("Frequency (MHz)", 
fontsize=self.label_font_size, fontweight="bold")
+        self.sp_fft.set_ylabel("Power (dBm)", fontsize=self.label_font_size, 
fontweight="bold")
+        self.plot_fft = plot(self.freq, self.fft_data, '-bo')
+
+        draw()
+
+    def update_plots(self):
+        eqscale = range(len(self.equalized_angle))
+        uneqscale = range(len(self.unequalized_angle))
+        self.plot_eq[0].set_data([eqscale, self.equalized_angle])
+        self.plot_eq[1].set_data([eqscale, self.derot_equalized_angle])
+        self.plot_uneq[0].set_data([uneqscale, self.unequalized_angle])
+        self.sp_eq.set_ylim([-4, 4])
+        self.sp_uneq.set_ylim([-4, 4])
+
+        #self.sp_iq.axis([min(self.time), max(self.time),
+        #                 1.5*min([min(self.acq_data_reals), 
min(self.acq_data_imags)]),
+        #                 1.5*max([max(self.acq_data_reals), 
max(self.acq_data_imags)])])
+
+        self.plot_const[0].set_data([self.acq_data_reals, self.acq_data_imags])
+        self.plot_const[1].set_data([self.derot_data_reals, 
self.derot_data_imags])
+        self.sp_const.axis([-2, 2, -2, 2])
+
+        self.plot_fft[0].set_data([self.freq, self.fft_data])
+
+        draw()
+        
+    def zoom(self, event):
+        newxlim = self.sp_eq.get_xlim()
+        if(newxlim != self.xlim):
+            self.xlim = newxlim
+            r = self.reals[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
+            i = self.imags[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))]
+
+            self.plot_const[0].set_data(r, i)
+            self.sp_const.axis([-2, 2, -2, 2])
+            self.manager.canvas.draw()
+            draw()
+
+    def click(self, event):
+        forward_valid_keys = [" ", "down", "right"]
+        backward_valid_keys = ["up", "left"]
+
+        if(find(event.key, forward_valid_keys)):
+            self.step_forward()
+            
+        elif(find(event.key, backward_valid_keys)):
+            self.step_backward()
+
+    def button_left_click(self, event):
+        self.step_backward()
+
+    def button_right_click(self, event):
+        self.step_forward()
+
+    def step_forward(self):
+        self.symbol += 1
+        self.get_data()
+        self.update_plots()
+
+    def step_backward(self):
+        # Step back in file position
+        self.symbol -= 1
+        if(self.h_acq_file.tell() >= 16*self.occ_tones):
+            self.h_acq_file.seek(-16*self.occ_tones, 1)
+        else:
+            self.symbol = 0
+            self.h_acq_file.seek(-self.h_acq_file.tell(),1)
+
+
+        if(self.h_derot_file.tell() >= 16*self.occ_tones):
+            self.h_derot_file.seek(-16*self.occ_tones, 1)
+        else:
+            self.symbol = 0
+            self.h_derot_file.seek(-self.h_derot_file.tell(),1)
+
+
+        if(self.h_fft_file.tell() >= 16*self.fft_size):
+            self.h_fft_file.seek(-16*self.fft_size, 1)
+        else:
+            self.symbol = 0
+            self.h_fft_file.seek(-self.h_fft_file.tell(),1)
+
+        self.get_data()
+        self.update_plots()
+        
+            
+
+#FIXME: there must be a way to do this with a Python builtin
+def find(item_in, list_search):
+    for l in list_search:
+        if item_in == l:
+            return True
+    return False
+
+def main():
+    usage="%prog: [options]"
+
+    parser = OptionParser(conflict_handler="resolve", usage=usage)
+    parser.add_option("", "--fft-size", type="int", default=512,
+                      help="Specify the size of the FFT [default=%default]")
+    parser.add_option("", "--occ-tones", type="int", default=200,
+                      help="Specify the number of occupied tones 
[default=%default]")
+    parser.add_option("-s", "--start", type="int", default=0,
+                      help="Specify the starting symbol to plot 
[default=%default]")
+    parser.add_option("-R", "--sample-rate", type="float", default=1.0,
+                      help="Set the sampler rate of the data 
[default=%default]")
+    
+    (options, args) = parser.parse_args ()
+
+    dc = draw_constellation(options)
+
+if __name__ == "__main__":
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    
+
+

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/plot_ofdm.m
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/plot_ofdm.m    2008-01-02 
17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/plot_ofdm.m    2008-01-02 
17:35:35 UTC (rev 7324)
@@ -1,13 +1,22 @@
 function plot_ofdm(fft_size, occ_tones)
 
-ofdm = read_complex_binary('ofdm_corr_out_c.dat');
+ofdm = read_complex_binary('ofdm_frame_acq_c.dat');
 ofdm_split = split_vect(ofdm, occ_tones);
 
+ofdm_derot = read_complex_binary('ofdm_frame_sink_c.dat');
+ofdm_derot_split = split_vect(ofdm_derot, occ_tones);
+
 fftc = read_complex_binary('fft_out_c.dat');
 fftc_split = split_vect(fftc, fft_size);
 
+size(ofdm_split)
+size(ofdm_derot_split)
+disp "DEROTATED SPLIT"
+ofdm_derot(1:100)
+
+
 figure(1)
-set(gcf, 'Position', [50 50 1000 600]);
+#set(gcf, 'Position', [50 50 1000 600]);
 
 a = size(ofdm_split);
 if nargin == 3
@@ -19,47 +28,47 @@
     maxcount = a(1);
 end
 
-for i = 1:20000
+for i = 1:size(ofdm_split)[0]
     x = ofdm_split(i,:);
     y = fftc_split(i+1,:);
     
-    subplot(2,2,1)
-    plot(real(x), imag(x), 'bo')
-    set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
+    subplot(2,2,1);
+    plot(real(x), imag(x), 'bo');
+    #set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
     axis([-1.5, 1.5, -1.5, 1.5])
-    title('I&Q Constellation', 'FontSize', 36);
-    xlabel('Inphase', 'FontSize', 32);
-    ylabel('Quadrature', 'FontSize', 32);
+    #title('I&Q Constellation', 'FontSize', 36);
+    #xlabel('Inphase', 'FontSize', 32);
+    #ylabel('Quadrature', 'FontSize', 32);
     
-    subplot(2,2,3)
-    plot(angle(x*j), 'bo')
-    set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
+    subplot(2,2,3);
+    plot(angle(x*j), 'bo');
+    #set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
     axis([0, occ_tones, -3.5, 3.5])
-    title('Equalized Symbol Angle', 'FontSize', 36);
-    xlabel('Bin Number (Occ. Tones)', 'FontSize', 32);
-    ylabel('Symbol Angle', 'FontSize', 32);
+    #title('Equalized Symbol Angle', 'FontSize', 36);
+    #xlabel('Bin Number (Occ. Tones)', 'FontSize', 32);
+    #ylabel('Symbol Angle', 'FontSize', 32);
     
-    subplot(2,2,2)
-    plot(angle(y*j), 'bo')
-    set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
+    subplot(2,2,2);
+    plot(angle(y*j), 'bo');
+    #set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
     axis([0, fft_size, -3.5, 3.5]) 
-    title('Unequalized Symbol Angle', 'FontSize', 36);
-    xlabel('Bin Number (FFT Size)', 'FontSize', 32);
-    ylabel('Symbol Angle', 'FontSize', 32);
+    #title('Unequalized Symbol Angle', 'FontSize', 36);
+    #xlabel('Bin Number (FFT Size)', 'FontSize', 32);
+    #ylabel('Symbol Angle', 'FontSize', 32);
     
     Y = 20*log10(abs(y) ./ max(abs(y)));
-    subplot(2,2,4)
-    plot(Y, 'b-')
-    set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
+    subplot(2,2,4);
+    plot(Y, 'b-');
+    #set(gca, 'FontSize', 30, 'FontWeight', 'Bold');
     axis([0, fft_size, -50, 1]);
-    title('Frequency Domain of Unequalized Rx', 'FontSize', 36);
-    xlabel('Bin Number (FFT Size)', 'FontSize', 32);
-    ylabel('Power (dB)', 'FontSize', 32);
+    #title('Frequency Domain of Unequalized Rx', 'FontSize', 36);
+    #xlabel('Bin Number (FFT Size)', 'FontSize', 32);
+    #ylabel('Power (dB)', 'FontSize', 32);
     
-    %     N = 20*log10(var(abs(x)-1))
+    #N = 20*log10(var(abs(x)-1));
     
     disp(sprintf('Symbol Number: %d\n', i))
-%     disp(sprintf('\tFreq Error: %f\n', anglesh_pn(1+(i-1)*fft_size)))
+    #disp(sprintf('\tFreq Error: %f\n', anglesh_pn(1+(i-1)*fft_size)))
     pause
 
 end

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/receive_path.py
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/receive_path.py        
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/receive_path.py        
2008-01-02 17:35:35 UTC (rev 7324)
@@ -20,7 +20,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
 from gnuradio import usrp
 from gnuradio import eng_notation
 import copy
@@ -33,9 +33,14 @@
 #                              receive path
 # /////////////////////////////////////////////////////////////////////////////
 
-class receive_path(gr.hier_block):
-    def __init__(self, fg, rx_callback, options):
+class receive_path(gr.hier_block2):
+    def __init__(self, rx_callback, options):
 
+       gr.hier_block2.__init__(self, "receive_path",
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
+                               gr.io_signature(0, 0, 0)) # Output signature
+
+
         options = copy.copy(options)    # make a copy so we can destructively 
modify
 
         self._verbose     = options.verbose
@@ -44,20 +49,20 @@
 
         # receiver
         self.ofdm_rx = \
-                     blks.ofdm_demod(fg, options, callback=self._rx_callback)
+                     blks2.ofdm_demod(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.ofdm_rx.ofdm_recv.chan_filt, self.probe)
 
+        self.connect(self, self.ofdm_rx)
+        self.connect(self.ofdm_rx, self.probe)
+
         # Display some information about the setup
         if self._verbose:
             self._print_verbage()
         
-        gr.hier_block.__init__(self, fg, self.ofdm_rx, None)
-
     def carrier_sensed(self):
         """
         Return True if we think carrier is present.

Modified: gnuradio/trunk/gnuradio-examples/python/ofdm/transmit_path.py
===================================================================
--- gnuradio/trunk/gnuradio-examples/python/ofdm/transmit_path.py       
2008-01-02 17:04:44 UTC (rev 7323)
+++ gnuradio/trunk/gnuradio-examples/python/ofdm/transmit_path.py       
2008-01-02 17:35:35 UTC (rev 7324)
@@ -19,7 +19,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru, blks
+from gnuradio import gr, gru, blks2
 from gnuradio import usrp
 from gnuradio import eng_notation
 
@@ -30,19 +30,23 @@
 #                              transmit path
 # /////////////////////////////////////////////////////////////////////////////
 
-class transmit_path(gr.hier_block): 
-    def __init__(self, fg, options):
+class transmit_path(gr.hier_block2): 
+    def __init__(self, options):
         '''
         See below for what options should hold
         '''
 
+       gr.hier_block2.__init__(self, "transmit_path",
+                               gr.io_signature(0, 0, 0), # Input signature
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex)) # 
Output signature
+
         options = copy.copy(options)    # make a copy so we can destructively 
modify
 
-        self._verbose      = options.verbose
+        self._verbose      = options.verbose         # turn verbose mode on/off
         self._tx_amplitude = options.tx_amplitude    # digital amplitude sent 
to USRP
 
         self.ofdm_tx = \
-                     blks.ofdm_mod(fg, options, msgq_limit=4, 
pad_for_usrp=False)
+                     blks2.ofdm_mod(options, msgq_limit=4, pad_for_usrp=False)
 
         self.amp = gr.multiply_const_cc(1)
         self.set_tx_amplitude(self._tx_amplitude)
@@ -52,8 +56,7 @@
             self._print_verbage()
 
         # Create and setup transmit path flow graph
-        fg.connect(self.ofdm_tx, self.amp)
-        gr.hier_block.__init__(self, fg, None, self.amp)
+        self.connect(self.ofdm_tx, self.amp, self)
 
     def set_tx_amplitude(self, ampl):
         """





reply via email to

[Prev in Thread] Current Thread [Next in Thread]