commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 03/06: gr-dtv: Vastly improved OFDM symbol


From: git
Subject: [Commit-gnuradio] [gnuradio] 03/06: gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver.
Date: Sun, 27 Dec 2015 21:43:03 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit 761b62d4660a121c78b6a7ad17fd7b08badcbb88
Author: flarroca <address@hidden>
Date:   Wed Dec 9 18:38:38 2015 -0800

    gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver.
---
 gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc | 178 +++++++++++-----------
 gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h  |  21 ++-
 2 files changed, 102 insertions(+), 97 deletions(-)

diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc 
b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
index 84b20f9..abef1d0 100644
--- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
+++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
@@ -34,12 +34,12 @@ namespace gr {
   namespace dtv {
 
     int
-    dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float 
threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha)
+    dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float 
threshold_factor_rise, float alpha)
     {
       d_avg_alpha = alpha;
       d_threshold_factor_rise = threshold_factor_rise;
-      d_threshold_factor_fall = threshold_factor_fall;
-      d_avg = 0;
+      d_avg_max = - (float)INFINITY;
+      d_avg_min =   (float)INFINITY;
 
       return (0);
     }
@@ -47,56 +47,50 @@ namespace gr {
     int
     dvbt_ofdm_sym_acquisition_impl::peak_detect_process(const float * datain, 
const int datain_length, int * peak_pos, int * peak_max)
     {
-      int state = 0;
-      float peak_val = -(float)INFINITY; int peak_index = 0; int 
peak_pos_length = 0;
+      unsigned int peak_index = 0;
+      int peak_pos_length = 0;
 
-      int i = 0;
+      volk_32f_index_max_16u(&peak_index, &datain[0], datain_length); 
 
-      while(i < datain_length) {
-        if (state == 0) {
-          if (datain[i] > d_avg * d_threshold_factor_rise) {
-            state = 1;
-          }
-          else {
-            d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg;
-            i++;
-          }
+      peak_pos_length = 1; 
+      if (datain_length >= d_fft_length) {
+        float min = datain[(peak_index + d_fft_length / 2) % d_fft_length];
+        if (d_avg_min == (float)INFINITY) {
+          d_avg_min = min;
         }
-        else if (state == 1) {
-          if (datain[i] > peak_val) {
-            peak_val = datain[i];
-            peak_index = i;
-            d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg;
-            i++;
-          }
-          else if (datain[i] > d_avg * d_threshold_factor_fall) {
-            d_avg = (d_avg_alpha) * datain[i] + (1 - d_avg_alpha) * d_avg;
-            i++;
-          }
-          else {
-            peak_pos[peak_pos_length] = peak_index;
-            peak_pos_length++;
-            state = 0;
-            peak_val = - (float)INFINITY;
-          }
+        else {
+          d_avg_min = d_avg_alpha * min + (1 - d_avg_alpha) * d_avg_min;
         }
       }
 
-      // Find peak of peaks
-      if (peak_pos_length) {
-        float max = datain[peak_pos[0]];
-        int maxi = 0;
+      if (d_avg_max == -(float)INFINITY) {
+        // Initialize d_avg_max with the first value. 
+        d_avg_max = datain[peak_index];
+      }
+      else if (datain[peak_index] > d_avg_max - d_threshold_factor_rise * 
(d_avg_max-d_avg_min)) {
+        d_avg_max = d_avg_alpha * datain[peak_index] + (1 - d_avg_alpha) * 
d_avg_max;
+      }
+      else {
+        peak_pos_length = 0; 
+      }
 
-        for (int i = 1; i < peak_pos_length; i++) {
-          if (datain[peak_pos[i]] > max) {
-            max = datain[peak_pos[i]];
-            maxi = i;
-          }
+      // We now check whether the peak is in the border of the search 
interval. This would mean that 
+      // the search interval is not correct, and it should be re-set. This 
happens for instance when the 
+      // hardware dropped some samples. 
+      // Our definition of "border of the search interval" depends if the 
search interval is "big" or not. 
+      if (datain_length < d_fft_length) {
+        if ((peak_index == 0) || (peak_index == (unsigned int)datain_length - 
1)) {
+          peak_pos_length = 0;
+        }
+      }
+      else {
+        if ((peak_index < 5) || (peak_index > (unsigned int)datain_length - 
5)) {
+          peak_pos_length = 0;
         }
-
-        *peak_max = maxi;
       }
 
+      peak_pos[0] = peak_index; 
+      *peak_max = 0;
       return (peak_pos_length);
     }
 
@@ -119,7 +113,8 @@ namespace gr {
       volk_32fc_magnitude_squared_32f(&d_norm[low], &in[low], size);
 
       // Calculate gamma on each point
-      low = lookup_stop - d_cp_length + 1;
+      // TODO check these boundaries!!!!!!!
+      low = lookup_stop - (d_cp_length - 1);
       size = lookup_start - low + 1;
 
       volk_32fc_x2_multiply_conjugate_32fc(&d_corr[low - d_fft_length], 
&in[low], &in[low - d_fft_length], size);
@@ -220,6 +215,12 @@ namespace gr {
       this->add_item_tag(0, offset, key, value);
     }
 
+    // Derotates the signal 
+    void dvbt_ofdm_sym_acquisition_impl::derotate(const gr_complex * in, 
gr_complex * out)
+    {
+      volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[0], d_fft_length);
+    }
+
     dvbt_ofdm_sym_acquisition::sptr
     dvbt_ofdm_sym_acquisition::make(int blocks, int fft_length, int 
occupied_tones, int cp_length, float snr)
     {
@@ -234,11 +235,10 @@ namespace gr {
       : block("dvbt_ofdm_sym_acquisition",
           io_signature::make(1, 1, sizeof (gr_complex) * blocks),
           io_signature::make(1, 1, sizeof (gr_complex) * blocks * fft_length)),
-      d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), 
d_snr(snr),
-      d_index(0), d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_count(0), 
d_nextphaseinc(0), d_nextpos(0), \
-        d_sym_acq_count(0),d_sym_acq_timeout(100), d_initial_acquisition(0), \
-        d_freq_correction_count(0), d_freq_correction_timeout(0), 
d_cp_start(0), \
-        d_to_consume(0), d_to_out(0)
+      d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), 
d_snr(snr), \
+        d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_nextphaseinc(0), 
d_nextpos(0), \
+        d_initial_acquisition(0), d_cp_start(0), \
+        d_to_consume(0), d_to_out(0), d_consumed(0), d_out(0)
     {
       set_relative_rate(1.0 / (double) (d_cp_length + d_fft_length));
 
@@ -296,7 +296,7 @@ namespace gr {
         exit(1);
       }
 
-      peak_detect_init(0.8, 0.9, 30, 0.9);
+      peak_detect_init(0.3, 0.9);
     }
 
     /*
@@ -319,7 +319,7 @@ namespace gr {
 
       // make sure we receive at least (symbol_length + fft_length)
       for (int i = 0; i < ninputs; i++) {
-        ninput_items_required[i] = (2 * d_fft_length + d_cp_length) * 
noutput_items;
+        ninput_items_required[i] = (d_cp_length + d_fft_length) * 
(noutput_items + 1);
       }
     }
 
@@ -336,45 +336,52 @@ namespace gr {
     {
         const gr_complex *in = (const gr_complex *) input_items[0];
         gr_complex *out = (gr_complex *) output_items[0];
-
-        int low, size;
-
-        // This is initial acquisition of symbol start
-        // TODO - make a FSM
-        if (!d_initial_acquisition) {
-          d_initial_acquisition = ml_sync(in, 2 * d_fft_length + d_cp_length - 
1, d_fft_length + d_cp_length - 1, \
-              &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
-
-          // Send sync_start downstream
-          send_sync_start();
-        }
-
-        // This is fractional frequency correction (pre FFT)
-        // It is also called coarse frequency correction
-        if (d_initial_acquisition) {
-          d_cp_found = ml_sync(in, d_cp_start + 16, d_cp_start, \
-              &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+        int low;
+
+        d_consumed = 0;
+        d_out = 0;
+
+        for (int i = 0; i < noutput_items; i++) {
+          // This is initial acquisition of symbol start
+          // TODO - make a FSM
+          if (!d_initial_acquisition) {
+            d_initial_acquisition = ml_sync(&in[d_consumed], 2 * d_fft_length 
+ d_cp_length - 1, d_fft_length + d_cp_length - 1, \
+                &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+            d_cp_found = d_initial_acquisition;
+          }
+          else {
+            // If we are here it means that in the previous iteration we found 
the CP. We
+            // now thus only search near it. 
+            d_cp_found = ml_sync(&in[d_consumed], d_cp_start + 8, 
std::max(d_cp_start - 8, d_cp_length+d_fft_length - 1), \
+                &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+            if (!d_cp_found) {
+              // We may have not found the CP because the smaller search range 
was too small (rare, but possible). 
+              // We re-try with the whole search range. 
+              d_cp_found = ml_sync(&in[d_consumed], 2 * d_fft_length + 
d_cp_length - 1, d_fft_length + d_cp_length - 1, \
+                  &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out );
+            }
+          }
 
           if (d_cp_found) {
-            d_freq_correction_count = 0;
-
-            // Derotate the signal and out
-            low = d_cp_start - d_fft_length + 1;
-            size = d_cp_start - (d_cp_start - d_fft_length + 1) + 1;
-
-            volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[low], size);
+            low = d_consumed + d_cp_start - d_fft_length + 1;
+            derotate(&in[low], &out[i * d_fft_length]);
           }
           else {
-            // If we have a number of consecutive misses then we restart 
acquisition
-            if (++d_freq_correction_count > d_freq_correction_timeout) {
-              d_initial_acquisition = 0;
-              d_freq_correction_count = 0;
-
-              // Restart with a half number so that we'll not endup with the 
same situation
-              // This will prevent peak_detect to not detect anything
-              d_to_consume = d_to_consume / 2;
-            }
+            // Send sync_start downstream
+            send_sync_start();
+            d_initial_acquisition = 0;
+
+            // Restart wit a half number so that we'll not end up with the 
same situation
+            // This will prevent peak_detect to not detect anything
+            d_to_consume = d_to_consume / 2;
+            d_consumed += d_to_consume;
+            consume_each(d_consumed);
+
+            // Tell runtime system how many output items we produced.
+            return (d_out);
           }
+          d_consumed += d_to_consume;
+          d_out += d_to_out;
         }
 
         // Tell runtime system how many input items we consumed on
@@ -386,3 +393,4 @@ namespace gr {
     }
   } /* namespace dtv */
 } /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h 
b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
index e7b92cb..0964361 100644
--- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
+++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
@@ -35,8 +35,6 @@ namespace gr {
       float d_snr;
       float d_rho;
 
-      int d_index;
-
       gr_complex * d_conj;
       float * d_norm;
       gr_complex * d_corr;
@@ -45,37 +43,35 @@ namespace gr {
 
       // For peak detector
       float d_threshold_factor_rise;
-      float d_threshold_factor_fall;
       float d_avg_alpha;
-      float d_avg;
+      float d_avg_min;
+      float d_avg_max;
       float d_phase;
       double d_phaseinc;
       int d_cp_found;
-      int d_count;
       double d_nextphaseinc;
       int d_nextpos;
 
-      int d_sym_acq_count;
-      int d_sym_acq_timeout;
-
       int d_initial_acquisition;
 
-      int d_freq_correction_count;
-      int d_freq_correction_timeout;
-
       int d_cp_start;
 
       gr_complex * d_derot;
       int d_to_consume;
       int d_to_out;
+      int d_consumed;
+      int d_out;
 
       int ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, 
int * cp_pos, gr_complex * derot, int * to_consume, int * to_out);
 
-      int peak_detect_init(float threshold_factor_rise, float 
threshold_factor_fall, int look_ahead, float alpha);
+      int peak_detect_init(float threshold_factor_rise, float alpha);
 
       int peak_detect_process(const float * datain, const int datain_length, 
int * peak_pos, int * peak_max);
 
       void send_sync_start();
+
+      void derotate(const gr_complex * in, gr_complex *out);
+
      public:
       dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int 
occupied_tones, int cp_length, float snr);
       ~dvbt_ofdm_sym_acquisition_impl();
@@ -92,3 +88,4 @@ namespace gr {
 } // namespace gr
 
 #endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H */
+



reply via email to

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