commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] r8217 - gnuradio/trunk/gnuradio-core/src/python/gnurad


From: trondeau
Subject: [Commit-gnuradio] r8217 - gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl
Date: Thu, 17 Apr 2008 08:37:19 -0600 (MDT)

Author: trondeau
Date: 2008-04-17 08:37:19 -0600 (Thu, 17 Apr 2008)
New Revision: 8217

Modified:
   gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py
Log:
Improved the pnac ofdm sync block. This is based on a VTC'99 paper by 
Tufvesson, et al. that does a bit more work than the Schmidl and Cox to produce 
a more identifiable peak for the timing. This seems to work well in the 
simulation for low frequency errors. The correlation doesn't seem to track 
well, though. See the comments for more info. Also, the peak detection requires 
unity amplitude for the threshold detection. So, who wants to make an OFDM AGC?

Modified: 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py
===================================================================
--- 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py    
    2008-04-17 04:54:51 UTC (rev 8216)
+++ 
gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py    
    2008-04-17 14:37:19 UTC (rev 8217)
@@ -26,7 +26,25 @@
 
 class ofdm_sync_pnac(gr.hier_block2):
     def __init__(self, fft_length, cp_length, kstime, logging=False):
-        
+        """
+        OFDM synchronization using PN Correlation and initial 
cross-correlation:
+        F. Tufvesson, O. Edfors, and M. Faulkner, "Time and Frequency 
Synchronization for OFDM using
+        PN-Sequency Preambles," IEEE Proc. VTC, 1999, pp. 2203-2207.
+
+        This implementation is meant to be a more robust version of the 
Schmidl and Cox receiver design.
+        By correlating against the preamble and using that as the input to the 
time-delayed correlation,
+        this circuit produces a very clean timing signal at the end of the 
preamble. The timing is 
+        more accurate and does not have the problem associated with 
determining the timing from the
+        plateau structure in the Schmidl and Cox.
+
+        This implementation appears to require that the signal is received 
with a normalized power or signal
+        scalling factor to reduce ambiguities intorduced from partial 
correlation of the cyclic prefix and
+        the peak detection. A better peak detection block might fix this.
+
+        Also, the cross-correlation falls apart as the frequency offset gets 
larger and completely fails
+        when an integer offset is introduced. Another thing to look at.
+        """
+
        gr.hier_block2.__init__(self, "ofdm_sync_pnac",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # 
Input signature
                                 gr.io_signature2(2, 2, gr.sizeof_float, 
gr.sizeof_char)) # Output signature
@@ -42,7 +60,6 @@
         kstime = [k.conjugate() for k in kstime[0:fft_length//2]]
         kstime.reverse()
         self.crosscorr_filter = gr.fir_filter_ccc(1, kstime)
-        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)
@@ -51,63 +68,58 @@
         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()
+        self.mag = gr.complex_to_mag_squared()
+        movingsum_taps = (fft_length//1)*[1.0,]
+        self.power = gr.fir_filter_fff(1,movingsum_taps)
      
         # Get magnitude (peaks) and angle (phase/freq error)
         self.c2mag = gr.complex_to_mag_squared()
         self.angle = gr.complex_to_arg()
-
+        self.compare = gr.sub_ff()
+        
         self.sample_and_hold = gr.sample_and_hold_ff()
 
         #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.threshold = gr.threshold_ff(0,0,0)      # threshold detection 
might need to be tweaked
+        self.peaks = gr.float_to_char()
 
         self.connect(self, self.input)
 
         # Cross-correlate input signal with known preamble
         self.connect(self.input, self.crosscorr_filter)
 
-        # use the output of the cross-correlation as input to Schmidl&Cox
+        # use the output of the cross-correlation as input time-shifted 
correlation
         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.corr, self.c2mag)
+        self.connect(self.corr, self.angle)
         self.connect(self.angle, (self.sample_and_hold,0))
+        
+        # Get the power of the input signal to compare against the correlation
+        self.connect(self.crosscorr_filter, self.mag, self.power)
 
-        # Get the power of the input signal to normalize the output of the 
correlation
-        self.connect(self.crosscorr_filter, 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))
+        # Compare the power to the correlator output to determine timing peak
+        # When the peak occurs, it peaks above zero, so the thresholder 
detects this
+        self.connect(self.c2mag, (self.compare,0))
+        self.connect(self.power, (self.compare,1))
+        self.connect(self.compare, self.threshold)
+        self.connect(self.threshold, self.peaks, (self.sample_and_hold,1))
 
-        self.connect(self.normalize, self.sub1, self.pk_detect)
-        self.connect(self.pk_detect, (self.sample_and_hold,1))
-
         # Set output signals
         #    Output 0: fine frequency correction value
         #    Output 1: timing signal
         self.connect(self.sample_and_hold, (self,0))
-        self.connect(self.pk_detect, (self,1))
+        self.connect(self.peaks, (self,1))
 
         if logging:
+            self.connect(self.compare, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-compare_f.dat"))
             self.connect(self.c2mag, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-theta_f.dat"))
-            self.connect(self.normalize, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-normalized_f.dat"))
-            self.connect(self.sub1, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-sub1_f.dat"))
+            self.connect(self.power, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-inputpower_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.threshold, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-threshold_f.dat"))
+            self.connect(self.peaks, gr.file_sink(gr.sizeof_char, 
"ofdm_sync_pnac-peaks_b.dat"))
             self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, 
"ofdm_sync_pnac-sample_and_hold_f.dat"))
             self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, 
"ofdm_sync_pnac-input_c.dat"))





reply via email to

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