Пример #1
0
	def __init__(self, dab_params, rx_params, verbose=False, debug=False):
		"""
		Hierarchical block for OFDM demodulation

		@param dab_params DAB parameter object (dab.parameters.dab_parameters)
		@param rx_params RX parameter object (dab.parameters.receiver_parameters)
		@param debug enables debug output to files
		@param verbose whether to produce verbose messages
		"""

		self.dp = dp = dab_params
		self.rp = rp = rx_params
		self.verbose = verbose

		if self.rp.softbits:
			gr.hier_block2.__init__(self,"ofdm_demod",
						gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature
						gr.io_signature2(2, 2, gr.sizeof_float*self.dp.num_carriers*2, gr.sizeof_char)) # output signature
		else:
			gr.hier_block2.__init__(self,"ofdm_demod",
						gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature
						gr.io_signature2(2, 2, gr.sizeof_char*self.dp.num_carriers/4, gr.sizeof_char)) # output signature

		

		# workaround for a problem that prevents connecting more than one block directly (see trac ticket #161)
		self.input = gr.kludge_copy(gr.sizeof_gr_complex)
		self.connect(self, self.input)
		
		# input filtering
		if self.rp.input_fft_filter: 
			if verbose: print "--> RX filter enabled"
			lowpass_taps = gr.firdes_low_pass(1.0,                     # gain
							  dp.sample_rate,          # sampling rate
							  rp.filt_bw,              # cutoff frequency
							  rp.filt_tb,              # width of transition band
							  gr.firdes.WIN_HAMMING)   # Hamming window
			self.fft_filter = gr.fft_filter_ccc(1, lowpass_taps)
		

		# correct sample rate offset, if enabled
		if self.rp.autocorrect_sample_rate:
			if verbose: print "--> dynamic sample rate correction enabled"
			self.rate_detect_ns = detect_null.detect_null(dp.ns_length, False)
			self.rate_estimator = dab_swig.estimate_sample_rate_bf(dp.sample_rate, dp.frame_length)
			self.rate_prober = gr.probe_signal_f()
			self.connect(self.input, self.rate_detect_ns, self.rate_estimator, self.rate_prober)
			# self.resample = gr.fractional_interpolator_cc(0, 1)
			self.resample = dab_swig.fractional_interpolator_triggered_update_cc(0,1)
			self.connect(self.rate_detect_ns, (self.resample,1))
			self.updater = Timer(0.1,self.update_correction)
			# self.updater = threading.Thread(target=self.update_correction)
			self.run_interpolater_update_thread = True
			self.updater.setDaemon(True)
			self.updater.start()
		else:
			self.run_interpolater_update_thread = False
			if self.rp.sample_rate_correction_factor != 1:
				if verbose: print "--> static sample rate correction enabled"
				self.resample = gr.fractional_interpolator_cc(0, self.rp.sample_rate_correction_factor)

		# timing and fine frequency synchronisation
		self.sync = ofdm_sync_dab2.ofdm_sync_dab(self.dp, self.rp, debug)

		# ofdm symbol sampler
		self.sampler = dab_swig.ofdm_sampler(dp.fft_length, dp.cp_length, dp.symbols_per_frame, rp.cp_gap)
		
		# fft for symbol vectors
		self.fft = gr.fft_vcc(dp.fft_length, True, [], True)

		# coarse frequency synchronisation
		self.cfs = dab_swig.ofdm_coarse_frequency_correct(dp.fft_length, dp.num_carriers, dp.cp_length)

		# diff phasor
		self.phase_diff = dab_swig.diff_phasor_vcc(dp.num_carriers)

		# remove pilot symbol
		self.remove_pilot = dab_swig.ofdm_remove_first_symbol_vcc(dp.num_carriers)

		# magnitude equalisation
		if self.rp.equalize_magnitude:
			if verbose: print "--> magnitude equalization enabled"
			self.equalizer = dab_swig.magnitude_equalizer_vcc(dp.num_carriers, rp.symbols_for_magnitude_equalization)

		# frequency deinterleaving
		self.deinterleave = dab_swig.frequency_interleaver_vcc(dp.frequency_deinterleaving_sequence_array)
		
		# symbol demapping
		self.demapper = dab_swig.qpsk_demapper_vcb(dp.num_carriers)

		#
		# connect everything
		#

		if self.rp.autocorrect_sample_rate or self.rp.sample_rate_correction_factor != 1:
			self.connect(self.input, self.resample)
			self.input2 = self.resample
		else:
			self.input2 = self.input
		if self.rp.input_fft_filter:
			self.connect(self.input2, self.fft_filter, self.sync)
		else:
			self.connect(self.input2, self.sync)

		# data stream
		self.connect((self.sync, 0), (self.sampler, 0), self.fft, (self.cfs, 0), self.phase_diff, (self.remove_pilot,0))
		if self.rp.equalize_magnitude:
			self.connect((self.remove_pilot,0), (self.equalizer,0), self.deinterleave)
		else:
			self.connect((self.remove_pilot,0), self.deinterleave)
		if self.rp.softbits:
			if verbose: print "--> using soft bits"
			self.softbit_interleaver = dab_swig.complex_to_interleaved_float_vcf(self.dp.num_carriers)
			self.connect(self.deinterleave, self.softbit_interleaver, (self,0))
		else:
			self.connect(self.deinterleave, self.demapper, (self,0))

		# control stream
		self.connect((self.sync, 1), (self.sampler, 1), (self.cfs, 1), (self.remove_pilot,1))
		if self.rp.equalize_magnitude:
			self.connect((self.remove_pilot,1), (self.equalizer,1), (self,1))
		else:
			self.connect((self.remove_pilot,1), (self,1))
			
		# calculate an estimate of the SNR
		self.phase_var_decim   = gr.keep_one_in_n(gr.sizeof_gr_complex*self.dp.num_carriers, self.rp.phase_var_estimate_downsample)
		self.phase_var_arg     = gr.complex_to_arg(dp.num_carriers)
		self.phase_var_v2s     = gr.vector_to_stream(gr.sizeof_float, dp.num_carriers)
		self.phase_var_mod     = dab_swig.modulo_ff(pi/2)
		self.phase_var_avg_mod = gr.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) 
		self.phase_var_sub_avg = gr.sub_ff()
		self.phase_var_sqr     = gr.multiply_ff()
		self.phase_var_avg     = gr.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) 
		self.probe_phase_var   = gr.probe_signal_f()
		self.connect((self.remove_pilot,0), self.phase_var_decim, self.phase_var_arg, self.phase_var_v2s, self.phase_var_mod, (self.phase_var_sub_avg,0), (self.phase_var_sqr,0))
		self.connect(self.phase_var_mod, self.phase_var_avg_mod, (self.phase_var_sub_avg,1))
		self.connect(self.phase_var_sub_avg, (self.phase_var_sqr,1))
		self.connect(self.phase_var_sqr, self.phase_var_avg, self.probe_phase_var)

		# measure processing rate
		self.measure_rate = dab_swig.measure_processing_rate(gr.sizeof_gr_complex, 2000000) 
		self.connect(self.input, self.measure_rate)

		# debugging
		if debug:
			self.connect(self.fft, gr.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/ofdm_after_fft.dat"))
			self.connect((self.cfs,0), gr.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_after_cfs.dat"))
			self.connect(self.phase_diff, gr.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_diff_phasor.dat"))
			self.connect((self.remove_pilot,0), gr.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_pilot_removed.dat"))
			self.connect((self.remove_pilot,1), gr.file_sink(gr.sizeof_char, "debug/ofdm_after_cfs_trigger.dat"))
			self.connect(self.deinterleave, gr.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_deinterleaved.dat"))
			if self.rp.equalize_magnitude:
				self.connect(self.equalizer, gr.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_equalizer.dat"))
			if self.rp.softbits:
				self.connect(self.softbit_interleaver, gr.file_sink(gr.sizeof_float*dp.num_carriers*2, "debug/softbits.dat"))
Пример #2
0
    def __init__(self, options, input_filename):
        gr.top_block.__init__(self)

        gr.enable_realtime_scheduling()

        if options.real:
            sizeof_input_samples = gr.sizeof_float
        else:
            sizeof_input_samples = gr.sizeof_gr_complex

        self.src = gr.file_source(sizeof_input_samples,
                                  input_filename,
                                  repeat = options.loop)
        self.u = generic_usrp_sink_c(interface = options.interface,
                                     mac_addr = options.mac_addr,
                                     subdev_spec = options.tx_subdev_spec)
        print 'Using %s' % str(self.u)
        print 'Possible tx frequency range: %s - %s' % \
            (n2s(self.u.freq_range()[0]), n2s(self.u.freq_range()[1]))

        # we need to find the closest decimation rate the USRP can handle
        # to the input file's sampling rate
        try:
            ideal_interp = self.u.dac_rate() / options.rate
            # pick the closest interpolation rate
            interp = [x for x in self.u.get_interp_rates()
                      if x <= ideal_interp][-1]
            self.u.set_interp(interp)
        except IndexError:
            sys.stderr.write('Failed to set USRP interpolation rate\n')
            raise SystemExit, 1

        output_rate = self.u.dac_rate() / interp
        resamp_ratio = output_rate / options.rate 

        # since the input file sample rate may not be exactly what our
        # output rate of the USRP (as determined by the interpolation rate),
        # we need to resample our input to the output rate
        num_filters = 32
        cutoff = 0.99 * options.rate / 2.
        transition = 0.1 * options.rate / 2.
        resamp_taps = gr.firdes_low_pass(num_filters * 1.0,
                                         num_filters * options.rate,
                                         cutoff,
                                         transition)
        self.resamp = gr.pfb_arb_resampler_ccf(resamp_ratio,
                                               resamp_taps,
                                               num_filters)

        if options.gain is None:
            # if no gain was specified, use the mid-point in dB
            g = self.u.gain_range()
            options.gain = float(g[0]+g[1])/2
        self.u.set_gain(options.gain)

        res = self.u.set_center_freq(options.freq)
        if not res:
            sys.stderr.write('Failed to set frequency\n')
            raise SystemExit, 1

        if options.real:
            # our samples are real
            # we need to convert them to complex without a hilbert filter
            self.hilbert = gr.hilbert_fc(64)
            self.connect(self.src, self.hilbert, self.resamp, self.u)
        else:
            # our samples are complex
            self.connect(self.src, self.resamp, self.u)