Example #1
0
 def test_diff_phasor_cc(self):
     src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j)
     expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j)
     src = blocks.vector_source_c(src_data)
     op = digital.diff_phasor_cc()
     dst = blocks.vector_sink_c()
     self.tb.connect(src, op)
     self.tb.connect(op, dst)
     self.tb.run()               # run the graph and wait for it to finish
     actual_result = dst.data()  # fetch the contents of the sink
     self.assertComplexTuplesAlmostEqual(expected_result, actual_result)
    def __init__(self, costas_alpha=0.04, gain_mu=0.025, input_rate=48000, output_rate=4800):
        gr.hier_block2.__init__(
            self, "CQPSK Demodulator",
            gr.io_signature(1, 1, gr.sizeof_gr_complex*1),
            gr.io_signature(1, 1, gr.sizeof_float*1),
        )

        ##################################################
        # Parameters
        ##################################################
        self.costas_alpha = costas_alpha
        self.gain_mu = gain_mu
        self.input_rate = input_rate
        self.output_rate = output_rate

        ##################################################
        # Variables
        ##################################################
        self.alpha = alpha = costas_alpha
        self.omega = omega = float(input_rate) / float(output_rate)
        self.gain_omega = gain_omega = 0.1 * gain_mu * gain_mu
        self.fmax = fmax = 2 * math.pi * 2400 / float(input_rate)
        self.beta = beta = 0.125 * alpha * alpha

        ##################################################
        # Blocks
        ##################################################
        self.to_float = blocks.complex_to_arg(1)
        self.rescale = blocks.multiply_const_vff((1 / (math.pi / 4), ))
        self.diffdec = digital.diff_phasor_cc()
        self.clock = op25_repeater.gardner_costas_cc(omega, gain_mu, gain_omega, alpha, beta, fmax, -fmax)
        self.agc = analog.feedforward_agc_cc(16, 1.0)



        ##################################################
        # Connections
        ##################################################
        self.connect((self.agc, 0), (self.clock, 0))
        self.connect((self.clock, 0), (self.diffdec, 0))
        self.connect((self.diffdec, 0), (self.to_float, 0))
        self.connect((self, 0), (self.agc, 0))
        self.connect((self.rescale, 0), (self, 0))
        self.connect((self.to_float, 0), (self.rescale, 0))
    def __init__(self,
                 input_rate=None,
                 demod_type='cqpsk',
                 relative_freq=0,
                 offset=0,
                 if_rate=_def_if_rate,
                 gain_mu=_def_gain_mu,
                 costas_alpha=_def_costas_alpha,
                 symbol_rate=_def_symbol_rate):
        """
	Hierarchical block for P25 demodulation.

	The complex input is tuned, decimated and demodulated
        @param input_rate: sample rate of complex input channel
        @type input_rate: int
	"""

        gr.hier_block2.__init__(
            self,
            "p25_demod_cb",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_char))  # Output signature
        #				gr.io_signature(0, 0, 0)) # Output signature
        p25_demod_base.__init__(self, if_rate=if_rate, symbol_rate=symbol_rate)

        self.input_rate = input_rate
        self.if_rate = if_rate
        self.symbol_rate = symbol_rate
        self.connect_state = None
        self.offset = 0
        self.sps = 0.0
        self.lo_freq = 0
        self.float_sink = None
        self.complex_sink = None

        # local osc
        self.lo = analog.sig_source_c(input_rate, analog.GR_SIN_WAVE, 0, 1.0,
                                      0)
        self.mixer = blocks.multiply_cc()
        lpf_coeffs = filter.firdes.low_pass(1.0, input_rate, 7250, 725,
                                            filter.firdes.WIN_HANN)
        decimation = int(input_rate / if_rate)
        self.lpf = filter.fir_filter_ccf(decimation, lpf_coeffs)

        resampled_rate = float(input_rate) / float(
            decimation)  # rate at output of self.lpf

        self.arb_resampler = filter.pfb.arb_resampler_ccf(
            float(self.if_rate) / resampled_rate)

        self.connect(self, (self.mixer, 0))
        self.connect(self.lo, (self.mixer, 1))
        self.connect(self.mixer, self.lpf, self.arb_resampler)

        levels = [-2.0, 0.0, 2.0, 4.0]
        self.slicer = op25_repeater.fsk4_slicer_fb(levels)

        omega = float(self.if_rate) / float(self.symbol_rate)
        gain_omega = 0.1 * gain_mu * gain_mu

        alpha = costas_alpha
        beta = 0.125 * alpha * alpha
        fmax = 2400  # Hz
        fmax = 2 * pi * fmax / float(self.if_rate)

        self.clock = op25_repeater.gardner_costas_cc(omega, gain_mu,
                                                     gain_omega, alpha, beta,
                                                     fmax, -fmax)

        self.agc = analog.feedforward_agc_cc(16, 1.0)

        # Perform Differential decoding on the constellation
        self.diffdec = digital.diff_phasor_cc()

        # take angle of the difference (in radians)
        self.to_float = blocks.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        self.rescale = blocks.multiply_const_ff((1 / (pi / 4)))

        # fm demodulator (needed in fsk4 case)
        fm_demod_gain = if_rate / (2.0 * pi * _def_symbol_deviation)
        self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

        self.connect_chain(demod_type)
        self.connect(self.slicer, self)

        self.set_relative_frequency(relative_freq)
Example #4
0
    def __init__(self,
                 input_rate	= None,
                 demod_type	= 'cqpsk',
                 filter_type	= None,
                 excess_bw      = _def_excess_bw,
                 relative_freq	= 0,
                 offset		= 0,
                 if_rate	= _def_if_rate,
                 gain_mu	= _def_gain_mu,
                 costas_alpha	= _def_costas_alpha,
                 symbol_rate	= _def_symbol_rate):
        """
	Hierarchical block for P25 demodulation.

	The complex input is tuned, decimated and demodulated
        @param input_rate: sample rate of complex input channel
        @type input_rate: int
	"""

	gr.hier_block2.__init__(self, "p25_demod_cb",
				gr.io_signature(1, 1, gr.sizeof_gr_complex),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_char)) # Output signature
#				gr.io_signature(0, 0, 0)) # Output signature
        p25_demod_base.__init__(self, if_rate=if_rate, symbol_rate=symbol_rate, filter_type=filter_type)

        self.input_rate = input_rate
        self.if_rate = if_rate
        self.symbol_rate = symbol_rate
        self.connect_state = None
        self.aux_fm_connected = False
        self.offset = 0
        self.sps = 0.0
        self.lo_freq = 0
        self.float_sink = None
        self.complex_sink = None
        self.if1 = 0
        self.if2 = 0
        self.t_cache = {}
        if filter_type == 'rrc':
            self.set_baseband_gain(0.61)

        # local osc
        self.lo = analog.sig_source_c (input_rate, analog.GR_SIN_WAVE, 0, 1.0, 0)
        self.mixer = blocks.multiply_cc()
        decimator_values = get_decim(input_rate)
        if decimator_values:
            self.decim, self.decim2 = decimator_values
            self.if1 = input_rate / self.decim
            self.if2 = self.if1 / self.decim2
            sys.stderr.write( 'Using two-stage decimator for speed=%d, decim=%d/%d if1=%d if2=%d\n' % (input_rate, self.decim, self.decim2, self.if1, self.if2))
            bpf_coeffs = filter.firdes.complex_band_pass(1.0, input_rate, -self.if1/2, self.if1/2, self.if1/2, filter.firdes.WIN_HAMMING)
            self.t_cache[0] = bpf_coeffs
            fa = 6250
            fb = self.if2 / 2
            lpf_coeffs = filter.firdes.low_pass(1.0, self.if1, (fb+fa)/2, fb-fa, filter.firdes.WIN_HAMMING)
            self.bpf = filter.fir_filter_ccc(self.decim,  bpf_coeffs)
            self.lpf = filter.fir_filter_ccf(self.decim2, lpf_coeffs)
            resampled_rate = self.if2
            self.bfo = analog.sig_source_c (self.if1, analog.GR_SIN_WAVE, 0, 1.0, 0)
            self.connect(self, self.bpf, (self.mixer, 0))
            self.connect(self.bfo, (self.mixer, 1))
        else:
            sys.stderr.write( 'Unable to use two-stage decimator for speed=%d\n' % (input_rate))
            # local osc
            self.lo = analog.sig_source_c (input_rate, analog.GR_SIN_WAVE, 0, 1.0, 0)
            lpf_coeffs = filter.firdes.low_pass(1.0, input_rate, 7250, 1450, filter.firdes.WIN_HANN)
            decimation = int(input_rate / if_rate)
            self.lpf = filter.fir_filter_ccf(decimation, lpf_coeffs)
            resampled_rate = float(input_rate) / float(decimation) # rate at output of self.lpf
            self.connect(self, (self.mixer, 0))
            self.connect(self.lo, (self.mixer, 1))
        self.connect(self.mixer, self.lpf)

        if self.if_rate != resampled_rate:
            self.if_out = filter.pfb.arb_resampler_ccf(float(self.if_rate) / resampled_rate)
            self.connect(self.lpf, self.if_out)
        else:
            self.if_out = self.lpf

        fa = 6250
        fb = fa + 625
        cutoff_coeffs = filter.firdes.low_pass(1.0, self.if_rate, (fb+fa)/2, fb-fa, filter.firdes.WIN_HANN)
        self.cutoff = filter.fir_filter_ccf(1, cutoff_coeffs)

        omega = float(self.if_rate) / float(self.symbol_rate)
        gain_omega = 0.1  * gain_mu * gain_mu

        alpha = costas_alpha
        beta = 0.125 * alpha * alpha
        fmax = 2400	# Hz
        fmax = 2*pi * fmax / float(self.if_rate)

        self.clock = op25_repeater.gardner_costas_cc(omega, gain_mu, gain_omega, alpha,  beta, fmax, -fmax)

        self.agc = analog.feedforward_agc_cc(16, 1.0)

        # Perform Differential decoding on the constellation
        self.diffdec = digital.diff_phasor_cc()

        # take angle of the difference (in radians)
        self.to_float = blocks.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        self.rescale = blocks.multiply_const_ff( (1 / (pi / 4)) )

        # fm demodulator (needed in fsk4 case)
        fm_demod_gain = if_rate / (2.0 * pi * _def_symbol_deviation)
        self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

        self.connect_chain(demod_type)
        self.connect(self.slicer, self)

        self.set_relative_frequency(relative_freq)
Example #5
0
    def __init__(self, 
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 costas_alpha=_def_costas_alpha,
                 gain_mu=_def_gain_mu,
                 mu=_def_mu,
                 omega_relative_limit=_def_omega_relative_limit,
                 gray_code=_def_gray_code,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered CQPSK demodulation

	The input is the complex modulated signal at baseband.
	The output is a stream of floats in [ -3 / -1 / +1 / +3 ]

	@param samples_per_symbol: samples per symbol >= 2
	@type samples_per_symbol: float
	@param excess_bw: Root-raised cosine filter excess bandwidth
	@type excess_bw: float
        @param costas_alpha: loop filter gain
        @type costas_alphas: float
        @param gain_mu: for M&M block
        @type gain_mu: float
        @param mu: for M&M block
        @type mu: float
        @param omega_relative_limit: for M&M block
        @type omega_relative_limit: float
        @param gray_code: Tell modulator to Gray code the bits
        @type gray_code: bool
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modualtion data to files?
        @type debug: bool
	"""

	gr.hier_block2.__init__(self, "cqpsk_demod",
			        gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
			        gr.io_signature(1, 1, gr.sizeof_float))       # Output signature

        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._costas_alpha = costas_alpha
        self._mm_gain_mu = gain_mu
        self._mm_mu = mu
        self._mm_omega_relative_limit = omega_relative_limit
        self._gray_code = gray_code

        if samples_per_symbol < 2:
            raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol

        arity = pow(2,self.bits_per_symbol())
 
        # Automatic gain control
        scale = (1.0/16384.0)
        self.pre_scaler = blocks.multiply_const_cc(scale)   # scale the signal from full-range to +-1
        #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
        self.agc = analog.feedforward_agc_cc(16, 2.0)
       
        # RRC data filter
        ntaps = 11 * samples_per_symbol
        self.rrc_taps = firdes.root_raised_cosine(
            1.0,                      # gain
            self._samples_per_symbol, # sampling rate
            1.0,                      # symbol rate
            self._excess_bw,          # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter=filter.interp_fir_filter_ccf(1, self.rrc_taps)        

        if not self._mm_gain_mu:
            sbs_to_mm = {2: 0.050, 3: 0.075, 4: 0.11, 5: 0.125, 6: 0.15, 7: 0.15}
            self._mm_gain_mu = sbs_to_mm[samples_per_symbol]

        self._mm_omega = self._samples_per_symbol
        self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu
        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
        fmin = -0.025
        fmax = 0.025
        
	if not _def_has_gr_digital:
            self.receiver=gr.mpsk_receiver_cc(arity, pi/4.0,
                                          self._costas_alpha, self._costas_beta,
                                          fmin, fmax,
                                          self._mm_mu, self._mm_gain_mu,
                                          self._mm_omega, self._mm_gain_omega,
                                          self._mm_omega_relative_limit)
	else:
            self.receiver=digital.mpsk_receiver_cc(arity, pi/4.0,
                                          2*pi/150,
                                          fmin, fmax,
                                          self._mm_mu, self._mm_gain_mu,
                                          self._mm_omega, self._mm_gain_omega,
                                          self._mm_omega_relative_limit)

	    #self.receiver.set_alpha(self._costas_alpha)
	    #self.receiver.set_beta(self._costas_beta)

        # Perform Differential decoding on the constellation
        self.diffdec = digital.diff_phasor_cc()

        # take angle of the difference (in radians)
        self.to_float = blocks.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        self.rescale = blocks.multiply_const_ff( 1 / (pi / 4) )

        if verbose:
            self._print_verbage()
        
        if log:
            self._setup_logging()
 
        # Connect & Initialize base class
        self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
                     self.diffdec, self.to_float, self.rescale, self)
Example #6
0
    def __init__(self):
        gr.top_block.__init__(self, "Tetra Rx Multi")

        options = self.get_options()

        self.src = blocks.file_source(gr.sizeof_gr_complex * 1,
                                      "/tmp/myout1.ch", False)

        ##################################################
        # Variables
        ##################################################
        self.srate_rx = srate_rx = options.sample_rate
        self.channels = srate_rx / 25000
        self.srate_channel = 36000
        self.afc_period = 15
        self.afc_gain = 0.01
        self.afc_channel = options.auto_tune or -1
        self.afc_ppm_step = 100
        self.debug = options.debug
        self.last_pwr = -100000
        self.sig_det_period = 10
        self.sig_det_bw = sig_det_bw = options.sig_detection_bw or srate_rx
        if self.sig_det_bw <= 1.:
            self.sig_det_bw *= srate_rx
        self.sig_det_threshold = options.sig_detection_threshold
        self.sig_det_channels = []
        for ch in range(self.channels):
            if ch >= self.channels / 2:
                ch_ = (self.channels - ch - 1)
            else:
                ch_ = ch
            if (float(ch_) / self.channels * 2) <= (self.sig_det_bw /
                                                    srate_rx):
                self.sig_det_channels.append(ch)

        self.channels = 10

        ##################################################
        # RPC server
        ##################################################
        self.xmlrpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
            ("localhost", options.listen_port), allow_none=True)
        self.xmlrpc_server.register_instance(self)
        threading.Thread(target=self.xmlrpc_server.serve_forever).start()

        ##################################################
        # Rx Blocks and connections
        ##################################################

        out_type, dst_path = options.output.split("://", 1)
        if out_type == "udp":
            dst_ip, dst_port = dst_path.split(':', 1)

        self.blocks_deinterleave_0 = blocks.deinterleave(
            gr.sizeof_gr_complex * 1, 1)

        self.squelch = []
        self.digital_mpsk_receiver_cc = []
        self.diff_phasor = []
        self.complex_to_arg = []
        self.multiply_const = []
        self.add_const = []
        self.float_to_uchar = []
        self.map_bits = []
        self.unpack_k_bits = []
        self.blocks_sink = []
        for ch in range(0, self.channels):
            mpsk = digital.mpsk_receiver_cc(4, math.pi / 4, math.pi / 100.0,
                                            -0.5, 0.5, 0.25, 0.001, 2, 0.001,
                                            0.001)
            diff_phasor = digital.diff_phasor_cc()
            complex_to_arg = blocks.complex_to_arg(1)
            multiply_const = blocks.multiply_const_vff((2. / math.pi, ))
            add_const = blocks.add_const_vff((1.5, ))
            float_to_uchar = blocks.float_to_uchar()
            map_bits = digital.map_bb(([3, 2, 0, 1, 3]))
            unpack_k_bits = blocks.unpack_k_bits_bb(2)

            brmchannels = [
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
                18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
                34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
                50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
                66, 67, 68, 69, 70, 71
            ]
            #brmchannels = [11,4,3,64,45,47,53,8,68,6,56,49,17,54,65,5,71,22,48,7,50] # itds kancl
            #brmchannels = [23,13,40,69,59,7,42,54,5,14,4,56,45,46,67,55,66,44,71,49,31,57,0,65,70] # doma - dole
            #brmchannels = [23,13,59,40,69,7,49,60,42,70,4,50,66,67,3,14,57,33,46,22,68,32,39,24,6,12,43,58,48,17,5,56,65,29,54,30,16,52,53,41,47,2,34,44,8] # doma - strecha
            #brmchannels = [67, 7, 23, 70] # doma - strecha - SDS
            #brmchannels = [67, 7, 23, 70,9,71,64,63,62,61,55,51,45,38,37,36,35,31,28,27,26,25,21,20,19,18,15,11,10,1,0] # doma - strecha - komplement

            if out_type == 'udp':
                sink = blocks.udp_sink(gr.sizeof_gr_char, dst_ip,
                                       int(dst_port) + ch, 1472, True)
            elif out_type == 'file':
                sink = blocks.file_sink(gr.sizeof_char, dst_path % ch, False)
                sink.set_unbuffered(True)
            else:
                raise ValueError("Invalid output URL '%s'" % options.output)

            print "connect %i" % ch

            if ch in brmchannels:
                self.connect(
                    (self.blocks_deinterleave_0, ch),
                    #(squelch, 0),
                    (mpsk, 0),
                    (diff_phasor, 0),
                    (complex_to_arg, 0),
                    (multiply_const, 0),
                    (add_const, 0),
                    (float_to_uchar, 0),
                    (map_bits, 0),
                    (unpack_k_bits, 0),
                    (sink, 0))

            self.digital_mpsk_receiver_cc.append(mpsk)
            self.diff_phasor.append(diff_phasor)
            self.complex_to_arg.append(complex_to_arg)
            self.multiply_const.append(multiply_const)
            self.add_const.append(add_const)
            self.float_to_uchar.append(float_to_uchar)
            self.map_bits.append(map_bits)
            self.unpack_k_bits.append(unpack_k_bits)
            self.blocks_sink.append(sink)

        self.connect((self.src, 0), (self.blocks_deinterleave_0, 0))

        ##################################################
        # signal strenght identification
        ##################################################
        '''
        self.pwr_probes = []
        for ch in range(self.channels):
            pwr_probe = analog.probe_avg_mag_sqrd_c(0, 1./self.srate_channel)
            self.pwr_probes.append(pwr_probe)
            print "connect %i"%ch
            self.connect((self.blocks_deinterleave_0, ch), (pwr_probe, 0))
        def _sig_det_probe():
            while True:
                pwr = [self.pwr_probes[ch].level()
                        for ch in range(self.channels)
                        if ch in self.sig_det_channels]
                pwr = [10 * math.log10(p) for p in pwr if p > 0.]
                if not pwr:
                    continue
                pwr = min(pwr) + self.sig_det_threshold
                print "power threshold target %f"%pwr
                if abs(pwr - self.last_pwr) > (self.sig_det_threshold / 2):
                    for s in []:
                        s.set_threshold(pwr)
                    self.last_pwr = pwr
                time.sleep(self.sig_det_period)

        if self.sig_det_threshold is not None:
            self._sig_det_probe_thread = threading.Thread(target=_sig_det_probe)
            self._sig_det_probe_thread.daemon = True
            self._sig_det_probe_thread.start()
        '''
        ##################################################
        # AFC blocks and connections
        ##################################################
        self.afc_selector = grc_blks2.selector(
            item_size=gr.sizeof_gr_complex,
            num_inputs=self.channels,
            num_outputs=1,
            input_index=0,
            output_index=0,
        )

        self.afc_demod = analog.quadrature_demod_cf(self.srate_channel /
                                                    (2 * math.pi))
        samp_afc = self.srate_channel * self.afc_period / 2
        self.afc_avg = blocks.moving_average_ff(samp_afc,
                                                1. / samp_afc * self.afc_gain)
        self.afc_probe = blocks.probe_signal_f()

        def _afc_probe():
            rt = 0.0
            while True:
                time.sleep(self.afc_period)
                if self.afc_channel == -1:
                    continue
                err = self.afc_probe.level()
                freq = err * self.afc_gain
                print "err: %f\tfreq: %f\trt %f" % (err, freq, rt)
                changed = False
                if err < -1:
                    rt += 0.1
                    changed = True
                elif err > 1:
                    rt -= 0.1
                    changed = True

                if changed:
                    os.system("echo \"setrot %f\" | nc localhost 3333" % rt)

        self.afc_channel = 0
        self._afc_err_thread = threading.Thread(target=_afc_probe)
        self._afc_err_thread.daemon = True
        self._afc_err_thread.start()

        for ch in range(self.channels):
            print "connect %i" % ch
            self.connect((self.blocks_deinterleave_0, ch),
                         (self.afc_selector, ch))
        self.connect((self.afc_selector, 0), (self.afc_demod, 0),
                     (self.afc_avg, 0), (self.afc_probe, 0))

        if self.afc_channel != -1:
            self.afc_selector.set_input_index(self.afc_channel)
    def __init__(self):
        gr.top_block.__init__(self, "Modes Uf Rx Sigmf V2")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Modes Uf Rx Sigmf V2")
        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", "modes_uf_rx_sigmf_v2")
        self.restoreGeometry(self.settings.value("geometry").toByteArray())

        ##################################################
        # Variables
        ##################################################
        self.sps = sps = 2
        self.samp_rate = samp_rate = 8000000

        self.rrc_taps = rrc_taps = firdes.root_raised_cosine(
            1, 1, 0.5, 0.4, 32)

        self.rms_alpha = rms_alpha = 1e-6
        self.rf_gain = rf_gain = 45
        self.qt_thresh = qt_thresh = 110
        self.es_thresh = es_thresh = 110
        self.det_mult = det_mult = 2
        self.det_avg_len = det_avg_len = 20
        self.cons_offset = cons_offset = 5
        self.burst_length = burst_length = 600
        self.bit_thresh = bit_thresh = 5
        self.avg_len = avg_len = 20

        ##################################################
        # Blocks
        ##################################################
        self._rms_alpha_tool_bar = Qt.QToolBar(self)
        self._rms_alpha_tool_bar.addWidget(Qt.QLabel("rms_alpha" + ": "))
        self._rms_alpha_line_edit = Qt.QLineEdit(str(self.rms_alpha))
        self._rms_alpha_tool_bar.addWidget(self._rms_alpha_line_edit)
        self._rms_alpha_line_edit.returnPressed.connect(
            lambda: self.set_rms_alpha(
                eng_notation.str_to_num(
                    str(self._rms_alpha_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._rms_alpha_tool_bar, 6, 3, 1, 1)
        for r in range(6, 7):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(3, 4):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._qt_thresh_tool_bar = Qt.QToolBar(self)
        self._qt_thresh_tool_bar.addWidget(Qt.QLabel("qt_thresh" + ": "))
        self._qt_thresh_line_edit = Qt.QLineEdit(str(self.qt_thresh))
        self._qt_thresh_tool_bar.addWidget(self._qt_thresh_line_edit)
        self._qt_thresh_line_edit.returnPressed.connect(
            lambda: self.set_qt_thresh(
                eng_notation.str_to_num(
                    str(self._qt_thresh_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._qt_thresh_tool_bar, 0, 2, 1, 2)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(2, 4):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._es_thresh_tool_bar = Qt.QToolBar(self)
        self._es_thresh_tool_bar.addWidget(Qt.QLabel('ES Thresh' + ": "))
        self._es_thresh_line_edit = Qt.QLineEdit(str(self.es_thresh))
        self._es_thresh_tool_bar.addWidget(self._es_thresh_line_edit)
        self._es_thresh_line_edit.returnPressed.connect(
            lambda: self.set_es_thresh(
                eng_notation.str_to_num(
                    str(self._es_thresh_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._es_thresh_tool_bar, 0, 5, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(5, 6):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._det_mult_tool_bar = Qt.QToolBar(self)
        self._det_mult_tool_bar.addWidget(Qt.QLabel("det_mult" + ": "))
        self._det_mult_line_edit = Qt.QLineEdit(str(self.det_mult))
        self._det_mult_tool_bar.addWidget(self._det_mult_line_edit)
        self._det_mult_line_edit.returnPressed.connect(
            lambda: self.set_det_mult(
                eng_notation.str_to_num(
                    str(self._det_mult_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._det_mult_tool_bar, 0, 6, 1, 2)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(6, 8):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._det_avg_len_tool_bar = Qt.QToolBar(self)
        self._det_avg_len_tool_bar.addWidget(Qt.QLabel("det_avg_len" + ": "))
        self._det_avg_len_line_edit = Qt.QLineEdit(str(self.det_avg_len))
        self._det_avg_len_tool_bar.addWidget(self._det_avg_len_line_edit)
        self._det_avg_len_line_edit.returnPressed.connect(
            lambda: self.set_det_avg_len(
                int(str(self._det_avg_len_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._det_avg_len_tool_bar, 0, 9, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(9, 10):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._cons_offset_tool_bar = Qt.QToolBar(self)
        self._cons_offset_tool_bar.addWidget(Qt.QLabel("cons_offset" + ": "))
        self._cons_offset_line_edit = Qt.QLineEdit(str(self.cons_offset))
        self._cons_offset_tool_bar.addWidget(self._cons_offset_line_edit)
        self._cons_offset_line_edit.returnPressed.connect(
            lambda: self.set_cons_offset(
                eng_notation.str_to_num(
                    str(self._cons_offset_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._cons_offset_tool_bar, 0, 8, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(8, 9):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._avg_len_tool_bar = Qt.QToolBar(self)
        self._avg_len_tool_bar.addWidget(Qt.QLabel("avg_len" + ": "))
        self._avg_len_line_edit = Qt.QLineEdit(str(self.avg_len))
        self._avg_len_tool_bar.addWidget(self._avg_len_line_edit)
        self._avg_len_line_edit.returnPressed.connect(lambda: self.set_avg_len(
            eng_notation.str_to_num(
                str(self._avg_len_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._avg_len_tool_bar, 0, 4, 1, 1)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(4, 5):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.vcc_es_tag_to_utc_0 = vcc.es_tag_to_utc(samp_rate)
        self.vcc_burst_snr_0 = vcc.burst_snr(25, 2)
        self.sigmf_source_0 = gr_sigmf.source(
            '/captures/adsb/20210127/MODE-S_2021-01-27T23:43:24.sigmf-data',
            "ci16" + ("_le" if sys.byteorder == "little" else "_be"), False)
        self._rf_gain_tool_bar = Qt.QToolBar(self)
        self._rf_gain_tool_bar.addWidget(Qt.QLabel("rf_gain" + ": "))
        self._rf_gain_line_edit = Qt.QLineEdit(str(self.rf_gain))
        self._rf_gain_tool_bar.addWidget(self._rf_gain_line_edit)
        self._rf_gain_line_edit.returnPressed.connect(lambda: self.set_rf_gain(
            eng_notation.str_to_num(
                str(self._rf_gain_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._rf_gain_tool_bar, 0, 0, 1, 2)
        for r in range(0, 1):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_time_sink_x_1 = qtgui.time_sink_f(
            burst_length / 2,  #size
            samp_rate,  #samp_rate
            "",  #name
            3  #number of inputs
        )
        self.qtgui_time_sink_x_1.set_update_time(0.010)
        self.qtgui_time_sink_x_1.set_y_axis(-5, 20)

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

        self.qtgui_time_sink_x_1.enable_tags(-1, True)
        self.qtgui_time_sink_x_1.set_trigger_mode(qtgui.TRIG_MODE_AUTO,
                                                  qtgui.TRIG_SLOPE_POS,
                                                  qt_thresh,
                                                  1.0 / samp_rate * 100, 0, "")
        self.qtgui_time_sink_x_1.enable_autoscale(True)
        self.qtgui_time_sink_x_1.enable_grid(True)
        self.qtgui_time_sink_x_1.enable_axis_labels(True)
        self.qtgui_time_sink_x_1.enable_control_panel(False)
        self.qtgui_time_sink_x_1.enable_stem_plot(False)

        if not True:
            self.qtgui_time_sink_x_1.disable_legend()

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

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

        self._qtgui_time_sink_x_1_win = sip.wrapinstance(
            self.qtgui_time_sink_x_1.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_1_win, 1, 0, 2,
                                       4)
        for r in range(1, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 4):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_time_sink_x_0_1 = qtgui.time_sink_f(
            burst_length / 2,  #size
            samp_rate / 2,  #samp_rate
            "soft chips",  #name
            3  #number of inputs
        )
        self.qtgui_time_sink_x_0_1.set_update_time(0.10)
        self.qtgui_time_sink_x_0_1.set_y_axis(-1, 1)

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

        self.qtgui_time_sink_x_0_1.enable_tags(-1, True)
        self.qtgui_time_sink_x_0_1.set_trigger_mode(qtgui.TRIG_MODE_TAG,
                                                    qtgui.TRIG_SLOPE_POS, 0, 0,
                                                    0, "es::event_type")
        self.qtgui_time_sink_x_0_1.enable_autoscale(True)
        self.qtgui_time_sink_x_0_1.enable_grid(False)
        self.qtgui_time_sink_x_0_1.enable_axis_labels(True)
        self.qtgui_time_sink_x_0_1.enable_control_panel(False)
        self.qtgui_time_sink_x_0_1.enable_stem_plot(False)

        if not True:
            self.qtgui_time_sink_x_0_1.disable_legend()

        labels = ['re', 'abs', 'mag', 'ph', '', '', '', '', '', '']
        widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        colors = [
            "blue", "red", "green", "black", "cyan", "magenta", "yellow",
            "dark red", "dark green", "blue"
        ]
        styles = [1, 2, 1, 1, 1, 1, 1, 1, 1, 1]
        markers = [0, -1, 0, -1, -1, -1, -1, -1, -1, -1]
        alphas = [1, 0.25, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

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

        self._qtgui_time_sink_x_0_1_win = sip.wrapinstance(
            self.qtgui_time_sink_x_0_1.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_1_win, 3, 0,
                                       3, 5)
        for r in range(3, 6):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 5):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_time_raster_sink_x_0 = qtgui.time_raster_sink_b(
            samp_rate / 2,
            20,
            56,
            ([]),
            ([]),
            "",
            1,
        )

        self.qtgui_time_raster_sink_x_0.set_update_time(0.10)
        self.qtgui_time_raster_sink_x_0.set_intensity_range(-1, 1)
        self.qtgui_time_raster_sink_x_0.enable_grid(False)
        self.qtgui_time_raster_sink_x_0.enable_axis_labels(True)

        labels = ['', '', '', '', '', '', '', '', '', '']
        colors = [1, 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 xrange(1):
            if len(labels[i]) == 0:
                self.qtgui_time_raster_sink_x_0.set_line_label(
                    i, "Data {0}".format(i))
            else:
                self.qtgui_time_raster_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_time_raster_sink_x_0.set_color_map(i, colors[i])
            self.qtgui_time_raster_sink_x_0.set_line_alpha(i, alphas[i])

        self._qtgui_time_raster_sink_x_0_win = sip.wrapinstance(
            self.qtgui_time_raster_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_raster_sink_x_0_win, 3,
                                       5, 3, 5)
        for r in range(3, 6):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(5, 10):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
            burst_length / 2,  #size
            "",  #name
            1  #number of inputs
        )
        self.qtgui_const_sink_x_0.set_update_time(0.010)
        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(True)
        self.qtgui_const_sink_x_0.enable_grid(True)
        self.qtgui_const_sink_x_0.enable_axis_labels(True)

        if not True:
            self.qtgui_const_sink_x_0.disable_legend()

        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 xrange(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, 1, 8, 2,
                                       2)
        for r in range(1, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(8, 10):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.pyqt_ctime_plot_0 = pyqt.ctime_plot('')
        self._pyqt_ctime_plot_0_win = self.pyqt_ctime_plot_0
        self.top_grid_layout.addWidget(self._pyqt_ctime_plot_0_win, 1, 4, 2, 2)
        for r in range(1, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(4, 6):
            self.top_grid_layout.setColumnStretch(c, 1)

        self.pyqt_const_plot_0 = pyqt.const_plot(label='')
        self._pyqt_const_plot_0_win = self.pyqt_const_plot_0
        self.top_grid_layout.addWidget(self._pyqt_const_plot_0_win, 1, 6, 2, 2)
        for r in range(1, 3):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(6, 8):
            self.top_grid_layout.setColumnStretch(c, 1)

        self.low_pass_filter_0_0 = filter.fir_filter_ccf(
            1,
            firdes.low_pass(1, samp_rate, 4e6, 250e3, firdes.WIN_BLACKMAN,
                            6.76))
        self.fosphor_glfw_sink_c_0 = fosphor.glfw_sink_c()
        self.fosphor_glfw_sink_c_0.set_fft_window(window.WIN_BLACKMAN_hARRIS)
        self.fosphor_glfw_sink_c_0.set_frequency_range(0, samp_rate)
        self.es_trigger_edge_f_0 = es.trigger_edge_f(es_thresh, burst_length,
                                                     burst_length / 3,
                                                     gr.sizeof_gr_complex, 300)
        self.es_sink_0 = es.sink(1 * [gr.sizeof_gr_complex], 4, 64, 0, 2, 0)
        self.es_handler_pdu_0 = es.es_make_handler_pdu(
            es.es_handler_print.TYPE_C32)
        self.epy_block_1 = epy_block_1.uf_frame_sync(tag_name='sync',
                                                     msg_len=112,
                                                     samp_rate=samp_rate,
                                                     sps=2)
        self.epy_block_0_0 = epy_block_0_0.uf_decode(msg_filter='All Messages',
                                                     verbose=True)
        self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(
            2, math.pi / 200, (rrc_taps), 32, 16, 1.1, 1)
        self.digital_diff_phasor_cc_0 = digital.diff_phasor_cc()
        self.digital_costas_loop_cc_0 = digital.costas_loop_cc(
            math.pi / 50, 2, False)
        self.digital_correlate_access_code_tag_xx_0_0_1_2_2_0_0_0 = digital.correlate_access_code_tag_bb(
            '00011111000111000001', 3, 'sync')
        self.digital_binary_slicer_fb_0_0 = digital.binary_slicer_fb()
        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex * 1,
                                                 samp_rate * 2, True)
        self.blocks_sub_xx_2_0 = blocks.sub_ff(1)
        self.blocks_sub_xx_0 = blocks.sub_ff(1)
        self.blocks_skiphead_0 = blocks.skiphead(gr.sizeof_float * 1, 1)
        self.blocks_rms_xx_1 = blocks.rms_cf(rms_alpha)
        self.blocks_pdu_to_tagged_stream_1 = blocks.pdu_to_tagged_stream(
            blocks.byte_t, 'packet_len')
        self.blocks_pdu_to_tagged_stream_0 = blocks.pdu_to_tagged_stream(
            blocks.complex_t, 'est_len')
        (self.blocks_pdu_to_tagged_stream_0).set_min_output_buffer(600)
        self.blocks_pdu_remove_0 = blocks.pdu_remove(
            pmt.intern("es::event_buffer"))
        self.blocks_multiply_const_xx_0 = blocks.multiply_const_cc(1.0 /
                                                                   65536.0)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff(
            (-1 * det_mult, ))
        self.blocks_moving_average_xx_0_0 = blocks.moving_average_ff(
            int(det_avg_len), 1.0 / det_avg_len, 4000, 1)
        self.blocks_moving_average_xx_0 = blocks.moving_average_ff(
            int(avg_len), 1.0 / avg_len, 4000, 1)
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            True, False)
        self.blocks_complex_to_real_1_0_0 = blocks.complex_to_real(1)
        self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1)
        self.blocks_complex_to_arg_0 = blocks.complex_to_arg(1)
        self.blocks_char_to_float_0_1 = blocks.char_to_float(1, 1 / 10.0)
        self.blocks_add_const_vxx_0 = blocks.add_const_vff((cons_offset, ))
        self.blocks_abs_xx_0 = blocks.abs_ff(1)
        self._bit_thresh_tool_bar = Qt.QToolBar(self)
        self._bit_thresh_tool_bar.addWidget(Qt.QLabel("bit_thresh" + ": "))
        self._bit_thresh_line_edit = Qt.QLineEdit(str(self.bit_thresh))
        self._bit_thresh_tool_bar.addWidget(self._bit_thresh_line_edit)
        self._bit_thresh_line_edit.returnPressed.connect(
            lambda: self.set_bit_thresh(
                eng_notation.str_to_num(
                    str(self._bit_thresh_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._bit_thresh_tool_bar, 6, 4, 1, 1)
        for r in range(6, 7):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(4, 5):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.analog_agc2_xx_0 = analog.agc2_cc(1e-1, 1e-2, 1.0, 1.0)
        self.analog_agc2_xx_0.set_max_gain(65536)
        self.ais_invert_0 = ais.invert()

        ##################################################
        # Connections
        ##################################################
        self.msg_connect((self.blocks_pdu_remove_0, 'pdus'),
                         (self.vcc_burst_snr_0, 'in'))
        self.msg_connect((self.epy_block_0_0, 'out'),
                         (self.blocks_pdu_to_tagged_stream_1, 'pdus'))
        self.msg_connect((self.epy_block_1, 'out'), (self.epy_block_0_0, 'in'))
        self.msg_connect((self.es_handler_pdu_0, 'pdus_out'),
                         (self.blocks_pdu_remove_0, 'pdus'))
        self.msg_connect((self.es_trigger_edge_f_0, 'edge_event'),
                         (self.es_handler_pdu_0, 'handle_event'))
        self.msg_connect((self.es_trigger_edge_f_0, 'which_stream'),
                         (self.es_sink_0, 'schedule_event'))
        self.msg_connect((self.vcc_burst_snr_0, 'out'),
                         (self.vcc_es_tag_to_utc_0, 'in'))
        self.msg_connect((self.vcc_es_tag_to_utc_0, 'out'),
                         (self.blocks_pdu_to_tagged_stream_0, 'pdus'))
        self.msg_connect((self.vcc_es_tag_to_utc_0, 'out'),
                         (self.pyqt_const_plot_0, 'cpdus'))
        self.msg_connect((self.vcc_es_tag_to_utc_0, 'out'),
                         (self.pyqt_ctime_plot_0, 'cpdus'))
        self.connect(
            (self.ais_invert_0, 0),
            (self.digital_correlate_access_code_tag_xx_0_0_1_2_2_0_0_0, 0))
        self.connect((self.analog_agc2_xx_0, 0),
                     (self.blocks_complex_to_arg_0, 0))
        self.connect((self.analog_agc2_xx_0, 0),
                     (self.blocks_complex_to_mag_squared_0, 0))
        self.connect((self.analog_agc2_xx_0, 0), (self.es_trigger_edge_f_0, 1))
        self.connect((self.analog_agc2_xx_0, 0),
                     (self.fosphor_glfw_sink_c_0, 0))
        self.connect((self.blocks_abs_xx_0, 0),
                     (self.blocks_moving_average_xx_0_0, 0))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.qtgui_time_sink_x_1, 2))
        self.connect((self.blocks_char_to_float_0_1, 0),
                     (self.qtgui_time_sink_x_0_1, 2))
        self.connect((self.blocks_complex_to_arg_0, 0),
                     (self.blocks_skiphead_0, 0))
        self.connect((self.blocks_complex_to_arg_0, 0),
                     (self.blocks_sub_xx_0, 0))
        self.connect((self.blocks_complex_to_arg_0, 0),
                     (self.qtgui_time_sink_x_1, 1))
        self.connect((self.blocks_complex_to_mag_squared_0, 0),
                     (self.blocks_moving_average_xx_0, 0))
        self.connect((self.blocks_complex_to_real_1_0_0, 0),
                     (self.blocks_sub_xx_2_0, 0))
        self.connect((self.blocks_complex_to_real_1_0_0, 0),
                     (self.qtgui_time_sink_x_0_1, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_xx_0, 0))
        self.connect((self.blocks_moving_average_xx_0, 0),
                     (self.es_trigger_edge_f_0, 0))
        self.connect((self.blocks_moving_average_xx_0, 0),
                     (self.qtgui_time_sink_x_1, 0))
        self.connect((self.blocks_moving_average_xx_0_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_multiply_const_xx_0, 0),
                     (self.blocks_throttle_0, 0))
        self.connect((self.blocks_pdu_to_tagged_stream_0, 0),
                     (self.low_pass_filter_0_0, 0))
        self.connect((self.blocks_pdu_to_tagged_stream_1, 0),
                     (self.qtgui_time_raster_sink_x_0, 0))
        self.connect((self.blocks_rms_xx_1, 0), (self.blocks_sub_xx_2_0, 1))
        self.connect((self.blocks_rms_xx_1, 0),
                     (self.qtgui_time_sink_x_0_1, 1))
        self.connect((self.blocks_skiphead_0, 0), (self.blocks_sub_xx_0, 1))
        self.connect((self.blocks_sub_xx_0, 0), (self.blocks_abs_xx_0, 0))
        self.connect((self.blocks_sub_xx_2_0, 0),
                     (self.digital_binary_slicer_fb_0_0, 0))
        self.connect((self.blocks_throttle_0, 0), (self.analog_agc2_xx_0, 0))
        self.connect((self.digital_binary_slicer_fb_0_0, 0),
                     (self.ais_invert_0, 0))
        self.connect(
            (self.digital_correlate_access_code_tag_xx_0_0_1_2_2_0_0_0, 0),
            (self.blocks_char_to_float_0_1, 0))
        self.connect(
            (self.digital_correlate_access_code_tag_xx_0_0_1_2_2_0_0_0, 0),
            (self.epy_block_1, 0))
        self.connect((self.digital_costas_loop_cc_0, 0),
                     (self.digital_diff_phasor_cc_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 0),
                     (self.qtgui_const_sink_x_0, 0))
        self.connect((self.digital_diff_phasor_cc_0, 0),
                     (self.blocks_complex_to_real_1_0_0, 0))
        self.connect((self.digital_diff_phasor_cc_0, 0),
                     (self.blocks_rms_xx_1, 0))
        self.connect((self.digital_pfb_clock_sync_xxx_0, 0),
                     (self.digital_costas_loop_cc_0, 0))
        self.connect((self.es_trigger_edge_f_0, 0), (self.es_sink_0, 0))
        self.connect((self.low_pass_filter_0_0, 0),
                     (self.digital_pfb_clock_sync_xxx_0, 0))
        self.connect((self.sigmf_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
Example #8
0
    def __init__(self):
        gr.top_block.__init__(self, "Psk31 Rx")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Psk31 Rx")
        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", "psk31_rx")

        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.center_freq = center_freq = 441800000
        self.samp_rate = samp_rate = 960000
        self.psk_offset = psk_offset = 1000
        self.psk_center = psk_center = center_freq + 141000
        self.int_rate = int_rate = 48000
        self.gain = gain = 10
        self.audio_rate = audio_rate = 8000

        ##################################################
        # Blocks
        ##################################################
        self._psk_offset_range = Range(0, 3000, 10, 1000, 200)
        self._psk_offset_win = RangeWidget(self._psk_offset_range, self.set_psk_offset, 'PSK offset', "counter_slider", float)
        self.top_grid_layout.addWidget(self._psk_offset_win)
        self._psk_center_range = Range(center_freq + 110000, center_freq + 150000, 1000, center_freq + 141000, 200)
        self._psk_center_win = RangeWidget(self._psk_center_range, self.set_psk_center, 'Tuning', "counter_slider", float)
        self.top_grid_layout.addWidget(self._psk_center_win)
        self._gain_range = Range(0, 50, 0.4, 10, 200)
        self._gain_win = RangeWidget(self._gain_range, self.set_gain, 'RX gain', "counter_slider", float)
        self.top_grid_layout.addWidget(self._gain_win)
        self.qtgui_waterfall_sink_x_2 = qtgui.waterfall_sink_f(
            1024, #size
            firdes.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            samp_rate / 120, #bw
            "", #name
            1 #number of inputs
        )
        self.qtgui_waterfall_sink_x_2.set_update_time(0.10)
        self.qtgui_waterfall_sink_x_2.enable_grid(False)
        self.qtgui_waterfall_sink_x_2.enable_axis_labels(True)


        self.qtgui_waterfall_sink_x_2.set_plot_pos_half(not False)

        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [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_waterfall_sink_x_2.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_2.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_2.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_2.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_2.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_2_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_2.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_2_win)
        self.qtgui_waterfall_sink_x_1 = qtgui.waterfall_sink_c(
            1024, #size
            firdes.WIN_BLACKMAN_hARRIS, #wintype
            0, #fc
            samp_rate / 20, #bw
            "", #name
            1 #number of inputs
        )
        self.qtgui_waterfall_sink_x_1.set_update_time(0.10)
        self.qtgui_waterfall_sink_x_1.enable_grid(False)
        self.qtgui_waterfall_sink_x_1.enable_axis_labels(True)



        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [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_waterfall_sink_x_1.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_1.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_1.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_1.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_1.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_1_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_1.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_1_win)
        self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c(
            1024, #size
            firdes.WIN_BLACKMAN_hARRIS, #wintype
            center_freq, #fc
            samp_rate, #bw
            "", #name
            1 #number of inputs
        )
        self.qtgui_waterfall_sink_x_0.set_update_time(0.10)
        self.qtgui_waterfall_sink_x_0.enable_grid(False)
        self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)



        labels = ['', '', '', '', '',
                  '', '', '', '', '']
        colors = [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_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
            else:
                self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
            self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
            self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])

        self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)

        self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_win)
        self.qtgui_time_sink_x_1 = qtgui.time_sink_c(
            1024, #size
            samp_rate / 120, #samp_rate
            "", #name
            1 #number of inputs
        )
        self.qtgui_time_sink_x_1.set_update_time(0.10)
        self.qtgui_time_sink_x_1.set_y_axis(-1, 1)

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

        self.qtgui_time_sink_x_1.enable_tags(True)
        self.qtgui_time_sink_x_1.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
        self.qtgui_time_sink_x_1.enable_autoscale(False)
        self.qtgui_time_sink_x_1.enable_grid(False)
        self.qtgui_time_sink_x_1.enable_axis_labels(True)
        self.qtgui_time_sink_x_1.enable_control_panel(False)
        self.qtgui_time_sink_x_1.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_1.set_line_label(i, "Re{{Data {0}}}".format(i/2))
                else:
                    self.qtgui_time_sink_x_1.set_line_label(i, "Im{{Data {0}}}".format(i/2))
            else:
                self.qtgui_time_sink_x_1.set_line_label(i, labels[i])
            self.qtgui_time_sink_x_1.set_line_width(i, widths[i])
            self.qtgui_time_sink_x_1.set_line_color(i, colors[i])
            self.qtgui_time_sink_x_1.set_line_style(i, styles[i])
            self.qtgui_time_sink_x_1.set_line_marker(i, markers[i])
            self.qtgui_time_sink_x_1.set_line_alpha(i, alphas[i])

        self._qtgui_time_sink_x_1_win = sip.wrapinstance(self.qtgui_time_sink_x_1.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_1_win)
        self.qtgui_time_sink_x_0 = qtgui.time_sink_c(
            1024, #size
            samp_rate / 120 / 16 / 16, #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(-1, 1)

        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(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 = ['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.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_number_sink_0 = qtgui.number_sink(
            gr.sizeof_float,
            0,
            qtgui.NUM_GRAPH_HORIZ,
            1
        )
        self.qtgui_number_sink_0.set_update_time(0.10)
        self.qtgui_number_sink_0.set_title("")

        labels = ['', '', '', '', '',
            '', '', '', '', '']
        units = ['', '', '', '', '',
            '', '', '', '', '']
        colors = [("black", "black"), ("black", "black"), ("black", "black"), ("black", "black"), ("black", "black"),
            ("black", "black"), ("black", "black"), ("black", "black"), ("black", "black"), ("black", "black")]
        factor = [1, 1, 1, 1, 1,
            1, 1, 1, 1, 1]

        for i in range(1):
            self.qtgui_number_sink_0.set_min(i, -1)
            self.qtgui_number_sink_0.set_max(i, 1)
            self.qtgui_number_sink_0.set_color(i, colors[i][0], colors[i][1])
            if len(labels[i]) == 0:
                self.qtgui_number_sink_0.set_label(i, "Data {0}".format(i))
            else:
                self.qtgui_number_sink_0.set_label(i, labels[i])
            self.qtgui_number_sink_0.set_unit(i, units[i])
            self.qtgui_number_sink_0.set_factor(i, factor[i])

        self.qtgui_number_sink_0.enable_autoscale(False)
        self._qtgui_number_sink_0_win = sip.wrapinstance(self.qtgui_number_sink_0.pyqwidget(), Qt.QWidget)
        self.top_grid_layout.addWidget(self._qtgui_number_sink_0_win)
        self.osmosdr_source_0 = osmosdr.source(
            args="numchan=" + str(1) + " " + ''
        )
        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_gain(gain, 0)
        self.osmosdr_source_0.set_if_gain(20, 0)
        self.osmosdr_source_0.set_bb_gain(20, 0)
        self.osmosdr_source_0.set_antenna('', 0)
        self.osmosdr_source_0.set_bandwidth(0, 0)
        self.ham_varicode_rx_0 = ham.varicode_rx()
        self.freq_xlating_fir_filter_xxx_1 = filter.freq_xlating_fir_filter_ccc(16, firdes.low_pass(10, audio_rate, 120, 40, firdes.WIN_HAMMING, 6.76), psk_offset, audio_rate)
        self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(samp_rate // int_rate, firdes.low_pass(1, samp_rate, 12000, 12000, firdes.WIN_HAMMING, 6.76), round(psk_center - center_freq,-3), samp_rate)
        self.digital_diff_phasor_cc_0 = digital.diff_phasor_cc()
        self.digital_costas_loop_cc_0 = digital.costas_loop_cc(5 * math.pi /100.0, 2, False)
        self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_cc(16, 0.25*0.175*0.175, 0.5, 0.175, 0.005)
        self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb()
        self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, 'psk31.txt', False)
        self.blocks_file_sink_0.set_unbuffered(True)
        self.blocks_complex_to_real_1 = blocks.complex_to_real(1)
        self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
        self.band_pass_filter_0 = filter.fir_filter_ccc(
            int_rate // audio_rate,
            firdes.complex_band_pass(
                1,
                int_rate,
                200,
                2800,
                200,
                firdes.WIN_HAMMING,
                6.76))
        self.audio_sink_0 = audio.sink(audio_rate, 'plughw:0,0', True)
        self.analog_agc_xx_0 = analog.agc_cc(1e-3, 0.1, 1.0)
        self.analog_agc_xx_0.set_max_gain(65536)



        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_agc_xx_0, 0), (self.blocks_complex_to_real_0, 0))
        self.connect((self.analog_agc_xx_0, 0), (self.freq_xlating_fir_filter_xxx_1, 0))
        self.connect((self.band_pass_filter_0, 0), (self.analog_agc_xx_0, 0))
        self.connect((self.blocks_complex_to_real_0, 0), (self.audio_sink_0, 0))
        self.connect((self.blocks_complex_to_real_0, 0), (self.qtgui_waterfall_sink_x_2, 0))
        self.connect((self.blocks_complex_to_real_1, 0), (self.digital_binary_slicer_fb_0, 0))
        self.connect((self.digital_binary_slicer_fb_0, 0), (self.ham_varicode_rx_0, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_diff_phasor_cc_0, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.qtgui_time_sink_x_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 0), (self.digital_clock_recovery_mm_xx_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 1), (self.qtgui_number_sink_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_time_sink_x_1, 0))
        self.connect((self.digital_diff_phasor_cc_0, 0), (self.blocks_complex_to_real_1, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.band_pass_filter_0, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_waterfall_sink_x_1, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_1, 0), (self.digital_costas_loop_cc_0, 0))
        self.connect((self.ham_varicode_rx_0, 0), (self.blocks_file_sink_0, 0))
        self.connect((self.osmosdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0))
        self.connect((self.osmosdr_source_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
    def __init__(self):
        gr.top_block.__init__(self)
        parser = OptionParser(option_class=eng_option)

        parser.add_option("-1",
                          "--one-channel",
                          action="store_true",
                          default=False,
                          help="software synthesized Q channel")
        parser.add_option("-a",
                          "--agc",
                          action="store_true",
                          default=False,
                          help="automatic gain control (overrides --gain)")
        parser.add_option("-c",
                          "--calibration",
                          type="eng_float",
                          default=0,
                          help="freq offset")
        parser.add_option("-d",
                          "--debug",
                          action="store_true",
                          default=False,
                          help="allow time at init to attach gdb")
        parser.add_option("-C",
                          "--costas-alpha",
                          type="eng_float",
                          default=0.125,
                          help="Costas alpha")
        parser.add_option("-g", "--gain", type="eng_float", default=1.0)
        parser.add_option("-i",
                          "--input-file",
                          type="string",
                          default="in.dat",
                          help="specify the input file")
        parser.add_option("-I",
                          "--imbe",
                          action="store_true",
                          default=False,
                          help="output IMBE codewords")
        parser.add_option("-L",
                          "--low-pass",
                          type="eng_float",
                          default=6.5e3,
                          help="low pass cut-off",
                          metavar="Hz")
        parser.add_option("-o",
                          "--output-file",
                          type="string",
                          default="out.dat",
                          help="specify the output file")
        parser.add_option("-p",
                          "--polarity",
                          action="store_true",
                          default=False,
                          help="use reversed polarity")
        parser.add_option("-r",
                          "--raw-symbols",
                          type="string",
                          default=None,
                          help="dump decoded symbols to file")
        parser.add_option("-s",
                          "--sample-rate",
                          type="int",
                          default=96000,
                          help="input sample rate")
        parser.add_option("-t",
                          "--tone-detect",
                          action="store_true",
                          default=False,
                          help="use experimental tone detect algorithm")
        parser.add_option("-v",
                          "--verbose",
                          action="store_true",
                          default=False,
                          help="additional output")
        parser.add_option("-6",
                          "--k6k",
                          action="store_true",
                          default=False,
                          help="use 6K symbol rate")
        (options, args) = parser.parse_args()

        sample_rate = options.sample_rate
        if options.k6k:
            symbol_rate = 6000
        else:
            symbol_rate = 4800
        samples_per_symbol = sample_rate // symbol_rate

        IN = blocks.file_source(gr.sizeof_gr_complex, options.input_file)

        if options.one_channel:
            C2F = blocks.complex_to_float()
            F2C = blocks.float_to_complex()

        # osc./mixer for mixing signal down to approx. zero IF
        LO = analog.sig_source_c(sample_rate, analog.GR_COS_WAVE,
                                 options.calibration, 1.0, 0)
        MIXER = blocks.multiply_cc()

        # get signal into normalized range (-1.0 - +1.0)
        if options.agc:
            AMP = analog.feedforward_agc_cc(16, 1.0)
        else:
            AMP = blocks.multiply_const_cc(options.gain)

        lpf_taps = filter.firdes.low_pass(1.0, sample_rate, options.low_pass,
                                          options.low_pass * 0.1,
                                          filter.firdes.WIN_HANN)

        decim_amt = 1
        if options.tone_detect:
            if sample_rate != 96000:
                print "warning, only 96K has been tested."
                print "other rates may require theta to be reviewed/adjusted."
            step_size = 7.5e-8
            theta = -4  # optimum timing sampling point
            cic_length = 48
            DEMOD = op25_repeater.tdetect_cc(samples_per_symbol, step_size,
                                             theta, cic_length)
        else:
            # decim by 2 to get 48k rate
            samples_per_symbol /= 2  # for DECIM
            sample_rate /= 2  # for DECIM
            decim_amt = 2
            # create Gardner/Costas loop
            # the loop will not work if the sample levels aren't normalized (above)
            timing_error_gain = 0.025  # loop error gain
            gain_omega = 0.25 * timing_error_gain * timing_error_gain
            alpha = options.costas_alpha
            beta = 0.125 * alpha * alpha
            fmin = -0.025  # fmin and fmax are in radians/s
            fmax = 0.025
            DEMOD = op25_repeater.gardner_costas_cc(samples_per_symbol,
                                                    timing_error_gain,
                                                    gain_omega, alpha, beta,
                                                    fmax, fmin)
        DECIM = filter.fir_filter_ccf(decim_amt, lpf_taps)

        # probably too much phase noise etc to attempt coherent demodulation
        # so we use differential
        DIFF = digital.diff_phasor_cc()

        # take angle of the phase difference (in radians)
        TOFLOAT = blocks.complex_to_arg()

        # convert from radians such that signal is in [-3, -1, +1, +3]
        RESCALE = blocks.multiply_const_ff(1 / (pi / 4.0))

        # optional polarity reversal (should be unnec. - now autodetected)
        p = 1.0
        if options.polarity:
            p = -1.0
        POLARITY = blocks.multiply_const_ff(p)

        # hard decision at specified points
        levels = [-2.0, 0.0, 2.0, 4.0]
        SLICER = op25_repeater.fsk4_slicer_fb(levels)

        # assemble received frames and route to Wireshark via UDP
        hostname = "127.0.0.1"
        port = 23456
        debug = 0
        if options.verbose:
            debug = 255
        do_imbe = False
        if options.imbe:
            do_imbe = True
        do_output = True  # enable block's output stream
        do_msgq = False  # msgq output not yet implemented
        msgq = gr.msg_queue(2)
        DECODER = op25_repeater.p25_frame_assembler(hostname, port, debug,
                                                    do_imbe, do_output,
                                                    do_msgq, msgq, False,
                                                    False)

        OUT = blocks.file_sink(gr.sizeof_char, options.output_file)

        if options.one_channel:
            self.connect(IN, C2F, F2C, (MIXER, 0))
        else:
            self.connect(IN, (MIXER, 0))
        self.connect(LO, (MIXER, 1))
        self.connect(MIXER, AMP, DECIM, DEMOD, DIFF, TOFLOAT, RESCALE,
                     POLARITY, SLICER, DECODER, OUT)

        if options.raw_symbols:
            SINKC = blocks.file_sink(gr.sizeof_char, options.raw_symbols)
            self.connect(SLICER, SINKC)

        if options.debug:
            print 'Ready for GDB to attach (pid = %d)' % (os.getpid(), )
            raw_input("Press 'Enter' to continue...")
    def __init__(self, system, site_uuid, overseer_uuid):

        gr.top_block.__init__(self, "p25 receiver")

        #set globals
        self.is_locked = False
        self.system = system
        self.instance_uuid = '%s' % uuid.uuid4()

        self.log = logging.getLogger('overseer.p25_control_demod.%s' %
                                     self.instance_uuid)
        self.protocol_log = logging.getLogger('protocol.%s' %
                                              self.instance_uuid)
        self.log.info('Initializing instance: %s site: %s overseer: %s' %
                      (self.instance_uuid, site_uuid, overseer_uuid))

        self.site_uuid = site_uuid
        self.overseer_uuid = overseer_uuid

        self.control_channel = system['channels'][
            system['default_control_channel']]
        self.control_channel_i = system['default_control_channel']

        self.channel_identifier_table = {}

        try:
            self.modulation = system['modulation']
        except:
            self.modulation = 'C4FM'

        self.channel_rate = 12500
        symbol_rate = 4800

        self.site_detail = {}
        self.site_detail['WACN ID'] = None
        self.site_detail['System ID'] = None
        self.site_detail['Control Channel'] = None
        self.site_detail['System Service Class'] = None
        self.site_detail['Site ID'] = None
        self.site_detail['RF Sub-system ID'] = None
        self.site_detail['RFSS Network Connection'] = None

        self.bad_messages = 0
        self.total_messages = 0
        self.quality = []

        self.keep_running = True

        self.source = None

        # channel filter
        channel_rate = self.channel_rate * 2
        self.control_prefilter = filter.freq_xlating_fir_filter_ccc(
            1, (1, ), 0, channel_rate)

        # power squelch
        #power_squelch = gr.pwr_squelch_cc(squelch, 1e-3, 0, True)
        #self.connect(self.channel_filter, power_squelch)

        autotuneq = gr.msg_queue(2)
        self.demod_watcher = demod_watcher(self)
        self.symbol_deviation = 600.0

        if self.modulation == 'C4FM':
            # FM demodulator
            fm_demod_gain = channel_rate / (2.0 * pi * self.symbol_deviation)
            self.fm_demod = fm_demod = analog.quadrature_demod_cf(
                fm_demod_gain)

            moving_sum = blocks.moving_average_ff(10000, 1, 40000)
            subtract = blocks.sub_ff(1)
            divide_const = blocks.multiply_const_vff((0.0001, ))
            self.probe = blocks.probe_signal_f()
            self.connect(self.fm_demod, moving_sum, divide_const, self.probe)

            # symbol filter
            symbol_decim = 1
            samples_per_symbol = channel_rate // symbol_rate
            symbol_coeffs = (1.0 / samples_per_symbol, ) * samples_per_symbol
            symbol_filter = filter.fir_filter_fff(symbol_decim, symbol_coeffs)

            demod_fsk4 = op25.fsk4_demod_ff(autotuneq, channel_rate,
                                            symbol_rate)
        elif self.modulation == 'CQPSK':
            # FM demodulator
            fm_demod_gain = channel_rate / (2.0 * pi * self.symbol_deviation)
            self.fm_demod = fm_demod = analog.quadrature_demod_cf(
                fm_demod_gain)

            moving_sum = blocks.moving_average_ff(10000, 1, 40000)
            subtract = blocks.sub_ff(1)
            divide_const = blocks.multiply_const_vff((0.0001, ))
            self.probe = blocks.probe_signal_f()
            self.connect(fm_demod, moving_sum, divide_const, self.probe)

            #self.resampler = filter.pfb.arb_resampler_ccf(float(48000)/float(channel_rate))
            self.resampler = blocks.multiply_const_cc(1.0)
            self.agc = analog.feedforward_agc_cc(1024, 1.0)
            self.symbol_filter_c = blocks.multiply_const_cc(1.0)

            gain_mu = 0.025
            omega = float(channel_rate) / float(symbol_rate)
            gain_omega = 0.1 * gain_mu * gain_mu

            alpha = 0.04
            beta = 0.125 * alpha * alpha
            fmax = 1200  # Hz
            fmax = 2 * pi * fmax / float(channel_rate)

            self.clock = repeater.gardner_costas_cc(omega, gain_mu, gain_omega,
                                                    alpha, beta, fmax, -fmax)
            self.diffdec = digital.diff_phasor_cc()
            self.to_float = blocks.complex_to_arg()
            self.rescale = blocks.multiply_const_ff((1 / (pi / 4)))

    # symbol slicer
        levels = [-2.0, 0.0, 2.0, 4.0]
        slicer = op25.fsk4_slicer_fb(levels)

        # frame decoder
        self.decodequeue = decodequeue = gr.msg_queue(1000)
        qsink = blocks.message_sink(gr.sizeof_char, self.decodequeue, False)
        self.decoder = decoder = repeater.p25_frame_assembler(
            '', 0, 0, False, True, True, autotuneq, False, False)

        if self.modulation == 'C4FM':
            self.connect(self.control_prefilter, fm_demod, symbol_filter,
                         demod_fsk4, slicer, decoder, qsink)
        elif self.modulation == 'CQPSK':
            self.connect(self.resampler, self.agc, self.symbol_filter_c,
                         self.clock, self.diffdec, self.to_float, self.rescale,
                         slicer, decoder, qsink)

##################################################
# Threads
##################################################
        self.connector = frontend_connector()
        self.client_redis = client_redis()
        self.redis_demod_publisher = redis_demod_publisher(parent_demod=self)

        quality_check_0 = threading.Thread(target=self.quality_check)
        quality_check_0.daemon = True
        quality_check_0.start()
        # Adjust the channel offset
        #
        self.tune_next_control_channel()

        #self.receive_engine()

        receive_engine = threading.Thread(target=self.receive_engine)
        receive_engine.daemon = True
        receive_engine.start()
Example #11
0
    def __init__(self):
        gr.top_block.__init__(self, "Tetra Rx Multi")

        options = self.get_options()

        ##################################################
        # Variables
        ##################################################
        self.srate_rx = srate_rx = options.sample_rate
        self.channels = srate_rx / 25000
        self.srate_channel = 36000
        self.afc_period = 5
        self.afc_gain = 1.
        self.afc_channel = options.auto_tune or -1
        self.afc_ppm_step = 100
        self.debug = options.debug
        self.last_pwr = -100000
        self.sig_det_period = 1
        self.sig_det_bw = sig_det_bw = options.sig_detection_bw or srate_rx
        if self.sig_det_bw <= 1.:
            self.sig_det_bw *= srate_rx
        self.sig_det_threshold = options.sig_detection_threshold
        self.sig_det_channels = []
        for ch in range(self.channels):
            if ch >= self.channels / 2:
                ch_ = (self.channels - ch - 1)
            else:
                ch_ = ch
            if (float(ch_) / self.channels * 2) <= (self.sig_det_bw /
                                                    srate_rx):
                self.sig_det_channels.append(ch)

        ##################################################
        # RPC server
        ##################################################
        self.xmlrpc_server = SimpleXMLRPCServer.SimpleXMLRPCServer(
            ("localhost", options.listen_port), allow_none=True)
        self.xmlrpc_server.register_instance(self)
        threading.Thread(target=self.xmlrpc_server.serve_forever).start()

        ##################################################
        # Rx Blocks and connections
        ##################################################
        self.src = osmosdr.source(args=options.args)
        self.src.set_sample_rate(srate_rx)
        self.src.set_center_freq(options.frequency, 0)
        self.src.set_freq_corr(options.ppm, 0)
        self.src.set_dc_offset_mode(0, 0)
        self.src.set_iq_balance_mode(0, 0)
        if options.gain is not None:
            self.src.set_gain_mode(False, 0)
            self.src.set_gain(36, 0)
        else:
            self.src.set_gain_mode(True, 0)

        out_type, dst_path = options.output.split("://", 1)
        if out_type == "udp":
            dst_ip, dst_port = dst_path.split(':', 1)

        self.freq_xlating = freq_xlating_fft_filter_ccc(1, (1, ), 0, srate_rx)

        self.channelizer = pfb.channelizer_ccf(
            self.channels,
            (firdes.root_raised_cosine(1, srate_rx, 18000, 0.35, 1024)),
            36. / 25., 100)

        self.squelch = []
        self.digital_mpsk_receiver_cc = []
        self.diff_phasor = []
        self.complex_to_arg = []
        self.multiply_const = []
        self.add_const = []
        self.float_to_uchar = []
        self.map_bits = []
        self.unpack_k_bits = []
        self.blocks_sink = []
        for ch in range(0, self.channels):
            squelch = analog.pwr_squelch_cc(0, 0.001, 0, True)
            mpsk = digital.mpsk_receiver_cc(4, math.pi / 4, math.pi / 100.0,
                                            -0.5, 0.5, 0.25, 0.001, 2, 0.001,
                                            0.001)
            diff_phasor = digital.diff_phasor_cc()
            complex_to_arg = blocks.complex_to_arg(1)
            multiply_const = blocks.multiply_const_vff((2. / math.pi, ))
            add_const = blocks.add_const_vff((1.5, ))
            float_to_uchar = blocks.float_to_uchar()
            map_bits = digital.map_bb(([3, 2, 0, 1, 3]))
            unpack_k_bits = blocks.unpack_k_bits_bb(2)

            if out_type == 'udp':
                sink = blocks.udp_sink(gr.sizeof_gr_char, dst_ip,
                                       int(dst_port) + ch, 1472, True)
            elif out_type == 'file':
                sink = blocks.file_sink(gr.sizeof_char, dst_path % ch, False)
                sink.set_unbuffered(True)
            else:
                raise ValueError("Invalid output URL '%s'" % options.output)

            self.connect((self.channelizer, ch), (squelch, 0), (mpsk, 0),
                         (diff_phasor, 0), (complex_to_arg, 0),
                         (multiply_const, 0), (add_const, 0),
                         (float_to_uchar, 0), (map_bits, 0),
                         (unpack_k_bits, 0), (sink, 0))

            self.squelch.append(squelch)
            self.digital_mpsk_receiver_cc.append(mpsk)
            self.diff_phasor.append(diff_phasor)
            self.complex_to_arg.append(complex_to_arg)
            self.multiply_const.append(multiply_const)
            self.add_const.append(add_const)
            self.float_to_uchar.append(float_to_uchar)
            self.map_bits.append(map_bits)
            self.unpack_k_bits.append(unpack_k_bits)
            self.blocks_sink.append(sink)

        self.connect((self.src, 0), (self.freq_xlating, 0),
                     (self.channelizer, 0))

        ##################################################
        # signal strenght identification
        ##################################################
        self.pwr_probes = []
        for ch in range(self.channels):
            pwr_probe = analog.probe_avg_mag_sqrd_c(0, 1. / self.srate_channel)
            self.pwr_probes.append(pwr_probe)
            self.connect((self.channelizer, ch), (pwr_probe, 0))

        def _sig_det_probe():
            while True:
                pwr = [
                    self.pwr_probes[ch].level() for ch in range(self.channels)
                    if ch in self.sig_det_channels
                ]
                pwr = [10 * math.log10(p) for p in pwr if p > 0.]
                if not pwr:
                    continue
                pwr = min(pwr) + self.sig_det_threshold
                print "Power level for squelch % 5.1f" % pwr
                if abs(pwr - self.last_pwr) > (self.sig_det_threshold / 2):
                    for s in self.squelch:
                        s.set_threshold(pwr)
                    self.last_pwr = pwr
                time.sleep(self.sig_det_period)

        if self.sig_det_threshold is not None:
            self._sig_det_probe_thread = threading.Thread(
                target=_sig_det_probe)
            self._sig_det_probe_thread.daemon = True
            self._sig_det_probe_thread.start()

        ##################################################
        # AFC blocks and connections
        ##################################################
        self.afc_selector = grc_blks2.selector(
            item_size=gr.sizeof_gr_complex,
            num_inputs=self.channels,
            num_outputs=1,
            input_index=0,
            output_index=0,
        )

        self.afc_demod = analog.quadrature_demod_cf(self.srate_channel /
                                                    (2 * math.pi))
        samp_afc = self.srate_channel * self.afc_period / 2
        self.afc_avg = blocks.moving_average_ff(samp_afc,
                                                1. / samp_afc * self.afc_gain)
        self.afc_probe = blocks.probe_signal_f()

        def _afc_probe():
            while True:
                time.sleep(self.afc_period)
                if self.afc_channel == -1:
                    continue
                err = self.afc_probe.level()
                if abs(err) < self.afc_ppm_step:
                    continue
                freq = self.freq_xlating.center_freq + err * self.afc_gain
                if self.debug:
                    print "err: %f\tfreq: %f" % (
                        err,
                        freq,
                    )
                self.freq_xlating.set_center_freq(freq)

        self._afc_err_thread = threading.Thread(target=_afc_probe)
        self._afc_err_thread.daemon = True
        self._afc_err_thread.start()

        for ch in range(self.channels):
            self.connect((self.channelizer, ch), (self.afc_selector, ch))
        self.connect((self.afc_selector, 0), (self.afc_demod, 0),
                     (self.afc_avg, 0), (self.afc_probe, 0))

        if self.afc_channel != -1:
            self.afc_selector.set_input_index(self.afc_channel)
Example #12
0
    def configure_blocks(self, protocol):
        if protocol == 'provoice' or protocol == 'analog_edacs':
            protocol = 'analog'
        self.log.debug('configure_blocks(%s)' % protocol)
        if not (protocol == 'p25' or protocol == 'p25_tdma'
                or protocol == 'p25_cqpsk' or protocol == 'p25_cqpsk_tdma'
                or protocol == 'provoice' or protocol == 'dsd_p25'
                or protocol == 'analog' or protocol == 'none'):
            raise Exception('Invalid protocol %s' % protocol)
        if self.protocol == protocol:
            return True
        self.lock()
        if self.protocol == 'analog':
            self.disconnect(self.source, self.signal_squelch, self.audiodemod,
                            self.high_pass, self.resampler, self.sink)
            self.signal_squelch = None
            self.audiodemod = None
            self.high_pass = None
            self.resampler = None

        elif self.protocol == 'p25' or 'p25_tdma':
            try:
                self.disconnect(self.source, self.prefilter,
                                self.fm_demod)  #, (self.subtract,0))
                self.disconnect(self.fm_demod, self.symbol_filter,
                                self.demod_fsk4, self.slicer, self.decoder,
                                self.float_conversion, self.sink)
                self.disconnect(self.slicer, self.decoder2, self.qsink)
                self.demod_watcher.keep_running = False

            except:
                pass
            #self.disconnect(self.fm_demod, self.avg, self.mult, (self.subtract,1))

            self.prefilter = None
            self.fm_demod = None
            #self.avg = None
            #self.mult = None
            #self.subtract = None
            self.symbol_filter = None
            self.demod_fsk4 = None
            self.slicer = None
            self.decoder = None
            self.decoder2 = None
            self.qsink = None
            self.imbe = None
            self.float_conversion = None
            self.resampler = None
        elif self.protocol == 'p25_cqpsk' or self.protocol == 'p25_cqpsk_tdma':
            self.disconnect(self.source, self.resampler, self.agc,
                            self.symbol_filter_c, self.clock, self.diffdec,
                            self.to_float, self.rescale, self.slicer,
                            self.decoder2, self.qsink)  #, (self.subtract,0))
            self.disconnect(self.slicer, self.decoder, self.float_conversion,
                            self.sink)

            self.prefilter = None
            self.resampler = None
            self.agc = None
            self.symbol_filter_c = None
            self.clock = None
            self.diffdec = None
            self.to_float = None
            self.rescale = None
            self.slicer = None

            self.imbe = None
            self.decodequeue3 = None
            self.decodequeue2 = None
            self.decodequeue = None

            self.demod_watcher = None
            self.decoder = None
            self.decoder2 = None
            self.qsink = None
            self.float_conversion = None

        elif self.protocol == 'provoice':
            self.disconnect(self.source, self.fm_demod, self.resampler_in,
                            self.dsd, self.out_squelch, self.sink)
            self.fm_demod = None
            self.resampler_in = None
            self.dsd = None
            self.out_squelch = None
        elif self.protocol == 'dsd_p25':
            self.disconnect(self.source, self.fm_demod, self.resampler_in,
                            self.dsd, self.sink)
            self.fm_demod = None
            self.resampler_in = None
            self.dsd = None
        self.protocol = protocol

        if protocol == 'analog':
            self.signal_squelch = analog.pwr_squelch_cc(-100, 0.01, 0, True)
            #self.tone_squelch = gr.tone_squelch_ff(audiorate, 4800.0, 0.05, 300, 0, True)
            #tone squelch is EDACS ONLY
            self.audiodemod = analog.fm_demod_cf(
                channel_rate=self.input_rate,
                audio_decim=1,
                deviation=15000,
                audio_pass=(self.input_rate * 0.25),
                audio_stop=((self.input_rate * 0.25) + 2000),
                gain=8,
                tau=75e-6)
            self.high_pass = filter.fir_filter_fff(
                1,
                firdes.high_pass(1, self.input_rate, 300, 30,
                                 firdes.WIN_HAMMING, 6.76))
            self.resampler = filter.rational_resampler_fff(
                interpolation=8000,
                decimation=self.input_rate,
                taps=None,
                fractional_bw=None,
            )
            self.connect(self.source, self.signal_squelch, self.audiodemod,
                         self.high_pass, self.resampler, self.sink)
        elif protocol == 'p25' or protocol == 'p25_tdma':
            self.symbol_deviation = symbol_deviation = 600.0
            if protocol == 'p25_tdma':
                symbol_rate = 6000
            else:
                symbol_rate = 4800
            channel_rate = self.input_rate

            self.prefilter = filter.freq_xlating_fir_filter_ccc(
                1, (1, ), 0, self.input_rate)

            fm_demod_gain = channel_rate / (2.0 * pi * symbol_deviation)
            self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

            #self.avg = blocks.moving_average_ff(1000, 1, 4000)
            #self.mult = blocks.multiply_const_vff((0.001, ))
            #self.subtract = blocks.sub_ff(1)

            symbol_decim = 1
            samples_per_symbol = channel_rate // symbol_rate
            symbol_coeffs = (1.0 / samples_per_symbol, ) * samples_per_symbol
            self.symbol_filter = filter.fir_filter_fff(symbol_decim,
                                                       symbol_coeffs)

            autotuneq = gr.msg_queue(2)
            self.demod_fsk4 = op25.fsk4_demod_ff(autotuneq, channel_rate,
                                                 symbol_rate)

            # symbol slicer
            levels = [-2.0, 0.0, 2.0, 4.0]
            self.slicer = op25.fsk4_slicer_fb(levels)

            self.imbe = repeater.vocoder(False, True, 0, "", 0, False)
            self.decodequeue3 = decodequeue3 = gr.msg_queue(10000)
            self.decodequeue2 = decodequeue2 = gr.msg_queue(10000)
            self.decodequeue = decodequeue = gr.msg_queue(10000)

            self.demod_watcher = None  #demod_watcher(decodequeue2, self.adjust_channel_offset)

            self.decoder = repeater.p25_frame_assembler(
                '', 0, 0, True, True, False, decodequeue2, True,
                (True if protocol == 'p25_tdma' else False))
            self.decoder2 = repeater.p25_frame_assembler(
                '', 0, 0, False, True, False, decodequeue3, False, False)

            self.qsink = blocks.message_sink(gr.sizeof_char, self.decodequeue,
                                             False)

            self.float_conversion = blocks.short_to_float(1, 8192)

            self.connect(self.source, self.prefilter,
                         self.fm_demod)  #, (self.subtract,0))
            #self.connect(self.fm_demod, self.symbol_filter, self.demod_fsk4, self.slicer, self.decoder, self.imbe, self.float_conversion, self.sink)
            self.connect(self.fm_demod, self.symbol_filter, self.demod_fsk4,
                         self.slicer, self.decoder, self.float_conversion,
                         self.sink)
            self.connect(self.slicer, self.decoder2, self.qsink)
            #self.connect(self.fm_demod, self.avg, self.mult, (self.subtract,1))
        elif protocol == 'p25_cqpsk' or protocol == 'p25_cqpsk_tdma':
            self.symbol_deviation = symbol_deviation = 600.0
            self.resampler = blocks.multiply_const_cc(1.0)
            self.agc = analog.feedforward_agc_cc(1024, 1.0)
            self.symbol_filter_c = blocks.multiply_const_cc(1.0)

            gain_mu = 0.025
            if protocol == 'p25_cqpsk_tdma':
                symbol_rate = 6000
            else:
                symbol_rate = 4800
            omega = float(self.input_rate) / float(symbol_rate)
            gain_omega = 0.1 * gain_mu * gain_mu

            alpha = 0.04
            beta = 0.125 * alpha * alpha
            fmax = 1200  # Hz
            fmax = 2 * pi * fmax / float(self.input_rate)

            self.clock = repeater.gardner_costas_cc(omega, gain_mu, gain_omega,
                                                    alpha, beta, fmax, -fmax)
            self.diffdec = digital.diff_phasor_cc()
            self.to_float = blocks.complex_to_arg()
            self.rescale = blocks.multiply_const_ff((1 / (pi / 4)))

            # symbol slicer
            levels = [-2.0, 0.0, 2.0, 4.0]
            self.slicer = op25.fsk4_slicer_fb(levels)

            #self.imbe = repeater.vocoder(False, True, 0, "", 0, False)
            self.decodequeue3 = decodequeue3 = gr.msg_queue(2)
            self.decodequeue2 = decodequeue2 = gr.msg_queue(2)
            self.decodequeue = decodequeue = gr.msg_queue(10000)

            #self.demod_watcher = demod_watcher(decodequeue2, self.adjust_channel_offset)
            self.decoder = repeater.p25_frame_assembler(
                '', 0, 0, True, True, False, decodequeue2, True,
                (False if protocol == 'p25_cqpsk' else True))
            self.decoder2 = repeater.p25_frame_assembler(
                '', 0, 0, False, True, True, decodequeue3, False, False)

            #temp for debug
            #self.debug_sink = blocks.file_sink(1, '/dev/null')
            #self.connect(self.slicer, self.debug_sink)

            self.qsink = blocks.message_sink(gr.sizeof_char, self.decodequeue,
                                             False)

            self.float_conversion = blocks.short_to_float(1, 8192)

            self.connect(self.source, self.resampler, self.agc,
                         self.symbol_filter_c, self.clock, self.diffdec,
                         self.to_float, self.rescale, self.slicer,
                         self.decoder2, self.qsink)  #, (self.subtract,0))
            self.connect(self.slicer, self.decoder, self.float_conversion,
                         self.sink)
        elif protocol == 'provoice':
            fm_demod_gain = 0.6
            self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

            self.resampler_in = filter.rational_resampler_fff(
                interpolation=48000,
                decimation=self.input_rate,
                taps=None,
                fractional_bw=None,
            )
            self.dsd = dsd.block_ff(dsd.dsd_FRAME_PROVOICE,
                                    dsd.dsd_MOD_AUTO_SELECT, 3, 0, False)
            self.out_squelch = analog.pwr_squelch_ff(-100, 0.01, 0, True)

            self.connect(self.source, self.fm_demod, self.resampler_in,
                         self.dsd, self.out_squelch, self.sink)
        elif protocol == 'dsd_p25':
            symbol_deviation = 600.0
            fm_demod_gain = 0.4  #self.input_rate / (2.0 * pi * symbol_deviation)
            self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

            self.resampler_in = filter.rational_resampler_fff(
                interpolation=48000,
                decimation=self.input_rate,
                taps=None,
                fractional_bw=None,
            )
            self.dsd = dsd.block_ff(dsd.dsd_FRAME_P25_PHASE_1,
                                    dsd.dsd_MOD_AUTO_SELECT, 3, 3, False)

            self.connect(self.source, self.fm_demod, self.resampler_in,
                         self.dsd, self.sink)
        self.unlock()
Example #13
0
    def __init__(self):
        grc_wxgui.top_block_gui.__init__(self, title="Psk31 Rx")
        _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
        self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

        ##################################################
        # Variables
        ##################################################
        self.center_freq = center_freq = 441000000
        self.samp_rate = samp_rate = 960000
        self.psk_offset = psk_offset = 1000
        self.psk_center = psk_center = center_freq + 141000
        self.int_rate = int_rate = 48000
        self.gain = gain = 30
        self.corr = corr = 0
        self.audio_rate = audio_rate = 8000

        ##################################################
        # Message Queues
        ##################################################
        blocks_message_sink_0_msgq_out = wxgui_termsink_0_msgq_in = gr.msg_queue(
            2)

        ##################################################
        # Blocks
        ##################################################
        _psk_offset_sizer = wx.BoxSizer(wx.VERTICAL)
        self._psk_offset_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_psk_offset_sizer,
            value=self.psk_offset,
            callback=self.set_psk_offset,
            label="PSK offset",
            converter=forms.float_converter(),
            proportion=0,
        )
        self._psk_offset_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_psk_offset_sizer,
            value=self.psk_offset,
            callback=self.set_psk_offset,
            minimum=0,
            maximum=3000,
            num_steps=300,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_psk_offset_sizer, 1, 0, 1, 2)
        _psk_center_sizer = wx.BoxSizer(wx.VERTICAL)
        self._psk_center_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_psk_center_sizer,
            value=self.psk_center,
            callback=self.set_psk_center,
            label="Tuning",
            converter=forms.float_converter(),
            proportion=0,
        )
        self._psk_center_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_psk_center_sizer,
            value=self.psk_center,
            callback=self.set_psk_center,
            minimum=center_freq + 110000,
            maximum=center_freq + 150000,
            num_steps=40,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_psk_center_sizer, 0, 0, 1, 2)
        self.nb = self.nb = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
        self.nb.AddPage(grc_wxgui.Panel(self.nb), "960 kHz")
        self.nb.AddPage(grc_wxgui.Panel(self.nb), "48 kHz")
        self.nb.AddPage(grc_wxgui.Panel(self.nb), "4 kHz")
        self.nb.AddPage(grc_wxgui.Panel(self.nb), "I/Q scope")
        self.nb.AddPage(grc_wxgui.Panel(self.nb), "Constellation")
        self.GridAdd(self.nb, 3, 0, 1, 2)
        _gain_sizer = wx.BoxSizer(wx.VERTICAL)
        self._gain_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_gain_sizer,
            value=self.gain,
            callback=self.set_gain,
            label='gain',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._gain_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_gain_sizer,
            value=self.gain,
            callback=self.set_gain,
            minimum=0,
            maximum=49.6,
            num_steps=124,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_gain_sizer, 2, 0, 1, 1)
        _corr_sizer = wx.BoxSizer(wx.VERTICAL)
        self._corr_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_corr_sizer,
            value=self.corr,
            callback=self.set_corr,
            label='corr',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._corr_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_corr_sizer,
            value=self.corr,
            callback=self.set_corr,
            minimum=-150,
            maximum=150,
            num_steps=300,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_corr_sizer, 2, 1, 1, 1)
        self.wxgui_waterfallsink2_2 = waterfallsink2.waterfall_sink_f(
            self.nb.GetPage(2).GetWin(),
            baseband_freq=0,
            dynamic_range=30,
            ref_level=-40,
            ref_scale=2.0,
            sample_rate=audio_rate,
            fft_size=512,
            fft_rate=15,
            average=False,
            avg_alpha=None,
            title="Waterfall Plot",
            win=window.blackmanharris,
            size=((800, 400)),
        )
        self.nb.GetPage(2).Add(self.wxgui_waterfallsink2_2.win)

        def wxgui_waterfallsink2_2_callback(x, y):
            self.set_psk_offset(x)

        self.wxgui_waterfallsink2_2.set_callback(
            wxgui_waterfallsink2_2_callback)
        self.wxgui_waterfallsink2_1 = waterfallsink2.waterfall_sink_c(
            self.nb.GetPage(1).GetWin(),
            baseband_freq=psk_center,
            dynamic_range=30,
            ref_level=-30,
            ref_scale=2.0,
            sample_rate=int_rate,
            fft_size=2048,
            fft_rate=15,
            average=False,
            avg_alpha=None,
            title="Waterfall Plot",
            size=((800, 400)),
        )
        self.nb.GetPage(1).Add(self.wxgui_waterfallsink2_1.win)
        self.wxgui_waterfallsink2_0 = waterfallsink2.waterfall_sink_c(
            self.nb.GetPage(0).GetWin(),
            baseband_freq=center_freq,
            dynamic_range=30,
            ref_level=-20,
            ref_scale=2.0,
            sample_rate=samp_rate,
            fft_size=2048,
            fft_rate=15,
            average=False,
            avg_alpha=None,
            title="Waterfall Plot",
            size=((800, 400)),
        )
        self.nb.GetPage(0).Add(self.wxgui_waterfallsink2_0.win)

        def wxgui_waterfallsink2_0_callback(x, y):
            self.set_psk_center(x)

        self.wxgui_waterfallsink2_0.set_callback(
            wxgui_waterfallsink2_0_callback)
        self.wxgui_termsink_0 = termsink.termsink(
            parent=self.GetWin(),
            size=(500, 100),
            msgq=wxgui_termsink_0_msgq_in,
        )
        self.Add(self.wxgui_termsink_0)
        self.wxgui_scopesink2_1 = scopesink2.scope_sink_c(
            self.nb.GetPage(4).GetWin(),
            title="Scope Plot",
            sample_rate=31.25,
            v_scale=0.4,
            v_offset=0,
            t_scale=0,
            ac_couple=False,
            xy_mode=True,
            num_inputs=1,
            trig_mode=wxgui.TRIG_MODE_AUTO,
            y_axis_label="Counts",
        )
        self.nb.GetPage(4).Add(self.wxgui_scopesink2_1.win)
        self.wxgui_scopesink2_0 = scopesink2.scope_sink_c(
            self.nb.GetPage(3).GetWin(),
            title="Scope Plot",
            sample_rate=500,
            v_scale=0.4,
            v_offset=0,
            t_scale=0,
            ac_couple=False,
            xy_mode=True,
            num_inputs=1,
            trig_mode=wxgui.TRIG_MODE_AUTO,
            y_axis_label="Counts",
        )
        self.nb.GetPage(3).Add(self.wxgui_scopesink2_0.win)
        self.wxgui_numbersink2_0 = numbersink2.number_sink_f(
            self.GetWin(),
            unit="Hz",
            minval=-500 / math.pi,
            maxval=500 / math.pi,
            factor=500 / math.pi,
            decimal_places=1,
            ref_level=0,
            sample_rate=500,
            number_rate=15,
            average=False,
            avg_alpha=None,
            label="Carrier tracking offset",
            peak_hold=False,
            show_gauge=True,
        )
        self.Add(self.wxgui_numbersink2_0.win)
        self.osmosdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " +
                                               "")
        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(corr, 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(0, 0)
        self.osmosdr_source_0.set_gain(gain, 0)
        self.osmosdr_source_0.set_if_gain(20, 0)
        self.osmosdr_source_0.set_bb_gain(20, 0)
        self.osmosdr_source_0.set_antenna("", 0)
        self.osmosdr_source_0.set_bandwidth(0, 0)

        self.ham_varicode_rx_0 = ham.varicode_rx()
        self.freq_xlating_fir_filter_xxx_1 = filter.freq_xlating_fir_filter_ccc(
            16, (firdes.low_pass(10, audio_rate, 120, 40, firdes.WIN_HAMMING,
                                 6.76)), psk_offset, audio_rate)
        self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(
            samp_rate / int_rate, (firdes.low_pass(1, samp_rate, 12000, 12000,
                                                   firdes.WIN_HAMMING, 6.76)),
            round(psk_center - center_freq, -3), samp_rate)
        self.digital_diff_phasor_cc_0 = digital.diff_phasor_cc()
        self.digital_costas_loop_cc_0 = digital.costas_loop_cc(
            5 * math.pi / 100.0, 2)
        self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_cc(
            16, 0.25 * 0.175 * 0.175, 0.5, 0.175, 0.005)
        self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb()
        self.blocks_message_sink_0 = blocks.message_sink(
            gr.sizeof_char * 1, blocks_message_sink_0_msgq_out, True)
        self.blocks_complex_to_real_1 = blocks.complex_to_real(1)
        self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
        self.band_pass_filter_0 = filter.fir_filter_ccc(
            int_rate / audio_rate,
            firdes.complex_band_pass(1, int_rate, 200, 2800, 200,
                                     firdes.WIN_HAMMING, 6.76))
        self.audio_sink_0 = audio.sink(audio_rate, "plughw:0,0", True)
        self.analog_agc_xx_0 = analog.agc_cc(1e-3, 0.1, 1.0)
        self.analog_agc_xx_0.set_max_gain(65536)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.freq_xlating_fir_filter_xxx_0, 0),
                     (self.wxgui_waterfallsink2_1, 0))
        self.connect((self.osmosdr_source_0, 0),
                     (self.wxgui_waterfallsink2_0, 0))
        self.connect((self.osmosdr_source_0, 0),
                     (self.freq_xlating_fir_filter_xxx_0, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_0, 0),
                     (self.band_pass_filter_0, 0))
        self.connect((self.blocks_complex_to_real_0, 0),
                     (self.wxgui_waterfallsink2_2, 0))
        self.connect((self.digital_costas_loop_cc_0, 1),
                     (self.wxgui_numbersink2_0, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_1, 0),
                     (self.digital_costas_loop_cc_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 0),
                     (self.wxgui_scopesink2_0, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0),
                     (self.digital_diff_phasor_cc_0, 0))
        self.connect((self.digital_costas_loop_cc_0, 0),
                     (self.digital_clock_recovery_mm_xx_0, 0))
        self.connect((self.ham_varicode_rx_0, 0),
                     (self.blocks_message_sink_0, 0))
        self.connect((self.digital_binary_slicer_fb_0, 0),
                     (self.ham_varicode_rx_0, 0))
        self.connect((self.blocks_complex_to_real_1, 0),
                     (self.digital_binary_slicer_fb_0, 0))
        self.connect((self.digital_diff_phasor_cc_0, 0),
                     (self.blocks_complex_to_real_1, 0))
        self.connect((self.blocks_complex_to_real_0, 0),
                     (self.audio_sink_0, 0))
        self.connect((self.band_pass_filter_0, 0), (self.analog_agc_xx_0, 0))
        self.connect((self.analog_agc_xx_0, 0),
                     (self.blocks_complex_to_real_0, 0))
        self.connect((self.analog_agc_xx_0, 0),
                     (self.freq_xlating_fir_filter_xxx_1, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0),
                     (self.wxgui_scopesink2_1, 0))