Merging trondeau/ofdmfix into branch at -r7582:7586. This allows for over-the-air...
authortrondeau <trondeau@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 6 Feb 2008 15:54:54 +0000 (15:54 +0000)
committertrondeau <trondeau@221aa14e-8319-0410-a670-987f0aec2ac5>
Wed, 6 Feb 2008 15:54:54 +0000 (15:54 +0000)
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@7587 221aa14e-8319-0410-a670-987f0aec2ac5

gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t
gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py
gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py

index 0fa6a3d3e54765a6baebe5326ed12a97790ed7b0..40a0ed852e0a0697d612178c47ffe8d8fd4af477 100644 (file)
@@ -48,7 +48,7 @@ gr_ofdm_frame_acquisition::gr_ofdm_frame_acquisition (unsigned occupied_carriers
                                                      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_signature  (1, 1, sizeof(gr_complex)*fft_length),
              gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char))),
     d_occupied_carriers(occupied_carriers),
     d_fft_length(fft_length),
@@ -101,44 +101,64 @@ gr_ofdm_frame_acquisition::coarse_freq_comp(int freq_delta, int 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;
+  unsigned int i = 0;
+  int search_delta = 0;
+  bool found = false;
+  
+  gr_complex h_sqrd = gr_complex(0.0,0.0);
+  float power = 0.0F;
 
   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]);
+  
+  while(!found && ((unsigned)abs(search_delta) <= d_freq_shift_len)) {
+    h_sqrd = gr_complex(0.0,0.0);
+    power = 0.0F;
+    
+    //FIXME: power calculation doesn't really make sense 
+    for(i = 0; i < d_occupied_carriers; i++) {
+      h_sqrd += (d_known_phase_diff[i] * d_symbol_phase_diff[i+zeros_on_left+search_delta]);
+      power += d_known_phase_diff[i]*d_known_phase_diff[i];
     }
-    if(fabs(sum) > max) {
-      max = sum;
-      index = i;
+    
+    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));
     }
-  }
-
-  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]);
+    //FIXME: these threshold values are arbitrary, although the decision metric is very good
+    // even at very low SNR
+    if((h_sqrd.real() > 0.95*power) && (h_sqrd.real() < 1.1*power)) {
+      found = true;
+      d_coarse_freq = search_delta;
+      d_phase_count = 1;
+     
+      //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));
+
+      if(VERBOSE) {
+       printf("CORR: Found, bin %d\tdB\tcorr power fraction %f\n",
+              search_delta, h_sqrd.real()/power);
+      }
+      break;
+    }
+    else {
+      if(search_delta <= 0)
+       search_delta = (-search_delta) + 2;
+      else
+       search_delta = -search_delta;
     }
   }
-
-  return true;  //FIXME: don't need ot return anything now
+  return found;
 }
 
+
 void
 gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, int zeros_on_left)
 {
@@ -184,7 +204,6 @@ gr_ofdm_frame_acquisition::general_work(int noutput_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];
@@ -193,19 +212,15 @@ gr_ofdm_frame_acquisition::general_work(int noutput_items,
   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];
-  }
-
+  found = correlate(symbol, zeros_on_left);
   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)
@@ -217,7 +232,6 @@ gr_ofdm_frame_acquisition::general_work(int noutput_items,
     d_phase_count = 1;
   }
 
-  consume(0,1);
-  consume(1,ninput_items[1]);
+  consume_each(1);
   return 1;
 }
index 6216df791cfc7e7bd03c35cc1711682f525a4bab..c529456565dd3a03fe7377ec5dcdf05b686ed0d5 100644 (file)
@@ -70,8 +70,7 @@ gr_ofdm_sampler::general_work (int noutput_items,
   int i=d_fft_length-1;
 
   // 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]) ) {
+  while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
     if(trigger[i]) {
       found = 1;
       index = i++;
index 6808deae2696ce93be157fa19e7d31c7ae0eed5f..e2f6b50263aa641ae1c43fd2423dec3d3c74968a 100644 (file)
@@ -105,6 +105,6 @@ int
   }
   else {   // only return up to passing the threshold
     //printf("Leave in State 1, only produced %d of %d\n",peak_ind,noutput_items);
-    return peak_ind;
+    return peak_ind+1;
   }
 }
index 9592755b1fa616e4fc37b659423a5f5018b7dd13..c5cb4df5c53590fd4701db08b9df19ac3bfcce18 100644 (file)
@@ -100,7 +100,6 @@ class ofdm_receiver(gr.hier_block2):
 
         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))
 
index 0ec22ccedbef52ca4422e54d5db9264d2289ce3f..71140bca58e7cce813daa862dbb38ae6450845e0 100644 (file)
@@ -35,7 +35,7 @@ class ofdm_sync_pn(gr.hier_block2):
         
        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
+                               gr.io_signature(1, 1, gr.sizeof_gr_complex*fft_length)) # Output signature
 
         # FIXME: when converting to hier_block2's, the output signature
         # should be the output of the divider (the normalized peaks) and
@@ -86,9 +86,9 @@ class ofdm_sync_pn(gr.hier_block2):
         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(9)
+        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(9)
         #self.pk_detect = gr.threshold_detector_fb(0.5)
         self.regen = gr.regenerate_bb(symbol_length)
 
@@ -123,15 +123,14 @@ class ofdm_sync_pn(gr.hier_block2):
         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.matched_filter, self.pk_detect)
+        self.connect(self.matched_filter, self.sub1, self.pk_detect)
+        #self.connect(self.matched_filter, 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"))