Beispiel #1
0
 def __init__(self):
     analog_source.__init__(self, mod_name="am-dsb", audio_rate=44.1e3)
     self.interp = filter.fractional_resampler_ff(
         0.0, self.audio_rate * 2 / 200e3)
     self.cnv = blocks.float_to_complex()
     self.add = blocks.add_const_cc(1.0)
     self.mod = blocks.multiply_cc()
     self.connect(self.random_source, self.interp, self.cnv, self.add, self)
Beispiel #2
0
    def __init__(self):
        gr.hier_block2.__init__(
            self,
            "BER Computation",
            gr.io_signaturev(
                2, 2, [gr.sizeof_gr_complex * 1, gr.sizeof_gr_complex * 1]),
            gr.io_signaturev(2, 2, [gr.sizeof_float * 1, gr.sizeof_float * 1]),
        )

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 32000

        ##################################################
        # Blocks
        ##################################################
        self.iir_filter_xxx_0_0 = filter.iir_filter_ffd([1], [1, 1], True)
        self.iir_filter_xxx_0 = filter.iir_filter_ffd([1], [1, 1], True)
        self.blocks_tag_gate_0 = blocks.tag_gate(gr.sizeof_gr_complex * 1,
                                                 False)
        self.blocks_tag_gate_0.set_single_key("")
        self.blocks_sub_xx_0 = blocks.sub_cc(1)
        self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_cc(0)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(0.5)
        self.blocks_max_xx_0_0 = blocks.max_ff(1, 1)
        self.blocks_max_xx_0 = blocks.max_ff(1, 1)
        self.blocks_divide_xx_0 = blocks.divide_ff(1)
        self.blocks_complex_to_mag_0_0 = blocks.complex_to_mag(1)
        self.blocks_complex_to_mag_0 = blocks.complex_to_mag(1)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(1)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.blocks_complex_to_mag_0_0, 0))
        self.connect((self.blocks_complex_to_mag_0, 0),
                     (self.iir_filter_xxx_0, 0))
        self.connect((self.blocks_complex_to_mag_0_0, 0),
                     (self.iir_filter_xxx_0_0, 0))
        self.connect((self.blocks_divide_xx_0, 0), (self, 0))
        self.connect((self.blocks_max_xx_0, 0), (self.blocks_divide_xx_0, 1))
        self.connect((self.blocks_max_xx_0_0, 0), (self.blocks_divide_xx_0, 0))
        self.connect((self.blocks_max_xx_0_0, 0), (self, 1))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_complex_to_mag_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0_0, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_sub_xx_0, 0), (self.blocks_tag_gate_0, 0))
        self.connect((self.blocks_tag_gate_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.blocks_tag_gate_0, 0),
                     (self.blocks_multiply_const_vxx_0_0, 0))
        self.connect((self.iir_filter_xxx_0, 0), (self.blocks_max_xx_0_0, 0))
        self.connect((self.iir_filter_xxx_0_0, 0), (self.blocks_max_xx_0, 0))
        self.connect((self, 0), (self.blocks_sub_xx_0, 0))
        self.connect((self, 1), (self.blocks_sub_xx_0, 1))
Beispiel #3
0
    def __init__(self, context, mode, rate=10000):
        gr.hier_block2.__init__(
            self,
            type(self).__name__,
            gr.io_signature(1, 1, gr.sizeof_float * 1),
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
        )

        self.__rate = rate

        self.connect(self, blocks.float_to_complex(1), blocks.add_const_cc(1), self)
Beispiel #4
0
    def __init__(self, context, mode, rate=10000):
        gr.hier_block2.__init__(
            self,
            type(self).__name__,
            gr.io_signature(1, 1, gr.sizeof_float * 1),
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
        )

        self.__rate = rate

        self.connect(self, blocks.float_to_complex(1), blocks.add_const_cc(1),
                     self)
 def __init__(self):
     gr.hier_block2.__init__(self, "transmitter_am",
                             gr.io_signature(1, 1, gr.sizeof_float),
                             gr.io_signature(1, 1, gr.sizeof_gr_complex))
     self.rate = 44.1e3 / 200e3
     self.interp = filter.fractional_interpolator_ff(0.0, self.rate)
     self.cnv = blocks.float_to_complex()
     self.mul = blocks.multiply_const_cc(1.0)
     self.add = blocks.add_const_cc(1.0)
     self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 0e3, 1.0)
     self.mod = blocks.multiply_cc()
     self.connect(self, self.interp, self.cnv, self.mul, self.add, self.mod,
                  self)
     self.connect(self.src, (self.mod, 1))
Beispiel #6
0
 def __init__(self):
     gr.hier_block2.__init__(self, "transmitter_am",
                             gr.io_signature(1, 1, gr.sizeof_float),
                             gr.io_signature(1, 1, gr.sizeof_gr_complex))
     self.rate = 44.1e3 / 200e3
     # self.rate = 200e3/44.1e3
     # Build the resampling MMSE filter (float input, float output)
     self.interp = filter.mmse_resampler_ff(0.0, self.rate)
     self.cnv = blocks.float_to_complex()
     self.mul = blocks.multiply_const_cc(1.0)
     self.add = blocks.add_const_cc(1.0)
     self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 0e3, 1.0)
     # self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 50e3, 1.0)
     self.mod = blocks.multiply_cc()
     self.connect(self, self.interp, self.cnv, self.mul, self.add, self.mod,
                  self)
     self.connect(self.src, (self.mod, 1))
def emulate_repeating_RF_channel(outputfile, framed_signal, fparams,
                                 n_sections, Nsuperframe, params, Nsettle):
    ### Set variables based on given parameters
    tot_linear_gain, noise_voltage = read_and_assert_channel_amplitudes(params)
    freq_offset = params.get('channel_frequency_offset', 0)
    DC_offset = params.get('DC_offset', 0)
    DC_offset *= np.exp(1j * 2 * np.pi *
                        np.random.rand(1))  # add a random phase
    DC_offset = DC_offset[0]
    # TODO: Understand why you get a list here

    print 'final SNRdB:', 10 * np.log10(tot_linear_gain**2 / noise_voltage**2)

    # get needed global parameters
    frame_period = fparams.frame_period

    ### Read Signal already Framed and apply channel effects, keep repeating, and writes the result to a temp file
    # GNURadio Flowgraph
    tb = gr.top_block()
    random_TxRx_unsync = np.random.randint(1000)
    Rx_num_samples = Nsuperframe + Nsettle  # the settle is important both for the HW and pdetec history
    Rx_num_samples += frame_period + 10  # we will only choose peaks whose frame is whole. I just add an guard interval of a few samples

    source = blocks.vector_source_c(framed_signal, True)  # keep repeating
    attenuation = blocks.multiply_const_cc(tot_linear_gain + 0 * 1j)
    channel = channels.channel_model(noise_voltage, freq_offset)
    dc_block = blocks.add_const_cc(DC_offset + 0 * 1j)
    skip = blocks.skiphead(gr.sizeof_gr_complex, random_TxRx_unsync)
    head = blocks.head(gr.sizeof_gr_complex, Rx_num_samples)
    fsink = blocks.file_sink(gr.sizeof_gr_complex, outputfile)

    tb.connect(source, attenuation)
    tb.connect(attenuation, channel)
    tb.connect(channel, dc_block)
    tb.connect(dc_block, skip)
    tb.connect(skip, head)
    tb.connect(head, fsink)

    tb.run()
    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
        scaling factor to reduce ambiguities introduced 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

        self.input = blocks.add_const_cc(0)

        symbol_length = fft_length + cp_length

        # PN Sync with cross-correlation input

        # cross-correlate with the known symbol
        kstime = [k.conjugate() for k in kstime[0:fft_length//2]]
        kstime.reverse()
        self.crosscorr_filter = filter.fir_filter_ccc(1, kstime)
        
        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc();
        self.corr = blocks.multiply_cc();

        # Create a moving sum filter for the input
        self.mag = blocks.complex_to_mag_squared()
        self.power = filter.fir_filter_fff(1, [1.0] * int(fft_length))

        # Get magnitude (peaks) and angle (phase/freq error)
        self.c2mag = blocks.complex_to_mag_squared()
        self.angle = blocks.complex_to_arg()
        self.compare = blocks.sub_ff()

        self.sample_and_hold = blocks.sample_and_hold_ff()

        #ML measurements input to sampler block and detect
        self.threshold = blocks.threshold_ff(0,0,0)      # threshold detection might need to be tweaked
        self.peaks = blocks.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 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.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)

        # 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))

        # Set output signals
        #    Output 0: fine frequency correction value
        #    Output 1: timing signal
        self.connect(self.sample_and_hold, (self,0))
        self.connect(self.peaks, (self,1))

        if logging:
            self.connect(self.compare, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-compare_f.dat"))
            self.connect(self.c2mag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-theta_f.dat"))
            self.connect(self.power, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-inputpower_f.dat"))
            self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-epsilon_f.dat"))
            self.connect(self.threshold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-threshold_f.dat"))
            self.connect(self.peaks, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pnac-peaks_b.dat"))
            self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pnac-sample_and_hold_f.dat"))
            self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pnac-input_c.dat"))
Beispiel #9
0
    def __init__(self):
        gr.top_block.__init__(self, "Vhf Tx")

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 4000000
        self.interpolation = interpolation = 80
        self.wpm = wpm = 15
        self.tune = tune = 100
        self.rf_gain = rf_gain = 0
        self.offset = offset = 200000
        self.if_gain = if_gain = 20
        self.cw_vector = cw_vector = (
            1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0,
            0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
            1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,
            1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0,
            0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1,
            1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
            1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0,
            1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0)
        self.correction = correction = 0
        self.band = band = 432
        self.audio_rate = audio_rate = samp_rate / interpolation

        ##################################################
        # Blocks
        ##################################################
        self.resamp = filter.rational_resampler_ccc(
            interpolation=interpolation,
            decimation=1,
            taps=None,
            fractional_bw=None)
        self.out = osmosdr.sink(args="numchan=" + str(1) + " " + 'hackrf=0')
        self.out.set_time_unknown_pps(osmosdr.time_spec_t())
        self.out.set_sample_rate(samp_rate)
        self.out.set_center_freq(band * 1e6 + 100000 - offset, 0)
        self.out.set_freq_corr(correction, 0)
        self.out.set_gain(rf_gain, 0)
        self.out.set_if_gain(if_gain, 0)
        self.out.set_bb_gain(20, 0)
        self.out.set_antenna('', 0)
        self.out.set_bandwidth(0, 0)
        self.offset_osc = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE,
                                              tune * 1000 + 100000, 0.9, 0, 0)
        self.mixer = blocks.multiply_vcc(1)
        self.cw_vector_source = blocks.vector_source_c(cw_vector, False, 1, [])
        self.cw_repeat = blocks.repeat(gr.sizeof_gr_complex * 1,
                                       int(1.2 * audio_rate / wpm))
        self.click_filter = filter.single_pole_iir_filter_cc(1e-2, 1)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(0.000001)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_const_vxx_0, 0), (self.resamp, 0))
        self.connect((self.click_filter, 0), (self.blocks_add_const_vxx_0, 0))
        self.connect((self.cw_repeat, 0), (self.click_filter, 0))
        self.connect((self.cw_vector_source, 0), (self.cw_repeat, 0))
        self.connect((self.mixer, 0), (self.out, 0))
        self.connect((self.offset_osc, 0), (self.mixer, 0))
        self.connect((self.resamp, 0), (self.mixer, 1))
Beispiel #10
0
	def __init__(self, name='Simulated Source', freq=0):
		Source.__init__(self, name=name)
		
		audio_rate = 1e4
		rf_rate = self.__sample_rate = 200e3
		interp = int(rf_rate / audio_rate)
		
		self.__freq = freq
		self.noise_level = -2
		
		interp_taps = firdes.low_pass(
			1,  # gain
			rf_rate,
			audio_rate / 2,
			audio_rate * 0.2,
			firdes.WIN_HAMMING)
		
		def make_interpolator():
			return filter.interp_fir_filter_ccf(interp, interp_taps)
		
		def make_channel(freq):
			osc = analog.sig_source_c(rf_rate, analog.GR_COS_WAVE, freq, 1, 0)
			mult = blocks.multiply_cc(1)
			self.connect(osc, (mult, 1))
			return mult
		
		self.bus = blocks.add_vcc(1)
		self.channel_model = channels.channel_model(
			noise_voltage=10 ** self.noise_level,
			frequency_offset=0,
			epsilon=1.01,  # TODO: expose this parameter
			#taps=...,  # TODO: apply something here?
			)
		self.throttle = blocks.throttle(gr.sizeof_gr_complex, rf_rate)
		self.connect(
			self.bus,
			self.channel_model,
			self.throttle,
			self)
		signals = []
		
		# Audio input signal
		pitch = analog.sig_source_f(audio_rate, analog.GR_SAW_WAVE, -1, 2000, 1000)
		audio_signal = vco = blocks.vco_f(audio_rate, 1, 1)
		self.connect(pitch, vco)
		
		# Baseband / DSB channel
		baseband_interp = make_interpolator()
		self.connect(
			audio_signal,
			blocks.float_to_complex(1),
			baseband_interp)
		signals.append(baseband_interp)
		
		# AM channel
		am_channel = make_channel(10e3)
		self.connect(
			audio_signal,
			blocks.float_to_complex(1),
			blocks.add_const_cc(1),
			make_interpolator(),
			am_channel)
		signals.append(am_channel)
		
		# NFM channel
		nfm_channel = make_channel(30e3)
		self.connect(
			audio_signal,
			analog.nbfm_tx(
				audio_rate=audio_rate,
				quad_rate=rf_rate,
				tau=75e-6,
				max_dev=5e3),
			nfm_channel)
		signals.append(nfm_channel)
		
		# VOR channels
		# TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal
		def add_vor(freq, angle):
			compensation = math.pi / 180 * -6.5  # empirical, calibrated against VOR receiver (and therefore probably wrong)
			angle = angle + compensation
			angle = angle % (2 * math.pi)
			vor_sig_freq = 30
			phase_shift = int(rf_rate / vor_sig_freq * (angle / (2 * math.pi)))
			vor_dev = 480
			vor_channel = make_channel(freq)
			vor_30 = analog.sig_source_f(audio_rate, analog.GR_COS_WAVE, vor_sig_freq, 1, 0)
			vor_add = blocks.add_cc(1)
			vor_audio = blocks.add_ff(1)
			# Audio/AM signal
			self.connect(
				vor_30,
				blocks.multiply_const_ff(0.3),  # M_n
				(vor_audio, 0))
			self.connect(audio_signal,
				blocks.multiply_const_ff(0.07),  # M_i
				(vor_audio, 1))
			# Carrier component
			self.connect(
				analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1),
				(vor_add, 0))
			# AM component
			self.connect(
				vor_audio,
				blocks.float_to_complex(1),
				make_interpolator(),
				blocks.delay(gr.sizeof_gr_complex, phase_shift),
				(vor_add, 1))
			# FM component
			vor_fm_mult = blocks.multiply_cc(1)
			self.connect(  # carrier generation
				analog.sig_source_f(rf_rate, analog.GR_COS_WAVE, 9960, 1, 0), 
				blocks.float_to_complex(1),
				(vor_fm_mult, 1))
			self.connect(  # modulation
				vor_30,
				filter.interp_fir_filter_fff(interp, interp_taps),  # float not complex
				analog.frequency_modulator_fc(2 * math.pi * vor_dev / rf_rate),
				blocks.multiply_const_cc(0.3),  # M_d
				vor_fm_mult,
				(vor_add, 2))
			self.connect(
				vor_add,
				vor_channel)
			signals.append(vor_channel)
		add_vor(-30e3, 0)
		add_vor(-60e3, math.pi / 2)
		
		bus_input = 0
		for signal in signals:
			self.connect(signal, (self.bus, bus_input))
			bus_input = bus_input + 1
Beispiel #11
0
    def __init__(self):
        gr.top_block.__init__(self, "Dcoffset Test", catch_exceptions=True)
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Dcoffset Test")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "dcoffset_test")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(
                    self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 2.4e6
        self.real = real = -0.011900
        self.imag = imag = -0.004100
        self.gain = gain = 16
        self.center_freq = center_freq = 95.7e6
        self.amp_on = amp_on = 14

        ##################################################
        # Blocks
        ##################################################
        self._real_range = Range(-0.1, 0.1, 0.0001, -0.011900, 200)
        self._real_win = RangeWidget(self._real_range, self.set_real, 'real',
                                     "counter_slider", float,
                                     QtCore.Qt.Horizontal)
        self.top_grid_layout.addWidget(self._real_win, 1, 0, 1, 1)
        for r in range(1, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._imag_range = Range(-0.1, 0.1, 0.0001, -0.004100, 200)
        self._imag_win = RangeWidget(self._imag_range, self.set_imag, 'imag',
                                     "counter_slider", float,
                                     QtCore.Qt.Horizontal)
        self.top_grid_layout.addWidget(self._imag_win, 1, 1, 1, 1)
        for r in range(1, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._gain_range = Range(0, 40, 8, 16, 200)
        self._gain_win = RangeWidget(self._gain_range, self.set_gain, 'Gain',
                                     "counter_slider", float,
                                     QtCore.Qt.Horizontal)
        self.top_grid_layout.addWidget(self._gain_win, 0, 1, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._center_freq_tool_bar = Qt.QToolBar(self)
        self._center_freq_tool_bar.addWidget(
            Qt.QLabel('Center Frequency' + ": "))
        self._center_freq_line_edit = Qt.QLineEdit(str(self.center_freq))
        self._center_freq_tool_bar.addWidget(self._center_freq_line_edit)
        self._center_freq_line_edit.returnPressed.connect(
            lambda: self.set_center_freq(
                eng_notation.str_to_num(str(self._center_freq_line_edit.text())
                                        )))
        self.top_grid_layout.addWidget(self._center_freq_tool_bar, 0, 0, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_time_sink_x_0 = qtgui.time_sink_c(
            2048,  #size
            samp_rate,  #samp_rate
            "",  #name
            4,  #number of inputs
            None  # parent
        )
        self.qtgui_time_sink_x_0.set_update_time(0.10)
        self.qtgui_time_sink_x_0.set_y_axis(-0.01, 0.01)

        self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")

        self.qtgui_time_sink_x_0.enable_tags(True)
        self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE,
                                                  qtgui.TRIG_SLOPE_POS, 0.0, 0,
                                                  0, "")
        self.qtgui_time_sink_x_0.enable_autoscale(True)
        self.qtgui_time_sink_x_0.enable_grid(True)
        self.qtgui_time_sink_x_0.enable_axis_labels(True)
        self.qtgui_time_sink_x_0.enable_control_panel(False)
        self.qtgui_time_sink_x_0.enable_stem_plot(False)

        labels = [
            'Add Const I', 'Add Const Q', 'Manual CorrectIQ I',
            'Manual CorrectIQ Q', 'Auto CorrectIQ I', 'Auto CorrectIQ Q',
            'Full CorrectIQ I', 'Full CorrectIQ Q', '', ''
        ]
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow',
            'dark red', 'dark green', 'dark blue'
        ]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
        styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]

        for i in range(8):
            if len(labels[i]) == 0:
                if (i % 2 == 0):
                    self.qtgui_time_sink_x_0.set_line_label(
                        i, "Re{{Data {0}}}".format(i / 2))
                else:
                    self.qtgui_time_sink_x_0.set_line_label(
                        i, "Im{{Data {0}}}".format(i / 2))
            else:
                self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
            self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
            self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_time_sink_x_0_win = sip.wrapinstance(
            self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
        self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
            2048,  #size
            window.WIN_BLACKMAN_hARRIS,  #wintype
            center_freq,  #fc
            samp_rate,  #bw
            "",  #name
            4,
            None  # parent
        )
        self.qtgui_freq_sink_x_0.set_update_time(0.10)
        self.qtgui_freq_sink_x_0.set_y_axis(-120, -20)
        self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
        self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0,
                                                  "")
        self.qtgui_freq_sink_x_0.enable_autoscale(False)
        self.qtgui_freq_sink_x_0.enable_grid(True)
        self.qtgui_freq_sink_x_0.set_fft_average(0.2)
        self.qtgui_freq_sink_x_0.enable_axis_labels(True)
        self.qtgui_freq_sink_x_0.enable_control_panel(False)
        self.qtgui_freq_sink_x_0.set_fft_window_normalized(False)

        labels = [
            'Add Const', 'Manual Offset', 'AutoSync Offset', 'CorrectIQ', '',
            '', '', '', '', ''
        ]
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "green", "black", "cyan", "magenta", "yellow",
            "dark red", "dark green", "dark blue"
        ]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(4):
            if len(labels[i]) == 0:
                self.qtgui_freq_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_freq_sink_x_0_win = sip.wrapinstance(
            self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win)
        self.osmosdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " +
                                               'rtl')
        self.osmosdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t())
        self.osmosdr_source_0.set_sample_rate(samp_rate)
        self.osmosdr_source_0.set_center_freq(center_freq, 0)
        self.osmosdr_source_0.set_freq_corr(0, 0)
        self.osmosdr_source_0.set_dc_offset_mode(0, 0)
        self.osmosdr_source_0.set_iq_balance_mode(0, 0)
        self.osmosdr_source_0.set_gain_mode(False, 0)
        self.osmosdr_source_0.set_gain(gain, 0)
        self.osmosdr_source_0.set_if_gain(0, 0)
        self.osmosdr_source_0.set_bb_gain(0, 0)
        self.osmosdr_source_0.set_antenna('', 0)
        self.osmosdr_source_0.set_bandwidth(0, 0)
        self.correctiq_correctiq_man_0 = correctiq.correctiq_man(real, imag)
        self.correctiq_correctiq_auto_0 = correctiq.correctiq_auto(
            samp_rate, center_freq, gain, 2)
        self.correctiq_correctiq_1 = correctiq.correctiq()
        self.blocks_add_const_vxx_1_0 = blocks.add_const_cc(real + 1j * imag)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_const_vxx_1_0, 0),
                     (self.qtgui_freq_sink_x_0, 0))
        self.connect((self.blocks_add_const_vxx_1_0, 0),
                     (self.qtgui_time_sink_x_0, 0))
        self.connect((self.correctiq_correctiq_1, 0),
                     (self.qtgui_freq_sink_x_0, 3))
        self.connect((self.correctiq_correctiq_1, 0),
                     (self.qtgui_time_sink_x_0, 3))
        self.connect((self.correctiq_correctiq_auto_0, 0),
                     (self.qtgui_freq_sink_x_0, 2))
        self.connect((self.correctiq_correctiq_auto_0, 0),
                     (self.qtgui_time_sink_x_0, 2))
        self.connect((self.correctiq_correctiq_man_0, 0),
                     (self.qtgui_freq_sink_x_0, 1))
        self.connect((self.correctiq_correctiq_man_0, 0),
                     (self.qtgui_time_sink_x_0, 1))
        self.connect((self.osmosdr_source_0, 0),
                     (self.blocks_add_const_vxx_1_0, 0))
        self.connect((self.osmosdr_source_0, 0),
                     (self.correctiq_correctiq_1, 0))
        self.connect((self.osmosdr_source_0, 0),
                     (self.correctiq_correctiq_auto_0, 0))
        self.connect((self.osmosdr_source_0, 0),
                     (self.correctiq_correctiq_man_0, 0))
 def test_add_const_cc(self):
     src_data = (1, 2, 3, 4, 5)
     expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j)
     op = blocks.add_const_cc(5j)
     self.help_cc((src_data,), expected_result, op)
    def __init__(self, fft_length, cp_length, kstime, overrate, logging=True):
        """
        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.
        """

        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_float,
                             gr.sizeof_char))  # Output signature

        self.input = blocks.add_const_cc(0)

        # cross-correlate with the known symbol
        kstime = [k.conjugate() for k in kstime]
        kstime.reverse()
        self.crosscorr_filter = filter.fir_filter_ccc(1, kstime)

        # PN Sync
        self.corrmag = blocks.complex_to_mag_squared()
        self.delay = blocks.delay(gr.sizeof_gr_complex,
                                  fft_length * overrate / 2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc()
        self.corr = blocks.multiply_cc()

        #self.sub = blocks.add_const_ff(-1)
        self.pk_detect = blocks.peak_detector_fb(0.40, 0.25,
                                                 fft_length * overrate,
                                                 0.00000000000)

        self.connect(self, self.input)
        self.connect(self.input, self.crosscorr_filter)
        self.connect(self.crosscorr_filter, self.corrmag)

        #self.inputmag = blocks.complex_to_mag_squared()
        #self.normalize = blocks.divide_ff()
        #self.inputmovingsum = filter.fir_filter_fff(1, [1.0] * (fft_length//2))
        self.square = blocks.multiply_ff()

        #self.connect(self.input,self.inputmag,self.inputmovingsum)
        self.connect(self.corrmag, (self.square, 0))
        self.connect(self.corrmag, (self.square, 1))
        self.dsquare = blocks.multiply_ff()
        self.connect(self.square, (self.dsquare, 0))
        self.connect(self.square, (self.dsquare, 1))
        self.connect(self.dsquare, self.pk_detect)

        # Create a moving sum filter for the corr output
        self.moving_sum_filter = filter.fir_filter_ccf(
            1, [1.0] * (fft_length * overrate // 2))

        # Get magnitude (peaks) and angle (phase/freq error)
        self.angle = blocks.complex_to_arg()

        self.sample_and_hold = blocks.sample_and_hold_ff()

        # Calculate the frequency offset from the correlation of the preamble
        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.angle)
        self.connect(self.angle, (self.sample_and_hold, 0))
        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))

        if logging:
            self.connect(
                self.dsquare,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-dsquare.dat"))
            self.connect(
                self.corrmag,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-corrmag.dat"))
            self.connect(
                self.angle,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pn-epsilon_f.dat"))
            self.connect(
                self.pk_detect,
                blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
            self.connect(
                self.sample_and_hold,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pn-sample_and_hold_f.dat"))
            self.connect(
                self.input,
                blocks.file_sink(gr.sizeof_gr_complex,
                                 "ofdm_sync_pn-input_c.dat"))
Beispiel #14
0
    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
        Synchronization for OFDM," IEEE Trans. Communications, vol. 45,
        no. 12, 1997.
        """

        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_float, gr.sizeof_char)) # Output signature

        self.input = blocks.add_const_cc(0)

        # PN Sync

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc();
        self.corr = blocks.multiply_cc();

        # Create a moving sum filter for the corr output
        self.moving_sum_filter = filter.fir_filter_ccf(1, [1.0] * (fft_length//2))

        # Create a moving sum filter for the input
        self.inputmag2 = blocks.complex_to_mag_squared()
        self.inputmovingsum = filter.fir_filter_fff(1, [1.0] * (fft_length//2))

        self.square = blocks.multiply_ff()
        self.normalize = blocks.divide_ff()

        # Get magnitude (peaks) and angle (phase/freq error)
        self.c2mag = blocks.complex_to_mag_squared()
        self.angle = blocks.complex_to_arg()

        self.sample_and_hold = blocks.sample_and_hold_ff()

        #ML measurements input to sampler block and detect
        self.sub1 = blocks.add_const_ff(-1)
        self.pk_detect = blocks.peak_detector_fb(0.20, 0.20, 30, 0.001)

        self.connect(self, self.input)

        # Calculate the frequency offset from the correlation of the preamble
        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))

        # Get the power of the input signal to normalize the output of the correlation
        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 = filter.fir_filter_fff(1,matched_filter_taps)
        self.connect(self.normalize, self.matched_filter)
        
        self.connect(self.matched_filter, self.sub1, self.pk_detect)
        #self.connect(self.matched_filter, 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))

        if logging:
            self.connect(self.matched_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat"))
            self.connect(self.normalize, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat"))
            self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat"))
            self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
            self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat"))
            self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
Beispiel #15
0
    def __init__(
            self,
            parent,
            unit='units',
            minval=0,
            maxval=1,
            factor=1,
            decimal_places=3,
            ref_level=0,
            sample_rate=1,
            number_rate=number_window.DEFAULT_NUMBER_RATE,
            average=False,
            avg_alpha=None,
            label='Number Plot',
            size=number_window.DEFAULT_WIN_SIZE,
            peak_hold=False,
            show_gauge=True,
            **kwargs  #catchall for backwards compatibility
    ):
        #ensure avg alpha
        if avg_alpha is None: avg_alpha = 2.0 / number_rate
        #init
        gr.hier_block2.__init__(
            self,
            "number_sink",
            gr.io_signature(1, 1, self._item_size),
            gr.io_signature(0, 0, 0),
        )
        #blocks
        sd = blocks.stream_to_vector_decimator(
            item_size=self._item_size,
            sample_rate=sample_rate,
            vec_rate=number_rate,
            vec_len=1,
        )
        if self._real:
            mult = blocks.multiply_const_ff(factor)
            add = blocks.add_const_ff(ref_level)
            avg = filter.single_pole_iir_filter_ff(1.0)
        else:
            mult = blocks.multiply_const_cc(factor)
            add = blocks.add_const_cc(ref_level)
            avg = filter.single_pole_iir_filter_cc(1.0)
        msgq = gr.msg_queue(2)
        sink = blocks.message_sink(self._item_size, msgq, True)
        #controller
        self.controller = pubsub()
        self.controller.subscribe(SAMPLE_RATE_KEY, sd.set_sample_rate)
        self.controller.publish(SAMPLE_RATE_KEY, sd.sample_rate)
        self.controller[AVERAGE_KEY] = average
        self.controller[AVG_ALPHA_KEY] = avg_alpha

        def update_avg(*args):
            if self.controller[AVERAGE_KEY]:
                avg.set_taps(self.controller[AVG_ALPHA_KEY])
            else:
                avg.set_taps(1.0)

        update_avg()
        self.controller.subscribe(AVERAGE_KEY, update_avg)
        self.controller.subscribe(AVG_ALPHA_KEY, update_avg)
        #start input watcher
        common.input_watcher(msgq, self.controller, MSG_KEY)
        #create window
        self.win = number_window.number_window(
            parent=parent,
            controller=self.controller,
            size=size,
            title=label,
            units=unit,
            real=self._real,
            minval=minval,
            maxval=maxval,
            decimal_places=decimal_places,
            show_gauge=show_gauge,
            average_key=AVERAGE_KEY,
            avg_alpha_key=AVG_ALPHA_KEY,
            peak_hold=peak_hold,
            msg_key=MSG_KEY,
            sample_rate_key=SAMPLE_RATE_KEY,
        )
        common.register_access_methods(self, self.controller)
        #backwards compadibility
        self.set_show_gauge = self.win.show_gauges
        #connect
        self.wxgui_connect(self, sd, mult, add, avg, sink)
Beispiel #16
0
 def test_add_const_cc(self):
     src_data = (1, 2, 3, 4, 5)
     expected_result = (1 + 5j, 2 + 5j, 3 + 5j, 4 + 5j, 5 + 5j)
     op = blocks.add_const_cc(5j)
     self.help_cc((src_data, ), expected_result, op)
Beispiel #17
0
    def __init__(self):
        gr.top_block.__init__(self, "Top Block")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Top Block")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "top_block")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 1000000
        self.frame_size = frame_size = 100
        self.add = add = 0

        ##################################################
        # Blocks
        ##################################################
        self._add_range = Range(-10, 10, 0.01, 0, 200)
        self._add_win = RangeWidget(self._add_range, self.set_add, 'add', "counter_slider", float)
        self.top_grid_layout.addWidget(self._add_win)
        self.qtgui_time_sink_x_0 = qtgui.time_sink_c(
            2000, #size
            samp_rate, #samp_rate
            "", #name
            2 #number of inputs
        )
        self.qtgui_time_sink_x_0.set_update_time(0.10)
        self.qtgui_time_sink_x_0.set_y_axis(-1, 1)

        self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")

        self.qtgui_time_sink_x_0.enable_tags(False)
        self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
        self.qtgui_time_sink_x_0.enable_autoscale(False)
        self.qtgui_time_sink_x_0.enable_grid(False)
        self.qtgui_time_sink_x_0.enable_axis_labels(True)
        self.qtgui_time_sink_x_0.enable_control_panel(False)
        self.qtgui_time_sink_x_0.enable_stem_plot(False)


        labels = ['', '', '', '', '',
            '', '', '', '', '']
        widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        colors = ['blue', 'red', 'green', 'black', 'cyan',
            'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 1.0, 1.0]
        styles = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        markers = [-1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1]


        for i in range(4):
            if len(labels[i]) == 0:
                if (i % 2 == 0):
                    self.qtgui_time_sink_x_0.set_line_label(i, "Re{{Data {0}}}".format(i/2))
                else:
                    self.qtgui_time_sink_x_0.set_line_label(i, "Im{{Data {0}}}".format(i/2))
            else:
                self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
            self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
            self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
        self.learning_tag_numerotation_0 = learning.tag_numerotation('step', frame_size, "cc")
        self.learning_sync_rl_preprocessor_0 = learning.sync_rl_preprocessor(frame_size, 20, 4, add, 1e-2)
        self.learning_error_estimator_0 = learning.error_estimator('step', frame_size, "cc", 10)
        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(add + (add*1j))
        self.analog_fastnoise_source_x_0 = analog.fastnoise_source_c(analog.GR_GAUSSIAN, 1, 0, 8192)



        ##################################################
        # Connections
        ##################################################
        self.msg_connect((self.learning_error_estimator_0, 'error'), (self.learning_sync_rl_preprocessor_0, 'error'))
        self.connect((self.analog_fastnoise_source_x_0, 0), (self.learning_tag_numerotation_0, 0))
        self.connect((self.blocks_add_const_vxx_0, 0), (self.learning_sync_rl_preprocessor_0, 0))
        self.connect((self.blocks_throttle_0, 0), (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_throttle_0, 0), (self.learning_error_estimator_0, 0))
        self.connect((self.blocks_throttle_0, 0), (self.qtgui_time_sink_x_0, 0))
        self.connect((self.learning_sync_rl_preprocessor_0, 0), (self.learning_error_estimator_0, 1))
        self.connect((self.learning_sync_rl_preprocessor_0, 0), (self.qtgui_time_sink_x_0, 1))
        self.connect((self.learning_tag_numerotation_0, 0), (self.blocks_throttle_0, 0))
Beispiel #18
0
    def __init__(self):
        gr.top_block.__init__(self, "Lab 3")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Lab 3")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "lab3")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.freqc = freqc = 900
        self.zeta = zeta = 0.707
        self.std_dev = std_dev = 0.01
        self.sps = sps = 8
        self.samp_rate = samp_rate = 1000
        self.nat_freq = nat_freq = 10000
        self.lw = lw = 2
        self.gain_ = gain_ = 0.5
        self.freqc_ = freqc_ = freqc
        self.fps = fps = 30
        self.fo = fo = 0
        self.const_qpsk = const_qpsk = digital.constellation_calcdist(digital.psk_4()[0], digital.psk_4()[1],
        4, 1).base()
        self.const_bpsk = const_bpsk = digital.constellation_calcdist(digital.psk_2()[0], digital.psk_2()[1],
        2, 1).base()
        self.bw = bw = 1
        self.buff_size = buff_size = 32768
        self.bSignal = bSignal = 0
        self.bSelectPLL = bSelectPLL = 0
        self.axis = axis = 2

        ##################################################
        # Blocks
        ##################################################
        self._zeta_range = Range(0, 4, 0.001, 0.707, 200)
        self._zeta_win = RangeWidget(self._zeta_range, self.set_zeta, 'Damping Factor (Zeta)', "counter_slider", float)
        self.top_grid_layout.addWidget(self._zeta_win, 13, 0, 1, 1)
        for r in range(13, 14):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.tab0 = Qt.QTabWidget()
        self.tab0_widget_0 = Qt.QWidget()
        self.tab0_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab0_widget_0)
        self.tab0_grid_layout_0 = Qt.QGridLayout()
        self.tab0_layout_0.addLayout(self.tab0_grid_layout_0)
        self.tab0.addTab(self.tab0_widget_0, 'Loop Filter Output')
        self.tab0_widget_1 = Qt.QWidget()
        self.tab0_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.tab0_widget_1)
        self.tab0_grid_layout_1 = Qt.QGridLayout()
        self.tab0_layout_1.addLayout(self.tab0_grid_layout_1)
        self.tab0.addTab(self.tab0_widget_1, 'Spectrum')
        self.top_grid_layout.addWidget(self.tab0, 0, 0, 10, 2)
        for r in range(0, 10):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._std_dev_range = Range(0, 0.1, 0.001, 0.01, 200)
        self._std_dev_win = RangeWidget(self._std_dev_range, self.set_std_dev, 'Noise Std. Dev', "counter_slider", float)
        self.top_grid_layout.addWidget(self._std_dev_win, 11, 0, 1, 1)
        for r in range(11, 12):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._nat_freq_range = Range(0, 100e3, 1, 10000, 200)
        self._nat_freq_win = RangeWidget(self._nat_freq_range, self.set_nat_freq, 'Natural Freq (Hz)', "counter_slider", float)
        self.top_grid_layout.addWidget(self._nat_freq_win, 13, 1, 1, 1)
        for r in range(13, 14):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._gain__range = Range(0.1, 1, 0.01, 0.5, 200)
        self._gain__win = RangeWidget(self._gain__range, self.set_gain_, 'Gain (Amp)', "counter_slider", float)
        self.top_grid_layout.addWidget(self._gain__win, 10, 1, 1, 1)
        for r in range(10, 11):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._freqc__range = Range(70, 6000, .01, freqc, 200)
        self._freqc__win = RangeWidget(self._freqc__range, self.set_freqc_, 'Carrier (MHz)', "counter_slider", float)
        self.top_grid_layout.addWidget(self._freqc__win, 10, 0, 1, 1)
        for r in range(10, 11):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._fo_range = Range(0, 100e3, 100, 0, 200)
        self._fo_win = RangeWidget(self._fo_range, self.set_fo, 'Frequency Offset (Hz)', "counter_slider", float)
        self.top_grid_layout.addWidget(self._fo_win, 11, 1, 1, 1)
        for r in range(11, 12):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        # Create the options list
        self._bSignal_options = (0, 1, 2, )
        # Create the labels list
        self._bSignal_labels = ('Tone', 'BPSK', 'QPSK', )
        # Create the combo box
        # Create the radio buttons
        self._bSignal_group_box = Qt.QGroupBox('Signal Select' + ": ")
        self._bSignal_box = Qt.QHBoxLayout()
        class variable_chooser_button_group(Qt.QButtonGroup):
            def __init__(self, parent=None):
                Qt.QButtonGroup.__init__(self, parent)
            @pyqtSlot(int)
            def updateButtonChecked(self, button_id):
                self.button(button_id).setChecked(True)
        self._bSignal_button_group = variable_chooser_button_group()
        self._bSignal_group_box.setLayout(self._bSignal_box)
        for i, _label in enumerate(self._bSignal_labels):
            radio_button = Qt.QRadioButton(_label)
            self._bSignal_box.addWidget(radio_button)
            self._bSignal_button_group.addButton(radio_button, i)
        self._bSignal_callback = lambda i: Qt.QMetaObject.invokeMethod(self._bSignal_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._bSignal_options.index(i)))
        self._bSignal_callback(self.bSignal)
        self._bSignal_button_group.buttonClicked[int].connect(
            lambda i: self.set_bSignal(self._bSignal_options[i]))
        self.top_grid_layout.addWidget(self._bSignal_group_box, 12, 0, 1, 1)
        for r in range(12, 13):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        # Create the options list
        self._bSelectPLL_options = (0, 1, 2, 3, )
        # Create the labels list
        self._bSelectPLL_labels = ('Standard', 'Costas', 'Costas w/ HL', 'QPSK Costas', )
        # Create the combo box
        # Create the radio buttons
        self._bSelectPLL_group_box = Qt.QGroupBox('PLL Order' + ": ")
        self._bSelectPLL_box = Qt.QHBoxLayout()
        class variable_chooser_button_group(Qt.QButtonGroup):
            def __init__(self, parent=None):
                Qt.QButtonGroup.__init__(self, parent)
            @pyqtSlot(int)
            def updateButtonChecked(self, button_id):
                self.button(button_id).setChecked(True)
        self._bSelectPLL_button_group = variable_chooser_button_group()
        self._bSelectPLL_group_box.setLayout(self._bSelectPLL_box)
        for i, _label in enumerate(self._bSelectPLL_labels):
            radio_button = Qt.QRadioButton(_label)
            self._bSelectPLL_box.addWidget(radio_button)
            self._bSelectPLL_button_group.addButton(radio_button, i)
        self._bSelectPLL_callback = lambda i: Qt.QMetaObject.invokeMethod(self._bSelectPLL_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._bSelectPLL_options.index(i)))
        self._bSelectPLL_callback(self.bSelectPLL)
        self._bSelectPLL_button_group.buttonClicked[int].connect(
            lambda i: self.set_bSelectPLL(self._bSelectPLL_options[i]))
        self.top_grid_layout.addWidget(self._bSelectPLL_group_box, 12, 1, 1, 1)
        for r in range(12, 13):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.wes_costas_cc_0 = wes.costas_cc(nat_freq / (samp_rate*1000), zeta, bSelectPLL)
        self.qtgui_time_sink_x_0_0 = qtgui.time_sink_c(
            4096, #size
            samp_rate*1000, #samp_rate
            "", #name
            1 #number of inputs
        )
        self.qtgui_time_sink_x_0_0.set_update_time(0.10)
        self.qtgui_time_sink_x_0_0.set_y_axis(-10000, 10000)

        self.qtgui_time_sink_x_0_0.set_y_label('Frequency (Hz)', "")

        self.qtgui_time_sink_x_0_0.enable_tags(True)
        self.qtgui_time_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
        self.qtgui_time_sink_x_0_0.enable_autoscale(False)
        self.qtgui_time_sink_x_0_0.enable_grid(True)
        self.qtgui_time_sink_x_0_0.enable_axis_labels(True)
        self.qtgui_time_sink_x_0_0.enable_control_panel(True)
        self.qtgui_time_sink_x_0_0.enable_stem_plot(False)


        labels = ['Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
            'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10']
        widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        colors = ['blue', 'red', 'green', 'black', 'cyan',
            'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 1.0, 1.0]
        styles = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        markers = [-1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1]


        for i in range(2):
            if len(labels[i]) == 0:
                if (i % 2 == 0):
                    self.qtgui_time_sink_x_0_0.set_line_label(i, "Re{{Data {0}}}".format(i/2))
                else:
                    self.qtgui_time_sink_x_0_0.set_line_label(i, "Im{{Data {0}}}".format(i/2))
            else:
                self.qtgui_time_sink_x_0_0.set_line_label(i, labels[i])
            self.qtgui_time_sink_x_0_0.set_line_width(i, widths[i])
            self.qtgui_time_sink_x_0_0.set_line_color(i, colors[i])
            self.qtgui_time_sink_x_0_0.set_line_style(i, styles[i])
            self.qtgui_time_sink_x_0_0.set_line_marker(i, markers[i])
            self.qtgui_time_sink_x_0_0.set_line_alpha(i, alphas[i])

        self._qtgui_time_sink_x_0_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0_0.pyqwidget(), Qt.QWidget)
        self.tab0_grid_layout_0.addWidget(self._qtgui_time_sink_x_0_0_win, 5, 0, 5, 1)
        for r in range(5, 10):
            self.tab0_grid_layout_0.setRowStretch(r, 1)
        for c in range(0, 1):
            self.tab0_grid_layout_0.setColumnStretch(c, 1)
        self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
            1024, #size
            firdes.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            samp_rate*1e3, #bw
            "", #name
            1
        )
        self.qtgui_freq_sink_x_0.set_update_time(1/fps)
        self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
        self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
        self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
        self.qtgui_freq_sink_x_0.enable_autoscale(False)
        self.qtgui_freq_sink_x_0.enable_grid(True)
        self.qtgui_freq_sink_x_0.set_fft_average(1.0)
        self.qtgui_freq_sink_x_0.enable_axis_labels(True)
        self.qtgui_freq_sink_x_0.enable_control_panel(False)



        labels = ['In-Phase', 'Quadrature', '', '', '',
            '', '', '', '', '']
        widths = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]
        colors = ["blue", "red", "green", "black", "cyan",
            "magenta", "yellow", "dark red", "dark green", "dark blue"]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
            1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
        self.tab0_grid_layout_1.addWidget(self._qtgui_freq_sink_x_0_win, 5, 0, 5, 1)
        for r in range(5, 10):
            self.tab0_grid_layout_1.setRowStretch(r, 1)
        for c in range(0, 1):
            self.tab0_grid_layout_1.setColumnStretch(c, 1)
        self.qtgui_freq_sink_x_0.set_processor_affinity([0])
        self.interp_fir_filter_xxx_1_0_0 = filter.interp_fir_filter_ccc(sps, (1,1,1,1,1,1,1,1))
        self.interp_fir_filter_xxx_1_0_0.declare_sample_delay(0)
        self.interp_fir_filter_xxx_1_0 = filter.interp_fir_filter_ccc(sps, (1,1,1,1,1,1,1,1))
        self.interp_fir_filter_xxx_1_0.declare_sample_delay(0)
        self.iio_pluto_source_0 = iio.pluto_source(epy_module_0.RX, int(freqc_*1e6), int(samp_rate*1000), 20000000, buff_size, True, True, True, 'manual', 32, '', True)
        self.iio_pluto_sink_0 = iio.pluto_sink(epy_module_0.TX, int(freqc_*1e6), int(samp_rate*1000), 20000000, buff_size, False, 10.0, '', True)
        self.digital_chunks_to_symbols_xx_1_0 = digital.chunks_to_symbols_bc(const_qpsk.points(), 1)
        self.digital_chunks_to_symbols_xx_1 = digital.chunks_to_symbols_bc(const_bpsk.points(), 1)
        self.blocks_tag_gate_0 = blocks.tag_gate(gr.sizeof_gr_complex * 1, False)
        self.blocks_tag_gate_0.set_single_key("")
        self.blocks_selector_0_0 = blocks.selector(gr.sizeof_gr_complex*1,bSignal,0)
        self.blocks_selector_0_0.set_enabled(True)
        self.blocks_null_sink_0 = blocks.null_sink(gr.sizeof_gr_complex*1)
        self.blocks_multiply_xx_0 = blocks.multiply_vcc(1)
        self.blocks_multiply_const_vxx_2 = blocks.multiply_const_cc(1/6.28*samp_rate*1000)
        self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(0)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(gain_ )
        self.blocks_add_xx_0 = blocks.add_vcc(1)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(1)
        self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate*1000, analog.GR_COS_WAVE, fo, 1, 0, 0)
        self.analog_random_source_x_0_0 = blocks.vector_source_b(list(map(int, numpy.random.randint(0, 4, 8192))), True)
        self.analog_random_source_x_0 = blocks.vector_source_b(list(map(int, numpy.random.randint(0, 2, 8192))), True)
        self.analog_noise_source_x_0 = analog.noise_source_c(analog.GR_GAUSSIAN, std_dev, 0)
        self.analog_agc_xx_0 = analog.agc_cc(1e-4, 1.0, 1.0)
        self.analog_agc_xx_0.set_max_gain(65536)



        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_agc_xx_0, 0), (self.qtgui_freq_sink_x_0, 0))
        self.connect((self.analog_agc_xx_0, 0), (self.wes_costas_cc_0, 0))
        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx_0, 1))
        self.connect((self.analog_random_source_x_0, 0), (self.digital_chunks_to_symbols_xx_1, 0))
        self.connect((self.analog_random_source_x_0_0, 0), (self.digital_chunks_to_symbols_xx_1_0, 0))
        self.connect((self.analog_sig_source_x_0, 0), (self.blocks_multiply_xx_0, 1))
        self.connect((self.blocks_add_const_vxx_0, 0), (self.blocks_selector_0_0, 0))
        self.connect((self.blocks_add_xx_0, 0), (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_multiply_xx_0, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0), (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_multiply_const_vxx_2, 0), (self.qtgui_time_sink_x_0_0, 0))
        self.connect((self.blocks_multiply_xx_0, 0), (self.iio_pluto_sink_0, 0))
        self.connect((self.blocks_selector_0_0, 0), (self.blocks_add_xx_0, 0))
        self.connect((self.blocks_tag_gate_0, 0), (self.blocks_multiply_const_vxx_2, 0))
        self.connect((self.digital_chunks_to_symbols_xx_1, 0), (self.interp_fir_filter_xxx_1_0, 0))
        self.connect((self.digital_chunks_to_symbols_xx_1_0, 0), (self.interp_fir_filter_xxx_1_0_0, 0))
        self.connect((self.iio_pluto_source_0, 0), (self.analog_agc_xx_0, 0))
        self.connect((self.interp_fir_filter_xxx_1_0, 0), (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.interp_fir_filter_xxx_1_0, 0), (self.blocks_selector_0_0, 1))
        self.connect((self.interp_fir_filter_xxx_1_0_0, 0), (self.blocks_selector_0_0, 2))
        self.connect((self.wes_costas_cc_0, 0), (self.blocks_null_sink_0, 0))
        self.connect((self.wes_costas_cc_0, 1), (self.blocks_tag_gate_0, 0))
Beispiel #19
0
	def __init__(
		self,
		parent,
		unit='units',
		minval=0,
		maxval=1,
		factor=1,
		decimal_places=3,
		ref_level=0,
		sample_rate=1,
		number_rate=number_window.DEFAULT_NUMBER_RATE,
		average=False,
		avg_alpha=None,
		label='Number Plot',
		size=number_window.DEFAULT_WIN_SIZE,
		peak_hold=False,
		show_gauge=True,
		**kwargs #catchall for backwards compatibility
	):
		#ensure avg alpha
		if avg_alpha is None: avg_alpha = 2.0/number_rate
		#init
		gr.hier_block2.__init__(
			self,
			"number_sink",
			gr.io_signature(1, 1, self._item_size),
			gr.io_signature(0, 0, 0),
		)
		#blocks
		sd = blocks.stream_to_vector_decimator(
			item_size=self._item_size,
			sample_rate=sample_rate,
			vec_rate=number_rate,
			vec_len=1,
		)
		if self._real:
			mult = blocks.multiply_const_ff(factor)
			add = blocks.add_const_ff(ref_level)
			avg = filter.single_pole_iir_filter_ff(1.0)
		else:
			mult = blocks.multiply_const_cc(factor)
			add = blocks.add_const_cc(ref_level)
			avg = filter.single_pole_iir_filter_cc(1.0)
		msgq = gr.msg_queue(2)
		sink = blocks.message_sink(self._item_size, msgq, True)
		#controller
		self.controller = pubsub()
		self.controller.subscribe(SAMPLE_RATE_KEY, sd.set_sample_rate)
		self.controller.publish(SAMPLE_RATE_KEY, sd.sample_rate)
		self.controller[AVERAGE_KEY] = average
		self.controller[AVG_ALPHA_KEY] = avg_alpha
		def update_avg(*args):
			if self.controller[AVERAGE_KEY]: avg.set_taps(self.controller[AVG_ALPHA_KEY])
			else: avg.set_taps(1.0)
		update_avg()
		self.controller.subscribe(AVERAGE_KEY, update_avg)
		self.controller.subscribe(AVG_ALPHA_KEY, update_avg)
		#start input watcher
		common.input_watcher(msgq, self.controller, MSG_KEY)
		#create window
		self.win = number_window.number_window(
			parent=parent,
			controller=self.controller,
			size=size,
			title=label,
			units=unit,
			real=self._real,
			minval=minval,
			maxval=maxval,
			decimal_places=decimal_places,
			show_gauge=show_gauge,
			average_key=AVERAGE_KEY,
			avg_alpha_key=AVG_ALPHA_KEY,
			peak_hold=peak_hold,
			msg_key=MSG_KEY,
			sample_rate_key=SAMPLE_RATE_KEY,
		)
		common.register_access_methods(self, self.controller)
		#backwards compadibility
		self.set_show_gauge = self.win.show_gauges
		#connect
		self.wxgui_connect(self, sd, mult, add, avg, sink)
Beispiel #20
0
    def __init__(self):
        gr.top_block.__init__(self, "Not titled yet")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Not titled yet")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "sim_tx")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(
                    self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.symbol_rate = symbol_rate = 500000
        self.tx_gain = tx_gain = 50
        self.samp_rate = samp_rate = symbol_rate * 2
        self.constel = constel = digital.constellation_calcdist([
            +0.70711 + +0.70711j, +1.0 + +0.0j, -1.0 + +0.0j,
            -0.70711 + -0.70711j, +0.0 + +1.0j, +0.70711 + -0.70711j,
            -0.70711 + +0.70711j, -0.0 + -1.0j
        ], list(range(0, 8)), 8, 1).base()
        self.constel.gen_soft_dec_lut(8)
        self.center_freq = center_freq = 1279e6

        ##################################################
        # Blocks
        ##################################################
        self._tx_gain_range = Range(0, 60, 1, 50, 200)
        self._tx_gain_win = RangeWidget(self._tx_gain_range, self.set_tx_gain,
                                        'TX Gain', "counter_slider", float)
        self.top_grid_layout.addWidget(self._tx_gain_win)
        self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
            1024,  #size
            firdes.WIN_BLACKMAN_hARRIS,  #wintype
            center_freq,  #fc
            samp_rate,  #bw
            "",  #name
            1)
        self.qtgui_freq_sink_x_0.set_update_time(0.10)
        self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
        self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
        self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0,
                                                  "")
        self.qtgui_freq_sink_x_0.enable_autoscale(False)
        self.qtgui_freq_sink_x_0.enable_grid(True)
        self.qtgui_freq_sink_x_0.set_fft_average(0.2)
        self.qtgui_freq_sink_x_0.enable_axis_labels(True)
        self.qtgui_freq_sink_x_0.enable_control_panel(False)

        labels = ['', '', '', '', '', '', '', '', '', '']
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "green", "black", "cyan", "magenta", "yellow",
            "dark red", "dark green", "dark blue"
        ]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_freq_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_freq_sink_x_0_win = sip.wrapinstance(
            self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win)
        self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c(
            1024,  #size
            "EVM Constellation",  #name
            1  #number of inputs
        )
        self.qtgui_const_sink_x_0_0.set_update_time(0.001)
        self.qtgui_const_sink_x_0_0.set_y_axis(-1.5, 1.5)
        self.qtgui_const_sink_x_0_0.set_x_axis(-1.5, 1.5)
        self.qtgui_const_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE,
                                                     qtgui.TRIG_SLOPE_POS, 0.0,
                                                     0, "")
        self.qtgui_const_sink_x_0_0.enable_autoscale(False)
        self.qtgui_const_sink_x_0_0.enable_grid(True)
        self.qtgui_const_sink_x_0_0.enable_axis_labels(True)

        labels = [
            'Reclocked', 'Reference', 'Filtered', 'Raw', '', '', '', '', '', ''
        ]
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "cyan", "yellow", "red", "red", "red", "red", "red",
            "red"
        ]
        styles = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        markers = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_const_sink_x_0_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_const_sink_x_0_0.set_line_label(i, labels[i])
            self.qtgui_const_sink_x_0_0.set_line_width(i, widths[i])
            self.qtgui_const_sink_x_0_0.set_line_color(i, colors[i])
            self.qtgui_const_sink_x_0_0.set_line_style(i, styles[i])
            self.qtgui_const_sink_x_0_0.set_line_marker(i, markers[i])
            self.qtgui_const_sink_x_0_0.set_line_alpha(i, alphas[i])

        self._qtgui_const_sink_x_0_0_win = sip.wrapinstance(
            self.qtgui_const_sink_x_0_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_0_win, 0, 0,
                                       2, 1)
        for r in range(0, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.iio_pluto_sink_0 = iio.pluto_sink('', int(center_freq),
                                               int(samp_rate), 2000000, 32768,
                                               False, 60 - tx_gain, '', True)
        self.digital_symbol_sync_xx_0 = digital.symbol_sync_cc(
            digital.TED_MOD_MUELLER_AND_MULLER, 2, 2 * 3.14159 / 100 * 0.6,
            1.0, 1.0, 1.5, 1, constel, digital.IR_MMSE_8TAP, 128, [])
        self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(2**-12)
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, False)
        self.blocks_file_source_0 = blocks.file_source(
            gr.sizeof_short * 1,
            '/Users/iracigt/Developer/DVB_hat/hdl/iq_bytes.bin',
            True,
            0 * 21690 * 2,
        )
        self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(-3.8 * (1 + 1j))

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.digital_symbol_sync_xx_0, 0))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.iio_pluto_sink_0, 0))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.qtgui_freq_sink_x_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.digital_symbol_sync_xx_0, 0),
                     (self.qtgui_const_sink_x_0_0, 0))
Beispiel #21
0
 def __init__(self):
     channel.__init__(self, snr_db=0)
     self.disconnect(self.add, self)
     self.disconnect(self.noise, (self.add, 1))
     self.add = blocks.add_const_cc(0.0)  # pass through
     self.connect(self, self.add, self)
Beispiel #22
0
    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
        Synchronization for OFDM," IEEE Trans. Communications, vol. 45,
        no. 12, 1997.
        """

        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_float,
                             gr.sizeof_char))  # Output signature

        self.input = blocks.add_const_cc(0)

        # PN Sync

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length / 2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc()
        self.corr = blocks.multiply_cc()

        # Create a moving sum filter for the corr output
        self.moving_sum_filter = filter.fir_filter_ccf(1, [1.0] *
                                                       (fft_length // 2))

        # Create a moving sum filter for the input
        self.inputmag2 = blocks.complex_to_mag_squared()
        self.inputmovingsum = filter.fir_filter_fff(1,
                                                    [1.0] * (fft_length // 2))

        self.square = blocks.multiply_ff()
        self.normalize = blocks.divide_ff()

        # Get magnitude (peaks) and angle (phase/freq error)
        self.c2mag = blocks.complex_to_mag_squared()
        self.angle = blocks.complex_to_arg()

        self.sample_and_hold = blocks.sample_and_hold_ff()

        #ML measurements input to sampler block and detect
        self.sub1 = blocks.add_const_ff(-1)
        self.pk_detect = blocks.peak_detector_fb(0.20, 0.20, 30, 0.001)

        self.connect(self, self.input)

        # Calculate the frequency offset from the correlation of the preamble
        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))

        # Get the power of the input signal to normalize the output of the correlation
        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 = filter.fir_filter_fff(1, matched_filter_taps)
        self.connect(self.normalize, self.matched_filter)

        self.connect(self.matched_filter, self.sub1, self.pk_detect)
        #self.connect(self.matched_filter, 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))

        if logging:
            self.connect(
                self.matched_filter,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat"))
            self.connect(
                self.normalize,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat"))
            self.connect(
                self.angle,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pn-epsilon_f.dat"))
            self.connect(
                self.pk_detect,
                blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
            self.connect(
                self.sample_and_hold,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pn-sample_and_hold_f.dat"))
            self.connect(
                self.input,
                blocks.file_sink(gr.sizeof_gr_complex,
                                 "ofdm_sync_pn-input_c.dat"))
Beispiel #23
0
    def __init__(self):
        gr.top_block.__init__(self, "Not titled yet")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Not titled yet")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "fir_siggen")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(
                    self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.tx_taps_hex = tx_taps_hex = [
            226, -36, -211, 246, 40, -527, 379, 850, -1179, -1172, 2637, 1447,
            -5739, -1633, 19484, 32767, 19484, -1633, -5739, 1447, 2637, -1172,
            -1179, 850, 379, -527, 40, 246, -211, -36, 226
        ]
        self.tx_taps_exp = tx_taps_exp = [
            -0.001129150390625, -0.009796142578125, -0.018341064453125,
            -0.025115966796875, -0.028533935546875, -0.027191162109375,
            -0.020172119140625, -0.00714111328125, 0.01141357421875,
            0.0343017578125, 0.0596923828125, 0.08526611328125,
            0.108551025390625, 0.127197265625, 0.139251708984375,
            0.143402099609375, 0.143402099609375, 0.139251708984375,
            0.127197265625, 0.108551025390625, 0.08526611328125,
            0.0596923828125, 0.0343017578125, 0.01141357421875,
            -0.00714111328125, -0.020172119140625, -0.027191162109375,
            -0.028533935546875, -0.025115966796875, -0.018341064453125,
            -0.009796142578125, -0.001129150390625
        ]
        self.tx_taps = tx_taps = firdes.root_raised_cosine(1, 2, 1, 0.2, 31)
        self.samp_rate = samp_rate = 32000
        self.act_taps = act_taps = [x * 2**-15 for x in tx_taps_hex]

        ##################################################
        # Blocks
        ##################################################
        self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
            1024,  #size
            "",  #name
            1  #number of inputs
        )
        self.qtgui_const_sink_x_0.set_update_time(0.10)
        self.qtgui_const_sink_x_0.set_y_axis(-2, 2)
        self.qtgui_const_sink_x_0.set_x_axis(-2, 2)
        self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE,
                                                   qtgui.TRIG_SLOPE_POS, 0.0,
                                                   0, "")
        self.qtgui_const_sink_x_0.enable_autoscale(False)
        self.qtgui_const_sink_x_0.enable_grid(False)
        self.qtgui_const_sink_x_0.enable_axis_labels(True)

        labels = ['', '', '', '', '', '', '', '', '', '']
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "red", "red", "red", "red", "red", "red", "red",
            "red"
        ]
        styles = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        markers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_const_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_const_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_const_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_const_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_const_sink_x_0.set_line_style(i, styles[i])
            self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])
            self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_const_sink_x_0_win = sip.wrapinstance(
            self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win)
        self.interp_fir_filter_xxx_0_0 = filter.interp_fir_filter_ccc(
            1, tx_taps_hex)
        self.interp_fir_filter_xxx_0_0.declare_sample_delay(0)
        self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_gr_complex * 1,
                                                     [1, 1])
        self.blocks_multiply_const_vxx_2 = blocks.multiply_const_cc(32)
        self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(2**-12)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(2**-8)
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, False)
        self.blocks_interleaved_char_to_complex_0 = blocks.interleaved_char_to_complex(
            False)
        self.blocks_file_source_0 = blocks.file_source(
            gr.sizeof_short * 1,
            '/Users/iracigt/Developer/DVB_hat/hdl/iq_bytes.bin',
            False,
            0 * 21690 * 2,
        )
        self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL)
        self.blocks_file_sink_0_0 = blocks.file_sink(
            gr.sizeof_short * 1,
            '/Users/iracigt/Developer/DVB_hat/hdl/fir_correct_u16.bin', False)
        self.blocks_file_sink_0_0.set_unbuffered(True)
        self.blocks_file_sink_0 = blocks.file_sink(
            gr.sizeof_char * 1,
            '/Users/iracigt/Developer/DVB_hat/hdl/fir_in_u8.bin', False)
        self.blocks_file_sink_0.set_unbuffered(True)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)
        self.blocks_complex_to_interleaved_char_0 = blocks.complex_to_interleaved_char(
            False)
        self.blocks_add_const_vxx_0_0 = blocks.add_const_cc(-4 * (1 + 1j))
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(64 + 64j)
        self.analog_const_source_x_0 = analog.sig_source_c(
            0, analog.GR_CONST_WAVE, 0, 0, 0)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_const_source_x_0, 0),
                     (self.blocks_stream_mux_0, 1))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.blocks_complex_to_interleaved_char_0, 0))
        self.connect((self.blocks_add_const_vxx_0_0, 0),
                     (self.blocks_stream_mux_0, 0))
        self.connect((self.blocks_complex_to_interleaved_char_0, 0),
                     (self.blocks_file_sink_0, 0))
        self.connect((self.blocks_complex_to_interleaved_char_0, 0),
                     (self.blocks_interleaved_char_to_complex_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_file_sink_0_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_interleaved_char_to_complex_0, 0),
                     (self.interp_fir_filter_xxx_0_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.qtgui_const_sink_x_0, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0),
                     (self.blocks_add_const_vxx_0_0, 0))
        self.connect((self.blocks_multiply_const_vxx_2, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_stream_mux_0, 0),
                     (self.blocks_multiply_const_vxx_2, 0))
        self.connect((self.interp_fir_filter_xxx_0_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
Beispiel #24
0
    def __init__(self, fft_length, cp_length, snr, kstime, 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.
        '''

        gr.hier_block2.__init__(self, "ofdm_sync_ml",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature

        self.input = blocks.add_const_cc(0)

        SNR = 10.0**(snr / 10.0)
        rho = SNR / (SNR + 1.0)
        symbol_length = fft_length + cp_length

        # ML Sync

        # Energy Detection from ML Sync

        self.connect(self, self.input)

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length)
        self.connect(self.input, self.delay)

        # magnitude squared blocks
        self.magsqrd1 = blocks.complex_to_mag_squared()
        self.magsqrd2 = blocks.complex_to_mag_squared()
        self.adder = blocks.add_ff()

        moving_sum_taps = [rho / 2 for i in range(cp_length)]
        self.moving_sum_filter = filter.fir_filter_fff(1,moving_sum_taps)

        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
        self.conjg = blocks.conjugate_cc();
        self.mixer = blocks.multiply_cc();

        movingsum2_taps = [1.0 for i in range(cp_length)]
        self.movingsum2 = filter.fir_filter_ccf(1,movingsum2_taps)

        # Correlator data handler
        self.c2mag = blocks.complex_to_mag()
        self.angle = blocks.complex_to_arg()
        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 = blocks.sub_ff()
        self.connect(self.c2mag,(self.diff,0))
        self.connect(self.moving_sum_filter,(self.diff,1))

        #ML measurements input to sampler block and detect
        self.f2c = blocks.float_to_complex()
        self.pk_detect = blocks.peak_detector_fb(0.2, 0.25, 30, 0.0005)
        self.sample_and_hold = blocks.sample_and_hold_ff()

        # use the sync loop values to set the sampler and the NCO
        #     self.diff = theta
        #     self.angle = epsilon

        self.connect(self.diff, self.pk_detect)

        # The DPLL corrects for timing differences between CP correlations
        use_dpll = 0
        if use_dpll:
            self.dpll = gr.dpll_bb(float(symbol_length),0.01)
            self.connect(self.pk_detect, self.dpll)
            self.connect(self.dpll, (self.sample_and_hold,1))
        else:
            self.connect(self.pk_detect, (self.sample_and_hold,1))

        self.connect(self.angle, (self.sample_and_hold,0))

        ################################
        # correlate against known symbol
        # This gives us the same timing signal as the PN sync block only on the preamble
        # we don't use the signal generated from the CP correlation because we don't want
        # to readjust the timing in the middle of the packet or we ruin the equalizer settings.
        kstime = [k.conjugate() for k in kstime]
        kstime.reverse()
        self.kscorr = filter.fir_filter_ccc(1, kstime)
        self.corrmag = blocks.complex_to_mag_squared()
        self.div = blocks.divide_ff()

        # The output signature of the correlation has a few spikes because the rest of the
        # system uses the repeated preamble symbol. It needs to work that generically if
        # anyone wants to use this against a WiMAX-like signal since it, too, repeats.
        # The output theta of the correlator above is multiplied with this correlation to
        # identify the proper peak and remove other products in this cross-correlation
        self.threshold_factor = 0.1
        self.slice = blocks.threshold_ff(self.threshold_factor, self.threshold_factor, 0)
        self.f2b = blocks.float_to_char()
        self.b2f = blocks.char_to_float()
        self.mul = blocks.multiply_ff()

        # Normalize the power of the corr output by the energy. This is not really needed
        # and could be removed for performance, but it makes for a cleaner signal.
        # if this is removed, the threshold value needs adjustment.
        self.connect(self.input, self.kscorr, self.corrmag, (self.div,0))
        self.connect(self.moving_sum_filter, (self.div,1))

        self.connect(self.div, (self.mul,0))
        self.connect(self.pk_detect, self.b2f, (self.mul,1))
        self.connect(self.mul, self.slice)

        # Set output signals
        #    Output 0: fine frequency correction value
        #    Output 1: timing signal
        self.connect(self.sample_and_hold, (self,0))
        self.connect(self.slice, self.f2b, (self,1))


        if logging:
            self.connect(self.moving_sum_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-energy_f.dat"))
            self.connect(self.diff, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat"))
            self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat"))
            self.connect(self.corrmag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-corrmag_f.dat"))
            self.connect(self.kscorr, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-kscorr_c.dat"))
            self.connect(self.div, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-div_f.dat"))
            self.connect(self.mul, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-mul_f.dat"))
            self.connect(self.slice, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-slice_f.dat"))
            self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat"))
            if use_dpll:
                self.connect(self.dpll, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat"))

            self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat"))
            self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat"))
Beispiel #25
0
    def __init__(self, fft_length, cp_length, snr, kstime, 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.
        '''

        gr.hier_block2.__init__(
            self,
            "ofdm_sync_ml",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature2(2, 2, gr.sizeof_float,
                             gr.sizeof_char))  # Output signature

        self.input = blocks.add_const_cc(0)

        SNR = 10.0**(snr / 10.0)
        rho = SNR / (SNR + 1.0)
        symbol_length = fft_length + cp_length

        # ML Sync

        # Energy Detection from ML Sync

        self.connect(self, self.input)

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length)
        self.connect(self.input, self.delay)

        # magnitude squared blocks
        self.magsqrd1 = blocks.complex_to_mag_squared()
        self.magsqrd2 = blocks.complex_to_mag_squared()
        self.adder = blocks.add_ff()

        moving_sum_taps = [rho / 2 for i in range(cp_length)]
        self.moving_sum_filter = filter.fir_filter_fff(1, moving_sum_taps)

        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
        self.conjg = blocks.conjugate_cc()
        self.mixer = blocks.multiply_cc()

        movingsum2_taps = [1.0 for i in range(cp_length)]
        self.movingsum2 = filter.fir_filter_ccf(1, movingsum2_taps)

        # Correlator data handler
        self.c2mag = blocks.complex_to_mag()
        self.angle = blocks.complex_to_arg()
        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 = blocks.sub_ff()
        self.connect(self.c2mag, (self.diff, 0))
        self.connect(self.moving_sum_filter, (self.diff, 1))

        #ML measurements input to sampler block and detect
        self.f2c = blocks.float_to_complex()
        self.pk_detect = blocks.peak_detector_fb(0.2, 0.25, 30, 0.0005)
        self.sample_and_hold = blocks.sample_and_hold_ff()

        # use the sync loop values to set the sampler and the NCO
        #     self.diff = theta
        #     self.angle = epsilon

        self.connect(self.diff, self.pk_detect)

        # The DPLL corrects for timing differences between CP correlations
        use_dpll = 0
        if use_dpll:
            self.dpll = gr.dpll_bb(float(symbol_length), 0.01)
            self.connect(self.pk_detect, self.dpll)
            self.connect(self.dpll, (self.sample_and_hold, 1))
        else:
            self.connect(self.pk_detect, (self.sample_and_hold, 1))

        self.connect(self.angle, (self.sample_and_hold, 0))

        ################################
        # correlate against known symbol
        # This gives us the same timing signal as the PN sync block only on the preamble
        # we don't use the signal generated from the CP correlation because we don't want
        # to readjust the timing in the middle of the packet or we ruin the equalizer settings.
        kstime = [k.conjugate() for k in kstime]
        kstime.reverse()
        self.kscorr = filter.fir_filter_ccc(1, kstime)
        self.corrmag = blocks.complex_to_mag_squared()
        self.div = blocks.divide_ff()

        # The output signature of the correlation has a few spikes because the rest of the
        # system uses the repeated preamble symbol. It needs to work that generically if
        # anyone wants to use this against a WiMAX-like signal since it, too, repeats.
        # The output theta of the correlator above is multiplied with this correlation to
        # identify the proper peak and remove other products in this cross-correlation
        self.threshold_factor = 0.1
        self.slice = blocks.threshold_ff(self.threshold_factor,
                                         self.threshold_factor, 0)
        self.f2b = blocks.float_to_char()
        self.b2f = blocks.char_to_float()
        self.mul = blocks.multiply_ff()

        # Normalize the power of the corr output by the energy. This is not really needed
        # and could be removed for performance, but it makes for a cleaner signal.
        # if this is removed, the threshold value needs adjustment.
        self.connect(self.input, self.kscorr, self.corrmag, (self.div, 0))
        self.connect(self.moving_sum_filter, (self.div, 1))

        self.connect(self.div, (self.mul, 0))
        self.connect(self.pk_detect, self.b2f, (self.mul, 1))
        self.connect(self.mul, self.slice)

        # Set output signals
        #    Output 0: fine frequency correction value
        #    Output 1: timing signal
        self.connect(self.sample_and_hold, (self, 0))
        self.connect(self.slice, self.f2b, (self, 1))

        if logging:
            self.connect(
                self.moving_sum_filter,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-energy_f.dat"))
            self.connect(
                self.diff,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat"))
            self.connect(
                self.angle,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_ml-epsilon_f.dat"))
            self.connect(
                self.corrmag,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_ml-corrmag_f.dat"))
            self.connect(
                self.kscorr,
                blocks.file_sink(gr.sizeof_gr_complex,
                                 "ofdm_sync_ml-kscorr_c.dat"))
            self.connect(
                self.div,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-div_f.dat"))
            self.connect(
                self.mul,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-mul_f.dat"))
            self.connect(
                self.slice,
                blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-slice_f.dat"))
            self.connect(
                self.pk_detect,
                blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat"))
            if use_dpll:
                self.connect(
                    self.dpll,
                    blocks.file_sink(gr.sizeof_char,
                                     "ofdm_sync_ml-dpll_b.dat"))

            self.connect(
                self.sample_and_hold,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_ml-sample_and_hold_f.dat"))
            self.connect(
                self.input,
                blocks.file_sink(gr.sizeof_gr_complex,
                                 "ofdm_sync_ml-input_c.dat"))
Beispiel #26
0
    def __init__(self):
        gr.top_block.__init__(self, "Testbench")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Testbench")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

        self.settings = Qt.QSettings("GNU Radio", "testbench")

        try:
            if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
                self.restoreGeometry(
                    self.settings.value("geometry").toByteArray())
            else:
                self.restoreGeometry(self.settings.value("geometry"))
        except:
            pass

        ##################################################
        # Variables
        ##################################################
        self.decim = decim = 1
        self.audio_samp_rate = audio_samp_rate = 40e3
        self.symbol_rate = symbol_rate = 20e3
        self.samp_rate = samp_rate = audio_samp_rate / decim
        self.sps = sps = float(samp_rate) / symbol_rate
        self.rolloff = rolloff = 0.2
        self.ntaps = ntaps = 31
        self.tx_taps_hex = tx_taps_hex = [
            119, -19, -111, 129, 21, -277, 199, 446, -619, -616, 1385, 760,
            -3014, -857, 10233, 17209, 10233, -857, -3014, 760, 1385, -616,
            -619, 446, 199, -277, 21, 129, -111, -19, 119
        ]
        self.sym_per_arm = sym_per_arm = 8
        self.nfilts = nfilts = 16
        self.ideal_taps = ideal_taps = firdes.root_raised_cosine(
            int(sps), samp_rate, symbol_rate, rolloff, ntaps)
        self.thresh = thresh = 70
        self.rrc_taps = rrc_taps = firdes.root_raised_cosine(
            nfilts, nfilts, 1.0 / float(sps), rolloff,
            int(sym_per_arm * sps * nfilts))
        self.quant_taps = quant_taps = [
            round(2**15 * x) / 2**15 for x in ideal_taps
        ]
        self.constel = constel = digital.constellation_calcdist([
            +0.70711 + +0.70711j, +1.0 + +0.0j, -1.0 + +0.0j,
            -0.70711 + -0.70711j, +0.0 + +1.0j, +0.70711 + -0.70711j,
            -0.70711 + +0.70711j, -0.0 + -1.0j
        ], list(range(0, 8)), 8, 1).base()
        self.constel.gen_soft_dec_lut(8)
        self.act_taps = act_taps = [x * 2**-15 for x in tx_taps_hex]

        ##################################################
        # Blocks
        ##################################################
        self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
            1024,  #size
            samp_rate,  #samp_rate
            "",  #name
            1  #number of inputs
        )
        self.qtgui_time_sink_x_0.set_update_time(0.10)
        self.qtgui_time_sink_x_0.set_y_axis(0, 50)

        self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")

        self.qtgui_time_sink_x_0.enable_tags(True)
        self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_AUTO,
                                                  qtgui.TRIG_SLOPE_POS, thresh,
                                                  512 / samp_rate, 0,
                                                  "phase_est")
        self.qtgui_time_sink_x_0.enable_autoscale(False)
        self.qtgui_time_sink_x_0.enable_grid(False)
        self.qtgui_time_sink_x_0.enable_axis_labels(True)
        self.qtgui_time_sink_x_0.enable_control_panel(True)
        self.qtgui_time_sink_x_0.enable_stem_plot(False)

        labels = [
            'Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
            'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10'
        ]
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow',
            'dark red', 'dark green', 'dark blue'
        ]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
        styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_time_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
            self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
            self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_time_sink_x_0_win = sip.wrapinstance(
            self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win, 0, 1, 2,
                                       1)
        for r in range(0, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
            1024,  #size
            firdes.WIN_BLACKMAN_hARRIS,  #wintype
            0,  #fc
            samp_rate,  #bw
            "",  #name
            1)
        self.qtgui_freq_sink_x_0.set_update_time(0.10)
        self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
        self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
        self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0,
                                                  "")
        self.qtgui_freq_sink_x_0.enable_autoscale(False)
        self.qtgui_freq_sink_x_0.enable_grid(False)
        self.qtgui_freq_sink_x_0.set_fft_average(0.1)
        self.qtgui_freq_sink_x_0.enable_axis_labels(True)
        self.qtgui_freq_sink_x_0.enable_control_panel(True)

        labels = ['', '', '', '', '', '', '', '', '', '']
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "green", "black", "cyan", "magenta", "yellow",
            "dark red", "dark green", "dark blue"
        ]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_freq_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
            self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
            self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_freq_sink_x_0_win = sip.wrapinstance(
            self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 3, 0, 1,
                                       2)
        for r in range(3, 4):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c(
            1024,  #size
            "EVM Constellation",  #name
            1  #number of inputs
        )
        self.qtgui_const_sink_x_0_0.set_update_time(0.001)
        self.qtgui_const_sink_x_0_0.set_y_axis(-1.5, 1.5)
        self.qtgui_const_sink_x_0_0.set_x_axis(-1.5, 1.5)
        self.qtgui_const_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE,
                                                     qtgui.TRIG_SLOPE_POS, 0.0,
                                                     0, "")
        self.qtgui_const_sink_x_0_0.enable_autoscale(False)
        self.qtgui_const_sink_x_0_0.enable_grid(True)
        self.qtgui_const_sink_x_0_0.enable_axis_labels(True)

        labels = [
            'Reclocked', 'Reference', 'Filtered', 'Raw', '', '', '', '', '', ''
        ]
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "cyan", "yellow", "red", "red", "red", "red", "red",
            "red"
        ]
        styles = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        markers = [2, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

        for i in range(1):
            if len(labels[i]) == 0:
                self.qtgui_const_sink_x_0_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_const_sink_x_0_0.set_line_label(i, labels[i])
            self.qtgui_const_sink_x_0_0.set_line_width(i, widths[i])
            self.qtgui_const_sink_x_0_0.set_line_color(i, colors[i])
            self.qtgui_const_sink_x_0_0.set_line_style(i, styles[i])
            self.qtgui_const_sink_x_0_0.set_line_marker(i, markers[i])
            self.qtgui_const_sink_x_0_0.set_line_alpha(i, alphas[i])

        self._qtgui_const_sink_x_0_0_win = sip.wrapinstance(
            self.qtgui_const_sink_x_0_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_0_win, 0, 0,
                                       2, 1)
        for r in range(0, 2):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.kc2qol_ldpc_decoder_fb_0 = kc2qol.ldpc_decoder_fb()
        self.kc2qol_dvbs2_pl_deframer_0 = kc2qol.dvbs2_pl_deframer(
            21600, pmt.intern('corr_est'), 0)
        self.kc2qol_dvbs2_8psk_demod_0 = kc2qol.dvbs2_8psk_demod(None)
        self.digital_symbol_sync_xx_0 = digital.symbol_sync_cc(
            digital.TED_MOD_MUELLER_AND_MULLER, sps, 2 * numpy.pi / 100 * 0.6,
            1.0, 1.0, 1.5, 1, constel, digital.IR_MMSE_8TAP, 128, [])
        self.digital_corr_est_cc_0 = digital.corr_est_cc([
            0.707 + 0.707j, 0.707 - 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            0.707 + 0.707j, 0.707 - 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, -0.707 + 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, 0.707 + 0.707j, 0.707 - 0.707j,
            0.707 + 0.707j, -0.707 + 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, 0.707 - 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, 0.707 - 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, 0.707 - 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, 0.707 - 0.707j, -0.707 - 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, -0.707 - 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            0.707 + 0.707j, 0.707 - 0.707j, 0.707 + 0.707j, -0.707 + 0.707j,
            -0.707 - 0.707j, 0.707 - 0.707j, 0.707 + 0.707j, 0.707 - 0.707j,
            -0.707 - 0.707j, -0.707 + 0.707j
        ], 1, 1, thresh / 90, digital.THRESHOLD_ABSOLUTE)
        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex * 1,
                                                 samp_rate, True)
        self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(
            1, 8, "", False, gr.GR_MSB_FIRST)
        self.blocks_null_sink_0 = blocks.null_sink(gr.sizeof_gr_complex * 1)
        self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(2**-12)
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, False)
        self.blocks_file_source_0 = blocks.file_source(
            gr.sizeof_short * 1,
            '/Users/iracigt/Developer/DVB_hat/hdl/iq_bytes.bin',
            True,
            0 * 21690 * 2,
        )
        self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL)
        self.blocks_file_sink_3 = blocks.file_sink(
            gr.sizeof_char * 1, '/Users/iracigt/Desktop/packets_ldpc.bin',
            False)
        self.blocks_file_sink_3.set_unbuffered(True)
        self.blocks_complex_to_mag_0 = blocks.complex_to_mag(1)
        self.blocks_add_const_vxx_0 = blocks.add_const_cc(-3.8 * (1 + 1j))

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.blocks_throttle_0, 0))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.qtgui_freq_sink_x_0, 0))
        self.connect((self.blocks_complex_to_mag_0, 0),
                     (self.qtgui_time_sink_x_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_repack_bits_bb_0, 0),
                     (self.blocks_file_sink_3, 0))
        self.connect((self.blocks_throttle_0, 0),
                     (self.digital_symbol_sync_xx_0, 0))
        self.connect((self.digital_corr_est_cc_0, 1),
                     (self.blocks_complex_to_mag_0, 0))
        self.connect((self.digital_corr_est_cc_0, 0),
                     (self.blocks_null_sink_0, 0))
        self.connect((self.digital_corr_est_cc_0, 0),
                     (self.kc2qol_dvbs2_pl_deframer_0, 0))
        self.connect((self.digital_symbol_sync_xx_0, 0),
                     (self.digital_corr_est_cc_0, 0))
        self.connect((self.digital_symbol_sync_xx_0, 0),
                     (self.qtgui_const_sink_x_0_0, 0))
        self.connect((self.kc2qol_dvbs2_8psk_demod_0, 0),
                     (self.kc2qol_ldpc_decoder_fb_0, 0))
        self.connect((self.kc2qol_dvbs2_pl_deframer_0, 0),
                     (self.kc2qol_dvbs2_8psk_demod_0, 0))
        self.connect((self.kc2qol_ldpc_decoder_fb_0, 0),
                     (self.blocks_repack_bits_bb_0, 0))
    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

        self.input = blocks.add_const_cc(0)

        symbol_length = fft_length + cp_length

        # PN Sync with cross-correlation input

        # cross-correlate with the known symbol
        kstime = [k.conjugate() for k in kstime[0:fft_length // 2]]
        kstime.reverse()
        self.crosscorr_filter = filter.fir_filter_ccc(1, kstime)

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length / 2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc()
        self.corr = blocks.multiply_cc()

        # Create a moving sum filter for the input
        self.mag = blocks.complex_to_mag_squared()
        movingsum_taps = (fft_length // 1) * [
            1.0,
        ]
        self.power = filter.fir_filter_fff(1, movingsum_taps)

        # Get magnitude (peaks) and angle (phase/freq error)
        self.c2mag = blocks.complex_to_mag_squared()
        self.angle = blocks.complex_to_arg()
        self.compare = blocks.sub_ff()

        self.sample_and_hold = blocks.sample_and_hold_ff()

        #ML measurements input to sampler block and detect
        self.threshold = blocks.threshold_ff(
            0, 0, 0)  # threshold detection might need to be tweaked
        self.peaks = blocksx.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 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.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)

        # 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))

        # Set output signals
        #    Output 0: fine frequency correction value
        #    Output 1: timing signal
        self.connect(self.sample_and_hold, (self, 0))
        self.connect(self.peaks, (self, 1))

        if logging:
            self.connect(
                self.compare,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-compare_f.dat"))
            self.connect(
                self.c2mag,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-theta_f.dat"))
            self.connect(
                self.power,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-inputpower_f.dat"))
            self.connect(
                self.angle,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-epsilon_f.dat"))
            self.connect(
                self.threshold,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-threshold_f.dat"))
            self.connect(
                self.peaks,
                blocks.file_sink(gr.sizeof_char, "ofdm_sync_pnac-peaks_b.dat"))
            self.connect(
                self.sample_and_hold,
                blocks.file_sink(gr.sizeof_float,
                                 "ofdm_sync_pnac-sample_and_hold_f.dat"))
            self.connect(
                self.input,
                blocks.file_sink(gr.sizeof_gr_complex,
                                 "ofdm_sync_pnac-input_c.dat"))