Ejemplo n.º 1
0
    def __init__(self):
        gr.top_block.__init__(self, "Borip Eb500")

        ##################################################
        # Variables
        ##################################################
        self.udp_port = udp_port = 19855
        self.samp_rate = samp_rate = 640000
        self.freq = freq = 14200000

        ##################################################
        # Blocks
        ##################################################
        self.sink = baz.udp_sink(gr.sizeof_short * 1, '127.0.0.1', 28888, 1472,
                                 False, True)
        self.eb500_control_0 = eb500.EB500Control(freq, samp_rate, 'eb500',
                                                  udp_port)
        self.eb200_if_stream_decode_0 = eb200.if_stream_decode(False)
        self.blocks_udp = blocks.udp_source(gr.sizeof_char * 1, '192.168.1.32',
                                            udp_port, 32796, False)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.sink, 0))
        self.connect((self.blocks_udp, 0), (self.eb200_if_stream_decode_0, 0))
        self.connect((self.eb200_if_stream_decode_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
Ejemplo n.º 2
0
def test_stacked_tx_commands():

    # Crimson TNG setup.
    channels = range(4)
    sample_rate = 20e6
    sample_count = int(sample_rate)

    # Waveform setup.
    wave_center = 15e6
    wave_freq = 1.0e6
    wave_ampl = 2.0e4

    # Generates complex samples.
    sigs = [
        analog.sig_source_c(sample_rate, analog.GR_SIN_WAVE, wave_freq,
                            wave_ampl, 0.0) for ch in channels
    ]

    # Stops flowgraph when sample size is reached.
    heds = [blocks.head(gr.sizeof_gr_complex, sample_count) for ch in channels]

    # Converts complex floats to interleaved shorts.
    c2ss = [blocks.complex_to_interleaved_short(True) for ch in channels]

    # Takes interleaved shorts and outputs to Crimson TNG.
    csnk = crimson.get_snk_s(channels, sample_rate, wave_center, 0.0)
    """                                       +-----------+
    +---------+   +---------+   +---------+   |           |
    | sigs[0] |-->| heds[0] |-->| c2ss[0] |-->|ch[0]      |
    +---------+   +---------+   +---------+   |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[1] |-->| heds[1] |-->| c2ss[1] |-->|ch[1]      |
    +---------+   +---------+   +---------+   |           |
                                              |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[N] |-->| heds[N] |-->| c2ss[N] |-->|ch[N]      |
    +---------+   +---------+   +---------+   |      csnk |
                                              +-----------+
    """

    # Connects flowgraph.
    flowgraph = gr.top_block()
    for ch in channels:
        flowgraph.connect(sigs[ch], heds[ch])
        flowgraph.connect(heds[ch], c2ss[ch])
        flowgraph.connect(c2ss[ch], (csnk, ch))

    # Runs each TX command at specified start times.
    csnk.set_time_now(uhd.time_spec(0.0))
    for second in range(5, 25, 5):
        csnk.set_start_time(uhd.time_spec(second))

        # Flowgraph stop running when head count is full.
        flowgraph.run()

        # Sets head count to zero for next TX command start time.
        for ch in channels:
            heds[ch].reset()
Ejemplo n.º 3
0
    def __init__(self, filename, dev_addrs,
                 onebit, gain, digital_gain, fs, fc, sync_pps):
        gr.top_block.__init__(self)

        if onebit:
            raise NotImplementedError("TODO: 1-bit mode not implemented.")
        
        uhd_srcs = [
            uhd.usrp_source(",".join(
                [addr, "num_recv_frames=256,recv_frame_size=16384"]),
                          uhd.stream_args(
                              cpu_format="fc32",
                              otwformat="sc16",
                              channels=[0]))
            for addr in dev_addrs]

        str2vec = blocks.streams_to_vector(2, len(uhd_srcs))
        self.connect(str2vec,
                     blocks.stream_to_vector(2 * len(uhd_srcs), 16*1024*1024),
                     blocks.file_sink(2 * len(uhd_srcs) * 16 * 1024 * 1024, filename, False))
        
        for ix, src in enumerate(uhd_srcs):
            src.set_clock_rate(fs*2, uhd.ALL_MBOARDS)
            src.set_samp_rate(fs)
            src.set_center_freq(uhd.tune_request(fc, 3e6))
            src.set_gain(gain, 0)
            # TODO Use offset tuning?
            if sync_pps:
                src.set_clock_source("external") # 10 MHz
                src.set_time_source("external") # PPS

            self.connect(src,  # [-1.0, 1.0]
                         blocks.multiply_const_cc(32767 * digital_gain[ix]), # [-32767.0, 32767.0]
                         blocks.complex_to_interleaved_short(), #[-32768, 32767]
                         blocks.short_to_char(), #[-128, 127]
                         blocks.stream_to_vector(1, 2), # I,Q,I,Q -> IQ, IQ
                         (str2vec, ix))

        print "Setting clocks..."
        if sync_pps:
            time.sleep(1.1) # Ensure there's been an edge.  TODO: necessary?
            last_pps_time = uhd_srcs[0].get_time_last_pps()
            while last_pps_time == uhd_srcs[0].get_time_last_pps():
                time.sleep(0.1)
            print "Got edge"
            [src.set_time_next_pps(uhd.time_spec(round(time.time())+1)) for src in uhd_srcs]
            time.sleep(1.0) # Wait for edge to set the clocks
        else:
            # No external PPS/10 MHz.  Just set each clock and accept some skew.
            t = time.time()
            [src.set_time_now(uhd.time_spec(time.time())) for src in uhd_srcs]
            if len(uhd_srcs) > 1:
                print "Uncabled; loosely synced only. Initial skew ~ %.1f ms" % (
                    (time.time()-t) * 1000)

        t_start = uhd.time_spec(time.time() + 1.5)
        [src.set_start_time(t_start) for src in uhd_srcs]
        print "ready"
Ejemplo n.º 4
0
 def test_complex_to_interleaved_short(self):
     src_data = (1+2j, 3+4j, 5+6j, 7+8j, 9+10j)
     expected_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
     src = blocks.vector_source_c(src_data)
     op = blocks.complex_to_interleaved_short()
     dst = blocks.vector_sink_s()
     self.tb.connect(src, op, dst)
     self.tb.run()
     self.assertEqual(expected_data, dst.data())
Ejemplo n.º 5
0
 def test_complex_to_interleaved_short(self):
     src_data = (1 + 2j, 3 + 4j, 5 + 6j, 7 + 8j, 9 + 10j)
     expected_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
     src = blocks.vector_source_c(src_data)
     op = blocks.complex_to_interleaved_short()
     dst = blocks.vector_sink_s()
     self.tb.connect(src, op, dst)
     self.tb.run()
     self.assertEqual(expected_data, dst.data())
Ejemplo n.º 6
0
    def __init__(self):

        gr.hier_block2.__init__(self, self.__class__.__name__,
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_short))

        self.clipper = Clipper(-1.0, 1.0)
        self.scaler = blocks.multiply_const_cc(C2IS_SCALE_FACTOR)
        self.c2is = blocks.complex_to_interleaved_short(vector=False)

        self.connect(self, self.clipper, self.scaler, self.c2is, self)
Ejemplo n.º 7
0
 def __init__(self, config):
     gr.top_block.__init__(self)
     ## Vars ##
     ## Interleaved Short input (sc16)
     if config['intype'] == SNAME_TO_ENUM['sc16']:
         fsrc = blocks.file_source(gr.sizeof_short * 1, config['infile'],
                                   False)
         # SEEK_SET is offset from beginning, sample_offset is in samples
         # Factor of 2 because vector of length 2 (since interleaved)
         fsrc.seek(config['sample_offset'] * 2, os.SEEK_SET)
         # sc16->fc32
         if config['outtype'] == SNAME_TO_ENUM['fc32']:
             ishort_to_cpxfloat = blocks.interleaved_short_to_complex(
                 False, False)
             # Copies sample_len then exits
             head = blocks.head(gr.sizeof_gr_complex * 1,
                                config['sample_len'])
             fsink = blocks.file_sink(gr.sizeof_gr_complex * 1,
                                      config['outfile'])
             self.connect(fsrc, ishort_to_cpxfloat, head, fsink)
         # sc16->sc16
         elif config['outtype'] == SNAME_TO_ENUM['sc16']:
             head = blocks.head(gr.sizeof_short, config['sample_len'])
             fsink = blocks.file_sink(gr.sizeof_short, config['outfile'])
             self.connect(fsrc, head, fsink)
     ## Complex float input (fc32)
     elif config['intype'] == SNAME_TO_ENUM['fc32']:
         fsrc = blocks.file_source(gr.sizeof_gr_complex * 1,
                                   config['infile'], False)
         # SEEK_SET is offset from beginning, sample_offset is in samples
         fsrc.seek(config['sample_offset'], os.SEEK_SET)
         # fc32->fc32
         if config['outtype'] == SNAME_TO_ENUM['fc32']:
             head = blocks.head(gr.sizeof_gr_complex * 1,
                                config['sample_len'])
             fsink = blocks.file_sink(gr.sizeof_gr_complex * 1,
                                      config['outfile'])
             self.connect(fsrc, head, fsink)
         # fc32->sc16
         elif config['outtype'] == SNAME_TO_ENUM['sc16']:
             cpxfloat_to_ishort = blocks.complex_to_interleaved_short(False)
             head = blocks.head(gr.sizeof_gr_complex * 1,
                                config['sample_len'])
             fsink = blocks.file_sink(gr.sizeof_short, config['outfile'])
             self.connect(fsrc, head, cpxfloat_to_ishort, fsink)
Ejemplo n.º 8
0
def run_tx(csnk, channels, stack, sample_rate, wave_freq):
    """                                       +-----------+
    +---------+   +---------+   +---------+   |           |
    | sigs[0] |-->| heds[0] |-->| c2ss[0] |-->|ch[0]      |
    +---------+   +---------+   +---------+   |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[1] |-->| heds[1] |-->| c2ss[1] |-->|ch[1]      |
    +---------+   +---------+   +---------+   |           |
                                              |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[N] |-->| heds[N] |-->| c2ss[N] |-->|ch[N]      |
    +---------+   +---------+   +---------+   |      csnk |
                                              +-----------+
    """
    for frame in stack:  #in fund_freq.py this is tx_stack

        # Connect.
        sigs = [
            analog.sig_source_c(sample_rate, analog.GR_SIN_WAVE, wave_freq,
                                2.0e4, 0.0) for ch in channels
        ]

        heds = [
            blocks.head(
                gr.sizeof_gr_complex, frame[1]
            )  #block_head=(sizeofstream_dataformat, nitems)= (sizeofgr_complex, frame[1]) = (16bit I & 16bit Q, tx_stack[ , it["sample_rate"]) in fund_freq test
            for ch in channels
        ]

        c2ss = [blocks.complex_to_interleaved_short(True) for ch in channels]

        flowgraph = gr.top_block()
        for ch in channels:
            flowgraph.connect(sigs[ch], heds[ch])
            flowgraph.connect(heds[ch], c2ss[ch])
            flowgraph.connect(c2ss[ch], (csnk, ch))

        # Run.
        csnk.set_start_time(uhd.time_spec(
            frame[0]))  #frame[0]= tx_stack[10, ] in fund_freq test
        flowgraph.run()
        #print("tx time spec is:", uhd.time_spec(frame[0]))
        for hed in heds:
            hed.reset()
Ejemplo n.º 9
0
    def __init__(self):
        gr.top_block.__init__(self, "Vdl2")

        ##################################################
        # Variables
        ##################################################
        self.center_freq = center_freq = 133e6

        ##################################################
        # Blocks
        ##################################################
        self.rational_resampler_xxx_0 = filter.rational_resampler_ccc(
            interpolation=105,
            decimation=100,
            taps=None,
            fractional_bw=None,
        )
        self.freq_xlating_fir_filter_xxx_0_1 = filter.freq_xlating_fir_filter_ccc(
            50, (firdes.complex_band_pass(1, 10e6, -50e3, 50e3, 5000)),
            136.975e6 - center_freq, 10e6)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((32767, ))
        self.blocks_file_source_0 = blocks.file_source(
            gr.sizeof_gr_complex * 1, "/tmp/decompress.iq", False)
        self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_short * 1,
                                                   "/tmp/vdl2.iq", False)
        self.blocks_file_sink_0.set_unbuffered(False)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_file_sink_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.freq_xlating_fir_filter_xxx_0_1, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.freq_xlating_fir_filter_xxx_0_1, 0),
                     (self.rational_resampler_xxx_0, 0))
        self.connect((self.rational_resampler_xxx_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
Ejemplo n.º 10
0
    def __init__(self, input_file, output_file):
        gr.top_block.__init__(self, "Uhd Shifter")

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 256000
        self.offset = offset = -25e3

        ##################################################
        # Blocks
        ##################################################
        self.signal_source = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE,
                                                 offset, 1, 0)
        self.resampler = filter.rational_resampler_ccc(
            interpolation=96,
            decimation=256,
            taps=None,
            fractional_bw=None,
        )
        self.multiply_const = blocks.multiply_const_vcc((32768, ))
        self.multi = blocks.multiply_vcc(1)
        self.file_source = blocks.file_source(gr.sizeof_gr_complex * 1,
                                              input_file, False)
        self.file_sink = blocks.file_sink(gr.sizeof_short * 1, output_file,
                                          False)
        self.file_sink.set_unbuffered(True)
        self.c2is = blocks.complex_to_interleaved_short()

        ##################################################
        # Connections
        ##################################################
        self.connect((self.multi, 0), (self.resampler, 0))
        self.connect((self.file_source, 0), (self.multi, 0))
        self.connect((self.signal_source, 0), (self.multi, 1))
        self.connect((self.c2is, 0), (self.file_sink, 0))
        self.connect((self.multiply_const, 0), (self.c2is, 0))
        self.connect((self.resampler, 0), (self.multiply_const, 0))
Ejemplo n.º 11
0
 def __init__(self, config):
     gr.top_block.__init__(self)
     ## Vars ##
     ## Interleaved Short input (sc16)
     if config["intype"] == SNAME_TO_ENUM["sc16"]:
         fsrc = blocks.file_source(gr.sizeof_short * 1, config["infile"], False)
         # SEEK_SET is offset from beginning, sample_offset is in samples
         # Factor of 2 because vector of length 2 (since interleaved)
         fsrc.seek(config["sample_offset"] * 2, os.SEEK_SET)
         # sc16->fc32
         if config["outtype"] == SNAME_TO_ENUM["fc32"]:
             ishort_to_cpxfloat = blocks.interleaved_short_to_complex(False, False)
             # Copies sample_len then exits
             head = blocks.head(gr.sizeof_gr_complex * 1, config["sample_len"])
             fsink = blocks.file_sink(gr.sizeof_gr_complex * 1, config["outfile"])
             self.connect(fsrc, ishort_to_cpxfloat, head, fsink)
         # sc16->sc16
         elif config["outtype"] == SNAME_TO_ENUM["sc16"]:
             head = blocks.head(gr.sizeof_short, config["sample_len"])
             fsink = blocks.file_sink(gr.sizeof_short, config["outfile"])
             self.connect(fsrc, head, fsink)
     ## Complex float input (fc32)
     elif config["intype"] == SNAME_TO_ENUM["fc32"]:
         fsrc = blocks.file_source(gr.sizeof_gr_complex * 1, config["infile"], False)
         # SEEK_SET is offset from beginning, sample_offset is in samples
         fsrc.seek(config["sample_offset"], os.SEEK_SET)
         # fc32->fc32
         if config["outtype"] == SNAME_TO_ENUM["fc32"]:
             head = blocks.head(gr.sizeof_gr_complex * 1, config["sample_len"])
             fsink = blocks.file_sink(gr.sizeof_gr_complex * 1, config["outfile"])
             self.connect(fsrc, head, fsink)
         # fc32->sc16
         elif config["outtype"] == SNAME_TO_ENUM["sc16"]:
             cpxfloat_to_ishort = blocks.complex_to_interleaved_short(False)
             head = blocks.head(gr.sizeof_gr_complex * 1, config["sample_len"])
             fsink = blocks.file_sink(gr.sizeof_short, config["outfile"])
             self.connect(fsrc, head, cpxfloat_to_ishort, fsink)
Ejemplo n.º 12
0
def tx_run(csnk, channels, sample_count, start_time_specs, sample_rate):
    """                                       +-----------+
    +---------+   +---------+   +---------+   |           |
    | sigs[0] |-->| heds[0] |-->| c2ss[0] |-->|ch[0]      |
    +---------+   +---------+   +---------+   |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[1] |-->| heds[1] |-->| c2ss[1] |-->|ch[1]      |
    +---------+   +---------+   +---------+   |           |
                                              |           |
    +---------+   +---------+   +---------+   |           |
    | sigs[N] |-->| heds[N] |-->| c2ss[N] |-->|ch[N]      |
    +---------+   +---------+   +---------+   |      csnk |
                                              +-----------+
    """

    sigs = [
        analog.sig_source_c(sample_rate, analog.GR_SIN_WAVE, 1.0e6, 2.0e4, 0.0)
        for ch in channels
    ]

    heds = [blocks.head(gr.sizeof_gr_complex, sample_count) for ch in channels]

    c2ss = [blocks.complex_to_interleaved_short(True) for ch in channels]

    flowgraph = gr.top_block()
    for ch in channels:
        flowgraph.connect(sigs[ch], heds[ch])
        flowgraph.connect(heds[ch], c2ss[ch])
        flowgraph.connect(c2ss[ch], (csnk, ch))

    for start_time_spec in start_time_specs:
        csnk.set_start_time(start_time_spec)

        flowgraph.run()
        for hed in heds:
            hed.reset()
    def __init__(self, input_file, output_file):
        gr.top_block.__init__(self, "Uhd Shifter")


        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 256000
        self.offset = offset = -25e3

        ##################################################
        # Blocks
        ##################################################
        self.signal_source = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, offset, 1, 0)
        self.resampler = filter.rational_resampler_ccc(
                interpolation=96,
                decimation=256,
                taps=None,
                fractional_bw=None,
        )
        self.multiply_const = blocks.multiply_const_vcc((32768, ))
        self.multi = blocks.multiply_vcc(1)
        self.file_source = blocks.file_source(gr.sizeof_gr_complex*1, input_file, False)
        self.file_sink = blocks.file_sink(gr.sizeof_short*1, output_file, False)
        self.file_sink.set_unbuffered(True)
        self.c2is = blocks.complex_to_interleaved_short()

        ##################################################
        # Connections
        ##################################################
        self.connect((self.multi, 0), (self.resampler, 0))
        self.connect((self.file_source, 0), (self.multi, 0))
        self.connect((self.signal_source, 0), (self.multi, 1))
        self.connect((self.c2is, 0), (self.file_sink, 0))
        self.connect((self.multiply_const, 0), (self.c2is, 0))
        self.connect((self.resampler, 0), (self.multiply_const, 0))
Ejemplo n.º 14
0
    def __init__(self):
        gr.top_block.__init__(self, "Shipping Passing App")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Shipping Passing App")
        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", "audioTxRx")
        self.restoreGeometry(self.settings.value("geometry").toByteArray())

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 32000
        self.msg_str = msg_str = "CSQ305438"

        self.QPSK = QPSK = digital.constellation_calcdist(
            ([1 + 1j, -1 + 1j, 1 - 1j, -1 - 1j]), ([0, 1, 3, 2]), 4, 1).base()

        ##################################################
        # Blocks
        ##################################################
        self._msg_str_tool_bar = Qt.QToolBar(self)
        self._msg_str_tool_bar.addWidget(Qt.QLabel("msg_str" + ": "))
        self._msg_str_line_edit = Qt.QLineEdit(str(self.msg_str))
        self._msg_str_tool_bar.addWidget(self._msg_str_line_edit)
        self._msg_str_line_edit.returnPressed.connect(lambda: self.set_msg_str(
            str(str(self._msg_str_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._msg_str_tool_bar)
        self.tutorial_my_qpsk_demod_cb_0 = tutorial.my_qpsk_demod_cb(True)
        self.tutorial_chat_sanitizer_0 = tutorial.chat_sanitizer('', '')
        self.gnuShipping_shippingReciever_0 = gnuShipping.shippingReciever(
            msg_str)
        self.digital_crc32_async_bb_1 = digital.crc32_async_bb(False)
        self.digital_crc32_async_bb_0 = digital.crc32_async_bb(True)
        self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_cc(
            1, 0.25 * 0.175 * 0.175, 0.5, 0.175, 0.005)
        self.digital_chunks_to_symbols_xx_0 = digital.chunks_to_symbols_bc(
            (QPSK.points()), 1)
        self.blocks_throttle_0_0 = blocks.throttle(gr.sizeof_char * 1,
                                                   samp_rate, True)
        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_char * 1, samp_rate,
                                                 True)
        self.blocks_tagged_stream_to_pdu_0 = blocks.tagged_stream_to_pdu(
            blocks.byte_t, 'pdu_length')
        self.blocks_tag_debug_0 = blocks.tag_debug(gr.sizeof_char * 1, '', "")
        self.blocks_tag_debug_0.set_display(True)
        self.blocks_short_to_float_0 = blocks.short_to_float(1, 1)
        self.blocks_repack_bits_bb_1 = blocks.repack_bits_bb(
            2, 8, 'pdu_length', True, gr.GR_LSB_FIRST)
        self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(
            8, 2, 'pdu_length', False, gr.GR_LSB_FIRST)
        self.blocks_pdu_to_tagged_stream_0 = blocks.pdu_to_tagged_stream(
            blocks.byte_t, 'pdu_length')
        self.blocks_message_debug_0 = blocks.message_debug()
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, False)
        self.blocks_float_to_short_0 = blocks.float_to_short(1, 1)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)
        self.audio_source_0 = audio.source(samp_rate, '', True)
        self.audio_sink_0 = audio.sink(samp_rate, '', True)

        ##################################################
        # Connections
        ##################################################
        self.msg_connect((self.blocks_tagged_stream_to_pdu_0, 'pdus'),
                         (self.digital_crc32_async_bb_0, 'in'))
        self.msg_connect((self.digital_crc32_async_bb_0, 'out'),
                         (self.gnuShipping_shippingReciever_0, 'in'))
        self.msg_connect((self.digital_crc32_async_bb_1, 'out'),
                         (self.blocks_message_debug_0, 'print_pdu'))
        self.msg_connect((self.digital_crc32_async_bb_1, 'out'),
                         (self.blocks_pdu_to_tagged_stream_0, 'pdus'))
        self.msg_connect((self.tutorial_chat_sanitizer_0, 'out'),
                         (self.digital_crc32_async_bb_1, 'in'))
        self.connect((self.audio_source_0, 0),
                     (self.blocks_float_to_short_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_short_to_float_0, 0))
        self.connect((self.blocks_float_to_short_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.digital_clock_recovery_mm_xx_0, 0))
        self.connect((self.blocks_pdu_to_tagged_stream_0, 0),
                     (self.blocks_tag_debug_0, 0))
        self.connect((self.blocks_pdu_to_tagged_stream_0, 0),
                     (self.blocks_throttle_0, 0))
        self.connect((self.blocks_repack_bits_bb_0, 0),
                     (self.digital_chunks_to_symbols_xx_0, 0))
        self.connect((self.blocks_repack_bits_bb_1, 0),
                     (self.blocks_tagged_stream_to_pdu_0, 0))
        self.connect((self.blocks_short_to_float_0, 0), (self.audio_sink_0, 0))
        self.connect((self.blocks_throttle_0, 0),
                     (self.blocks_repack_bits_bb_0, 0))
        self.connect((self.blocks_throttle_0_0, 0),
                     (self.blocks_repack_bits_bb_1, 0))
        self.connect((self.digital_chunks_to_symbols_xx_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0),
                     (self.tutorial_my_qpsk_demod_cb_0, 0))
        self.connect((self.tutorial_my_qpsk_demod_cb_0, 0),
                     (self.blocks_throttle_0_0, 0))
Ejemplo n.º 15
0
    def __init__(self,
                 baudrate=1200.0,
                 raw_file='',
                 udp_dest_audio='127.0.0.1',
                 udp_dest_iq='127.0.0.1',
                 udp_port_audio=7355,
                 udp_port_iq=7356):
        gr.top_block.__init__(self, "satnogs raw to udp")

        ##################################################
        # Parameters
        ##################################################
        self.baudrate = baudrate
        self.raw_file = raw_file
        self.udp_dest_audio = udp_dest_audio
        self.udp_dest_iq = udp_dest_iq
        self.udp_port_audio = udp_port_audio
        self.udp_port_iq = udp_port_iq

        ##################################################
        # Variables
        ##################################################
        self.sps = sps = 4
        self.audio_samp_rate = audio_samp_rate = 48000
        self.if_freq = if_freq = 12000
        self.decimation = decimation = satnogs.find_decimation(
            baudrate, 2, audio_samp_rate, sps)

        ##################################################
        # Blocks
        ##################################################
        self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_ccf(
            audio_samp_rate / (baudrate * decimation), taps=None, flt_size=32)
        self.pfb_arb_resampler_xxx_0.declare_sample_delay(0)
        self.low_pass_filter_0_0 = filter.fir_filter_ccf(
            1,
            firdes.low_pass(1, audio_samp_rate, 0.42 * audio_samp_rate / 2.0,
                            0.05 * audio_samp_rate, firdes.WIN_HAMMING, 6.76))
        self.blocks_udp_sink_0_0 = blocks.udp_sink(gr.sizeof_short * 1,
                                                   udp_dest_iq, udp_port_iq,
                                                   1472, True)
        self.blocks_udp_sink_0 = blocks.udp_sink(gr.sizeof_short * 1,
                                                 udp_dest_audio,
                                                 udp_port_audio, 1472, True)
        self.blocks_throttle_1 = blocks.throttle(gr.sizeof_gr_complex * 1,
                                                 baudrate * decimation, True)
        self.blocks_rotator_cc_0_0 = blocks.rotator_cc(
            2.0 * math.pi * (if_freq / audio_samp_rate))
        self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(16383)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(1 / 16768)
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, False)
        self.blocks_float_to_short_0 = blocks.float_to_short(1, 16383.0)
        self.blocks_file_source_0 = blocks.file_source(gr.sizeof_short * 1,
                                                       raw_file, False, 0, 0)
        self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL)
        self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)
        self.analog_agc2_xx_0_1 = analog.agc2_cc(1e-3, 1e-3, 0.5, 1.0)
        self.analog_agc2_xx_0_1.set_max_gain(65536)
        self.analog_agc2_xx_0_0 = analog.agc2_cc(0.01, 0.001, 0.015, 1.0)
        self.analog_agc2_xx_0_0.set_max_gain(65536)
        self.analog_agc2_xx_0 = analog.agc2_cc(1e-2, 1e-3, 1.5e-2, 1.0)
        self.analog_agc2_xx_0.set_max_gain(65536)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_agc2_xx_0, 0),
                     (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.analog_agc2_xx_0_0, 0),
                     (self.low_pass_filter_0_0, 0))
        self.connect((self.analog_agc2_xx_0_1, 0),
                     (self.pfb_arb_resampler_xxx_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_udp_sink_0_0, 0))
        self.connect((self.blocks_complex_to_real_0, 0),
                     (self.blocks_float_to_short_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_float_to_short_0, 0),
                     (self.blocks_udp_sink_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_throttle_1, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.blocks_rotator_cc_0_0, 0),
                     (self.blocks_complex_to_real_0, 0))
        self.connect((self.blocks_throttle_1, 0), (self.analog_agc2_xx_0, 0))
        self.connect((self.blocks_throttle_1, 0), (self.analog_agc2_xx_0_1, 0))
        self.connect((self.low_pass_filter_0_0, 0),
                     (self.blocks_rotator_cc_0_0, 0))
        self.connect((self.pfb_arb_resampler_xxx_0, 0),
                     (self.analog_agc2_xx_0_0, 0))
    def __init__(self, center_frequency, sample_rate, decimation, filename, sample_format=None, threshold=7.0,
                 burst_width=40e3, offline=False, max_queue_len=500, handle_multiple_frames_per_burst=False,
                 raw_capture_filename=None, debug_id=None, max_bursts=0, verbose=False, file_info="",
                 samples_per_symbol=10, config={}):
        gr.top_block.__init__(self, "Top Block")
        self.handle_sigint = False
        self._center_frequency = center_frequency
        self._burst_width = burst_width
        self._input_sample_rate = sample_rate
        self._verbose = verbose
        self._threshold = threshold
        self._filename = filename
        self._offline = offline
        self._max_queue_len = max_queue_len
        self._handle_multiple_frames_per_burst = handle_multiple_frames_per_burst
        self._decimation = decimation

        # Sample rate of the bursts exiting the burst downmix block
        self._burst_sample_rate = 25000 * samples_per_symbol
        if (self._input_sample_rate / self._decimation) % self._burst_sample_rate != 0:
            raise RuntimeError("Selected sample rate and decimation can not be matched. Please try a different combination. Sample rate divided by decimation must be a multiple of %d." % self._burst_sample_rate)

        self._fft_size = 2**round(math.log(self._input_sample_rate / 1000, 2))  # FFT is approx. 1 ms long
        self._burst_pre_len = 2 * self._fft_size

        # Keep 16 ms of signal after the FFT loses track
        self._burst_post_len = int(self._input_sample_rate * 16e-3)

        # Just to keep the code below a bit more portable
        tb = self

        if self._decimation > 1:
            self._use_channelizer = True

            # We will set up a filter bank with an odd number of outputs and
            # and an over sampling ratio to still get the desired decimation.

            # The goal is to reconstruct signals which (due to Doppler shift) end up
            # on the border of two channels.

            # For this to work the desired decimation must be even.
            if self._decimation % 2:
                raise RuntimeError("The desired decimation must be 1 or an even number.")

            self._channels = self._decimation + 1

            if self._decimation >= 8:
                self._use_fft_channelizer = True

                if 2**int(math.log(self._decimation, 2)) != self._decimation:
                    raise RuntimeError("Decimations >= 8 must be a power of two.")
                self._channel_sample_rate = self._input_sample_rate // self._decimation

                # On low end ARM machines we only create a single burst downmixer to not
                # overload the CPU. Rather drop bursts than samples.
                if platform.machine() == 'aarch64' and multiprocessing.cpu_count() == 4:
                    self._n_burst_downmixers = 1
                else:
                    self._n_burst_downmixers = 2
            else:
                self._use_fft_channelizer = False

                self._n_burst_downmixers = self._channels
                self._channelizer_over_sample_ratio = self._channels / (self._channels - 1.)
                channelizer_output_sample_rate = int(round(float(self._input_sample_rate) / self._channels * self._channelizer_over_sample_ratio))
                self._channel_sample_rate = channelizer_output_sample_rate
                assert channelizer_output_sample_rate == self._input_sample_rate / self._decimation
                assert channelizer_output_sample_rate % self._burst_sample_rate == 0

                # The over sampled region of the FIR filter contains half of the signal width and
                # the transition region of the FIR filter.
                # The bandwidth is simply increased by the signal width.
                # A signal which has its center frequency directly on the border of
                # two channels will reconstruct correctly on both channels.
                self._fir_bw = (self._input_sample_rate / self._channels + self._burst_width) / 2

                # The remaining bandwidth inside the over sampled region is used to
                # contain the transition region of the filter.
                # It can be multiplied by two as it is allowed to continue into the
                # transition region of the neighboring channel.
                # Some details can be found here: https://youtu.be/6ngYp8W-AX0?t=2289
                self._fir_tw = (channelizer_output_sample_rate / 2 - self._fir_bw) * 2

                # Real world data shows only a minor degradation in performance when
                # doubling the transition width.
                self._fir_tw *= 2

                # If the over sampling ratio is not large enough, there is not
                # enough room to construct a transition region.
                if self._fir_tw < 0:
                    raise RuntimeError("PFB over sampling ratio not enough to create a working FIR filter. Please try a different decimation.")

                self._pfb_fir_filter = gnuradio.filter.firdes.low_pass_2(1, self._input_sample_rate, self._fir_bw, self._fir_tw, 60)

                # If the transition width approaches 0, the filter size goes up significantly.
                if len(self._pfb_fir_filter) > 300:
                    print("Warning: The PFB FIR filter has an abnormal large number of taps:", len(self._pfb_fir_filter), file=sys.stderr)
                    print("Consider reducing the decimation factor or use a decimation >= 8.", file=sys.stderr)

                pfb_input_delay = (len(self._pfb_fir_filter) + 1) // 2 - self._channels / self._channelizer_over_sample_ratio
                self._channelizer_delay = pfb_input_delay / self._decimation

                if self._verbose:
                    print("self._channels", self._channels, file=sys.stderr)
                    print("len(self._pfb_fir_filter)", len(self._pfb_fir_filter), file=sys.stderr)
                    print("self._channelizer_over_sample_ratio", self._channelizer_over_sample_ratio, file=sys.stderr)
                    print("self._fir_bw", self._fir_bw, file=sys.stderr)
                    print("self._fir_tw", self._fir_tw, file=sys.stderr)
                    print("self._channel_sample_rate", self._channel_sample_rate, file=sys.stderr)
        else:
            self._use_channelizer = False
            self._channel_sample_rate = self._input_sample_rate
            self._channels = 1

        # After 90 ms there needs to be a pause in the frame sturcture.
        # Let's make that the limit for a detected burst
        self._max_burst_len = int(self._channel_sample_rate * 0.09)

        if self._verbose:
            print("require %.1f dB" % self._threshold, file=sys.stderr)
            print("burst_width: %d Hz" % self._burst_width, file=sys.stderr)
            print("source:", config['source'], file=sys.stderr)

        if config['source'] == 'osmosdr':
            d = config["osmosdr-source"]

            # work around https://github.com/gnuradio/gnuradio/issues/5121
            sys.path.append('/usr/local/lib/python3/dist-packages')
            import osmosdr
            if 'device_args' in d:
                source = osmosdr.source(args=d['device_args'])
            else:
                source = osmosdr.source()

            source.set_sample_rate(self._input_sample_rate)
            source.set_center_freq(self._center_frequency, 0)

            # Set a rough time estimate for potential rx_time tags from USRP devices
            # This prevents the output from having bogous time stamps if no GPSDO is available
            source.set_time_now(osmosdr.time_spec_t(time.time()))

            if 'gain' in d:
                gain = int(d['gain'])
                source.set_gain(gain, 0)
                print("(RF) Gain:", source.get_gain(0), '(Requested %d)' % gain, file=sys.stderr)

            for key, value in d.items():
                if key.endswith("_gain"):
                    gain_option_name = key.split('_')[0]
                    gain_value = int(value)

                    def match_gain(gain, gain_names):
                        for gain_name in gain_names:
                            if gain.lower() == gain_name.lower():
                                return gain_name
                        return None

                    gain_name = match_gain(gain_option_name, source.get_gain_names())

                    if gain_name is not None:
                        source.set_gain(gain_value, gain_name, 0)
                        print(gain_name, "Gain:", source.get_gain(gain_name, 0), '(Requested %d)' % gain_value, file=sys.stderr)
                    else:
                        print("WARNING: Gain", gain_option_name, "not supported by source!", file=sys.stderr)
                        print("Supported gains:", source.get_gain_names(), file=sys.stderr)

            if 'bandwidth' in d:
                bandwidth = int(d['bandwidth'])
                source.set_bandwidth(bandwidth, 0)
                print("Bandwidth:", source.get_bandwidth(0), '(Requested %d)' % bandwidth, file=sys.stderr)
            else:
                source.set_bandwidth(0, 0)
                print("Warning: Setting bandwidth to", source.get_bandwidth(0), file=sys.stderr)

            if 'antenna' in d:
                antenna = d['antenna']
                source.set_antenna(antenna, 0)
                print("Antenna:", source.get_antenna(0), '(Requested %s)' % antenna, file=sys.stderr)
            else:
                print("Warning: Setting antenna to", source.get_antenna(0), file=sys.stderr)

            if 'clock_source' in d:
                print("Setting clock source to:", d['clock_source'], file=sys.stderr)
                source.set_clock_source(d['clock_source'], 0)

            if 'time_source' in d:
                print("Setting time source to:", d['time_source'], file=sys.stderr)
                source.set_time_source(d['time_source'], 0)
                while (time.time() % 1) < 0.4 or (time.time() % 1) > 0.6:
                    pass
                t = time.time()
                source.set_time_next_pps(osmosdr.time_spec_t(int(t) + 1))
                time.sleep(1)

            #source.set_freq_corr($corr0, 0)
            #source.set_dc_offset_mode($dc_offset_mode0, 0)
            #source.set_iq_balance_mode($iq_balance_mode0, 0)
            #source.set_gain_mode($gain_mode0, 0)

        elif config['source'] == 'soapy':
            d = config["soapy-source"]

            try:
                from gnuradio import soapy
            except ImportError:
                raise ImportError("gr-soapy not found. Make sure you are running GNURadio >= 3.9.2.0")

            if 'driver' not in d:
                print("No driver specified for soapy", file=sys.stderr)
                print("Run 'SoapySDRUtil -i' to see available drivers(factories)", file=sys.stderr)
                exit(1)
            dev = 'driver=' + d['driver']

            # Strip quotes
            def sanitize(s):
                if s.startswith('"') and s.endswith('"'):
                    return s.strip('""')
                if s.startswith("'") and s.endswith("'"):
                    return s.strip("''")
                return s

            # Remove all outer quotes from the args if they are present in the config
            if 'device_args' in d:
                dev_args = sanitize(d['device_args'])
            elif 'dev_args' in d:
                dev_args = sanitize(d['dev_args'])
            else:
                dev_args = ''

            stream_args = sanitize(d['stream_args']) if 'stream_args' in d else ''
            tune_args = sanitize(d['tune_args']) if 'tune_args' in d else ''
            other_settings = sanitize(d['other_settings']) if 'other_settings' in d else ''

            # We only support a single channel. Apply tune_args and other_settings to that channel.
            source = soapy.source(dev, "fc32", 1, dev_args, stream_args, [tune_args], [other_settings])

            source.set_sample_rate(0, self._input_sample_rate)
            source.set_frequency(0, self._center_frequency)

            if 'gain' in d:
                gain = int(d['gain'])
                source.set_gain_mode(0, False)  # AGC: OFF
                source.set_gain(0, gain)
                print("Gain:", source.get_gain(0), '(Requested %d)' % gain, file=sys.stderr)

            for key, value in d.items():
                if key.endswith("_gain"):
                    gain_option_name = key.split('_')[0]
                    gain_value = int(value)

                    def match_gain(gain, gain_names):
                        for gain_name in gain_names:
                            if gain.lower() == gain_name.lower():
                                return gain_name
                        return None

                    gain_name = match_gain(gain_option_name, source.list_gains(0))

                    if gain_name is not None:
                        source.set_gain(0, gain_name, gain_value)
                        print(gain_name, "Gain:", source.get_gain(0, gain_name), '(Requested %d)' % gain_value, source.get_gain_range(0, gain_name), file=sys.stderr)
                    else:
                        print("WARNING: Gain", gain_option_name, "not supported by source!", file=sys.stderr)
                        print("Supported gains:", source.list_gains(0), file=sys.stderr)

            if 'bandwidth' in d:
                bandwidth = int(d['bandwidth'])
                source.set_bandwidth(0, bandwidth)
                print("Bandwidth:", source.get_bandwidth(0), '(Requested %d)' % bandwidth, file=sys.stderr)
            else:
                source.set_bandwidth(0, 0)
                print("Warning: Setting bandwidth to", source.get_bandwidth(0), file=sys.stderr)

            if 'antenna' in d:
                antenna = d['antenna']
                source.set_antenna(0, antenna)
                print("Antenna:", source.get_antenna(0), '(Requested %s)' % antenna, file=sys.stderr)
            else:
                print("Warning: Setting antenna to", source.get_antenna(0), file=sys.stderr)

            #source.set_frequency_correction(0, f_corr)
            #source.set_dc_offset_mode(0, True)
            #source.set_dc_offset(0, dc_off)
            #source.set_iq_balance(0, iq_bal)
        elif config['source'] == 'zeromq-sub':
            d = config["zeromq-sub-source"]

            from gnuradio import zeromq

            if 'address' not in d:
                print("No address specified for zeromq sub", file=sys.stderr)
                exit(1)

            pass_tags = False
            if 'pass_tags' in d:
                pass_tags = bool(distutils.util.strtobool(d['pass_tags']))

            timeout = 100
            if 'timeout' in d:
                timeout = int(d['timeout'])

            high_water_mark = -1
            if 'high_water_mark' in d:
                high_water_mark = int(d['high_water_mark'])

            source = zeromq.sub_source(gr.sizeof_gr_complex, 1, d['address'], timeout, pass_tags, high_water_mark, '')

        elif config['source'] == 'uhd':
            d = config["uhd-source"]

            from gnuradio import uhd

            dev_addr = ""
            if "device_addr" in d:
                dev_addr = d['device_addr']
            dev_args = d['device_args']

            cpu_format = 'fc32'
            wire_format = 'sc16'
            stream_args = ""

            stream_args = uhd.stream_args(cpu_format, wire_format, args=stream_args)
            source = uhd.usrp_source(dev_addr + "," + dev_args, stream_args)

            source.set_samp_rate(self._input_sample_rate)
            source.set_center_freq(self._center_frequency)

            if 'gain' in d:
                gain = int(d['gain'])
                source.set_gain(gain, 0)
                print("Gain:", source.get_gain(0), '(Requested %d)' % gain, file=sys.stderr)

            if 'bandwidth' in d:
                bandwidth = int(d['bandwidth'])
                source.set_bandwidth(bandwidth, 0)
                print("Bandwidth:", source.get_bandwidth(0), '(Requested %d)' % bandwidth, file=sys.stderr)
            else:
                source.set_bandwidth(0)
                print("Warning: Setting bandwidth to", source.get_bandwidth(0), file=sys.stderr)

            if 'antenna' in d:
                antenna = d['antenna']
                source.set_antenna(antenna, 0)
                print("Antenna:", source.get_antenna(0), '(Requested %s)' % antenna, file=sys.stderr)
            else:
                print("Warning: Setting antenna to", source.get_antenna(0), file=sys.stderr)

            print("mboard sensors:", source.get_mboard_sensor_names(0), file=sys.stderr)
            #for sensor in source.get_mboard_sensor_names(0):
            #    print(sensor, source.get_mboard_sensor(sensor, 0))

            gpsdo_sources = ('gpsdo', 'jacksonlabs')

            time_source = None
            if 'time_source' in d:
                time_source = d['time_source']
                if time_source in gpsdo_sources:
                    source.set_time_source("gpsdo", 0)
                else:
                    source.set_time_source(time_source, 0)

            clock_source = None
            if 'clock_source' in d:
                clock_source = d['time_source']
                if clock_source in gpsdo_sources:
                    source.set_clock_source("gpsdo", 0)
                else:
                    source.set_clock_source(clock_source, 0)

            if time_source in gpsdo_sources or clock_source in gpsdo_sources:
                print("Waiting for gps_locked...", file=sys.stderr)
                while True:
                    try:
                        if d['time_source'] == "jacksonlabs":
                            servo = source.get_mboard_sensor("gps_servo", 0)
                            # See https://lists.ettus.com/empathy/thread/6ZOCFQSKLHSG2IH3ID7XPWVKHVHZXPBP
                            gps_locked = str(servo).split()[8] == "6"
                        else:
                            gps_locked = source.get_mboard_sensor("gps_locked", 0).to_bool()

                        if gps_locked:
                            break
                    except ValueError as e:
                        print(e, file=sys.stderr)
                        pass
                    time.sleep(1)

                print("gps_locked!", file=sys.stderr)

            if clock_source:
                print("Waiting for ref_locked...", file=sys.stderr)
                while True:
                    try:
                        ref_locked = source.get_mboard_sensor("ref_locked", 0)
                        if ref_locked.to_bool():
                            break
                    except ValueError as e:
                        print(e, file=sys.stderr)
                        pass
                    time.sleep(1)
                print("ref_locked!", file=sys.stderr)

            if time_source:
                if time_source in gpsdo_sources:
                    while True:
                        try:
                            gps_time = uhd.time_spec_t(source.get_mboard_sensor("gps_time").to_int())
                            break
                        except ValueError as e:
                            print(e, file=sys.stderr)
                            pass
                        time.sleep(1)

                    next_pps_time = gps_time + 1
                else:
                    system_time = uhd.time_spec_t(int(time.time()))
                    next_pps_time = system_time + 1

                source.set_time_next_pps(next_pps_time)
                print("Next PPS at", next_pps_time.get_real_secs(), file=sys.stderr)

                print("Sleeping 2 seconds...", file=sys.stderr)
                time.sleep(2)

                # TODO: Check result for plausibility
                print("USRP  time:", source.get_time_last_pps(0).get_real_secs(), file=sys.stderr)
            else:
                # Set a rough time estimate for rx_time tags from the USRP.
                # This prevents the output from having bogous time stamps if no GPSDO is available.
                source.set_time_now(uhd.time_spec_t(time.time()))

            self.source = source

        else:
            if sample_format == "cu8":
                converter = iridium.iuchar_to_complex()
                itemsize = gr.sizeof_char
                scale = 1
                itemtype = np.uint8
            elif sample_format == "ci8":
                converter = blocks.interleaved_char_to_complex()
                itemsize = gr.sizeof_char
                scale = 1 / 128.
                itemtype = np.int8
            elif sample_format == "ci16_le":
                converter = blocks.interleaved_short_to_complex()
                itemsize = gr.sizeof_short
                scale = 1 / 32768.
                itemtype = np.int16
            elif sample_format == "cf32_le":
                converter = None
                itemsize = gr.sizeof_gr_complex
                itemtype = np.complex64
            else:
                raise RuntimeError("Unknown sample format for offline mode given")

            if config['source'] == 'stdin':
                file_source = blocks.file_descriptor_source(itemsize=itemsize, fd=0, repeat=False)
            elif config['source'] == 'object':
                from iridium.file_object_source import file_object_source
                file_source = file_object_source(fileobject=config['object'], itemtype=itemtype)
            else:
                file_source = blocks.file_source(itemsize=itemsize, filename=config['file'], repeat=False)

            self.source = file_source  # XXX: keep reference

            if converter:
                multi = blocks.multiply_const_cc(scale)
                tb.connect(file_source, converter, multi)
                source = multi
            else:
                source = file_source

        self._fft_burst_tagger = iridium.fft_burst_tagger(center_frequency=self._center_frequency,
                                                          fft_size=self._fft_size,
                                                          sample_rate=self._input_sample_rate,
                                                          burst_pre_len=self._burst_pre_len,
                                                          burst_post_len=self._burst_post_len,
                                                          burst_width=int(self._burst_width),
                                                          max_bursts=max_bursts,
                                                          max_burst_len=int(self._input_sample_rate * 0.09),
                                                          threshold=self._threshold,
                                                          history_size=512,
                                                          offline=self._offline,
                                                          debug=self._verbose)
        self._fft_burst_tagger.set_min_output_buffer(1024 * 64)

        # Initial filter to filter the detected bursts. Runs at burst_sample_rate. Used to decimate the signal.
        input_filter = gnuradio.filter.firdes.low_pass_2(1, self._channel_sample_rate, self._burst_width / 2, self._burst_width, 40)
        #input_filter = gnuradio.filter.firdes.low_pass_2(1, self._channel_sample_rate, 42e3/2, 24e3, 40)
        #print len(input_filter)

        # Filter to find the start of the signal. Should be fairly narrow.
        start_finder_filter = gnuradio.filter.firdes.low_pass_2(1, self._burst_sample_rate, 5e3 / 2, 10e3 / 2, 60)
        #print len(start_finder_filter)

        self._iridium_qpsk_demod = iridium.iridium_qpsk_demod(self._channels)
        self._frame_sorter = iridium.frame_sorter()
        self._iridium_frame_printer = iridium.iridium_frame_printer(file_info)

        if raw_capture_filename:
            multi = blocks.multiply_const_cc(32768)
            converter = blocks.complex_to_interleaved_short()
            raw_sink = blocks.file_sink(itemsize=gr.sizeof_short, filename=raw_capture_filename + '.sigmf-data')
            tb.connect(source, multi, converter, raw_sink)

            # Enable the following if not fast enough
            #self._burst_to_pdu_converters = []
            #self._burst_downmixers = []
            #return

        tb.connect(source, self._fft_burst_tagger)

        if self._use_channelizer:
            self._burst_to_pdu_converters = []
            self._burst_downmixers = []
            sinks = []

            for channel in range(self._channels):
                if not self._use_fft_channelizer:
                    center = channel if channel <= self._channels / 2 else (channel - self._channels)
                    relative_center = center / float(self._channels)
                    relative_span = 1. / self._channels
                    relative_sample_rate = relative_span * self._channelizer_over_sample_ratio

                    # Second and third parameters tell the block where after the PFB it sits.
                    burst_to_pdu_converter = iridium.tagged_burst_to_pdu(self._max_burst_len,
                                                                         relative_center,
                                                                         relative_span,
                                                                         relative_sample_rate,
                                                                         -self._channelizer_delay,
                                                                         self._max_queue_len,
                                                                         not self._offline)
                    self._burst_to_pdu_converters.append(burst_to_pdu_converter)

                burst_downmixer = iridium.burst_downmix(self._burst_sample_rate,
                                                        int(0.007 * self._burst_sample_rate),
                                                        0,
                                                        (input_filter),
                                                        (start_finder_filter),
                                                        self._handle_multiple_frames_per_burst)

                if debug_id is not None:
                    burst_downmixer.debug_id(debug_id)

                self._burst_downmixers.append(burst_downmixer)

            channelizer_debug_sinks = []
            #channelizer_debug_sinks = [blocks.file_sink(itemsize=gr.sizeof_gr_complex, filename="/tmp/channel-%d.f32"%i) for i in range(self._channels)]

            if self._use_fft_channelizer:
                if not channelizer_debug_sinks and self._offline:
                    # HACK: if there are no stream outputs active GNURadio has issues terminating the
                    # flowgraph on completion. Connect some dummy sinks to them.
                    channelizer_debug_sinks = [blocks.null_sink(gr.sizeof_gr_complex) for i in range(self._channels)]

                activate_streams = len(channelizer_debug_sinks) > 0
                self._channelizer = iridium.fft_channelizer(1024, self._channels - 1, activate_streams, self._n_burst_downmixers, self._max_burst_len,
                                                            self._max_queue_len * self._n_burst_downmixers, not self._offline)
            else:
                self._channelizer = gnuradio.filter.pfb.channelizer_ccf(numchans=self._channels, taps=self._pfb_fir_filter, oversample_rate=self._channelizer_over_sample_ratio)

            tb.connect(self._fft_burst_tagger, self._channelizer)

            for i in range(self._channels):
                if channelizer_debug_sinks:
                    tb.connect((self._channelizer, i), channelizer_debug_sinks[i])

            for i in range(self._n_burst_downmixers):
                if self._burst_to_pdu_converters:
                    tb.connect((self._channelizer, i), self._burst_to_pdu_converters[i])
                    tb.msg_connect((self._burst_to_pdu_converters[i], 'cpdus'), (self._burst_downmixers[i], 'cpdus'))
                    tb.msg_connect((self._burst_downmixers[i], 'burst_handled'), (self._burst_to_pdu_converters[i], 'burst_handled'))
                else:
                    tb.msg_connect((self._channelizer, 'cpdus%d' % i), (self._burst_downmixers[i], 'cpdus'))
                    tb.msg_connect((self._burst_downmixers[i], 'burst_handled'), (self._channelizer, 'burst_handled'))

                tb.msg_connect((self._burst_downmixers[i], 'cpdus'), (self._iridium_qpsk_demod, 'cpdus%d' % i))
        else:
            burst_downmix = iridium.burst_downmix(self._burst_sample_rate, int(0.007 * self._burst_sample_rate), 0, (input_filter), (start_finder_filter), self._handle_multiple_frames_per_burst)
            if debug_id is not None:
                burst_downmix.debug_id(debug_id)

            burst_to_pdu = iridium.tagged_burst_to_pdu(self._max_burst_len,
                                                       0.0, 1.0, 1.0,
                                                       0,
                                                       self._max_queue_len, not self._offline)

            tb.connect(self._fft_burst_tagger, burst_to_pdu)

            tb.msg_connect((burst_to_pdu, 'cpdus'), (burst_downmix, 'cpdus'))
            tb.msg_connect((burst_downmix, 'burst_handled'), (burst_to_pdu, 'burst_handled'))

            # Final connection to the demodulator. It prints the output to stdout
            tb.msg_connect((burst_downmix, 'cpdus'), (self._iridium_qpsk_demod, 'cpdus'))

            self._burst_downmixers = [burst_downmix]
            self._burst_to_pdu_converters = [burst_to_pdu]

        tb.msg_connect((self._iridium_qpsk_demod, 'pdus'), (self._frame_sorter, 'pdus'))
        tb.msg_connect((self._frame_sorter, 'pdus'), (self._iridium_frame_printer, 'pdus'))
Ejemplo n.º 17
0
    def __init__(self):
        gr.top_block.__init__(self, "Not titled yet")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("Not titled yet")
        qtgui.util.check_set_qss()
        try:
            self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
        except:
            pass
        self.top_scroll_layout = Qt.QVBoxLayout()
        self.setLayout(self.top_scroll_layout)
        self.top_scroll = Qt.QScrollArea()
        self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
        self.top_scroll_layout.addWidget(self.top_scroll)
        self.top_scroll.setWidgetResizable(True)
        self.top_widget = Qt.QWidget()
        self.top_scroll.setWidget(self.top_widget)
        self.top_layout = Qt.QVBoxLayout(self.top_widget)
        self.top_grid_layout = Qt.QGridLayout()
        self.top_layout.addLayout(self.top_grid_layout)

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

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

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

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

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

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

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

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_const_source_x_0, 0),
                     (self.blocks_stream_mux_0, 1))
        self.connect((self.blocks_add_const_vxx_0, 0),
                     (self.blocks_complex_to_interleaved_char_0, 0))
        self.connect((self.blocks_add_const_vxx_0_0, 0),
                     (self.blocks_stream_mux_0, 0))
        self.connect((self.blocks_complex_to_interleaved_char_0, 0),
                     (self.blocks_file_sink_0, 0))
        self.connect((self.blocks_complex_to_interleaved_char_0, 0),
                     (self.blocks_interleaved_char_to_complex_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_file_sink_0_0, 0))
        self.connect((self.blocks_file_source_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_interleaved_char_to_complex_0, 0),
                     (self.interp_fir_filter_xxx_0_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.blocks_multiply_const_vxx_1, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.qtgui_const_sink_x_0, 0))
        self.connect((self.blocks_multiply_const_vxx_1, 0),
                     (self.blocks_add_const_vxx_0_0, 0))
        self.connect((self.blocks_multiply_const_vxx_2, 0),
                     (self.blocks_add_const_vxx_0, 0))
        self.connect((self.blocks_stream_mux_0, 0),
                     (self.blocks_multiply_const_vxx_2, 0))
        self.connect((self.interp_fir_filter_xxx_0_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
Ejemplo n.º 18
0
    def __init__(self,
                 center_frequency,
                 sample_rate,
                 decimation,
                 filename,
                 sample_format=None,
                 threshold=7.0,
                 signal_width=40e3,
                 offline=False,
                 max_queue_len=500,
                 handle_multiple_frames_per_burst=False,
                 raw_capture_filename=None,
                 debug_id=None,
                 max_bursts=0,
                 verbose=False,
                 file_info=None):
        gr.top_block.__init__(self, "Top Block")
        self._center_frequency = center_frequency
        self._burst_width = 40e3
        self._input_sample_rate = sample_rate
        self._verbose = verbose
        self._threshold = threshold
        self._filename = filename
        self._offline = offline
        self._max_queue_len = max_queue_len
        self._handle_multiple_frames_per_burst = handle_multiple_frames_per_burst

        self._fft_size = int(
            math.pow(2, 1 + int(math.log(self._input_sample_rate / 1000,
                                         2))))  # fft is approx 1ms long
        self._burst_pre_len = 2 * self._fft_size
        self._burst_post_len = 8 * self._fft_size

        # Just to keep the code below a bit more portable
        tb = self

        if decimation > 1:
            self._use_pfb = True

            # We will set up a filter bank with an odd number of outputs and
            # and an over sampling ratio to still get the desired decimation.

            # The goal is to still catch signal which (due to doppler shift) end up
            # on the border of two channels.

            # For this to work the desired decimation must be even.
            if decimation % 2:
                raise RuntimeError(
                    "The desired decimation must be 1 or an even number")

            self._channels = decimation + 1
            self._pfb_over_sample_ratio = self._channels / (self._channels -
                                                            1.)
            pfb_output_sample_rate = int(
                round(
                    float(self._input_sample_rate) / self._channels *
                    self._pfb_over_sample_ratio))
            assert pfb_output_sample_rate == self._input_sample_rate / decimation

            # The over sampled region of the FIR filter contains half of the signal width and
            # the transition region of the FIR filter.
            # The bandwidth is simply increased by the signal width.
            # A signal which has its center frequency directly on the border of
            # two channels will reconstruct correclty on both channels.
            self._fir_bw = (self._input_sample_rate / self._channels +
                            self._burst_width) / 2

            # The remaining bandwidth inside the over samples region is used to
            # contain the transistion region of the filter.
            # It can be multiplied by two as it is allowed to continue into the
            # transition region of the neighboring channel.
            # TODO: Draw a nice graphic how this works.
            self._fir_tw = (pfb_output_sample_rate / 2 - self._fir_bw) * 2

            # If the over sampling ratio is not large enough, there is not
            # enough room to construct a transition region.
            if self._fir_tw < 0:
                raise RuntimeError(
                    "PFB over sampling ratio not enough to create a working FIR filter"
                )

            self._pfb_fir_filter = gnuradio.filter.firdes.low_pass_2(
                1, self._input_sample_rate, self._fir_bw, self._fir_tw, 60)

            # If the transition width approaches 0, the filter size goes up significantly.
            if len(self._pfb_fir_filter) > 200:
                print(
                    "Warning: The PFB FIR filter has an abnormal large number of taps:",
                    len(self._pfb_fir_filter),
                    file=sys.stderr)
                print(
                    "Consider reducing the decimation factor or increase the over sampling ratio",
                    file=sys.stderr)

            self._burst_sample_rate = pfb_output_sample_rate
            if self._verbose:
                print("self._channels", self._channels, file=sys.stderr)
                print("len(self._pfb_fir_filter)",
                      len(self._pfb_fir_filter),
                      file=sys.stderr)
                print("self._pfb_over_sample_ratio",
                      self._pfb_over_sample_ratio,
                      file=sys.stderr)
                print("self._fir_bw", self._fir_bw, file=sys.stderr)
                print("self._fir_tw", self._fir_tw, file=sys.stderr)
                print("self._burst_sample_rate",
                      self._burst_sample_rate,
                      file=sys.stderr)
        else:
            self._use_pfb = False
            self._burst_sample_rate = self._input_sample_rate

        # After 90 ms there needs to be a pause in the frame sturcture.
        # Let's make that the limit for a detected burst
        self._max_burst_len = int(self._burst_sample_rate * 0.09)

        if self._verbose:
            print("require %.1f dB" % self._threshold, file=sys.stderr)
            print("burst_width: %d Hz" % self._burst_width, file=sys.stderr)

        if self._filename.endswith(".conf"):
            import configparser
            config = configparser.ConfigParser()
            config.read(self._filename)
            items = config.items("osmosdr-source")
            d = {key: value for key, value in items}

            import osmosdr
            if 'device_args' in d:
                source = osmosdr.source(args=d['device_args'])
            else:
                source = osmosdr.source()

            source.set_sample_rate(self._input_sample_rate)
            source.set_center_freq(self._center_frequency, 0)

            if 'gain' in d:
                gain = int(d['gain'])
                source.set_gain(gain, 0)
                print("(RF) Gain:",
                      source.get_gain(0),
                      '(Requested %d)' % gain,
                      file=sys.stderr)

            for key, value in d.items():
                if key.endswith("_gain"):
                    gain_option_name = key.split('_')[0]
                    gain_value = int(value)

                    def match_gain(gain, gain_names):
                        for gain_name in gain_names:
                            if gain.lower() == gain_name.lower():
                                return gain_name
                        return None

                    gain_name = match_gain(gain_option_name,
                                           source.get_gain_names())

                    if gain_name is not None:
                        source.set_gain(gain_value, gain_name, 0)
                        print(gain_name,
                              "Gain:",
                              source.get_gain(gain_name, 0),
                              '(Requested %d)' % gain_value,
                              file=sys.stderr)
                    else:
                        print("WARNING: Gain",
                              gain_option_name,
                              "not supported by source!",
                              file=sys.stderr)
                        print("Supported gains:",
                              source.get_gain_names(),
                              file=sys.stderr)

            if 'bandwidth' in d:
                bandwidth = int(d['bandwidth'])
                source.set_bandwidth(bandwidth, 0)
                print("Bandwidth:",
                      source.get_bandwidth(0),
                      '(Requested %d)' % bandwidth,
                      file=sys.stderr)
            else:
                source.set_bandwidth(0, 0)
                print("Warning: Setting bandwidth to",
                      source.get_bandwidth(0),
                      file=sys.stderr)

            if 'antenna' in d:
                antenna = d['antenna']
                source.set_antenna(antenna, 0)
                print("Antenna:",
                      source.get_antenna(0),
                      '(Requested %s)' % antenna,
                      file=sys.stderr)
            else:
                print("Warning: Setting antenna to",
                      source.get_antenna(0),
                      file=sys.stderr)

            #source.set_freq_corr($corr0, 0)
            #source.set_dc_offset_mode($dc_offset_mode0, 0)
            #source.set_iq_balance_mode($iq_balance_mode0, 0)
            #source.set_gain_mode($gain_mode0, 0)
            #source.set_antenna($ant0, 0)

        else:
            if sample_format == "rtl":
                converter = iridium.iuchar_to_complex()
                itemsize = gr.sizeof_char
                scale = 1
            elif sample_format == "hackrf":
                converter = blocks.interleaved_char_to_complex()
                itemsize = gr.sizeof_char
                scale = 1 / 128.
            elif sample_format == "sc16":
                converter = blocks.interleaved_short_to_complex()
                itemsize = gr.sizeof_short
                scale = 1 / 32768.
            elif sample_format == "float":
                converter = None
                itemsize = gr.sizeof_gr_complex
            else:
                raise RuntimeError(
                    "Unknown sample format for offline mode given")

            file_source = blocks.file_source(itemsize=itemsize,
                                             filename=self._filename,
                                             repeat=False)

            if converter:
                multi = blocks.multiply_const_cc(scale)
                tb.connect(file_source, converter, multi)
                source = multi
            else:
                source = file_source

        #fft_burst_tagger::make(float center_frequency, int fft_size, int sample_rate,
        #                    int burst_pre_len, int burst_post_len, int burst_width,
        #                    int max_bursts, float threshold, int history_size, bool debug)

        self._fft_burst_tagger = iridium.fft_burst_tagger(
            center_frequency=self._center_frequency,
            fft_size=self._fft_size,
            sample_rate=self._input_sample_rate,
            burst_pre_len=self._burst_pre_len,
            burst_post_len=self._burst_post_len,
            burst_width=int(self._burst_width),
            max_bursts=max_bursts,
            threshold=self._threshold,
            history_size=512,
            debug=self._verbose)

        # Initial filter to filter the detected bursts. Runs at burst_sample_rate. Used to decimate the signal.
        # TODO: Should probably be set to self._burst_width
        input_filter = gnuradio.filter.firdes.low_pass_2(
            1, self._burst_sample_rate, 40e3 / 2, 40e3, 40)
        #input_filter = gnuradio.filter.firdes.low_pass_2(1, self._burst_sample_rate, 42e3/2, 24e3, 40)
        #print len(input_filter)

        # Filter to find the start of the signal. Should be fairly narrow.
        # TODO: 250000 appears as magic number here
        start_finder_filter = gnuradio.filter.firdes.low_pass_2(
            1, 250000, 5e3 / 2, 10e3 / 2, 60)
        #print len(start_finder_filter)

        self._iridium_qpsk_demod = iridium.iridium_qpsk_demod_cpp()
        self._frame_sorter = iridium.frame_sorter()
        self._iridium_frame_printer = iridium.iridium_frame_printer(file_info)

        #self._iridium_qpsk_demod = iridium.iridium_qpsk_demod(250000)

        if raw_capture_filename:
            multi = blocks.multiply_const_cc(32768)
            converter = blocks.complex_to_interleaved_short()
            raw_sink = blocks.file_sink(itemsize=gr.sizeof_short,
                                        filename=raw_capture_filename)
            tb.connect(source, multi, converter, raw_sink)

            # Enable the following if not fast enough
            #self._burst_to_pdu_converters = []
            #self._burst_downmixers = []
            #return

        tb.connect(source, self._fft_burst_tagger)

        if self._use_pfb:
            self._burst_to_pdu_converters = []
            self._burst_downmixers = []
            sinks = []

            for channel in range(self._channels):
                center = channel if channel <= self._channels / 2 else (
                    channel - self._channels)

                # Second and third parameters tell the block where after the PFB it sits.
                relative_center = center / float(self._channels)
                relative_span = 1. / self._channels
                relative_sample_rate = relative_span * self._pfb_over_sample_ratio
                burst_to_pdu_converter = iridium.tagged_burst_to_pdu(
                    self._max_burst_len, relative_center, relative_span,
                    relative_sample_rate, self._max_queue_len,
                    not self._offline)
                burst_downmixer = iridium.burst_downmix(
                    self._burst_sample_rate, int(0.007 * 250000), 0,
                    (input_filter), (start_finder_filter),
                    self._handle_multiple_frames_per_burst)

                if debug_id is not None: burst_downmixer.debug_id(debug_id)

                self._burst_downmixers.append(burst_downmixer)
                self._burst_to_pdu_converters.append(burst_to_pdu_converter)

            #pfb_debug_sinks = [blocks.file_sink(itemsize=gr.sizeof_gr_complex, filename="/tmp/channel-%d.f32"%i) for i in range(self._channels)]
            pfb_debug_sinks = None

            pfb = gnuradio.filter.pfb.channelizer_ccf(
                numchans=self._channels,
                taps=self._pfb_fir_filter,
                oversample_rate=self._pfb_over_sample_ratio)

            tb.connect(self._fft_burst_tagger, pfb)

            for i in range(self._channels):
                tb.connect((pfb, i), self._burst_to_pdu_converters[i])
                if pfb_debug_sinks:
                    tb.connect((pfb, i), pfb_debug_sinks[i])

                tb.msg_connect((self._burst_to_pdu_converters[i], 'cpdus'),
                               (self._burst_downmixers[i], 'cpdus'))
                tb.msg_connect(
                    (self._burst_downmixers[i], 'burst_handled'),
                    (self._burst_to_pdu_converters[i], 'burst_handled'))

                tb.msg_connect((self._burst_downmixers[i], 'cpdus'),
                               (self._iridium_qpsk_demod, 'cpdus'))
        else:
            burst_downmix = iridium.burst_downmix(
                self._burst_sample_rate, int(0.007 * 250000), 0,
                (input_filter), (start_finder_filter),
                self._handle_multiple_frames_per_burst)
            if debug_id is not None: burst_downmix.debug_id(debug_id)

            burst_to_pdu = iridium.tagged_burst_to_pdu(self._max_burst_len,
                                                       0.0, 1.0, 1.0,
                                                       self._max_queue_len,
                                                       not self._offline)

            tb.connect(self._fft_burst_tagger, burst_to_pdu)

            tb.msg_connect((burst_to_pdu, 'cpdus'), (burst_downmix, 'cpdus'))
            tb.msg_connect((burst_downmix, 'burst_handled'),
                           (burst_to_pdu, 'burst_handled'))

            # Final connection to the demodulator. It prints the output to stdout
            tb.msg_connect((burst_downmix, 'cpdus'),
                           (self._iridium_qpsk_demod, 'cpdus'))

            self._burst_downmixers = [burst_downmix]
            self._burst_to_pdu_converters = [burst_to_pdu]

        tb.msg_connect((self._iridium_qpsk_demod, 'pdus'),
                       (self._frame_sorter, 'pdus'))
        tb.msg_connect((self._frame_sorter, 'pdus'),
                       (self._iridium_frame_printer, 'pdus'))
Ejemplo n.º 19
0
    def __init__(self,
                 center_frequency,
                 sample_rate,
                 decimation,
                 filename,
                 sample_format=None,
                 threshold=7.0,
                 burst_width=40e3,
                 offline=False,
                 max_queue_len=500,
                 handle_multiple_frames_per_burst=False,
                 raw_capture_filename=None,
                 debug_id=None,
                 max_bursts=0,
                 verbose=False,
                 file_info=None,
                 samples_per_symbol=10,
                 config={}):
        gr.top_block.__init__(self, "Top Block")
        self.handle_sigint = False
        self._center_frequency = center_frequency
        self._burst_width = burst_width
        self._input_sample_rate = sample_rate
        self._verbose = verbose
        self._threshold = threshold
        self._filename = filename
        self._offline = offline
        self._max_queue_len = max_queue_len
        self._handle_multiple_frames_per_burst = handle_multiple_frames_per_burst

        # Sample rate of the bursts exiting the burst downmix block
        self._burst_sample_rate = 25000 * samples_per_symbol
        assert (self._input_sample_rate /
                decimation) % self._burst_sample_rate == 0

        self._fft_size = 2**round(math.log(self._input_sample_rate / 1000,
                                           2))  # FFT is approx. 1 ms long
        self._burst_pre_len = 2 * self._fft_size

        # Keep 16 ms of signal after the FFT loses track
        self._burst_post_len = int(self._input_sample_rate * 16e-3)

        # Just to keep the code below a bit more portable
        tb = self

        if decimation > 1:
            self._use_pfb = True

            # We will set up a filter bank with an odd number of outputs and
            # and an over sampling ratio to still get the desired decimation.

            # The goal is to reconstruct signals which (due to Doppler shift) end up
            # on the border of two channels.

            # For this to work the desired decimation must be even.
            if decimation % 2:
                raise RuntimeError(
                    "The desired decimation must be 1 or an even number")

            self._channels = decimation + 1
            self._pfb_over_sample_ratio = self._channels / (self._channels -
                                                            1.)
            pfb_output_sample_rate = int(
                round(
                    float(self._input_sample_rate) / self._channels *
                    self._pfb_over_sample_ratio))
            assert pfb_output_sample_rate == self._input_sample_rate / decimation
            assert pfb_output_sample_rate % self._burst_sample_rate == 0

            # The over sampled region of the FIR filter contains half of the signal width and
            # the transition region of the FIR filter.
            # The bandwidth is simply increased by the signal width.
            # A signal which has its center frequency directly on the border of
            # two channels will reconstruct correctly on both channels.
            self._fir_bw = (self._input_sample_rate / self._channels +
                            self._burst_width) / 2

            # The remaining bandwidth inside the over sampled region is used to
            # contain the transition region of the filter.
            # It can be multiplied by two as it is allowed to continue into the
            # transition region of the neighboring channel.
            # Some details can be found here: https://youtu.be/6ngYp8W-AX0?t=2289
            self._fir_tw = (pfb_output_sample_rate / 2 - self._fir_bw) * 2

            # Real world data shows only a minor degradation in performance when
            # doubling the transition width.
            self._fir_tw *= 2

            # If the over sampling ratio is not large enough, there is not
            # enough room to construct a transition region.
            if self._fir_tw < 0:
                raise RuntimeError(
                    "PFB over sampling ratio not enough to create a working FIR filter"
                )

            self._pfb_fir_filter = gnuradio.filter.firdes.low_pass_2(
                1, self._input_sample_rate, self._fir_bw, self._fir_tw, 60)

            # If the transition width approaches 0, the filter size goes up significantly.
            if len(self._pfb_fir_filter) > 300:
                print(
                    "Warning: The PFB FIR filter has an abnormal large number of taps:",
                    len(self._pfb_fir_filter),
                    file=sys.stderr)
                print("Consider reducing the decimation factor",
                      file=sys.stderr)

            pfb_input_delay = (
                len(self._pfb_fir_filter) +
                1) // 2 - self._channels / self._pfb_over_sample_ratio
            self._pfb_delay = pfb_input_delay / decimation
            self._channel_sample_rate = pfb_output_sample_rate
            if self._verbose:
                print("self._channels", self._channels, file=sys.stderr)
                print("len(self._pfb_fir_filter)",
                      len(self._pfb_fir_filter),
                      file=sys.stderr)
                print("self._pfb_over_sample_ratio",
                      self._pfb_over_sample_ratio,
                      file=sys.stderr)
                print("self._fir_bw", self._fir_bw, file=sys.stderr)
                print("self._fir_tw", self._fir_tw, file=sys.stderr)
                print("self._channel_sample_rate",
                      self._channel_sample_rate,
                      file=sys.stderr)
        else:
            self._use_pfb = False
            self._channel_sample_rate = self._input_sample_rate
            self._channels = 1

        # After 90 ms there needs to be a pause in the frame sturcture.
        # Let's make that the limit for a detected burst
        self._max_burst_len = int(self._channel_sample_rate * 0.09)

        if self._verbose:
            print("require %.1f dB" % self._threshold, file=sys.stderr)
            print("burst_width: %d Hz" % self._burst_width, file=sys.stderr)

        if config['source'] == 'osmosdr':
            d = config["osmosdr-source"]

            # work around https://github.com/gnuradio/gnuradio/issues/5121
            sys.path.append('/usr/local/lib/python3/dist-packages')
            import osmosdr
            if 'device_args' in d:
                source = osmosdr.source(args=d['device_args'])
            else:
                source = osmosdr.source()

            source.set_time_now(osmosdr.time_spec_t.get_system_time())

            source.set_sample_rate(self._input_sample_rate)
            source.set_center_freq(self._center_frequency, 0)

            if 'gain' in d:
                gain = int(d['gain'])
                source.set_gain(gain, 0)
                print("(RF) Gain:",
                      source.get_gain(0),
                      '(Requested %d)' % gain,
                      file=sys.stderr)

            for key, value in d.items():
                if key.endswith("_gain"):
                    gain_option_name = key.split('_')[0]
                    gain_value = int(value)

                    def match_gain(gain, gain_names):
                        for gain_name in gain_names:
                            if gain.lower() == gain_name.lower():
                                return gain_name
                        return None

                    gain_name = match_gain(gain_option_name,
                                           source.get_gain_names())

                    if gain_name is not None:
                        source.set_gain(gain_value, gain_name, 0)
                        print(gain_name,
                              "Gain:",
                              source.get_gain(gain_name, 0),
                              '(Requested %d)' % gain_value,
                              file=sys.stderr)
                    else:
                        print("WARNING: Gain",
                              gain_option_name,
                              "not supported by source!",
                              file=sys.stderr)
                        print("Supported gains:",
                              source.get_gain_names(),
                              file=sys.stderr)

            if 'bandwidth' in d:
                bandwidth = int(d['bandwidth'])
                source.set_bandwidth(bandwidth, 0)
                print("Bandwidth:",
                      source.get_bandwidth(0),
                      '(Requested %d)' % bandwidth,
                      file=sys.stderr)
            else:
                source.set_bandwidth(0, 0)
                print("Warning: Setting bandwidth to",
                      source.get_bandwidth(0),
                      file=sys.stderr)

            if 'antenna' in d:
                antenna = d['antenna']
                source.set_antenna(antenna, 0)
                print("Antenna:",
                      source.get_antenna(0),
                      '(Requested %s)' % antenna,
                      file=sys.stderr)
            else:
                print("Warning: Setting antenna to",
                      source.get_antenna(0),
                      file=sys.stderr)

            #source.set_freq_corr($corr0, 0)
            #source.set_dc_offset_mode($dc_offset_mode0, 0)
            #source.set_iq_balance_mode($iq_balance_mode0, 0)
            #source.set_gain_mode($gain_mode0, 0)
            #source.set_antenna($ant0, 0)

        else:
            if sample_format == "cu8":
                converter = iridium.iuchar_to_complex()
                itemsize = gr.sizeof_char
                scale = 1
                itemtype = np.uint8
            elif sample_format == "ci8":
                converter = blocks.interleaved_char_to_complex()
                itemsize = gr.sizeof_char
                scale = 1 / 128.
                itemtype = np.int8
            elif sample_format == "ci16_le":
                converter = blocks.interleaved_short_to_complex()
                itemsize = gr.sizeof_short
                scale = 1 / 32768.
                itemtype = np.int16
            elif sample_format == "cf32_le":
                converter = None
                itemsize = gr.sizeof_gr_complex
                itemtype = np.complex64
            else:
                raise RuntimeError(
                    "Unknown sample format for offline mode given")

            if config['source'] == 'stdin':
                file_source = blocks.file_descriptor_source(itemsize=itemsize,
                                                            fd=0,
                                                            repeat=False)
            elif config['source'] == 'object':
                from iridium.file_object_source import file_object_source
                file_source = file_object_source(fileobject=config['object'],
                                                 itemtype=itemtype)
            else:
                file_source = blocks.file_source(itemsize=itemsize,
                                                 filename=config['file'],
                                                 repeat=False)

            self.source = file_source  # XXX: keep reference

            if converter:
                multi = blocks.multiply_const_cc(scale)
                tb.connect(file_source, converter, multi)
                source = multi
            else:
                source = file_source

        self._fft_burst_tagger = iridium.fft_burst_tagger(
            center_frequency=self._center_frequency,
            fft_size=self._fft_size,
            sample_rate=self._input_sample_rate,
            burst_pre_len=self._burst_pre_len,
            burst_post_len=self._burst_post_len,
            burst_width=int(self._burst_width),
            max_bursts=max_bursts,
            threshold=self._threshold,
            history_size=512,
            offline=self._offline,
            debug=self._verbose)

        # Initial filter to filter the detected bursts. Runs at burst_sample_rate. Used to decimate the signal.
        input_filter = gnuradio.filter.firdes.low_pass_2(
            1, self._channel_sample_rate, self._burst_width / 2,
            self._burst_width, 40)
        #input_filter = gnuradio.filter.firdes.low_pass_2(1, self._channel_sample_rate, 42e3/2, 24e3, 40)
        #print len(input_filter)

        # Filter to find the start of the signal. Should be fairly narrow.
        start_finder_filter = gnuradio.filter.firdes.low_pass_2(
            1, self._burst_sample_rate, 5e3 / 2, 10e3 / 2, 60)
        #print len(start_finder_filter)

        self._iridium_qpsk_demod = iridium.iridium_qpsk_demod_cpp(
            self._channels)
        self._frame_sorter = iridium.frame_sorter()
        self._iridium_frame_printer = iridium.iridium_frame_printer(file_info)

        if raw_capture_filename:
            multi = blocks.multiply_const_cc(32768)
            converter = blocks.complex_to_interleaved_short()
            raw_sink = blocks.file_sink(itemsize=gr.sizeof_short,
                                        filename=raw_capture_filename)
            tb.connect(source, multi, converter, raw_sink)

            # Enable the following if not fast enough
            #self._burst_to_pdu_converters = []
            #self._burst_downmixers = []
            #return

        tb.connect(source, self._fft_burst_tagger)

        if self._use_pfb:
            self._burst_to_pdu_converters = []
            self._burst_downmixers = []
            sinks = []

            for channel in range(self._channels):
                center = channel if channel <= self._channels / 2 else (
                    channel - self._channels)

                # Second and third parameters tell the block where after the PFB it sits.
                relative_center = center / float(self._channels)
                relative_span = 1. / self._channels
                relative_sample_rate = relative_span * self._pfb_over_sample_ratio
                burst_to_pdu_converter = iridium.tagged_burst_to_pdu(
                    self._max_burst_len, relative_center, relative_span,
                    relative_sample_rate, -self._pfb_delay,
                    self._max_queue_len, not self._offline)
                burst_downmixer = iridium.burst_downmix(
                    self._burst_sample_rate,
                    int(0.007 * self._burst_sample_rate), 0, (input_filter),
                    (start_finder_filter),
                    self._handle_multiple_frames_per_burst)

                if debug_id is not None: burst_downmixer.debug_id(debug_id)

                self._burst_downmixers.append(burst_downmixer)
                self._burst_to_pdu_converters.append(burst_to_pdu_converter)

            #pfb_debug_sinks = [blocks.file_sink(itemsize=gr.sizeof_gr_complex, filename="/tmp/channel-%d.f32"%i) for i in range(self._channels)]
            pfb_debug_sinks = None

            pfb = gnuradio.filter.pfb.channelizer_ccf(
                numchans=self._channels,
                taps=self._pfb_fir_filter,
                oversample_rate=self._pfb_over_sample_ratio)

            tb.connect(self._fft_burst_tagger, pfb)

            for i in range(self._channels):
                tb.connect((pfb, i), self._burst_to_pdu_converters[i])
                if pfb_debug_sinks:
                    tb.connect((pfb, i), pfb_debug_sinks[i])

                tb.msg_connect((self._burst_to_pdu_converters[i], 'cpdus'),
                               (self._burst_downmixers[i], 'cpdus'))
                tb.msg_connect(
                    (self._burst_downmixers[i], 'burst_handled'),
                    (self._burst_to_pdu_converters[i], 'burst_handled'))

                tb.msg_connect((self._burst_downmixers[i], 'cpdus'),
                               (self._iridium_qpsk_demod, 'cpdus%d' % i))
        else:
            burst_downmix = iridium.burst_downmix(
                self._burst_sample_rate, int(0.007 * self._burst_sample_rate),
                0, (input_filter), (start_finder_filter),
                self._handle_multiple_frames_per_burst)
            if debug_id is not None: burst_downmix.debug_id(debug_id)

            burst_to_pdu = iridium.tagged_burst_to_pdu(self._max_burst_len,
                                                       0.0, 1.0, 1.0, 0,
                                                       self._max_queue_len,
                                                       not self._offline)

            tb.connect(self._fft_burst_tagger, burst_to_pdu)

            tb.msg_connect((burst_to_pdu, 'cpdus'), (burst_downmix, 'cpdus'))
            tb.msg_connect((burst_downmix, 'burst_handled'),
                           (burst_to_pdu, 'burst_handled'))

            # Final connection to the demodulator. It prints the output to stdout
            tb.msg_connect((burst_downmix, 'cpdus'),
                           (self._iridium_qpsk_demod, 'cpdus'))

            self._burst_downmixers = [burst_downmix]
            self._burst_to_pdu_converters = [burst_to_pdu]

        tb.msg_connect((self._iridium_qpsk_demod, 'pdus'),
                       (self._frame_sorter, 'pdus'))
        tb.msg_connect((self._frame_sorter, 'pdus'),
                       (self._iridium_frame_printer, 'pdus'))
    def __init__(self,
                 satellite='NOAA-XX',
                 gain=35,
                 freq=1698e6,
                 sync_check=False,
                 side="A:0",
                 rate=2e6,
                 frames_file=os.environ['HOME'] +
                 '/data/noaa/frames/NOAA-XX.hrpt',
                 baseband_file=os.environ['HOME'] +
                 '/data/noaa/baseband/NOAA-XX.dat'):
        grc_wxgui.top_block_gui.__init__(self,
                                         title="Enhanced NOAA HRPT Receiver")
        _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
        self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

        ##################################################
        # Parameters
        ##################################################
        self.satellite = satellite
        self.gain = gain
        self.freq = freq
        self.sync_check = sync_check
        self.side = side
        self.rate = rate
        self.frames_file = frames_file
        self.baseband_file = baseband_file

        ##################################################
        # Variables
        ##################################################
        self.sym_rate = sym_rate = 600 * 1109
        self.samp_rate = samp_rate = rate
        self.config_filename = config_filename = os.environ[
            'HOME'] + '/.gnuradio/noaa_hrpt.conf'
        self.sps = sps = samp_rate / sym_rate
        self._saved_pll_alpha_config = ConfigParser.ConfigParser()
        self._saved_pll_alpha_config.read(config_filename)
        try:
            saved_pll_alpha = self._saved_pll_alpha_config.getfloat(
                satellite, 'pll_alpha')
        except:
            saved_pll_alpha = 0.005
        self.saved_pll_alpha = saved_pll_alpha
        self._saved_clock_alpha_config = ConfigParser.ConfigParser()
        self._saved_clock_alpha_config.read(config_filename)
        try:
            saved_clock_alpha = self._saved_clock_alpha_config.getfloat(
                satellite, 'clock_alpha')
        except:
            saved_clock_alpha = 0.001
        self.saved_clock_alpha = saved_clock_alpha
        self.sync_check_txt = sync_check_txt = sync_check
        self.side_text = side_text = side
        self._saved_gain_config = ConfigParser.ConfigParser()
        self._saved_gain_config.read(config_filename)
        try:
            saved_gain = self._saved_gain_config.getfloat(satellite, 'gain')
        except:
            saved_gain = gain
        self.saved_gain = saved_gain
        self.satellite_text = satellite_text = satellite
        self.sample_rate_text = sample_rate_text = samp_rate
        self.rate_tb = rate_tb = rate
        self.pll_alpha = pll_alpha = saved_pll_alpha
        self.max_clock_offset = max_clock_offset = 0.1
        self.max_carrier_offset = max_carrier_offset = 2 * math.pi * 100e3 / samp_rate
        self.hs = hs = int(sps / 2.0)
        self.gain_slider = gain_slider = gain
        self.freq_tb = freq_tb = freq
        self.frames_outfile_text = frames_outfile_text = frames_file
        self.datetime_text = datetime_text = strftime("%A, %B %d %Y %H:%M:%S",
                                                      localtime())
        self.clock_alpha = clock_alpha = saved_clock_alpha

        ##################################################
        # Blocks
        ##################################################
        _gain_slider_sizer = wx.BoxSizer(wx.VERTICAL)
        self._gain_slider_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_gain_slider_sizer,
            value=self.gain_slider,
            callback=self.set_gain_slider,
            label="Gain",
            converter=forms.int_converter(),
            proportion=0,
        )
        self._gain_slider_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_gain_slider_sizer,
            value=self.gain_slider,
            callback=self.set_gain_slider,
            minimum=0,
            maximum=100,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=int,
            proportion=1,
        )
        self.GridAdd(_gain_slider_sizer, 2, 0, 1, 1)
        self.displays = self.displays = wx.Notebook(self.GetWin(),
                                                    style=wx.NB_TOP)
        self.displays.AddPage(grc_wxgui.Panel(self.displays), "RX NOAA HRPT")
        self.displays.AddPage(grc_wxgui.Panel(self.displays), "Information")
        self.Add(self.displays)
        _clock_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
        self._clock_alpha_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_clock_alpha_sizer,
            value=self.clock_alpha,
            callback=self.set_clock_alpha,
            label="Clock alpha",
            converter=forms.float_converter(),
            proportion=0,
        )
        self._clock_alpha_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_clock_alpha_sizer,
            value=self.clock_alpha,
            callback=self.set_clock_alpha,
            minimum=0.001,
            maximum=0.1,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_clock_alpha_sizer, 2, 2, 1, 1)
        self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
            self.displays.GetPage(0).GetWin(),
            baseband_freq=0,
            y_per_div=5,
            y_divs=10,
            ref_level=-70,
            ref_scale=2.0,
            sample_rate=samp_rate,
            fft_size=1024,
            fft_rate=15,
            average=True,
            avg_alpha=0.4,
            title="NOAA HRPT FFT Spectrum",
            peak_hold=False,
        )
        self.displays.GetPage(0).Add(self.wxgui_fftsink2_0.win)
        self.uhd_usrp_source_0 = uhd.usrp_source(
            device_addr="",
            stream_args=uhd.stream_args(
                cpu_format="fc32",
                channels=range(1),
            ),
        )
        self.uhd_usrp_source_0.set_subdev_spec(side, 0)
        self.uhd_usrp_source_0.set_samp_rate(samp_rate)
        self.uhd_usrp_source_0.set_center_freq(freq, 0)
        self.uhd_usrp_source_0.set_gain(gain_slider, 0)
        self._sync_check_txt_static_text = forms.static_text(
            parent=self.GetWin(),
            value=self.sync_check_txt,
            callback=self.set_sync_check_txt,
            label="Continuous sync check",
            converter=forms.str_converter(),
        )
        self.GridAdd(self._sync_check_txt_static_text, 0, 2, 1, 1)
        self._side_text_static_text = forms.static_text(
            parent=self.GetWin(),
            value=self.side_text,
            callback=self.set_side_text,
            label="USRP Side",
            converter=forms.str_converter(),
        )
        self.GridAdd(self._side_text_static_text, 0, 0, 1, 1)
        self._satellite_text_static_text = forms.static_text(
            parent=self.GetWin(),
            value=self.satellite_text,
            callback=self.set_satellite_text,
            label="Satellite",
            converter=forms.str_converter(),
        )
        self.GridAdd(self._satellite_text_static_text, 0, 1, 1, 1)
        self._sample_rate_text_static_text = forms.static_text(
            parent=self.displays.GetPage(1).GetWin(),
            value=self.sample_rate_text,
            callback=self.set_sample_rate_text,
            label="Sample rate",
            converter=forms.float_converter(),
        )
        self.displays.GetPage(1).GridAdd(self._sample_rate_text_static_text, 3,
                                         0, 1, 1)
        self._rate_tb_text_box = forms.text_box(
            parent=self.GetWin(),
            value=self.rate_tb,
            callback=self.set_rate_tb,
            label="Sample rate",
            converter=forms.float_converter(),
        )
        self.GridAdd(self._rate_tb_text_box, 1, 0, 1, 1)
        self.poesweather_noaa_hrpt_deframer_0 = poesweather.noaa_hrpt_deframer(
            False)
        _pll_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
        self._pll_alpha_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_pll_alpha_sizer,
            value=self.pll_alpha,
            callback=self.set_pll_alpha,
            label="PLL Alpha",
            converter=forms.float_converter(),
            proportion=0,
        )
        self._pll_alpha_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_pll_alpha_sizer,
            value=self.pll_alpha,
            callback=self.set_pll_alpha,
            minimum=0.005,
            maximum=0.5,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.GridAdd(_pll_alpha_sizer, 2, 1, 1, 1)
        self.pll = noaa.hrpt_pll_cf(pll_alpha, pll_alpha**2 / 4.0,
                                    max_carrier_offset)
        self._freq_tb_text_box = forms.text_box(
            parent=self.GetWin(),
            value=self.freq_tb,
            callback=self.set_freq_tb,
            label="Frequency",
            converter=forms.float_converter(),
        )
        self.GridAdd(self._freq_tb_text_box, 1, 1, 1, 1)
        self._frames_outfile_text_static_text = forms.static_text(
            parent=self.displays.GetPage(1).GetWin(),
            value=self.frames_outfile_text,
            callback=self.set_frames_outfile_text,
            label="Frames filename",
            converter=forms.str_converter(),
        )
        self.displays.GetPage(1).GridAdd(self._frames_outfile_text_static_text,
                                         4, 0, 1, 1)
        self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(
            sps / 2.0, clock_alpha**2 / 4.0, 0.5, clock_alpha,
            max_clock_offset)
        self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb()
        self._datetime_text_static_text = forms.static_text(
            parent=self.displays.GetPage(1).GetWin(),
            value=self.datetime_text,
            callback=self.set_datetime_text,
            label="Acquisition start",
            converter=forms.str_converter(),
        )
        self.displays.GetPage(1).GridAdd(self._datetime_text_static_text, 2, 0,
                                         1, 1)
        self.blocks_moving_average_xx_0 = blocks.moving_average_ff(
            hs, 1.0 / hs, 4000)
        self.blocks_file_sink_1 = blocks.file_sink(gr.sizeof_short * 1,
                                                   baseband_file)
        self.blocks_file_sink_1.set_unbuffered(False)
        self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_short * 1,
                                                   frames_file)
        self.blocks_file_sink_0.set_unbuffered(False)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
        )
        self.analog_agc_xx_0 = analog.agc_cc(1e-5, 1.0, 1.0 / 32768.0, 1.0)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_agc_xx_0, 0), (self.pll, 0))
        self.connect((self.pll, 0), (self.blocks_moving_average_xx_0, 0))
        self.connect((self.uhd_usrp_source_0, 0), (self.wxgui_fftsink2_0, 0))
        self.connect((self.uhd_usrp_source_0, 0), (self.analog_agc_xx_0, 0))
        self.connect((self.blocks_moving_average_xx_0, 0),
                     (self.digital_clock_recovery_mm_xx_0, 0))
        self.connect((self.digital_clock_recovery_mm_xx_0, 0),
                     (self.digital_binary_slicer_fb_0, 0))
        self.connect((self.poesweather_noaa_hrpt_deframer_0, 0),
                     (self.blocks_file_sink_0, 0))
        self.connect((self.digital_binary_slicer_fb_0, 0),
                     (self.poesweather_noaa_hrpt_deframer_0, 0))
        self.connect((self.uhd_usrp_source_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_file_sink_1, 0))
	def __init__(self, satellite='NOAA-XX', gain=35, freq=1698e6, sync_check=False, side="A:0", rate=2e6, frames_file=os.environ['HOME'] + '/data/noaa/frames/NOAA-XX.hrpt', baseband_file=os.environ['HOME'] + '/data/noaa/baseband/NOAA-XX.dat'):
		grc_wxgui.top_block_gui.__init__(self, title="Enhanced NOAA HRPT Receiver")
		_icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
		self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

		##################################################
		# Parameters
		##################################################
		self.satellite = satellite
		self.gain = gain
		self.freq = freq
		self.sync_check = sync_check
		self.side = side
		self.rate = rate
		self.frames_file = frames_file
		self.baseband_file = baseband_file

		##################################################
		# Variables
		##################################################
		self.sym_rate = sym_rate = 600*1109
		self.samp_rate = samp_rate = rate
		self.config_filename = config_filename = os.environ['HOME']+'/.gnuradio/noaa_hrpt.conf'
		self.sps = sps = samp_rate/sym_rate
		self._saved_pll_alpha_config = ConfigParser.ConfigParser()
		self._saved_pll_alpha_config.read(config_filename)
		try: saved_pll_alpha = self._saved_pll_alpha_config.getfloat(satellite, 'pll_alpha')
		except: saved_pll_alpha = 0.005
		self.saved_pll_alpha = saved_pll_alpha
		self._saved_clock_alpha_config = ConfigParser.ConfigParser()
		self._saved_clock_alpha_config.read(config_filename)
		try: saved_clock_alpha = self._saved_clock_alpha_config.getfloat(satellite, 'clock_alpha')
		except: saved_clock_alpha = 0.001
		self.saved_clock_alpha = saved_clock_alpha
		self.sync_check_txt = sync_check_txt = sync_check
		self.side_text = side_text = side
		self._saved_gain_config = ConfigParser.ConfigParser()
		self._saved_gain_config.read(config_filename)
		try: saved_gain = self._saved_gain_config.getfloat(satellite, 'gain')
		except: saved_gain = gain
		self.saved_gain = saved_gain
		self.satellite_text = satellite_text = satellite
		self.sample_rate_text = sample_rate_text = samp_rate
		self.rate_tb = rate_tb = rate
		self.pll_alpha = pll_alpha = saved_pll_alpha
		self.max_clock_offset = max_clock_offset = 0.1
		self.max_carrier_offset = max_carrier_offset = 2*math.pi*100e3/samp_rate
		self.hs = hs = int(sps/2.0)
		self.gain_slider = gain_slider = gain
		self.freq_tb = freq_tb = freq
		self.frames_outfile_text = frames_outfile_text = frames_file
		self.datetime_text = datetime_text = strftime("%A, %B %d %Y %H:%M:%S", localtime())
		self.clock_alpha = clock_alpha = saved_clock_alpha

		##################################################
		# Blocks
		##################################################
		_gain_slider_sizer = wx.BoxSizer(wx.VERTICAL)
		self._gain_slider_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_gain_slider_sizer,
			value=self.gain_slider,
			callback=self.set_gain_slider,
			label="Gain",
			converter=forms.int_converter(),
			proportion=0,
		)
		self._gain_slider_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_gain_slider_sizer,
			value=self.gain_slider,
			callback=self.set_gain_slider,
			minimum=0,
			maximum=100,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=int,
			proportion=1,
		)
		self.GridAdd(_gain_slider_sizer, 2, 0, 1, 1)
		self.displays = self.displays = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
		self.displays.AddPage(grc_wxgui.Panel(self.displays), "RX NOAA HRPT")
		self.displays.AddPage(grc_wxgui.Panel(self.displays), "Information")
		self.Add(self.displays)
		_clock_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
		self._clock_alpha_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_clock_alpha_sizer,
			value=self.clock_alpha,
			callback=self.set_clock_alpha,
			label="Clock alpha",
			converter=forms.float_converter(),
			proportion=0,
		)
		self._clock_alpha_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_clock_alpha_sizer,
			value=self.clock_alpha,
			callback=self.set_clock_alpha,
			minimum=0.001,
			maximum=0.1,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.GridAdd(_clock_alpha_sizer, 2, 2, 1, 1)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
			self.displays.GetPage(0).GetWin(),
			baseband_freq=0,
			y_per_div=5,
			y_divs=10,
			ref_level=-70,
			ref_scale=2.0,
			sample_rate=samp_rate,
			fft_size=1024,
			fft_rate=15,
			average=True,
			avg_alpha=0.4,
			title="NOAA HRPT FFT Spectrum",
			peak_hold=False,
		)
		self.displays.GetPage(0).Add(self.wxgui_fftsink2_0.win)
		self.uhd_usrp_source_0 = uhd.usrp_source(
			device_addr="",
			stream_args=uhd.stream_args(
				cpu_format="fc32",
				channels=range(1),
			),
		)
		self.uhd_usrp_source_0.set_subdev_spec(side, 0)
		self.uhd_usrp_source_0.set_samp_rate(samp_rate)
		self.uhd_usrp_source_0.set_center_freq(freq, 0)
		self.uhd_usrp_source_0.set_gain(gain_slider, 0)
		self._sync_check_txt_static_text = forms.static_text(
			parent=self.GetWin(),
			value=self.sync_check_txt,
			callback=self.set_sync_check_txt,
			label="Continuous sync check",
			converter=forms.str_converter(),
		)
		self.GridAdd(self._sync_check_txt_static_text, 0, 2, 1, 1)
		self._side_text_static_text = forms.static_text(
			parent=self.GetWin(),
			value=self.side_text,
			callback=self.set_side_text,
			label="USRP Side",
			converter=forms.str_converter(),
		)
		self.GridAdd(self._side_text_static_text, 0, 0, 1, 1)
		self._satellite_text_static_text = forms.static_text(
			parent=self.GetWin(),
			value=self.satellite_text,
			callback=self.set_satellite_text,
			label="Satellite",
			converter=forms.str_converter(),
		)
		self.GridAdd(self._satellite_text_static_text, 0, 1, 1, 1)
		self._sample_rate_text_static_text = forms.static_text(
			parent=self.displays.GetPage(1).GetWin(),
			value=self.sample_rate_text,
			callback=self.set_sample_rate_text,
			label="Sample rate",
			converter=forms.float_converter(),
		)
		self.displays.GetPage(1).GridAdd(self._sample_rate_text_static_text, 3, 0, 1, 1)
		self._rate_tb_text_box = forms.text_box(
			parent=self.GetWin(),
			value=self.rate_tb,
			callback=self.set_rate_tb,
			label="Sample rate",
			converter=forms.float_converter(),
		)
		self.GridAdd(self._rate_tb_text_box, 1, 0, 1, 1)
		self.poesweather_noaa_hrpt_deframer_0 = poesweather.noaa_hrpt_deframer(False)
		_pll_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
		self._pll_alpha_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_pll_alpha_sizer,
			value=self.pll_alpha,
			callback=self.set_pll_alpha,
			label="PLL Alpha",
			converter=forms.float_converter(),
			proportion=0,
		)
		self._pll_alpha_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_pll_alpha_sizer,
			value=self.pll_alpha,
			callback=self.set_pll_alpha,
			minimum=0.005,
			maximum=0.5,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.GridAdd(_pll_alpha_sizer, 2, 1, 1, 1)
		self.pll = noaa.hrpt_pll_cf(pll_alpha, pll_alpha**2/4.0, max_carrier_offset)
		self._freq_tb_text_box = forms.text_box(
			parent=self.GetWin(),
			value=self.freq_tb,
			callback=self.set_freq_tb,
			label="Frequency",
			converter=forms.float_converter(),
		)
		self.GridAdd(self._freq_tb_text_box, 1, 1, 1, 1)
		self._frames_outfile_text_static_text = forms.static_text(
			parent=self.displays.GetPage(1).GetWin(),
			value=self.frames_outfile_text,
			callback=self.set_frames_outfile_text,
			label="Frames filename",
			converter=forms.str_converter(),
		)
		self.displays.GetPage(1).GridAdd(self._frames_outfile_text_static_text, 4, 0, 1, 1)
		self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff(sps/2.0, clock_alpha**2/4.0, 0.5, clock_alpha, max_clock_offset)
		self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb()
		self._datetime_text_static_text = forms.static_text(
			parent=self.displays.GetPage(1).GetWin(),
			value=self.datetime_text,
			callback=self.set_datetime_text,
			label="Acquisition start",
			converter=forms.str_converter(),
		)
		self.displays.GetPage(1).GridAdd(self._datetime_text_static_text, 2, 0, 1, 1)
		self.blocks_moving_average_xx_0 = blocks.moving_average_ff(hs, 1.0/hs, 4000)
		self.blocks_file_sink_1 = blocks.file_sink(gr.sizeof_short*1, baseband_file)
		self.blocks_file_sink_1.set_unbuffered(False)
		self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_short*1, frames_file)
		self.blocks_file_sink_0.set_unbuffered(False)
		self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short()
		self.analog_agc_xx_0 = analog.agc_cc(1e-5, 1.0, 1.0/32768.0, 1.0)

		##################################################
		# Connections
		##################################################
		self.connect((self.analog_agc_xx_0, 0), (self.pll, 0))
		self.connect((self.pll, 0), (self.blocks_moving_average_xx_0, 0))
		self.connect((self.uhd_usrp_source_0, 0), (self.wxgui_fftsink2_0, 0))
		self.connect((self.uhd_usrp_source_0, 0), (self.analog_agc_xx_0, 0))
		self.connect((self.blocks_moving_average_xx_0, 0), (self.digital_clock_recovery_mm_xx_0, 0))
		self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0))
		self.connect((self.poesweather_noaa_hrpt_deframer_0, 0), (self.blocks_file_sink_0, 0))
		self.connect((self.digital_binary_slicer_fb_0, 0), (self.poesweather_noaa_hrpt_deframer_0, 0))
		self.connect((self.uhd_usrp_source_0, 0), (self.blocks_complex_to_interleaved_short_0, 0))
		self.connect((self.blocks_complex_to_interleaved_short_0, 0), (self.blocks_file_sink_1, 0))
Ejemplo n.º 22
0
    def coreTest(self, rx_gain, tx_amp, centre_freq, sample_rate=20e6):
        """
        |<------------ TX CHAIN ---------->| |<----- RX CHAIN ---->|
                                    +------+ +------+
        +--------+    +--------+    |      | |      |    +---------+
        | sig[0] |--->| c2s[0] |--->|ch0   | |   ch0|--->| vsnk[0] |
        +--------+    +--------+    |      | |      |    +---------+
        +--------+    +--------+    |      | |      |    +---------+
        | sig[1] |--->| c2s[1] |--->|ch1   | |   ch1|--->| vsnk[1] |
        +--------+    +--------+    |      | |      |    +---------+
        +--------+    +--------+    |      | |      |    +---------+
        | sig[2] |--->| c2s[2] |--->|ch2   | |   ch2|--->| vsnk[2] |
        +--------+    +--------+    |      | |      |    +---------+
        +--------+    +--------+    |      | |      |    +---------+
        | sig[3] |--->| c2s[3] |--->|ch3   | |   ch3|--->| vsnk[3] |
        +--------+    +--------+    | csnk | | csrc |    +---------+
                                    +------+ +------+
        """

        # Is above 40 MHz, disable Channels C & D
        if centre_freq > 40e6:
            self.channels = range(2)

        tb = gr.top_block()

        # Variables.
        wave_freq = 1e6

        sc = uhd.stream_cmd_t(uhd.stream_cmd_t.STREAM_MODE_NUM_SAMPS_AND_DONE)
        sc.num_samps = 64

        # Blocks and Connections (TX CHAIN).
        sigs = [
            analog.sig_source_c(sample_rate, analog.GR_SIN_WAVE, wave_freq,
                                tx_amp, 0.0) for channel in self.channels
        ]

        c2ss = [
            blocks.complex_to_interleaved_short(True)
            for channel in self.channels
        ]

        csnk = crimson_sink_s(self.channels, sample_rate, centre_freq, 0.0)

        for channel in self.channels:
            tb.connect(sigs[channel], c2ss[channel])
            tb.connect(c2ss[channel], (csnk, channel))

        # Blocks and Connections (RX CHAIN).
        csrc = crimson_source_c(self.channels, sample_rate, centre_freq,
                                rx_gain)

        vsnk = [blocks.vector_sink_c() for channel in self.channels]

        for channel in self.channels:
            tb.connect((csrc, channel), vsnk[channel])

        # Reset TX and RX times to be roughly in sync.
        csnk.set_time_now(uhd.time_spec_t(0.0))
        csrc.set_time_now(uhd.time_spec_t(0.0))

        # Issue stream command to start RX chain somewhere in the middle of the test.
        sc.stream_now = False
        sc.time_spec = uhd.time_spec_t(self.test_time / 2.0)
        csrc.issue_stream_cmd(sc)

        # Run the test.
        tb.start()
        time.sleep(self.test_time)
        tb.stop()
        tb.wait()

        # Return a vsnk sample for further processing and verification.
        # vsnk are to be processed in individual unit tests, eg. def test_xyz_t(self):
        # Read sigproc.py for further information on signal processing and vsnks.

        return vsnk, csnk, csrc
    def __init__(self, datatype='short', radio_id='F5BE35', sat_name='4F3'):
        gr.top_block.__init__(
            self, "4F3_F5BE35_20180903_043626.400121_UTC_80M.short")
        Qt.QWidget.__init__(self)
        self.setWindowTitle("4F3_F5BE35_20180903_043626.400121_UTC_80M.short")
        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", "inmarsat_cband_x310_record")
        self.restoreGeometry(self.settings.value("geometry").toByteArray())

        ##################################################
        # Parameters
        ##################################################
        self.datatype = datatype
        self.radio_id = radio_id
        self.sat_name = sat_name

        ##################################################
        # Variables
        ##################################################
        self.ts_str = ts_str = dt.strftime(dt.utcnow(),
                                           "%Y%m%d_%H%M%S.%f") + '_UTC'
        self.samp_rate = samp_rate = 100e6
        self.rf_freq = rf_freq = 3627.5e6
        self.resamp_rate = resamp_rate = 0.8
        self.hs_lo = hs_lo = 5150e6
        self.path = path = "/data1/captures/inmarsat_c/"
        self.if_freq = if_freq = hs_lo - rf_freq
        self.fn = fn = "{:s}_{:s}_{:s}_{:s}M.{:s}".format(
            sat_name, radio_id, ts_str,
            str(int(samp_rate / 1e6 * resamp_rate)), datatype)
        self.rx_gain = rx_gain = 10
        self.if_freq_lbl = if_freq_lbl = if_freq
        self.fp = fp = "{:s}{:s}".format(path, fn)

        ##################################################
        # Blocks
        ##################################################
        self._samp_rate_tool_bar = Qt.QToolBar(self)
        self._samp_rate_tool_bar.addWidget(Qt.QLabel('SAMP_RATE' + ": "))
        self._samp_rate_line_edit = Qt.QLineEdit(str(self.samp_rate))
        self._samp_rate_tool_bar.addWidget(self._samp_rate_line_edit)
        self._samp_rate_line_edit.returnPressed.connect(
            lambda: self.set_samp_rate(
                eng_notation.str_to_num(
                    str(self._samp_rate_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._samp_rate_tool_bar, 9, 0, 1, 1)
        for r in range(9, 10):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._rx_gain_tool_bar = Qt.QToolBar(self)
        self._rx_gain_tool_bar.addWidget(Qt.QLabel('GAIN' + ": "))
        self._rx_gain_line_edit = Qt.QLineEdit(str(self.rx_gain))
        self._rx_gain_tool_bar.addWidget(self._rx_gain_line_edit)
        self._rx_gain_line_edit.returnPressed.connect(lambda: self.set_rx_gain(
            eng_notation.str_to_num(
                str(self._rx_gain_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._rx_gain_tool_bar, 9, 3, 1, 1)
        for r in range(9, 10):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(3, 4):
            self.top_grid_layout.setColumnStretch(c, 1)
        self._rf_freq_tool_bar = Qt.QToolBar(self)
        self._rf_freq_tool_bar.addWidget(Qt.QLabel("rf_freq" + ": "))
        self._rf_freq_line_edit = Qt.QLineEdit(str(self.rf_freq))
        self._rf_freq_tool_bar.addWidget(self._rf_freq_line_edit)
        self._rf_freq_line_edit.returnPressed.connect(lambda: self.set_rf_freq(
            eng_notation.str_to_num(
                str(self._rf_freq_line_edit.text().toAscii()))))
        self.top_grid_layout.addWidget(self._rf_freq_tool_bar, 10, 0, 1, 1)
        for r in range(10, 11):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(0, 1):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.uhd_usrp_source_0 = uhd.usrp_source(
            ",".join(("addr=192.168.40.2", "")),
            uhd.stream_args(
                cpu_format="fc32",
                channels=range(1),
            ),
        )
        self.uhd_usrp_source_0.set_clock_source('gpsdo', 0)
        self.uhd_usrp_source_0.set_time_source('gpsdo', 0)
        self.uhd_usrp_source_0.set_subdev_spec('A:0', 0)
        self.uhd_usrp_source_0.set_samp_rate(samp_rate)
        self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()),
                                            uhd.ALL_MBOARDS)
        self.uhd_usrp_source_0.set_center_freq(if_freq, 0)
        self.uhd_usrp_source_0.set_gain(rx_gain, 0)
        self.uhd_usrp_source_0.set_antenna('RX2', 0)
        self.pfb_arb_resampler_xxx_0 = pfb.arb_resampler_ccf(resamp_rate,
                                                             taps=None,
                                                             flt_size=64)
        self.pfb_arb_resampler_xxx_0.declare_sample_delay(0)

        self._if_freq_lbl_tool_bar = Qt.QToolBar(self)

        if None:
            self._if_freq_lbl_formatter = None
        else:
            self._if_freq_lbl_formatter = lambda x: eng_notation.num_to_str(x)

        self._if_freq_lbl_tool_bar.addWidget(Qt.QLabel('IF [MHz]' + ": "))
        self._if_freq_lbl_label = Qt.QLabel(
            str(self._if_freq_lbl_formatter(self.if_freq_lbl)))
        self._if_freq_lbl_tool_bar.addWidget(self._if_freq_lbl_label)
        self.top_grid_layout.addWidget(self._if_freq_lbl_tool_bar, 10, 1, 1, 1)
        for r in range(10, 11):
            self.top_grid_layout.setRowStretch(r, 1)
        for c in range(1, 2):
            self.top_grid_layout.setColumnStretch(c, 1)
        self.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(rf_freq,
                                                       samp_rate * resamp_rate)
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((-1, ))
        self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex(
            False, True)
        self.blocks_float_to_complex_0 = blocks.float_to_complex(1)
        self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_short * 1, fp,
                                                   False)
        self.blocks_file_sink_0.set_unbuffered(False)
        self.blocks_complex_to_interleaved_short_0 = blocks.complex_to_interleaved_short(
            False)
        self.blocks_complex_to_float_0 = blocks.complex_to_float(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)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_agc2_xx_0, 0),
                     (self.blocks_complex_to_float_0, 0))
        self.connect((self.blocks_complex_to_float_0, 0),
                     (self.blocks_float_to_complex_0, 0))
        self.connect((self.blocks_complex_to_float_0, 1),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_file_sink_0, 0))
        self.connect((self.blocks_complex_to_interleaved_short_0, 0),
                     (self.blocks_interleaved_short_to_complex_0, 0))
        self.connect((self.blocks_float_to_complex_0, 0),
                     (self.blocks_complex_to_interleaved_short_0, 0))
        self.connect((self.blocks_interleaved_short_to_complex_0, 0),
                     (self.fosphor_glfw_sink_c_0, 0))
        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.blocks_float_to_complex_0, 1))
        self.connect((self.pfb_arb_resampler_xxx_0, 0),
                     (self.analog_agc2_xx_0, 0))
        self.connect((self.uhd_usrp_source_0, 0),
                     (self.pfb_arb_resampler_xxx_0, 0))