[Top][All Lists]
[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"))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8217 - gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl,
trondeau <=