From 9967e2e7664dbc96a5d1587c194cc648d01cf487 Mon Sep 17 00:00:00 2001
From: trondeau <trondeau@221aa14e-8319-0410-a670-987f0aec2ac5>
Date: Sat, 4 Aug 2007 15:21:34 +0000
Subject: merged -r5966:6112 on trondeau/ofdm_mod. Allows for generic
 constellations (supports bpsk, qpsk, 8psk, qam16, qam64, and qam256
 currently), fixes some bugs in the correlation and altered default parameters
 for over-the-air operation. This merge fixes ticket:156 and ticket:157.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@6113 221aa14e-8319-0410-a670-987f0aec2ac5
---
 gnuradio-core/src/lib/general/general.i            |   2 +
 .../src/lib/general/gr_ofdm_bpsk_mapper.cc         |   4 +-
 .../src/lib/general/gr_ofdm_correlator.cc          |  28 ++--
 gnuradio-core/src/lib/general/gr_ofdm_correlator.h |   2 +-
 .../src/lib/general/gr_ofdm_frame_sink.cc          | 126 +++++++++--------
 gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h |  38 ++---
 gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i |  10 +-
 .../src/lib/general/gr_ofdm_mapper_bcv.cc          | 156 ++++++++++++++++++++-
 gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h |  48 +++++--
 gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i |  26 ++--
 .../src/lib/general/gr_ofdm_qpsk_mapper.cc         |   4 +-
 gnuradio-core/src/lib/general/gr_ofdm_sampler.cc   |   4 +-
 gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py |  51 +++++--
 gnuradio-core/src/python/gnuradio/blksimpl/psk.py  |   6 +
 gnuradio-core/src/python/gnuradio/gruimpl/crc.py   |   4 +-
 15 files changed, 375 insertions(+), 134 deletions(-)

(limited to 'gnuradio-core/src')

diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index a6a356f4e3..e9780ea133 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -96,6 +96,7 @@
 #include <gr_ofdm_correlator.h>
 #include <gr_ofdm_cyclic_prefixer.h>
 #include <gr_ofdm_bpsk_demapper.h>
+#include <gr_ofdm_mapper_bcv.h>
 #include <gr_ofdm_bpsk_mapper.h>
 #include <gr_ofdm_qpsk_mapper.h>
 #include <gr_ofdm_qam_mapper.h>
@@ -203,6 +204,7 @@
 %include "gr_ofdm_correlator.i"
 %include "gr_ofdm_cyclic_prefixer.i"
 %include "gr_ofdm_bpsk_demapper.i"
+%include "gr_ofdm_mapper_bcv.i"
 %include "gr_ofdm_bpsk_mapper.i"
 %include "gr_ofdm_qpsk_mapper.i"
 %include "gr_ofdm_qam_mapper.i"
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc
index da32886806..f634ed3f63 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_mapper.cc
@@ -59,7 +59,7 @@ static float
 randombit()
 {
   int r = rand()&1;
-  return (float)(-1 + 2*r);
+  return (float)(1 - 2*r);
 }
 
 int
@@ -105,7 +105,7 @@ gr_ofdm_bpsk_mapper::work(int noutput_items,
   i = 0;
   while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
     unsigned char bit = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
-    out[i + zeros_on_left] = gr_complex(-1+2*(bit));
+    out[i + zeros_on_left] = gr_complex(1-2*(bit));
     i++;
     d_bit_offset++;
     if(d_bit_offset == 8) {
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
index 4c7b67ff74..e396eeb8e6 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
@@ -99,12 +99,13 @@ gr_ofdm_correlator::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);
 
-  assert(d_freq_shift_len + freq_delta >= 0);
-  assert(symbol_count <= MAX_NUM_SYMBOLS);
+  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];
+  //assert(d_freq_shift_len + freq_delta >= 0);
+  //assert(symbol_count <= MAX_NUM_SYMBOLS);
+
+  //return d_phase_lut[MAX_NUM_SYMBOLS * (d_freq_shift_len + freq_delta) + symbol_count];
 }
 
 bool
@@ -118,7 +119,7 @@ gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *curr
   gr_complex h_sqrd = gr_complex(0.0,0.0);
   float power = 0.0F;
 
-  while(!found && ((unsigned)abs(search_delta) < d_freq_shift_len)) {
+  while(!found && ((unsigned)abs(search_delta) <= d_freq_shift_len)) {
     h_sqrd = gr_complex(0.0,0.0);
     power = 0.0F;
 
@@ -126,17 +127,18 @@ gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *curr
       h_sqrd = h_sqrd + previous[i+zeros_on_left+search_delta] * 
 	conj(coarse_freq_comp(search_delta,1)*current[i+zeros_on_left+search_delta]) * 
 	d_diff_corr_factor[i];
+      
       power = power + norm(current[i+zeros_on_left+search_delta]); // No need to do coarse freq here
     }
     
 #if VERBOSE
-      printf("bin %d\th_sqrd = ( %f, %f )\t power = %f\t real(h)/p = %f\t angle = %f\n", 
-	     search_delta, h_sqrd.real(), h_sqrd.imag(), power, h_sqrd.real()/power, arg(h_sqrd)); 
-#endif
-
-      // FIXME: Look at h_sqrd.read() > power
-    if((h_sqrd.real() > 0.82*power)  && (h_sqrd.real() < 1.1 * power)) {
+    printf("bin %d\th_sqrd = ( %f, %f )\t power = %f\t real(h)/p = %f\t angle = %f\n", 
+	   search_delta, h_sqrd.real(), h_sqrd.imag(), power, h_sqrd.real()/power, arg(h_sqrd)); 
+#endif      
+    // FIXME: Look at h_sqrd.read() > power
+    if((h_sqrd.real() > 0.82*power) && (h_sqrd.real() < 1.1 * power)) {
       found = true;
+      //printf("search delta: %d\n", search_delta);
       d_coarse_freq = search_delta;
       d_phase_count = 1;
       //d_snr_est = 10*log10(power/(power-h_sqrd.real()));
@@ -220,6 +222,10 @@ gr_ofdm_correlator::general_work(int noutput_items,
   
 
   d_phase_count++;
+  if(d_phase_count == MAX_NUM_SYMBOLS) {
+    d_phase_count = 1;
+  }
+
   consume_each(1);
   return 1;
 }
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h b/gnuradio-core/src/lib/general/gr_ofdm_correlator.h
index 981df7e1ce..55ee4e1907 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h
+++ b/gnuradio-core/src/lib/general/gr_ofdm_correlator.h
@@ -35,7 +35,7 @@ gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length
 			 unsigned int cplen,
 			 const std::vector<gr_complex> &known_symbol1, 
 			 const std::vector<gr_complex> &known_symbol2,
-			 unsigned int max_fft_shift_len=4);
+			 unsigned int max_fft_shift_len=10);
 
 /*!
  * \brief take a vector of complex constellation points in from an FFT
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
index 68cadce040..d75b693a2b 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
@@ -74,55 +74,57 @@ gr_ofdm_frame_sink::enter_have_header()
 	    d_packetlen, d_packet_whitener_offset);
 }
 
-unsigned char gr_ofdm_frame_sink::bpsk_slicer(gr_complex x)
-{
-  return (unsigned char)(x.real() > 0 ? 1 : 0);
-}
-
-unsigned char gr_ofdm_frame_sink::qpsk_slicer(gr_complex x)
-{
-  unsigned char i = (x.real() > 0 ? 1 : 0);
-  unsigned char q = (x.imag() > 0 ? 1 : 0);
-
-  return (q << 1) | i;
-}
 
-unsigned int gr_ofdm_frame_sink::bpsk_demapper(const gr_complex *in,
-					       unsigned char *out)
+unsigned char gr_ofdm_frame_sink::slicer(const gr_complex x)
 {
-  unsigned int i=0, bytes_produced=0;
-
-  while(i < d_occupied_carriers) {
-
-    while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
-      //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag()); 
-      d_partial_byte |= bpsk_slicer(in[i++]) << (d_byte_offset++);
-    }
-
-    if(d_byte_offset == 8) {
-      out[bytes_produced++] = d_partial_byte;
-      d_byte_offset = 0;
-      d_partial_byte = 0;
+  unsigned int table_size = d_sym_value_out.size();
+  unsigned int min_index = 0;
+  float min_euclid_dist = norm(x - d_sym_position[0]);
+  float euclid_dist = 0;
+  
+  for (unsigned int j = 1; j < table_size; j++){
+    euclid_dist = norm(x - d_sym_position[j]);
+    if (euclid_dist < min_euclid_dist){
+      min_euclid_dist = euclid_dist;
+      min_index = j;
     }
   }
-
-  return bytes_produced;
+  return d_sym_value_out[min_index];
 }
 
-unsigned int gr_ofdm_frame_sink::qpsk_demapper(const gr_complex *in,
-					       unsigned char *out)
+unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
+					  unsigned char *out)
 {
   unsigned int i=0, bytes_produced=0;
 
   while(i < d_occupied_carriers) {
-    
+    if(d_nresid > 0) {
+      d_partial_byte |= d_resid;
+      d_byte_offset += d_nresid;
+      d_nresid = 0;
+      d_resid = 0;
+    }
+
     while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
-      //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag()); 
-      d_partial_byte |= qpsk_slicer(in[i++]) << (d_byte_offset);
-      d_byte_offset += 2;
+      //fprintf(stderr, "%f+j%f  = %d\n", in[i].real(), in[i].imag(), slicer(in[i])); 
+      unsigned char bits = slicer(in[i++]);
+      if((8 - d_byte_offset) >= d_nbits) {
+	d_partial_byte |= bits << (d_byte_offset);
+	d_byte_offset += d_nbits;
+      }
+      else {
+	d_nresid = d_nbits-(8-d_byte_offset);
+	int mask = ((1<<(8-d_byte_offset))-1);
+	d_partial_byte |= (bits & mask) << d_byte_offset;
+	d_resid = bits >> (8-d_byte_offset);
+	d_byte_offset += (d_nbits - d_nresid);
+      }
+      //printf("demod symbol: %.4f + j%.4f   bits: %x   partial_byte: %x   byte_offset: %d   resid: %x   nresid: %d\n", 
+      //     in[i-1].real(), in[i-1].imag(), bits, d_partial_byte, d_byte_offset, d_resid, d_nresid);
     }
 
     if(d_byte_offset == 8) {
+      //printf("demod byte: %x \n\n", d_partial_byte);
       out[bytes_produced++] = d_partial_byte;
       d_byte_offset = 0;
       d_partial_byte = 0;
@@ -132,34 +134,31 @@ unsigned int gr_ofdm_frame_sink::qpsk_demapper(const gr_complex *in,
   return bytes_produced;
 }
 
+
 gr_ofdm_frame_sink_sptr
-gr_make_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
-			const std::string &mod)
+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)
 {
-  return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(target_queue, occupied_carriers, mod));
+  return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(sym_position, sym_value_out,
+							target_queue, occupied_carriers));
 }
 
 
-gr_ofdm_frame_sink::gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
-				       const std::string &mod)
+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_sync_block ("ofdm_frame_sink",
 		   gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)),
 		   gr_make_io_signature (0, 0, 0)),
     d_target_queue(target_queue), d_occupied_carriers(occupied_carriers), 
-    d_byte_offset(0), d_partial_byte(0)
+    d_byte_offset(0), d_partial_byte(0),
+    d_resid(0), d_nresid(0)
 {
-  d_bytes_out = new unsigned char[(int)ceil(d_occupied_carriers/4.0)];
-
-  if(mod == "qpsk") {
-    d_demapper = &gr_ofdm_frame_sink::qpsk_demapper;
-  }
-  else if(mod == "bpsk") {
-    d_demapper = &gr_ofdm_frame_sink::bpsk_demapper;
-  }
-  else {
-    throw std::invalid_argument("Modulation type must be BPSK or QPSK.");  
-  }
+  d_bytes_out = new unsigned char[d_occupied_carriers];
 
+  set_sym_value_out(sym_position, sym_value_out);
+  
   enter_search();
 }
 
@@ -168,6 +167,24 @@ gr_ofdm_frame_sink::~gr_ofdm_frame_sink ()
   delete [] d_bytes_out;
 }
 
+bool
+gr_ofdm_frame_sink::set_sym_value_out(const std::vector<gr_complex> &sym_position, 
+				      const std::vector<unsigned char> &sym_value_out)
+{
+  if (sym_position.size() != sym_value_out.size())
+    return false;
+
+  if (sym_position.size()<1)
+    return false;
+
+  d_sym_position  = sym_position;
+  d_sym_value_out = sym_value_out;
+  d_nbits = (unsigned long)(log10(d_sym_value_out.size()) / log10(2));
+
+  return true;
+}
+
+
 int
 gr_ofdm_frame_sink::work (int noutput_items,
 			  gr_vector_const_void_star &input_items,
@@ -181,9 +198,8 @@ gr_ofdm_frame_sink::work (int noutput_items,
   if (VERBOSE)
     fprintf(stderr,">>> Entering state machine\n");
   
-  //bytes = bpsk_demapper(&in[0], d_bytes_out);
-  bytes = (this->*d_demapper)(&in[0], d_bytes_out);  
-
+  bytes = demapper(&in[0], d_bytes_out);
+  
   switch(d_state) {
       
   case STATE_SYNC_SEARCH:    // Look for flag indicating beginning of pkt
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
index 13f61b782d..f1c9b76fea 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
@@ -30,8 +30,9 @@ class gr_ofdm_frame_sink;
 typedef boost::shared_ptr<gr_ofdm_frame_sink> gr_ofdm_frame_sink_sptr;
 
 gr_ofdm_frame_sink_sptr 
-gr_make_ofdm_frame_sink (gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
-			 const std::string &mod);
+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);
 
 /*!
  * \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs
@@ -44,8 +45,9 @@ gr_make_ofdm_frame_sink (gr_msg_queue_sptr target_queue, unsigned int occupied_t
 class gr_ofdm_frame_sink : public gr_sync_block
 {
   friend gr_ofdm_frame_sink_sptr 
-  gr_make_ofdm_frame_sink (gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
-			   const std::string &mod);
+  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);
 
  private:
   enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER};
@@ -69,9 +71,17 @@ class gr_ofdm_frame_sink : public gr_sync_block
   int                d_packet_whitener_offset;  // offset into whitener string to use
   int		     d_packetlen_cnt;		// how many so far
 
+  std::vector<gr_complex>    d_sym_position;
+  std::vector<unsigned char> d_sym_value_out;
+  unsigned int d_nbits;
+
+  unsigned char d_resid;
+  unsigned int d_nresid;
+
  protected:
-  gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
-		     const std::string &mod);
+  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);
 
   void enter_search();
   void enter_have_sync();
@@ -82,17 +92,13 @@ class gr_ofdm_frame_sink : public gr_sync_block
     // confirm that two copies of header info are identical
     return ((d_header >> 16) ^ (d_header & 0xffff)) == 0;
   }
+  
+  unsigned char slicer(const gr_complex x);
+  unsigned int demapper(const gr_complex *in,
+			unsigned char *out);
 
-  unsigned char bpsk_slicer(gr_complex x);
-  unsigned int bpsk_demapper(const gr_complex *in,
-			     unsigned char *out);  
-
-  unsigned char qpsk_slicer(gr_complex x);
-  unsigned int qpsk_demapper(const gr_complex *in,
-			     unsigned char *out);
-
-  // pointer to mod-specific demapper
-  unsigned int (gr_ofdm_frame_sink::*d_demapper)(const gr_complex *in, unsigned char *out);
+  bool set_sym_value_out(const std::vector<gr_complex> &sym_position, 
+			 const std::vector<unsigned char> &sym_value_out);
 
  public:
   ~gr_ofdm_frame_sink();
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
index 4f4f81d22c..296eb65912 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
@@ -23,14 +23,16 @@
 GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink);
 
 gr_ofdm_frame_sink_sptr 
-gr_make_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
-			const std::string &mod);
+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);
 
 class gr_ofdm_frame_sink : public gr_sync_block
 {
  protected:
-  gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
-		     const std::string &mod);
+  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);
 
  public:
   ~gr_ofdm_frame_sink();
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
index 76a7c94d9c..4ff55b5d80 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004,2005 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -20,22 +20,166 @@
  * Boston, MA 02110-1301, USA.
  */
 
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <gr_ofdm_mapper_bcv.h>
 #include <gr_io_signature.h>
+#include <stdexcept>
+
+gr_ofdm_mapper_bcv_sptr
+gr_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned int msgq_limit, 
+			 unsigned int occupied_carriers, unsigned int fft_length)
+{
+  return gr_ofdm_mapper_bcv_sptr (new gr_ofdm_mapper_bcv (constellation, msgq_limit, 
+							  occupied_carriers, fft_length));
+}
+
+// Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
+gr_ofdm_mapper_bcv::gr_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned int msgq_limit, 
+					unsigned int occupied_carriers, unsigned int fft_length)
+  : gr_sync_block ("ofdm_mapper_bcv",
+		   gr_make_io_signature (0, 0, 0),
+		   gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
+    d_constellation(constellation),
+    d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false),
+    d_occupied_carriers(occupied_carriers),
+    d_fft_length(fft_length),
+    d_bit_offset(0),
+    d_pending_flag(0),
+    d_resid(0),
+    d_nresid(0)
+{
+  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));
+}
 
 gr_ofdm_mapper_bcv::~gr_ofdm_mapper_bcv(void)
 {
 }
 
-gr_ofdm_mapper_bcv::gr_ofdm_mapper_bcv (unsigned bits_per_symbol,unsigned int vlen)
-  : gr_sync_decimator ("ofdm_mapper_bcv",
-		       gr_make_io_signature (1, 1, sizeof(unsigned char)),
-		       gr_make_io_signature (1, 1, sizeof(gr_complex)*vlen),
-		       bits_per_symbol)
+int gr_ofdm_mapper_bcv::randsym()
 {
+  return (rand() % d_constellation.size());
 }
 
+int
+gr_ofdm_mapper_bcv::work(int noutput_items,
+			  gr_vector_const_void_star &input_items,
+			  gr_vector_void_star &output_items)
+{
+  gr_complex *out = (gr_complex *)output_items[0];
+  
+  unsigned int i=0;
+  unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
+  unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
+
+  //printf("OFDM BPSK Mapper:  ninput_items: %d   noutput_items: %d\n", ninput_items[0], noutput_items);
+
+  if(d_eof) {
+    return -1;
+  }
+  
+  if(!d_msg) {
+    d_msg = d_msgq->delete_head();	   // block, waiting for a message
+    d_msg_offset = 0;
+    d_bit_offset = 0;
+    d_pending_flag = 1;			   // new packet, write start of packet flag
+    
+    if((d_msg->length() == 0) && (d_msg->type() == 1)) {
+      d_msg.reset();
+      return -1;		// We're done; no more messages coming.
+    }
+  }
+
+  char *out_flag = 0;
+  if(output_items.size() == 2)
+    out_flag = (char *) output_items[1];
+  
+
+  // Build a single symbol:
+  // Initialize all bins to 0 to set unused carriers
+  memset(out, 0, d_fft_length*sizeof(gr_complex));
+  
+  i = 0;
+  unsigned char bits = 0;
+  while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
+    
+    // need new data to process
+    if(d_bit_offset == 0) {
+      d_msgbytes = d_msg->msg()[d_msg_offset];
+      //printf("mod message byte: %x\n", d_msgbytes);
+    }
+
+    if(d_nresid > 0) {
+      d_resid |= (((1 << d_nresid)-1) & d_msgbytes) << (d_nbits - d_nresid);
+      bits = d_resid;
+
+      out[i + zeros_on_left] = d_constellation[bits];
+      i++;
+
+      d_bit_offset += d_nresid;
+      d_nresid = 0;
+      d_resid = 0;
+      //printf("mod bit(r): %x   resid: %x   nresid: %d    bit_offset: %d\n", 
+      //     bits, d_resid, d_nresid, d_bit_offset);
+    }
+    else {
+      if((8 - d_bit_offset) >= d_nbits) {
+	bits = ((1 << d_nbits)-1) & (d_msgbytes >> d_bit_offset);
+	d_bit_offset += d_nbits;
+	
+	out[i + zeros_on_left] = d_constellation[bits];
+	i++;
+	
+	/*
+	printf("mod bit: %x  out: %.4f + j%.4f    resid: %x   nresid: %d    bit_offset: %d\n", 
+	       bits, out[i-1 + zeros_on_left].real(), out[i-1 + zeros_on_left].imag(), 
+	       d_resid, d_nresid, d_bit_offset);
+	*/
+      }
+      else {
+	unsigned int extra = 8-d_bit_offset;
+	d_resid = ((1 << extra)-1) & (d_msgbytes >> d_bit_offset);
+	d_bit_offset += extra;
+	d_nresid = d_nbits - extra;
+      }
+      
+    }
+            
+    if(d_bit_offset == 8) {
+      d_bit_offset = 0;
+      d_msg_offset++;
+    }
+  }
+
+  // Ran out of data to put in symbol
+  if (d_msg_offset == d_msg->length()) {
+    if(d_nresid > 0) {
+      d_resid |= 0x00;
+      bits = d_resid;
+      d_nresid = 0;
+      d_resid = 0;
+    }
+
+    while(i < d_occupied_carriers) {   // finish filling out the symbol
+      out[i + zeros_on_left] = d_constellation[randsym()];
+      i++;
+    }
+
+    if (d_msg->type() == 1)	        // type == 1 sets EOF
+      d_eof = true;
+    d_msg.reset();   			// finished packet, free message
+    assert(d_bit_offset == 0);
+  }
+
+  if (out_flag)
+    out_flag[0] = d_pending_flag;
+  d_pending_flag = 0;
+
+  return 1;  // produced symbol
+}
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h
index 7b55d90ceb..a9b676a3c9 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h
+++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -23,14 +23,16 @@
 #ifndef INCLUDED_GR_OFDM_MAPPER_BCV_H
 #define INCLUDED_GR_OFDM_MAPPER_BCV_H
 
-#include <gr_sync_decimator.h>
+#include <gr_sync_block.h>
+#include <gr_message.h>
+#include <gr_msg_queue.h>
 
 class gr_ofdm_mapper_bcv;
 typedef boost::shared_ptr<gr_ofdm_mapper_bcv> gr_ofdm_mapper_bcv_sptr;
 
 gr_ofdm_mapper_bcv_sptr 
-gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen);
-
+gr_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit, 
+			 unsigned occupied_carriers, unsigned int fft_length);
 
 /*!
  * \brief take a stream of bytes in and map to a vector of complex
@@ -39,18 +41,44 @@ gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen);
  *
  */
 
-class gr_ofdm_mapper_bcv : public gr_sync_decimator
+class gr_ofdm_mapper_bcv : public gr_sync_block
 {
   friend gr_ofdm_mapper_bcv_sptr
-  gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen);
+  gr_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit, 
+			   unsigned occupied_carriers, unsigned int fft_length);
+ protected:
+  gr_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned msgq_limit, 
+		      unsigned occupied_carriers, unsigned int fft_length);
+
+ private:
+  std::vector<gr_complex> d_constellation;
+  gr_msg_queue_sptr	d_msgq;
+  gr_message_sptr	d_msg;
+  unsigned		d_msg_offset;
+  bool			d_eof;
+  
+  unsigned int 		d_occupied_carriers;
+  unsigned int 		d_fft_length;
+  unsigned int 		d_bit_offset;
+  int			d_pending_flag;
+
+  unsigned long  d_nbits;
+  unsigned char  d_msgbytes;
+  
+  unsigned char d_resid;
+  unsigned int d_nresid;
 
-protected:
-  gr_ofdm_mapper_bcv (unsigned int bits_per_symbol, unsigned int vlen);
+  int randsym();
 
-public:
+ public:
   ~gr_ofdm_mapper_bcv(void);
-};
 
+  gr_msg_queue_sptr	msgq() const { return d_msgq; }
+
+  int work(int noutput_items,
+	   gr_vector_const_void_star &input_items,
+	   gr_vector_void_star &output_items);
 
+};
 
 #endif
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i
index e786c70f51..30c6929262 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i
+++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.i
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004,2006 Free Software Foundation, Inc.
+ * Copyright 2006,2007 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -20,17 +20,27 @@
  * Boston, MA 02110-1301, USA.
  */
 
-GR_SWIG_BLOCK_MAGIC(gr,ofdm_mapper_bcv)
+GR_SWIG_BLOCK_MAGIC(gr,ofdm_mapper_bcv);
 
 gr_ofdm_mapper_bcv_sptr 
-gr_make_ofdm_mapper_bcv (unsigned int bits_per_symbol, 
-			 unsigned int vlen);
+gr_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation,
+			 unsigned int msgq_limit,
+			 unsigned int bits_per_symbol, 
+			 unsigned int fft_length);
 
-class gr_ofdm_mapper_bcv : public gr_sync_decimator
+
+class gr_ofdm_mapper_bcv : public gr_sync_block
 {
  protected:
-  gr_ofdm_mapper_bcv (unsigned int bits_per_symbol,
-		      unsigned int vlen);
-
+  gr_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation,
+		      unsigned int msgq_limit,
+		      unsigned int bits_per_symbol,
+		      unsigned int fft_length);
+  
  public:
+  gr_msg_queue_sptr msgq();
+  
+  int work(int noutput_items,
+	   gr_vector_const_void_star &input_items,
+	   gr_vector_void_star &output_items);
 };
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_qpsk_mapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_qpsk_mapper.cc
index 011d15f6f7..39c5bbdee8 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_qpsk_mapper.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_qpsk_mapper.cc
@@ -60,7 +60,7 @@ randombit()
 {
   int r1 = rand()&1;
   int r2 = rand()&1;
-  return gr_complex((0.707)*(-1 + 2*r1),(0.707)*(-1 + 2*r2));
+  return gr_complex((0.707)*(1 - 2*r1),(0.707)*(1 - 2*r2));
 }
 
 int
@@ -111,7 +111,7 @@ gr_ofdm_qpsk_mapper::work(int noutput_items,
     unsigned char bit1 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
     d_bit_offset++;
     
-    out[i + zeros_on_left] = gr_complex((0.707)*(-1+2*(bit0)), (0.707)*(-1+2*(bit1)) );
+    out[i + zeros_on_left] = gr_complex((0.707)*(1-2*(bit0)), (0.707)*(1-2*(bit1)) );
     i++;
     if(d_bit_offset == 8) {
       d_bit_offset = 0;
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
index 02897bb6b1..56b5d50a4e 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
@@ -69,11 +69,12 @@ gr_ofdm_sampler::general_work (int noutput_items,
 
   int i=d_fft_length-1;
 
-  while(!found && i<std::min(ninput_items[0],ninput_items[1]) )
+  while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
     if(trigger[i])
       found = 1;
     else
       i++;
+  }
 
   if(found) {
     assert(i-d_fft_length+1 >= 0);
@@ -89,6 +90,5 @@ gr_ofdm_sampler::general_work (int noutput_items,
     //  ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+1), found);
  }
 
-
   return found;
 }
diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py
index d4fef81ecf..b040d8c7f4 100644
--- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py
+++ b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py
@@ -24,6 +24,7 @@ import math
 from numpy import fft
 from gnuradio import gr, ofdm_packet_utils
 import gnuradio.gr.gr_threading as _threading
+import psk, qam
 
 from gnuradio.blksimpl.ofdm_receiver import ofdm_receiver
 
@@ -81,15 +82,21 @@ class ofdm_mod(gr.hier_block):
             padded_preambles.append(padded)
             
         symbol_length = options.fft_length + options.cp_length
-
-        # The next step will all us to pass a constellation into a generic mapper function instead
-        # of using these hard-coded versions
-        if self._modulation == "bpsk":
-            self._pkt_input = gr.ofdm_bpsk_mapper(msgq_limit, options.occupied_tones, options.fft_length)
-        elif self._modulation == "qpsk":
-            self._pkt_input = gr.ofdm_qpsk_mapper(msgq_limit, options.occupied_tones, options.fft_length)
-        else:
-            print "Modulation type not supported (must be \"bpsk\" or \"qpsk\""
+        
+        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)
@@ -104,7 +111,8 @@ class ofdm_mod(gr.hier_block):
             self._print_verbage()
 
         if options.log:
-            fg.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat"))
+            fg.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length,
+                                                     "ofdm_mapper_c.dat"))
 
         gr.hier_block.__init__(self, fg, None, self.scale)
 
@@ -119,8 +127,8 @@ class ofdm_mod(gr.hier_block):
             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)
-
+            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)
@@ -208,9 +216,22 @@ class ofdm_demod(gr.hier_block):
         self.ofdm_recv = ofdm_receiver(fg, self._fft_length, self._cp_length,
                                        self._occupied_tones, self._snr, preambles,
                                        options.log)
-        self.ofdm_demod = gr.ofdm_frame_sink(self._rcvd_pktq,
-                                             self._occupied_tones,
-                                             self._modulation)
+
+        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)
         
         fg.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
         fg.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))
diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/psk.py b/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
index 5dcf4935e5..acedf3b69a 100644
--- a/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
+++ b/gnuradio-core/src/python/gnuradio/blksimpl/psk.py
@@ -53,6 +53,12 @@ constellation = {
     8 : make_constellation(8)            # 8PSK
     }
 
+gray_constellation = {
+    2 : make_gray_constellation(2),           # BPSK
+    4 : make_gray_constellation(4),           # QPSK
+    8 : make_gray_constellation(8)            # 8PSK
+    }
+
 # -----------------------
 # Do Gray code
 # -----------------------
diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py
index ad8ce88793..d31aca0ea7 100644
--- a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py
+++ b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py
@@ -1,5 +1,5 @@
 #
-# Copyright 2005 Free Software Foundation, Inc.
+# Copyright 2005,2007 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -25,7 +25,7 @@ import struct
 
 def gen_and_append_crc32(s):
     crc = gr.crc32(s)
-    return s + struct.pack(">I", hexint(crc))
+    return s + struct.pack(">I", hexint(crc) & 0xFFFFFFFF)
 
 def check_crc32(s):
     if len(s) < 4:
-- 
cgit v1.2.3