commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r7317 - gnuradio/branches/developers/trondeau/ofdm2/gn


From: trondeau
Subject: [Commit-gnuradio] r7317 - gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general
Date: Tue, 1 Jan 2008 07:03:26 -0700 (MST)

Author: trondeau
Date: 2008-01-01 07:03:25 -0700 (Tue, 01 Jan 2008)
New Revision: 7317

Modified:
   
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
   
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
   
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
   
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
Log:
uses known-symbol with alternating 0 bins (from Schmidl and Cox sync routine) 
to do frame acquisition finding integer frequency offset, and equalizer. 
Equalizer is calculated against known symbol for all non-zero bins and linearly 
interpolates for zero bins. Frequency offset calculation doesn't work for 
certain (odd, I think) integer frequency offsets, which I think is a rotation 
problem in the way I'm calculating the correlation.

Modified: 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
===================================================================
--- 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
      2008-01-01 13:58:14 UTC (rev 7316)
+++ 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
      2008-01-01 14:03:25 UTC (rev 7317)
@@ -27,6 +27,7 @@
 #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)
@@ -35,42 +36,37 @@
 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_symbol1, 
-                               const std::vector<gr_complex> &known_symbol2,
+                               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_symbol1, known_symbol2,
-                                                                       
max_fft_shift_len));
+                                                                       
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_symbol1, 
-                                                     const 
std::vector<gr_complex> &known_symbol2,
+                                                     const 
std::vector<gr_complex> &known_symbol,
                                                      unsigned int 
max_fft_shift_len)
   : gr_block ("ofdm_frame_acquisition",
-             gr_make_io_signature (1, 1, sizeof(gr_complex)*fft_length),
+             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_symbol1(known_symbol1),
-    d_known_symbol2(known_symbol2),
+    d_known_symbol(known_symbol),
     d_coarse_freq(0),
     d_phase_count(0)
 {
-  d_diff_corr_factor.resize(d_occupied_carriers);
+  d_symbol_phase_diff.resize(d_fft_length);
+  d_known_phase_diff.resize(d_occupied_carriers);
   d_hestimate.resize(d_occupied_carriers);
 
-  std::vector<gr_complex>::iterator i1, i2;
-
   unsigned int i = 0, j = 0;
-  gr_complex one(1.0, 0.0);
-  for(i1 = d_known_symbol1.begin(), i2 = d_known_symbol2.begin(); i1 != 
d_known_symbol1.end(); i1++, i2++) {
-    d_diff_corr_factor[i] = one / ((*i1) * conj(*i2));
-    i++;
+
+  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];
@@ -91,7 +87,7 @@
 {
   unsigned ninputs = ninput_items_required.size ();
   for (unsigned i = 0; i < ninputs; i++)
-    ninput_items_required[i] = 2;
+    ninput_items_required[i] = 1;
 }
 
 gr_complex
@@ -102,91 +98,81 @@
 
   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 d_phase_lut[MAX_NUM_SYMBOLS * (d_freq_shift_len + freq_delta) + 
symbol_count];
 }
 
+
+
 bool
-gr_ofdm_frame_acquisition::correlate(const gr_complex *previous, const 
gr_complex *current, 
-                                    int zeros_on_left)
+gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int 
zeros_on_left)
 {
-  unsigned int i = 0;
-  int search_delta = 0;
-  bool found = false;
+  unsigned int i = 0, j = 0;
 
-  gr_complex h_sqrd = gr_complex(0.0,0.0);
-  float power = 0.0F;
+  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]));
+  }
 
-  while(!found && ((unsigned)abs(search_delta) <= d_freq_shift_len)) {
-    h_sqrd = gr_complex(0.0,0.0);
-    power = 0.0F;
-
-    for(i = 0; i < d_occupied_carriers; i++) {
-      h_sqrd = h_sqrd + previous[i+zeros_on_left+search_delta] * 
-       
conj(coarse_freq_comp(search_delta,1)*current[i+zeros_on_left+search_delta]) * 
-       d_diff_corr_factor[i];
-      
-      power = power + norm(current[i+zeros_on_left+search_delta]); // No need 
to do coarse freq here
+  int index = 0;
+  float max = 0, sum=0;
+  for(i = 0; i < d_fft_length - d_occupied_carriers; i++) {
+    sum = 0;
+    for(j = 0; j < d_occupied_carriers; j++) {
+      //sum += fabs(d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
+      sum += (d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
     }
-    
-#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)) {
-      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()));
+    if(fabs(sum) > max) {
+      max = sum;
+      index = i;
+    }
+  }
 
-      // check for low noise power; sets maximum SNR at 100 dB
-      if(fabs(h_sqrd.imag()) <= 1e-12) {
-       d_snr_est = 100.0;
-      }
-      else {
-       d_snr_est = 10*log10(fabs(h_sqrd.real()/h_sqrd.imag()));
-      }
+  printf("Corr: %.4f\n", max);
+  d_coarse_freq = index - zeros_on_left;
 
-#if VERBOSE
-      printf("CORR: Found, bin %d\tSNR Est %f dB\tcorr power fraction %f\n", 
-             search_delta, d_snr_est, h_sqrd.real()/power);
-#endif
-
-      // 
search_delta,10*log10(h_sqrd.real()/fabs(h_sqrd.imag())),h_sqrd.real()/power);
-      break;
-    }
-    else {
-      if(search_delta <= 0)
-       search_delta = (-search_delta) + 2;
-      else
-       search_delta = -search_delta;
-    }
+  if(0) {
+    fprintf(stderr, "Coarse Freq Offset: %d\n", d_coarse_freq);
+    fprintf(stderr, "Known:  ");
+    for(i = 0; i < 18; i++) 
+      fprintf(stderr, "%+.4f ", d_known_phase_diff[i]);
+    fprintf(stderr, "\nSymbol: ");
+    for(i = 0; i < 18; i++)
+      fprintf(stderr, "%+.4f ", 
d_symbol_phase_diff[zeros_on_left+d_coarse_freq+i]);
+    fprintf(stderr, "\n");
   }
-  return found;
+
+  return true;  //FIXME: don't need ot return anything now
 }
 
 void
-gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *previous, 
const gr_complex *current, 
-                                       int zeros_on_left)
+gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, int 
zeros_on_left)
 {
   unsigned int i=0;
 
-  for(i = 0; i < d_occupied_carriers; i++) {
-    // FIXME possibly add small epsilon in divisor to protect from div 0
-    //d_hestimate[i] = 0.5F * (d_known_symbol1[i] / previous[i+zeros_on_left] +
-    //                     d_known_symbol2[i] / 
(coarse_freq_comp(d_coarse_freq,1)*
-    //                                           
current[i+zeros_on_left+d_coarse_freq]));
-    d_hestimate[i] = 0.5F * (d_known_symbol1[i] / 
previous[i+zeros_on_left+d_coarse_freq] +
-                            d_known_symbol2[i] / 
(coarse_freq_comp(d_coarse_freq,1)*
-                                                  
current[i+zeros_on_left+d_coarse_freq]));
+  // 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);    
   }
-#if VERBOSE
-  fprintf(stderr, "\n");
-#endif
+
+  // 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(0) {
+    for(i = 0; i < d_occupied_carriers; i++) {
+      fprintf(stderr, "%+.4f + j%+.4f    ", d_hestimate[i].real(), 
d_hestimate[i].imag());
+    }
+    fprintf(stderr, "\n");
+  }
 }
 
 int
@@ -195,37 +181,40 @@
                                        gr_vector_const_void_star &input_items,
                                        gr_vector_void_star &output_items)
 {
-  const gr_complex *in = (const gr_complex *)input_items[0];
-  const gr_complex *previous = &in[0];
-  const gr_complex *current = &in[d_fft_length];
+  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];
   
-  unsigned int i=0;
-
   int unoccupied_carriers = d_fft_length - d_occupied_carriers;
   int zeros_on_left = (int)ceil(unoccupied_carriers/2.0);
 
-  bool corr = correlate(previous, current, zeros_on_left);
-  if(corr) {
-    calculate_equalizer(previous, current, zeros_on_left);
+  int found = 0;
+  for(int i = 0; i < ninput_items[1]; i++) {
+    found += trigger[i];
+  }
+
+  if(found) {
+    correlate(symbol, zeros_on_left);
+    calculate_equalizer(symbol, zeros_on_left);
     sig[0] = 1;
   }
   else {
     sig[0] = 0;
   }
 
-  for(i = 0; i < d_occupied_carriers; i++) {
-    out[i] = 
d_hestimate[i]*coarse_freq_comp(d_coarse_freq,d_phase_count)*current[i+zeros_on_left+d_coarse_freq];
+  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_each(1);
+  consume(0,1);
+  consume(1,ninput_items[1]);
   return 1;
 }

Modified: 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
===================================================================
--- 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
       2008-01-01 13:58:14 UTC (rev 7316)
+++ 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
       2008-01-01 14:03:25 UTC (rev 7317)
@@ -33,8 +33,7 @@
 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_symbol1, 
-                               const std::vector<gr_complex> &known_symbol2,
+                               const std::vector<gr_complex> &known_symbol, 
                                unsigned int max_fft_shift_len=10);
 
 /*!
@@ -71,32 +70,30 @@
   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_symbol1, 
-                                 const std::vector<gr_complex> &known_symbol2,
+                                 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_symbol1, 
-                            const std::vector<gr_complex> &known_symbol2,
+                            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 *previous, const gr_complex *current, int 
zeros_on_left);
-  void calculate_equalizer(const gr_complex *previous, 
-                          const gr_complex *current, int zeros_on_left);
+  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_symbol1, d_known_symbol2; // !< \brief known 
symbols at start of frame
-  std::vector<gr_complex> d_diff_corr_factor; // !< \brief factor used in 
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
-  signed int d_coarse_freq;             // !< \brief search distance in number 
of bins
+  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
 

Modified: 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
===================================================================
--- 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
       2008-01-01 13:58:14 UTC (rev 7316)
+++ 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
       2008-01-01 14:03:25 UTC (rev 7317)
@@ -28,8 +28,7 @@
 gr_make_ofdm_frame_acquisition (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,
+                               const std::vector<gr_complex> &known_symbol, 
                                unsigned int max_fft_shift_len=4);
 
 class gr_ofdm_frame_acquisition : public gr_sync_decimator
@@ -38,8 +37,7 @@
   gr_ofdm_frame_acquisition (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,
+                            const std::vector<gr_complex> &known_symbol, 
                             unsigned int max_fft_shift_len);
 
  public:

Modified: 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
===================================================================
--- 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
        2008-01-01 13:58:14 UTC (rev 7316)
+++ 
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
        2008-01-01 14:03:25 UTC (rev 7317)
@@ -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);
   }





reply via email to

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