diff options
author | trondeau <trondeau@221aa14e-8319-0410-a670-987f0aec2ac5> | 2008-01-02 17:35:35 +0000 |
---|---|---|
committer | trondeau <trondeau@221aa14e-8319-0410-a670-987f0aec2ac5> | 2008-01-02 17:35:35 +0000 |
commit | ce16514534e5d7ebbc4fe46e2b09a25ccc5fdafd (patch) | |
tree | 2d9ae1179cb26f213125accabaea8eb05d63f109 /gnuradio-core/src/python | |
parent | 481636b7be1462dc9f1909ac4700002af63dc8c0 (diff) |
Merging ofdm2 branch -r7047:7321 into trunk. This updates the OFDM code to hier_block2 in blks2impl and removed from blksimpl. The new code
implements a decision feedback sync loop to lock the phase/freq, removes two unnecessary premables and performs frame sync and equalization off
single preamble symbol. Also adds/updates Python plotting tools and a branchless clip algorithm in gr_math.h.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@7324 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src/python')
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am | 6 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py (renamed from gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py) | 96 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py | 112 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py | 49 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py (renamed from gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_ml.py) | 83 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py (renamed from gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pn.py) | 95 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py | 131 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am | 6 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py | 64 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py | 41 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py | 126 |
11 files changed, 447 insertions, 362 deletions
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am index e3d83aeee9..934326d8f3 100644 --- a/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am @@ -40,6 +40,12 @@ grblkspython_PYTHON = \ cpm.py \ nbfm_rx.py \ nbfm_tx.py \ + ofdm.py \ + ofdm_receiver.py \ + ofdm_sync_fixed.py \ + ofdm_sync_pn.py \ + ofdm_sync_pnac.py \ + ofdm_sync_ml.py \ pkt.py \ psk.py \ qam.py \ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py index b040d8c7f4..491ef1a19b 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm.py @@ -1,4 +1,4 @@ - +#!/usr/bin/env python # # Copyright 2006,2007 Free Software Foundation, Inc. # @@ -21,40 +21,41 @@ # import math -from numpy import fft from gnuradio import gr, ofdm_packet_utils import gnuradio.gr.gr_threading as _threading import psk, qam -from gnuradio.blksimpl.ofdm_receiver import ofdm_receiver +from gnuradio.blks2impl.ofdm_receiver import ofdm_receiver # ///////////////////////////////////////////////////////////////////////////// # mod/demod with packets as i/o # ///////////////////////////////////////////////////////////////////////////// -class ofdm_mod(gr.hier_block): +class ofdm_mod(gr.hier_block2): """ Modulates an OFDM stream. Based on the options fft_length, occupied_tones, and cp_length, this block creates OFDM symbols using a specified modulation option. Send packets by calling send_pkt """ - def __init__(self, fg, options, msgq_limit=2, pad_for_usrp=True): + def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. - @param fg: flow graph - @type fg: flow graph @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param msgq_limit: maximum number of messages in message queue @type msgq_limit: int @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ + gr.hier_block2.__init__(self, "ofdm_mod", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length @@ -71,10 +72,10 @@ class ofdm_mod(gr.hier_block): ksfreq[i] = 0 # hard-coded known symbols - preambles = (ksfreq, - known_symbols_4512_1[0:self._occupied_tones], - known_symbols_4512_2[0:self._occupied_tones]) - + preambles = (ksfreq,) +# known_symbols_4512_1[0:self._occupied_tones], +# known_symbols_4512_2[0:self._occupied_tones]) + padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] @@ -96,25 +97,29 @@ class ofdm_mod(gr.hier_block): rotated_const = map(lambda pt: pt * rot, qam.constellation[arity]) #print rotated_const self._pkt_input = gr.ofdm_mapper_bcv(rotated_const, msgq_limit, - options.occupied_tones, options.fft_length) + options.occupied_tones, options.fft_length) self.preambles = gr.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = gr.fft_vcc(self._fft_length, False, win, True) self.cp_adder = gr.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) - fg.connect((self._pkt_input, 0), (self.preambles, 0)) - fg.connect((self._pkt_input, 1), (self.preambles, 1)) - fg.connect(self.preambles, self.ifft, self.cp_adder, self.scale) + self.connect((self._pkt_input, 0), (self.preambles, 0)) + self.connect((self._pkt_input, 1), (self.preambles, 1)) + self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self) if options.verbose: self._print_verbage() if options.log: - fg.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, - "ofdm_mapper_c.dat")) - - gr.hier_block.__init__(self, fg, None, self.scale) + self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + "ofdm_mapper_c.dat")) + self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + "ofdm_preambles.dat")) + self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, + "ofdm_ifft_c.dat")) + self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, + "ofdm_cp_adder_c.dat")) def send_pkt(self, payload='', eof=False): """ @@ -138,7 +143,7 @@ class ofdm_mod(gr.hier_block): Adds OFDM-specific options to the Options Parser """ normal.add_option("-m", "--modulation", type="string", default="bpsk", - help="set modulation type (bpsk or qpsk) [default=%default]") + help="set modulation type (bpsk, qpsk, 8psk, qam{16,64}) [default=%default]") expert.add_option("", "--fft-length", type="intx", default=512, help="set the number of FFT bins [default=%default]") expert.add_option("", "--occupied-tones", type="intx", default=200, @@ -159,7 +164,7 @@ class ofdm_mod(gr.hier_block): print "CP length: %3d" % (self._cp_length) -class ofdm_demod(gr.hier_block): +class ofdm_demod(gr.hier_block2): """ Demodulates a received OFDM stream. Based on the options fft_length, occupied_tones, and cp_length, this block performs synchronization, FFT, and demodulation of incoming OFDM @@ -169,19 +174,22 @@ class ofdm_demod(gr.hier_block): app via the callback. """ - def __init__(self, fg, options, callback=None): + def __init__(self, options, callback=None): """ Hierarchical block for demodulating and deframing packets. The input is the complex modulated signal at baseband. Demodulated packets are sent to the handler. - @param fg: flow graph - @type fg: flow graph @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param callback: function of two args: ok, payload @type callback: ok: bool; payload: string """ + gr.hier_block2.__init__(self, "ofdm_demod", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY self._modulation = options.modulation @@ -190,30 +198,19 @@ class ofdm_demod(gr.hier_block): self._cp_length = options.cp_length self._snr = options.snr - # Use freq domain to get doubled-up known symbol for correlation in time domain ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if(i&1): ksfreq[i] = 0 - zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) - zeros_on_right = self._fft_length - self._occupied_tones - zeros_on_left - ks0 = zeros_on_left*[0.0,] - ks0.extend(ksfreq) - ks0.extend(zeros_on_right*[0.0,]) - - ks0time = fft.ifft(ks0) - # ADD SCALING FACTOR - ks0time = ks0time.tolist() - # hard-coded known symbols - preambles = (ks0time, - known_symbols_4512_1[0:self._occupied_tones], - known_symbols_4512_2[0:self._occupied_tones]) + preambles = (ksfreq,) + #known_symbols_4512_1[0:self._occupied_tones], + #known_symbols_4512_2[0:self._occupied_tones]) symbol_length = self._fft_length + self._cp_length - self.ofdm_recv = ofdm_receiver(fg, self._fft_length, self._cp_length, + self.ofdm_recv = ofdm_receiver(self._fft_length, self._cp_length, self._occupied_tones, self._snr, preambles, options.log) @@ -231,18 +228,27 @@ class ofdm_demod(gr.hier_block): #print rotated_const self.ofdm_demod = gr.ofdm_frame_sink(rotated_const, range(arity), self._rcvd_pktq, - self._occupied_tones) - - fg.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0)) - fg.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1)) + self._occupied_tones, + 0.25, 0.25*.25/4.0) + + self.connect(self, self.ofdm_recv) + self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0)) + self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1)) + + # added output signature to work around bug, though it might not be a bad + # thing to export, anyway + self.connect(self.ofdm_recv.chan_filt, self) + + if options.log: + self.connect(self.ofdm_demod, gr.file_sink(gr.sizeof_gr_complex*self._occupied_tones, "ofdm_frame_sink_c.dat")) + else: + self.connect(self.ofdm_demod, gr.null_sink(gr.sizeof_gr_complex*self._occupied_tones)) if options.verbose: self._print_verbage() - gr.hier_block.__init__(self, fg, self.ofdm_recv, None) self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) - def add_options(normal, expert): """ Adds OFDM-specific options to the Options Parser diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py new file mode 100644 index 0000000000..9592755b1f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_receiver.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# +# Copyright 2006, 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import math +from numpy import fft +from gnuradio import gr +from gnuradio.blks2impl.ofdm_sync_ml import ofdm_sync_ml +from gnuradio.blks2impl.ofdm_sync_pn import ofdm_sync_pn +from gnuradio.blks2impl.ofdm_sync_pnac import ofdm_sync_pnac +from gnuradio.blks2impl.ofdm_sync_fixed import ofdm_sync_fixed + +class ofdm_receiver(gr.hier_block2): + """ + Performs receiver synchronization on OFDM symbols. + + The receiver performs channel filtering as well as symbol, frequency, and phase synchronization. + The synchronization routines are available in three flavors: preamble correlator (Schmidl and Cox), + modifid preamble correlator with autocorrelation (not yet working), and cyclic prefix correlator + (Van de Beeks). + """ + + def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, logging=False): + """ + Hierarchical block for receiving OFDM symbols. + + The input is the complex modulated signal at baseband. + Synchronized packets are sent back to the demodulator. + + @param fft_length: total number of subcarriers + @type fft_length: int + @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length) + @type cp_length: int + @param occupied_tones: number of subcarriers used for data + @type occupied_tones: int + @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer + @type snr: float + @param ks: known symbols used as preambles to each packet + @type ks: list of lists + @param logging: turn file logging on or off + @type logging: bool + """ + + gr.hier_block2.__init__(self, "ofdm_receiver", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature + + bw = (float(occupied_tones) / float(fft_length)) / 2.0 + tb = bw*0.08 + chan_coeffs = gr.firdes.low_pass (1.0, # gain + 1.0, # sampling rate + bw+tb, # midpoint of trans. band + tb, # width of trans. band + gr.firdes.WIN_HAMMING) # filter type + self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs) + + win = [1 for i in range(fft_length)] + + zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0)) + zeros_on_right = fft_length - occupied_tones - zeros_on_left + ks0 = zeros_on_left*[0.0,] + ks0.extend(ks[0]) + ks0.extend(zeros_on_right*[0.0,]) + + ks0time = fft.ifft(ks0) + # ADD SCALING FACTOR + ks0time = ks0time.tolist() + + SYNC = "pn" + if SYNC == "ml": + self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, logging) + elif SYNC == "pn": + self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging) + elif SYNC == "pnac": + self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time) + elif SYNC == "fixed": + self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, logging) + + self.fft_demod = gr.fft_vcc(fft_length, True, win, True) + self.ofdm_frame_acq = gr.ofdm_frame_acquisition(occupied_tones, fft_length, + cp_length, ks[0]) + + 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)) + + if logging: + self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "chan_filt_c.dat")) + self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "fft_out_c.dat")) + self.connect(self.ofdm_frame_acq, + gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_frame_acq_c.dat")) + self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "found_corr_b.dat")) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py new file mode 100644 index 0000000000..74acc8fdea --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_fixed.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import math +from gnuradio import gr + +class ofdm_sync_fixed(gr.hier_block2): + def __init__(self, fft_length, cp_length, logging=False): + + gr.hier_block2.__init__(self, "ofdm_sync_fixed", + 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 + + # Use a fixed trigger point instead of sync block + symbol_length = fft_length + cp_length + data = (symbol_length)*[0,] + data[(symbol_length)-1] = 1 + self.peak_trigger = gr.vector_source_b(data, True) + self.sampler = gr.ofdm_sampler(fft_length, symbol_length) + + self.connect(self, (self.sampler,0)) + self.connect(self.peak_trigger, (self.sampler,1)) + self.connect(self.sampler, (self,0)) + self.connect(self.peak_trigger, (self,1)) + + if logging: + self.connect(self.peak_trigger, gr.file_sink(gr.sizeof_char, "ofdm_sync_fixed-peaks_b.dat")) + self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, + "ofdm_sync_fixed-sampler_c.dat")) + diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_ml.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py index d58f56cffc..a93852623e 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_ml.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_ml.py @@ -23,19 +23,22 @@ import math from gnuradio import gr -class ofdm_sync_ml(gr.hier_block): - def __init__(self, fg, fft_length, cp_length, snr, logging): +class ofdm_sync_ml(gr.hier_block2): + def __init__(self, fft_length, cp_length, snr, logging): ''' Maximum Likelihood OFDM synchronizer: J. van de Beek, M. Sandell, and P. O. Borjesson, "ML Estimation of Time and Frequency Offset in OFDM Systems," IEEE Trans. Signal Processing, vol. 45, no. 7, pp. 1800-1805, 1997. ''' - self.fg = fg - - # FIXME: when converting to hier_block2's, the output signature + # FIXME: change the output signature # should be the output of the divider (the normalized peaks) and # the angle value out of the sample and hold block + # move sampler out of this block + + gr.hier_block2.__init__(self, "ofdm_sync_ml", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex*fft_length)) # Output signature self.input = gr.add_const_cc(0) @@ -47,9 +50,11 @@ class ofdm_sync_ml(gr.hier_block): # Energy Detection from ML Sync + self.connect(self, self.input) + # Create a delay line self.delay = gr.delay(gr.sizeof_gr_complex, fft_length) - self.fg.connect(self.input, self.delay) + self.connect(self.input, self.delay) # magnitude squared blocks self.magsqrd1 = gr.complex_to_mag_squared() @@ -59,11 +64,11 @@ class ofdm_sync_ml(gr.hier_block): moving_sum_taps = [rho/2 for i in range(cp_length)] self.moving_sum_filter = gr.fir_filter_fff(1,moving_sum_taps) - self.fg.connect(self.input,self.magsqrd1) - self.fg.connect(self.delay,self.magsqrd2) - self.fg.connect(self.magsqrd1,(self.adder,0)) - self.fg.connect(self.magsqrd2,(self.adder,1)) - self.fg.connect(self.adder,self.moving_sum_filter) + self.connect(self.input,self.magsqrd1) + self.connect(self.delay,self.magsqrd2) + self.connect(self.magsqrd1,(self.adder,0)) + self.connect(self.magsqrd2,(self.adder,1)) + self.connect(self.adder,self.moving_sum_filter) # Correlation from ML Sync @@ -76,60 +81,62 @@ class ofdm_sync_ml(gr.hier_block): # Correlator data handler self.c2mag = gr.complex_to_mag() self.angle = gr.complex_to_arg() - self.fg.connect(self.input,(self.mixer,1)) - self.fg.connect(self.delay,self.conjg,(self.mixer,0)) - self.fg.connect(self.mixer,self.movingsum2,self.c2mag) - self.fg.connect(self.movingsum2,self.angle) + self.connect(self.input,(self.mixer,1)) + self.connect(self.delay,self.conjg,(self.mixer,0)) + self.connect(self.mixer,self.movingsum2,self.c2mag) + self.connect(self.movingsum2,self.angle) # ML Sync output arg, need to find maximum point of this self.diff = gr.sub_ff() - self.fg.connect(self.c2mag,(self.diff,0)) - self.fg.connect(self.moving_sum_filter,(self.diff,1)) + self.connect(self.c2mag,(self.diff,0)) + self.connect(self.moving_sum_filter,(self.diff,1)) #ML measurements input to sampler block and detect nco_sensitivity = -1.0/fft_length self.f2c = gr.float_to_complex() self.sampler = gr.ofdm_sampler(fft_length,symbol_length) self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005) + #self.pk_detect = gr.peak_detector2_fb() self.sample_and_hold = gr.sample_and_hold_ff() self.nco = gr.frequency_modulator_fc(nco_sensitivity) self.sigmix = gr.multiply_cc() # Mix the signal with an NCO controlled by the sync loop - self.fg.connect(self.input, (self.sigmix,0)) - self.fg.connect(self.nco, (self.sigmix,1)) - self.fg.connect(self.sigmix, (self.sampler,0)) + self.connect(self.input, (self.sigmix,0)) + self.connect(self.nco, (self.sigmix,1)) + self.connect(self.sigmix, (self.sampler,0)) # use the sync loop values to set the sampler and the NCO # self.diff = theta # self.angle = epsilon - self.fg.connect(self.diff, self.pk_detect) + self.connect(self.diff, self.pk_detect) use_dpll = 1 if use_dpll: self.dpll = gr.dpll_bb(float(symbol_length),0.01) - self.fg.connect(self.pk_detect, self.dpll) - self.fg.connect(self.dpll, (self.sampler,1)) - self.fg.connect(self.dpll, (self.sample_and_hold,1)) + self.connect(self.pk_detect, self.dpll) + self.connect(self.dpll, (self.sampler,1)) + self.connect(self.dpll, (self.sample_and_hold,1)) else: - self.fg.connect(self.pk_detect, (self.sampler,1)) - self.fg.connect(self.pk_detect, (self.sample_and_hold,1)) + self.connect(self.pk_detect, (self.sampler,1)) + self.connect(self.pk_detect, (self.sample_and_hold,1)) - self.fg.connect(self.angle, (self.sample_and_hold,0)) - self.fg.connect(self.sample_and_hold, self.nco) + self.connect(self.angle, (self.sample_and_hold,0)) + self.connect(self.sample_and_hold, self.nco) + + self.connect(self.sampler, self) if logging: - self.fg.connect(self.diff, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat")) - self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat")) - self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat")) + self.connect(self.diff, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat")) + self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat")) + self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat")) if use_dpll: - self.fg.connect(self.dpll, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat")) + self.connect(self.dpll, gr.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat")) - self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-sigmix_c.dat")) - self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_ml-sampler_c.dat")) - self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat")) - self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-nco_c.dat")) - self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat")) + self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-sigmix_c.dat")) + self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_ml-sampler_c.dat")) + self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat")) + self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-nco_c.dat")) + self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat")) - gr.hier_block.__init__(self, fg, self.input, self.sampler) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pn.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py index 56425868f9..e3e0ad9d25 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pn.py +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pn.py @@ -24,15 +24,18 @@ import math from numpy import fft from gnuradio import gr -class ofdm_sync_pn(gr.hier_block): - def __init__(self, fg, fft_length, cp_length, logging=False): - ''' OFDM synchronization using PN Correlation: +class ofdm_sync_pn(gr.hier_block2): + def __init__(self, fft_length, cp_length, logging=False): + """ + OFDM synchronization using PN Correlation: T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing Synchonization for OFDM," IEEE Trans. Communications, vol. 45, no. 12, 1997. - ''' + """ - self.fg = fg + 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 # FIXME: when converting to hier_block2's, the output signature # should be the output of the divider (the normalized peaks) and @@ -84,52 +87,60 @@ class ofdm_sync_pn(gr.hier_block): #ML measurements input to sampler block and detect self.sub1 = gr.add_const_ff(-1) - self.pk_detect = gr.peak_detector_fb(0.2, 0.25, 30, 0.0005) + self.pk_detect = gr.peak_detector_fb(0.20, 0.20, 30, 0.001) + #self.pk_detect = gr.peak_detector2_fb() + #self.pk_detect = gr.threshold_detector_fb(0.5) self.regen = gr.regenerate_bb(symbol_length) + # FIXME: If sampler doesn't get proper input, it can completely + # stall the flowgraph. self.sampler = gr.ofdm_sampler(fft_length,symbol_length) + + self.connect(self, self.input) - self.fg.connect(self.input, self.delay) - self.fg.connect(self.input, (self.corr,0)) - self.fg.connect(self.delay, self.conjg) - self.fg.connect(self.conjg, (self.corr,1)) - self.fg.connect(self.corr, self.moving_sum_filter) - self.fg.connect(self.moving_sum_filter, self.c2mag) - self.fg.connect(self.moving_sum_filter, self.angle) - self.fg.connect(self.angle, (self.sample_and_hold,0)) - self.fg.connect(self.sample_and_hold, self.nco) - - self.fg.connect(self.input, (self.sigmix,0)) - self.fg.connect(self.nco, (self.sigmix,1)) - self.fg.connect(self.sigmix, (self.sampler,0)) - - self.fg.connect(self.input, self.inputmag2, self.inputmovingsum) - self.fg.connect(self.inputmovingsum, (self.square,0)) - self.fg.connect(self.inputmovingsum, (self.square,1)) - self.fg.connect(self.square, (self.normalize,1)) - self.fg.connect(self.c2mag, (self.normalize,0)) + self.connect(self.input, self.delay) + self.connect(self.input, (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.angle, (self.sample_and_hold,0)) + self.connect(self.sample_and_hold, self.nco) + + self.connect(self.input, (self.sigmix,0)) + self.connect(self.nco, (self.sigmix,1)) + self.connect(self.sigmix, (self.sampler,0)) + + self.connect(self.input, 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)) # Create a moving sum filter for the corr output matched_filter_taps = [1.0/cp_length for i in range(cp_length)] self.matched_filter = gr.fir_filter_fff(1,matched_filter_taps) - self.fg.connect(self.normalize, self.matched_filter) + self.connect(self.normalize, self.matched_filter) - self.fg.connect(self.matched_filter, self.sub1, self.pk_detect) - self.fg.connect(self.pk_detect, self.regen) - self.fg.connect(self.regen, (self.sampler,1)) - self.fg.connect(self.pk_detect, (self.sample_and_hold,1)) + self.connect(self.matched_filter, self.sub1, 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.fg.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) - self.fg.connect(self.normalize, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) - self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) - self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) - self.fg.connect(self.regen, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-regen_b.dat")) - self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-sigmix_c.dat")) - self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_pn-sampler_c.dat")) - self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) - self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-nco_c.dat")) - self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat")) - - gr.hier_block.__init__(self, fg, self.input, self.sampler) + self.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) + self.connect(self.normalize, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) + self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) + self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) + self.connect(self.regen, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-regen_b.dat")) + self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-sigmix_c.dat")) + self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_sync_pn-sampler_c.dat")) + self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) + self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-nco_c.dat")) + self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat")) + diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py new file mode 100644 index 0000000000..5c16a57039 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/ofdm_sync_pnac.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# +# Copyright 2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import math +from numpy import fft +from gnuradio import gr + +class ofdm_sync_pnac(gr.hier_block2): + def __init__(self, fft_length, cp_length, ks): + + # FIXME: change the output signature + # should be the output of the divider (the normalized peaks) and + # the angle value out of the sample and hold block + # move sampler out of this block + + gr.hier_block2.__init__(self, "ofdm_sync_pnac", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex*fft_length)) # Output signature + + + self.input = gr.add_const_cc(0) + + symbol_length = fft_length + cp_length + + # PN Sync + + # autocorrelate with the known symbol + ks = ks[0:fft_length//2] + ks.reverse() + self.crosscorr_filter = gr.fir_filter_ccc(1, ks) + 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) + + # Correlation from ML Sync + 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() + + # Get magnitude (peaks) and angle (phase/freq error) + self.c2mag = gr.complex_to_mag_squared() + self.angle = gr.complex_to_arg() + + self.sample_and_hold = gr.sample_and_hold_ff() + + # Mix the signal with an NCO controlled by the sync loop + nco_sensitivity = -1.0/fft_length + self.nco = gr.frequency_modulator_fc(nco_sensitivity) + 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.2, 0.25, 30, 0.0005) + + self.sampler = gr.ofdm_sampler(fft_length,symbol_length) + + self.connect(self, self.input) + self.connect(self.input, self.crosscorr_filter) + 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.angle, (self.sample_and_hold,0)) + self.connect(self.sample_and_hold, self.nco) + + self.connect(self.input, (self.sigmix,0)) + self.connect(self.nco, (self.sigmix,1)) + self.connect(self.sigmix, (self.sampler,0)) + + self.connect(self.input, 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)) + self.connect(self.normalize, self.sub1, self.pk_detect) + + self.connect(self.pk_detect, (self.sampler,1)) + self.connect(self.pk_detect, (self.sample_and_hold,1)) + + self.connect(self.sampler, self) + + if 1: + self.connect(self.normalize, gr.file_sink(gr.sizeof_float, + "ofdm_sync_pnac-theta_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.sigmix, gr.file_sink(gr.sizeof_gr_complex, + "ofdm_sync_pnac-sigmix_c.dat")) + self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, + "ofdm_sync_pnac-sampler_c.dat")) + self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, + "ofdm_sync_pnac-sample_and_hold_f.dat")) + self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, + "ofdm_sync_pnac-nco_c.dat")) + self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, + "ofdm_sync_pnac-input_c.dat")) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am index b75fade58d..74fa098d46 100644 --- a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am +++ b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am @@ -40,12 +40,6 @@ grblkspython_PYTHON = \ cpm.py \ nbfm_rx.py \ nbfm_tx.py \ - ofdm.py \ - ofdm_receiver.py \ - ofdm_sync_fixed.py \ - ofdm_sync_ml.py \ - ofdm_sync_pnac.py \ - ofdm_sync_pn.py \ pkt.py \ psk.py \ qam.py \ diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py deleted file mode 100644 index d16d2e2940..0000000000 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_receiver.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006, 2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import math -from gnuradio import gr -from gnuradio.blksimpl.ofdm_sync_ml import ofdm_sync_ml -from gnuradio.blksimpl.ofdm_sync_pn import ofdm_sync_pn -from gnuradio.blksimpl.ofdm_sync_pnac import ofdm_sync_pnac - -class ofdm_receiver(gr.hier_block): - def __init__(self, fg, fft_length, cp_length, occupied_tones, snr, ks, logging=False): - self.fg = fg - - bw = (float(occupied_tones) / float(fft_length)) / 2.0 - tb = bw*0.08 - chan_coeffs = gr.firdes.low_pass (1.0, # gain - 1.0, # sampling rate - bw+tb, # midpoint of trans. band - tb, # width of trans. band - gr.firdes.WIN_HAMMING) # filter type - self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs) - - win = [1 for i in range(fft_length)] - - SYNC = "pn" - if SYNC == "ml": - self.ofdm_sync = ofdm_sync_ml(fg, fft_length, cp_length, snr, logging) - elif SYNC == "pn": - self.ofdm_sync = ofdm_sync_pn(fg, fft_length, cp_length, logging) - elif SYNC == "pnac": - self.ofdm_sync = ofdm_sync_pnac(fg, fft_length, cp_length, ks[0]) - - self.fft_demod = gr.fft_vcc(fft_length, True, win, True) - self.ofdm_corr = gr.ofdm_correlator(occupied_tones, fft_length, - cp_length, ks[1], ks[2]) - - self.fg.connect(self.chan_filt, self.ofdm_sync, self.fft_demod, self.ofdm_corr) - - if logging: - self.fg.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "chan_filt_c.dat")) - self.fg.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "fft_out_c.dat")) - self.fg.connect(self.ofdm_corr, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_corr_out_c.dat")) - self.fg.connect((self.ofdm_corr,1), gr.file_sink(1, "found_corr_b.dat")) - - gr.hier_block.__init__(self, fg, self.chan_filt, self.ofdm_corr) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py deleted file mode 100644 index b56f65660e..0000000000 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_fixed.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import math -from gnuradio import gr - -class ofdm_sync_fixed(gr.hier_block): - def __init__(self, fg, fft_length, cp_length, snr): - self.fg = fg - - # Use a fixed trigger point instead of sync block - data = (fft_length+cp_len)*[0,] - data[(fft_length+cp_len)-1] = 1 - peak_trigger = gr.vector_source_b(data, True) - - self.fg.connect(peak_trigger, (self.sampler,1)) - - if 1: - self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, - "ofdm_sync_fixed-sampler_c.dat")) - - gr.hier_block.__init__(self, fg, (self.sampler,0), self.sampler) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py b/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py deleted file mode 100644 index e3774e3410..0000000000 --- a/gnuradio-core/src/python/gnuradio/blksimpl/ofdm_sync_pnac.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import math -from numpy import fft -from gnuradio import gr - -class ofdm_sync_pnac(gr.hier_block): - def __init__(self, fg, fft_length, cp_length, ks): - self.fg = fg - - # FIXME: when converting to hier_block2's, the output signature - # should be the output of the divider (the normalized peaks) and - # the angle value out of the sample and hold block - - self.input = gr.add_const_cc(0) - - symbol_length = fft_length + cp_length - - # PN Sync - - # autocorrelate with the known symbol - ks = ks[0:fft_length//2] - ks.reverse() - self.crosscorr_filter = gr.fir_filter_ccc(1, ks) - self.fg.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) - - # Correlation from ML Sync - 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() - - # Get magnitude (peaks) and angle (phase/freq error) - self.c2mag = gr.complex_to_mag_squared() - self.angle = gr.complex_to_arg() - - self.sample_and_hold = gr.sample_and_hold_ff() - - # Mix the signal with an NCO controlled by the sync loop - nco_sensitivity = -1.0/fft_length - self.nco = gr.frequency_modulator_fc(nco_sensitivity) - 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.2, 0.25, 30, 0.0005) - - self.sampler = gr.ofdm_sampler(fft_length,symbol_length) - - self.fg.connect(self.input, self.crosscorr_filter) - self.fg.connect(self.crosscorr_filter, self.delay) - self.fg.connect(self.crosscorr_filter, (self.corr,0)) - self.fg.connect(self.delay, self.conjg) - self.fg.connect(self.conjg, (self.corr,1)) - self.fg.connect(self.corr, self.moving_sum_filter) - self.fg.connect(self.moving_sum_filter, self.c2mag) - self.fg.connect(self.moving_sum_filter, self.angle) - self.fg.connect(self.angle, (self.sample_and_hold,0)) - self.fg.connect(self.sample_and_hold, self.nco) - - self.fg.connect(self.input, (self.sigmix,0)) - self.fg.connect(self.nco, (self.sigmix,1)) - self.fg.connect(self.sigmix, (self.sampler,0)) - - self.fg.connect(self.input, self.inputmag2, self.inputmovingsum) - self.fg.connect(self.inputmovingsum, (self.square,0)) - self.fg.connect(self.inputmovingsum, (self.square,1)) - self.fg.connect(self.square, (self.normalize,1)) - self.fg.connect(self.c2mag, (self.normalize,0)) - self.fg.connect(self.normalize, self.sub1, self.pk_detect) - - self.fg.connect(self.pk_detect, (self.sampler,1)) - self.fg.connect(self.pk_detect, (self.sample_and_hold,1)) - - - if 1: - self.fg.connect(self.normalize, gr.file_sink(gr.sizeof_float, - "ofdm_sync_pnac-theta_f.dat")) - self.fg.connect(self.angle, gr.file_sink(gr.sizeof_float, - "ofdm_sync_pnac-epsilon_f.dat")) - self.fg.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, - "ofdm_sync_pnac-peaks_b.dat")) - self.fg.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, - "ofdm_sync_pnac-sigmix_c.dat")) - self.fg.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, - "ofdm_sync_pnac-sampler_c.dat")) - self.fg.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, - "ofdm_sync_pnac-sample_and_hold_f.dat")) - self.fg.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, - "ofdm_sync_pnac-nco_c.dat")) - self.fg.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, - "ofdm_sync_pnac-input_c.dat")) - - gr.hier_block.__init__(self, fg, self.input, self.sampler) |