Beispiel #1
0
    def test_descriptor_001(self):
        src_data = range(1000)
        expected_result = range(1000)

        filename = "tmp.32f"
        fhandle0 = open(filename, "wb")
        fd0 = fhandle0.fileno()

        src = blocks.vector_source_f(src_data)
        snk = blocks.file_descriptor_sink(gr.sizeof_float, fd0)

        self.tb.connect(src, snk)
        self.tb.run()
        os.fsync(fd0)
        fhandle0.close()

        fhandle1 = open(filename, "rb")
        fd1 = fhandle1.fileno()
        src2 = blocks.file_descriptor_source(gr.sizeof_float, fd1, False)
        snk2 = blocks.vector_sink_f()

        self.tb.disconnect(src, snk)
        self.tb.connect(src2, snk2)
        self.tb.run()
        os.fsync(fd1)
        fhandle1.close()

        os.remove(filename)

        result_data = snk2.data()
        self.assertFloatTuplesAlmostEqual(expected_result, result_data)
    def test_file_descriptor(self):
        src_data = range(1000)
        expected_result = range(1000)

        snk2 = blocks.vector_sink_f()

        with tempfile.NamedTemporaryFile() as temp:
            fhandle0 = open(temp.name, "wb")
            fd0 = fhandle0.fileno()

            src = blocks.vector_source_f(src_data)
            snk = blocks.file_descriptor_sink(gr.sizeof_float, fd0)

            self.tb.connect(src, snk)
            self.tb.run()
            os.fsync(fd0)
            fhandle0.close()

            fhandle1 = open(temp.name, "rb")
            fd1 = fhandle1.fileno()
            src2 = blocks.file_descriptor_source(gr.sizeof_float, fd1, False)

            self.tb.disconnect(src, snk)
            self.tb.connect(src2, snk2)
            self.tb.run()
            os.fsync(fd1)
            fhandle1.close()

        result_data = snk2.data()
        self.assertFloatTuplesAlmostEqual(expected_result, result_data)
        self.assertEqual(len(snk2.tags()), 0)
Beispiel #3
0
 def init_audio(self, config):
     filename = config['args'].replace('audio:', '')
     if filename.startswith('file:'):
         filename = filename.replace('file:', '')
         repeat = False
         s2f = blocks.short_to_float()
         K = 1 / 32767.0
         src = blocks.multiply_const_ff(K)
         throttle = blocks.throttle(
             gr.sizeof_short,
             self.sample_rate)  # may be redundant in stdin case ?
         if filename == '-':
             fd = 0  # stdin
             fsrc = blocks.file_descriptor_source(gr.sizeof_short, fd,
                                                  repeat)
         else:
             fsrc = blocks.file_source(gr.sizeof_short, filename, repeat)
         self.tb.connect(fsrc, throttle, s2f, src)
     else:
         src = audio.source(self.sample_rate, filename)
     gain = 1.0
     if config['gains'].startswith('audio:'):
         gain = float(config['gains'].replace('audio:', ''))
     self.src = blocks.multiply_const_ff(gain)
     self.tb.connect(src, self.src)
    def test_file_descriptor(self):
        src_data = range(1000)
        expected_result = range(1000)

        snk2 = blocks.vector_sink_f()

        with tempfile.NamedTemporaryFile() as temp:
            fhandle0 = open(temp.name, "wb")
            fd0 = fhandle0.fileno()

            src = blocks.vector_source_f(src_data)
            snk = blocks.file_descriptor_sink(gr.sizeof_float, fd0)

            self.tb.connect(src, snk)
            self.tb.run()
            os.fsync(fd0)
            fhandle0.close()

            fhandle1 = open(temp.name, "rb")
            fd1 = fhandle1.fileno()
            src2 = blocks.file_descriptor_source(gr.sizeof_float, fd1, False)

            self.tb.disconnect(src, snk)
            self.tb.connect(src2, snk2)
            self.tb.run()
            os.fsync(fd1)
            fhandle1.close()

        result_data = snk2.data()
        self.assertFloatTuplesAlmostEqual(expected_result, result_data)
        self.assertEqual(len(snk2.tags()), 0)
Beispiel #5
0
 def __init__(self, itemsize, addr, port, server=True):
     # init hier block
     gr.hier_block2.__init__(
         self, 'tcp_source',
         gr.io_signature(0, 0, 0),
         gr.io_signature(1, 1, itemsize),
     )
     fd = _get_sock_fd(addr, port, server)
     self.connect(blocks.file_descriptor_source(itemsize, fd), self)
Beispiel #6
0
 def __init__(self, itemsize, addr, port, server=True):
     #init hier block
     gr.hier_block2.__init__(
         self, 'tcp_source',
         gr.io_signature(0, 0, 0),
         gr.io_signature(1, 1, itemsize),
     )
     fd = _get_sock_fd(addr, port, server)
     self.connect(blocks.file_descriptor_source(itemsize, fd), self)
Beispiel #7
0
def test_file_descriptor_source():
    tmp_f = tempfile.TemporaryFile()
    array.array('f', [random.random() for _ in range(262144)]).tofile(tmp_f)
    tmp_f.seek(0)

    top = gr.top_block()
    src = blocks.file_descriptor_source(gr.sizeof_float, os.dup(tmp_f.fileno()), True)
    probe = blocks.probe_rate(gr.sizeof_float)
    top.connect(src, probe)

    return top, probe
def test_file_descriptor_source():
    tmp_f = tempfile.TemporaryFile()
    array.array('f', [random.random() for _ in range(262144)]).tofile(tmp_f)
    tmp_f.seek(0)

    top = gr.top_block()
    src = blocks.file_descriptor_source(gr.sizeof_float, os.dup(tmp_f.fileno()), True)
    probe = blocks.probe_rate(gr.sizeof_float)
    top.connect(src, probe)

    return top, probe
 def __init__(self, addr, port, rate, freq1, freq2, corr):
   gr.hier_block2.__init__(
     self,
     name = "red_pitaya_source",
     input_signature = gr.io_signature(0, 0, 0),
     output_signature = gr.io_signature(1, 1, gr.sizeof_gr_complex)
   )
   self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   self.sock.connect((addr, port))
   fd = os.dup(self.sock.fileno())
   self.connect(blocks.file_descriptor_source(gr.sizeof_gr_complex, fd), self)
   self.set_rate(rate)
   self.set_freq1(freq1, corr)
   self.set_freq2(freq2, corr)
 def __init__(self, addr, port, freq, corr):
     gr.hier_block2.__init__(self,
                             name="red_pitaya_source",
                             input_signature=gr.io_signature(0, 0, 0),
                             output_signature=gr.io_signature(
                                 1, 1, gr.sizeof_gr_complex))
     self.ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     self.ctrl_sock.connect((addr, port))
     self.ctrl_sock.send(struct.pack('<I', 0))
     self.data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     self.data_sock.connect((addr, port))
     self.data_sock.send(struct.pack('<I', 1))
     fd = os.dup(self.data_sock.fileno())
     self.connect(blocks.file_descriptor_source(gr.sizeof_gr_complex, fd),
                  self)
     self.set_freq(freq, corr)
 def __init__(self, addr, port, freq, corr):
   gr.hier_block2.__init__(
     self,
     name = "red_pitaya_source",
     input_signature = gr.io_signature(0, 0, 0),
     output_signature = gr.io_signature(1, 1, gr.sizeof_gr_complex)
   )
   self.ctrl_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   self.ctrl_sock.connect((addr, port))
   self.ctrl_sock.send(struct.pack('<I', 0))
   self.data_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   self.data_sock.connect((addr, port))
   self.data_sock.send(struct.pack('<I', 1))
   fd = os.dup(self.data_sock.fileno())
   self.connect(blocks.file_descriptor_source(gr.sizeof_gr_complex, fd), self)
   self.set_freq(freq, corr)
    def _tcp_client(self):
        dst = blocks.vector_sink_s()
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        for t in (0, 0.2):
# wait until server listens
            sleep(t)
            try:
                sock.connect((self.addr, self.port))
            except socket.error as e:
                if e.errno != 111:
                    raise
                continue
            break
        fd = os.dup(sock.fileno())
        self.tb_rcv.connect(blocks.file_descriptor_source(self.itemsize, fd), dst)
        self.tb_rcv.run()
        self.assertEqual(self.data, dst.data())
 def _tcp_client(self):
     dst = blocks.vector_sink_s()
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     for t in (0, 0.2):
         # wait until server listens
         sleep(t)
         try:
             sock.connect((self.addr, self.port))
         except socket.error as e:
             if e.errno != 111:
                 raise
             continue
         break
     fd = os.dup(sock.fileno())
     self.tb_rcv.connect(blocks.file_descriptor_source(self.itemsize, fd),
                         dst)
     self.tb_rcv.run()
     self.assertEqual(self.data, dst.data())
Beispiel #14
0
    def __init__(self):
        grc_wxgui.top_block_gui.__init__(self, title="Dvbc Tx Wxgui")
        _icon_path = "/usr/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
        self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

        ##################################################
        # Variables
        ##################################################
        self._symrate_config = ConfigParser.ConfigParser()
        self._symrate_config.read('./dvbc.conf')
        try:
            symrate = self._symrate_config.getint('dvbc', 'symbolrate')
        except:
            symrate = 0
        self.symrate = symrate
        self._mode_config = ConfigParser.ConfigParser()
        self._mode_config.read('./dvbc.conf')
        try:
            mode = self._mode_config.get('dvbc', 'mode')
        except:
            mode = 0
        self.mode = mode
        self._center_freq_config = ConfigParser.ConfigParser()
        self._center_freq_config.read('./dvbc.conf')
        try:
            center_freq = self._center_freq_config.getint(
                'hackrf', 'frequency')
        except:
            center_freq = 0
        self.center_freq = center_freq
        self.samp_rate = samp_rate = symrate * 2
        self.rrc_taps = rrc_taps = 100
        self._rf_gain_config = ConfigParser.ConfigParser()
        self._rf_gain_config.read('./dvbc.conf')
        try:
            rf_gain = self._rf_gain_config.getint('hackrf', 'rf-gain')
        except:
            rf_gain = 0
        self.rf_gain = rf_gain
        self._if_gain_config = ConfigParser.ConfigParser()
        self._if_gain_config.read('./dvbc.conf')
        try:
            if_gain = self._if_gain_config.getint('hackrf', 'if-gain')
        except:
            if_gain = 0
        self.if_gain = if_gain
        self.anz0 = anz0 = str(
            center_freq / 1000000) + "MHZ / " + mode + " / " + str(
                symrate / 1000) + " kSym/s"

        infile = str(sys.argv[1])

        if mode == "16QAM":
            mod = dvbc.MOD_16QAM
        elif mode == "32QAM":
            mod = dvbc.MOD_32QAM
        elif mode == "64QAM":
            mod = dvbc.MOD_64QAM
        elif mode == "128QAM":
            mod = dvbc.MOD_128QAM
        elif mode == "256QAM":
            mod = dvbc.MOD_256QAM
        else:
            sys.stderr.write(
                "MODE IN CONFIG WRONG! Values: 16QAM, 32QAM, 64QAM, 128QAM or 256QAM \n"
            )
            sys.exit(1)

        print "Frequency: ", center_freq / 1000000, "Mhz / Mode: ", mode, "/ Symbolrate: ", symrate / 1000, "\n"

        ##################################################
        # Blocks
        ##################################################
        self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
            self.GetWin(),
            baseband_freq=center_freq,
            y_per_div=10,
            y_divs=10,
            ref_level=0,
            ref_scale=2.0,
            sample_rate=samp_rate,
            fft_size=1024,
            fft_rate=15,
            average=False,
            avg_alpha=None,
            title='FFT Plot',
            peak_hold=False,
        )
        self.Add(self.wxgui_fftsink2_0.win)
        self.osmosdr_sink_1 = osmosdr.sink(args="numchan=" + str(1) + " " +
                                           'hackrf,buffers=128,buflen=32768')
        self.osmosdr_sink_1.set_sample_rate(samp_rate)
        self.osmosdr_sink_1.set_center_freq(center_freq, 0)
        self.osmosdr_sink_1.set_freq_corr(0, 0)
        self.osmosdr_sink_1.set_gain(rf_gain, 0)
        self.osmosdr_sink_1.set_if_gain(if_gain, 0)
        self.osmosdr_sink_1.set_bb_gain(0, 0)
        self.osmosdr_sink_1.set_antenna('', 0)
        self.osmosdr_sink_1.set_bandwidth(8750000, 0)

        self.fft_filter_xxx_0 = filter.fft_filter_ccc(
            1, (firdes.root_raised_cosine(0.85, samp_rate, samp_rate / 2, 0.15,
                                          rrc_taps)), 1)
        self.fft_filter_xxx_0.declare_sample_delay(0)
        self.dvbc_symbolmapper_bb_0 = dvbc.symbolmapper_bb(mod)
        self.dvbc_modulator_bc_0 = dvbc.modulator_bc(mod)
        self.dtv_dvbt_reed_solomon_enc_0 = dtv.dvbt_reed_solomon_enc(
            2, 8, 0x11d, 255, 239, 8, 51, 8)
        self.dtv_dvbt_energy_dispersal_0 = dtv.dvbt_energy_dispersal(1)
        self.dtv_dvbt_convolutional_interleaver_0 = dtv.dvbt_convolutional_interleaver(
            136, 12, 17)

        if infile == "-":
            self.blocks_file_descriptor_source_0 = blocks.file_descriptor_source(
                gr.sizeof_char * 1, 0, True)
        else:
            self.blocks_file_source_0 = blocks.file_source(
                gr.sizeof_char * 1, infile, True)

        self._anz0_static_text = forms.static_text(
            parent=self.GetWin(),
            value=self.anz0,
            callback=self.set_anz0,
            label='Parameter',
            converter=forms.str_converter(),
        )
        self.Add(self._anz0_static_text)

        ##################################################
        # Connections
        ##################################################

        if infile == "-":
            self.connect((self.blocks_file_descriptor_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))
        else:
            self.connect((self.blocks_file_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))

        self.connect((self.dtv_dvbt_convolutional_interleaver_0, 0),
                     (self.dvbc_symbolmapper_bb_0, 0))
        self.connect((self.dtv_dvbt_energy_dispersal_0, 0),
                     (self.dtv_dvbt_reed_solomon_enc_0, 0))
        self.connect((self.dtv_dvbt_reed_solomon_enc_0, 0),
                     (self.dtv_dvbt_convolutional_interleaver_0, 0))
        self.connect((self.dvbc_modulator_bc_0, 0), (self.fft_filter_xxx_0, 0))
        self.connect((self.dvbc_symbolmapper_bb_0, 0),
                     (self.dvbc_modulator_bc_0, 0))
        self.connect((self.fft_filter_xxx_0, 0), (self.osmosdr_sink_1, 0))
        self.connect((self.fft_filter_xxx_0, 0), (self.wxgui_fftsink2_0, 0))
Beispiel #15
0
    def __init__(self):
        gr.top_block.__init__(self, "Dvbt2 Master")

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = (8000000.0 * 8) / 7
        self._rf_gain_config = ConfigParser.ConfigParser()
        self._rf_gain_config.read('./dvbt2.conf')
        try:
            rf_gain = self._rf_gain_config.getint('hackrf', 'rf-gain')
        except:
            rf_gain = 0
        self.rf_gain = rf_gain
        self._if_gain_config = ConfigParser.ConfigParser()
        self._if_gain_config.read('./dvbt2.conf')
        try:
            if_gain = self._if_gain_config.getint('hackrf', 'if-gain')
        except:
            if_gain = 0
        self.if_gain = if_gain
        self._center_freq_config = ConfigParser.ConfigParser()
        self._center_freq_config.read('./dvbt2.conf')
        try:
            center_freq = self._center_freq_config.getint(
                'hackrf', 'frequency')
        except:
            center_freq = 0
        self.center_freq = center_freq
        self._band_width_config = ConfigParser.ConfigParser()
        self._band_width_config.read('./dvbt2.conf')
        try:
            band_width = self._band_width_config.getint('hackrf', 'bandwidth')
        except:
            band_width = 0
        self.band_width = band_width
        self._VERSION_config = ConfigParser.ConfigParser()
        self._VERSION_config.read('./dvbt2.conf')
        try:
            VERSION = self._VERSION_config.getint('dvbt2', 'version')
        except:
            VERSION = 0
        self.VERSION = VERSION
        self._PREAMBLE_config = ConfigParser.ConfigParser()
        self._PREAMBLE_config.read('./dvbt2.conf')
        try:
            PREAMBLE = self._PREAMBLE_config.get('dvbt2', 'preamble')
        except:
            PREAMBLE = '0'
        self.PREAMBLE = PREAMBLE
        self._PILOT_config = ConfigParser.ConfigParser()
        self._PILOT_config.read('./dvbt2.conf')
        try:
            PILOT = self._PILOT_config.getint('dvbt2', 'pilot-pattern')
        except:
            PILOT = 0
        self.PILOT = PILOT
        self._PAPR_config = ConfigParser.ConfigParser()
        self._PAPR_config.read('./dvbt2.conf')
        try:
            PAPR = self._PAPR_config.get('dvbt2', 'papr')
        except:
            PAPR = '0'
        self.PAPR = PAPR
        self._L1MOD_config = ConfigParser.ConfigParser()
        self._L1MOD_config.read('./dvbt2.conf')
        try:
            L1MOD = self._L1MOD_config.get('dvbt2', 'L1-mod')
        except:
            L1MOD = '0'
        self.L1MOD = L1MOD
        self._GI_config = ConfigParser.ConfigParser()
        self._GI_config.read('./dvbt2.conf')
        try:
            GI = self._GI_config.get('dvbt2', 'guard-interval')
        except:
            GI = '0'
        self.GI = GI
        self._FFTSIZE_config = ConfigParser.ConfigParser()
        self._FFTSIZE_config.read('./dvbt2.conf')
        try:
            FFTSIZE = self._FFTSIZE_config.get('dvbt2', 'fft-size')
        except:
            FFTSIZE = '0'
        self.FFTSIZE = FFTSIZE
        self._FECBLKS_config = ConfigParser.ConfigParser()
        self._FECBLKS_config.read('./dvbt2.conf')
        try:
            FECBLKS = self._FECBLKS_config.getint('dvbt2', 'fec-blocks')
        except:
            FECBLKS = 0
        self.FECBLKS = FECBLKS
        self._DATASYM_config = ConfigParser.ConfigParser()
        self._DATASYM_config.read('./dvbt2.conf')
        try:
            DATASYM = self._DATASYM_config.getint('dvbt2', 'datasymbols')
        except:
            DATASYM = 0
        self.DATASYM = DATASYM
        self._CONSTELLATION_config = ConfigParser.ConfigParser()
        self._CONSTELLATION_config.read('./dvbt2.conf')
        try:
            CONSTELLATION = self._CONSTELLATION_config.get(
                'dvbt2', 'constellation')
        except:
            CONSTELLATION = '0'
        self.CONSTELLATION = CONSTELLATION
        self._CODERATE_config = ConfigParser.ConfigParser()
        self._CODERATE_config.read('./dvbt2.conf')
        try:
            CODERATE = self._CODERATE_config.get('dvbt2', 'coderate')
        except:
            CODERATE = '0'
        self.CODERATE = CODERATE
        self._CARREXT_config = ConfigParser.ConfigParser()
        self._CARREXT_config.read('./dvbt2.conf')
        try:
            CARREXT = self._CARREXT_config.get('dvbt2', 'ext-carriers')
        except:
            CARREXT = '0'
        self.CARREXT = CARREXT

        infile = str(sys.argv[1])

        if VERSION == 111:
            ver = dtv.VERSION_111
        elif VERSION == 131:
            ver = dtv.VERSION_131
        else:
            sys.stderr.write("VERSION IN CONFIG WRONG! Values: 111 or 131 \n")
            sys.exit(1)

        if PREAMBLE == "SISO":
            preamb = dtv.PREAMBLE_T2_SISO
        elif PREAMBLE == "MISO":
            preamb = dtv.PREAMBLE_T2_MISO
        else:
            sys.stderr.write(
                "PREAMBLE IN CONFIG WRONG! Values: SISO or MISO \n")
            sys.exit(1)

        if PILOT == 1:
            pil = dtv.PILOT_PP1
        elif PILOT == 2:
            pil = dtv.PILOT_PP2
        elif PILOT == 3:
            pil = dtv.PILOT_PP3
        elif PILOT == 4:
            pil = dtv.PILOT_PP4
        elif PILOT == 5:
            pil = dtv.PILOT_PP5
        elif PILOT == 6:
            pil = dtv.PILOT_PP6
        elif PILOT == 7:
            pil = dtv.PILOT_PP7
        elif PILOT == 8:
            pil = dtv.PILOT_PP8
        else:
            sys.stderr.write(
                "PILOT-PATTERN IN CONFIG WRONG! Values: 1, 2, 3, 4, 5, 6, 7 or 8 \n"
            )
            sys.exit(1)

        if PAPR == "on":
            pap = dtv.PAPR_ON
        elif PAPR == "off":
            pap = dtv.PAPR_OFF
        else:
            sys.stderr.write("PAPR IN CONFIG WRONG! Values: on or off \n")
            sys.exit(1)

        if L1MOD == "QPSK":
            l1m = dtv.L1_MOD_QPSK
        elif L1MOD == "BPSK":
            l1m = dtv.L1_MOD_BPSK
        elif L1MOD == "16QAM":
            l1m = dtv.L1_MOD_16QAM
        elif L1MOD == "64QAM":
            l1m = dtv.L1_MOD_64QAM
        else:
            sys.stderr.write(
                "L1-MOD IN CONFIG WRONG! Values: QPSK, BPSK, 16QAM or 64QAM \n"
            )
            sys.exit(1)

        if GI == "1/32":
            gint = dtv.GI_1_32
            mul = 1
            div = 32
        elif GI == "1/16":
            gint = dtv.GI_1_16
            mul = 1
            div = 16
        elif GI == "1/8":
            gint = dtv.GI_1_8
            mul = 1
            div = 8
        elif GI == "1/4":
            gint = dtv.GI_1_4
            mul = 1
            div = 4
        elif GI == "1/128":
            gint = dtv.GI_1_128
            mul = 1
            div = 128
        elif GI == "19/128":
            gint = dtv.GI_19_128
            mul = 19
            div = 128
        elif GI == "19/256":
            gint = dtv.GI_19_256
            mul = 19
            div = 256
        else:
            sys.stderr.write(
                "GUARD-INTERVAL IN CONFIG WRONG! Values: 1/32, 1/16, 1/8, 1/4, 1/128, 19/128, 19/256 \n"
            )
            sys.exit(1)

        if FFTSIZE == "16k":
            ffts = dtv.FFTSIZE_16K
            fft_length = 16384
        elif FFTSIZE == "32k":
            ffts = dtv.FFTSIZE_32K
            fft_length = 32768
        else:
            sys.stderr.write("FFTSIZE IN CONFIG WRONG! Values: 16k or 32k \n")
            sys.exit(1)

        if CONSTELLATION == "QPSK":
            const = dtv.MOD_QPSK
        elif CONSTELLATION == "16QAM":
            const = dtv.MOD_16QAM
        elif CONSTELLATION == "64QAM":
            const = dtv.MOD_64QAM
        elif CONSTELLATION == "256QAM":
            const = dtv.MOD_256QAM
        else:
            sys.stderr.write(
                "CONSTELLATION IN CONFIG WRONG! Values: QPSK 16QAM 64QAM 256QAM \n"
            )
            sys.exit(1)

        if CODERATE == "1/2":
            codr = dtv.C1_2
        elif CODERATE == "2/5":
            codr = dtv.C2_5
        elif CODERATE == "3/5":
            codr = dtv.C3_5
        elif CODERATE == "2/3":
            codr = dtv.C2_3
        elif CODERATE == "3/4":
            codr = dtv.C3_4
        elif CODERATE == "4/5":
            codr = dtv.C4_5
        elif CODERATE == "5/6":
            codr = dtv.C5_6
        else:
            sys.stderr.write(
                "CODERATE IN CONFIG WRONG! Values: 1/2 2/5 3/5 2/3 3/4 4/5 5/6 \n"
            )
            sys.exit(1)

        if CARREXT == "on":
            extcarr = dtv.CARRIERS_EXTENDED
        elif CARREXT == "off":
            extcarr = dtv.CARRIERS_NORMAL
        else:
            sys.stderr.write(
                "EXT-CARRIERS IN CONFIG WRONG! Values: on or off \n")
            sys.exit(1)

        cp_length = fft_length + (fft_length * mul) / div

        ##################################################
        # Blocks
        ##################################################
        self.osmosdr_sink_0 = osmosdr.sink(args="numchan=" + str(1) + " " +
                                           'hackrf,buffers=128,buflen=32768')
        self.osmosdr_sink_0.set_sample_rate(samp_rate)
        self.osmosdr_sink_0.set_center_freq(center_freq, 0)
        self.osmosdr_sink_0.set_freq_corr(0, 0)
        self.osmosdr_sink_0.set_gain(rf_gain, 0)
        self.osmosdr_sink_0.set_if_gain(if_gain, 0)
        self.osmosdr_sink_0.set_bb_gain(0, 0)
        self.osmosdr_sink_0.set_antenna('', 0)
        self.osmosdr_sink_0.set_bandwidth(band_width, 0)

        self.dtv_dvbt2_pilotgenerator_cc_0 = dtv.dvbt2_pilotgenerator_cc(
            extcarr, ffts, pil, gint, DATASYM, pap, ver, preamb, dtv.MISO_TX1,
            dtv.EQUALIZATION_OFF, dtv.BANDWIDTH_8_0_MHZ, fft_length)
        self.dtv_dvbt2_p1insertion_cc_0 = dtv.dvbt2_p1insertion_cc(
            extcarr, ffts, gint, DATASYM, preamb, dtv.SHOWLEVELS_OFF, 3.3)
        self.dtv_dvbt2_modulator_bc_0 = dtv.dvbt2_modulator_bc(
            dtv.FECFRAME_NORMAL, const, dtv.ROTATION_OFF)
        self.dtv_dvbt2_interleaver_bb_0 = dtv.dvbt2_interleaver_bb(
            dtv.FECFRAME_NORMAL, codr, const)
        self.dtv_dvbt2_freqinterleaver_cc_0 = dtv.dvbt2_freqinterleaver_cc(
            extcarr, ffts, pil, gint, DATASYM, pap, ver, preamb)
        self.dtv_dvbt2_framemapper_cc_0 = dtv.dvbt2_framemapper_cc(
            dtv.FECFRAME_NORMAL, codr, const, dtv.ROTATION_OFF, FECBLKS, 3,
            extcarr, ffts, gint, l1m, pil, 2, DATASYM, pap, ver, preamb,
            dtv.INPUTMODE_NORMAL, dtv.RESERVED_OFF, dtv.L1_SCRAMBLED_OFF,
            dtv.INBAND_OFF)
        self.dtv_dvbt2_cellinterleaver_cc_0 = dtv.dvbt2_cellinterleaver_cc(
            dtv.FECFRAME_NORMAL, const, FECBLKS, 3)
        self.dtv_dvb_ldpc_bb_0 = dtv.dvb_ldpc_bb(dtv.STANDARD_DVBT2,
                                                 dtv.FECFRAME_NORMAL, codr,
                                                 dtv.MOD_OTHER)
        self.dtv_dvb_bch_bb_0 = dtv.dvb_bch_bb(dtv.STANDARD_DVBT2,
                                               dtv.FECFRAME_NORMAL, codr)
        self.dtv_dvb_bbscrambler_bb_0 = dtv.dvb_bbscrambler_bb(
            dtv.STANDARD_DVBT2, dtv.FECFRAME_NORMAL, codr)
        self.dtv_dvb_bbheader_bb_0 = dtv.dvb_bbheader_bb(
            dtv.STANDARD_DVBT2, dtv.FECFRAME_NORMAL, codr, dtv.RO_0_35,
            dtv.INPUTMODE_HIEFF, dtv.INBAND_OFF, 168, 4000000)
        self.digital_ofdm_cyclic_prefixer_0 = digital.ofdm_cyclic_prefixer(
            fft_length, cp_length, 0, '')
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((0.2, ))

        if infile == "-":
            self.blocks_file_descriptor_source_0 = blocks.file_descriptor_source(
                gr.sizeof_char * 1, 0, True)
        else:
            self.blocks_file_source_0 = blocks.file_source(
                gr.sizeof_char * 1, infile, True)

        ##################################################
        # Connections
        ##################################################

        if infile == "-":
            self.connect((self.blocks_file_descriptor_source_0, 0),
                         (self.dtv_dvb_bbheader_bb_0, 0))
        else:
            self.connect((self.blocks_file_source_0, 0),
                         (self.dtv_dvb_bbheader_bb_0, 0))

        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.osmosdr_sink_0, 0))
        self.connect((self.digital_ofdm_cyclic_prefixer_0, 0),
                     (self.dtv_dvbt2_p1insertion_cc_0, 0))
        self.connect((self.dtv_dvb_bbheader_bb_0, 0),
                     (self.dtv_dvb_bbscrambler_bb_0, 0))
        self.connect((self.dtv_dvb_bbscrambler_bb_0, 0),
                     (self.dtv_dvb_bch_bb_0, 0))
        self.connect((self.dtv_dvb_bch_bb_0, 0), (self.dtv_dvb_ldpc_bb_0, 0))
        self.connect((self.dtv_dvb_ldpc_bb_0, 0),
                     (self.dtv_dvbt2_interleaver_bb_0, 0))
        self.connect((self.dtv_dvbt2_cellinterleaver_cc_0, 0),
                     (self.dtv_dvbt2_framemapper_cc_0, 0))
        self.connect((self.dtv_dvbt2_framemapper_cc_0, 0),
                     (self.dtv_dvbt2_freqinterleaver_cc_0, 0))
        self.connect((self.dtv_dvbt2_freqinterleaver_cc_0, 0),
                     (self.dtv_dvbt2_pilotgenerator_cc_0, 0))
        self.connect((self.dtv_dvbt2_interleaver_bb_0, 0),
                     (self.dtv_dvbt2_modulator_bc_0, 0))
        self.connect((self.dtv_dvbt2_modulator_bc_0, 0),
                     (self.dtv_dvbt2_cellinterleaver_cc_0, 0))
        self.connect((self.dtv_dvbt2_p1insertion_cc_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.dtv_dvbt2_pilotgenerator_cc_0, 0),
                     (self.digital_ofdm_cyclic_prefixer_0, 0))
Beispiel #16
0
    def __init__(self):
        gr.top_block.__init__(self, "Dvbt Tx")

        ##################################################
        # Variables
        ##################################################
        self._bandwidth_config = ConfigParser.ConfigParser()
        self._bandwidth_config.read('./dvbt.conf')
        try:
            bandwidth = self._bandwidth_config.getint('dvbt', 'bandwidth')
        except:
            bandwidth = 8000000
        self.bandwidth = bandwidth
        self.samp_rate = samp_rate = (bandwidth / 7) * 8
        self._rf_gain_config = ConfigParser.ConfigParser()
        self._rf_gain_config.read('./dvbt.conf')
        try:
            rf_gain = self._rf_gain_config.getint('hackrf', 'rf_gain')
        except:
            rf_gain = 0
        self.rf_gain = rf_gain
        self._mode_config = ConfigParser.ConfigParser()
        self._mode_config.read('./dvbt.conf')
        try:
            mode = self._mode_config.get('dvbt', 'mode')
        except:
            mode = 0
        self.mode = mode
        self._if_gain_config = ConfigParser.ConfigParser()
        self._if_gain_config.read('./dvbt.conf')
        try:
            if_gain = self._if_gain_config.getint('hackrf', 'if_gain')
        except:
            if_gain = 0
        self.if_gain = if_gain
        self._guard_interval_config = ConfigParser.ConfigParser()
        self._guard_interval_config.read('./dvbt.conf')
        try:
            guard_interval = self._guard_interval_config.get(
                'dvbt', 'guard_interval')
        except:
            guard_interval = 0
        self.guard_interval = guard_interval
        self._frequency_config = ConfigParser.ConfigParser()
        self._frequency_config.read('./dvbt.conf')
        try:
            frequency = self._frequency_config.getint('hackrf', 'frequency')
        except:
            frequency = 858000000
        self.frequency = frequency
        self._constellation_config = ConfigParser.ConfigParser()
        self._constellation_config.read('./dvbt.conf')
        try:
            constellation = self._constellation_config.get(
                'dvbt', 'constellation')
        except:
            constellation = 0
        self.constellation = constellation
        self._coderate_config = ConfigParser.ConfigParser()
        self._coderate_config.read('./dvbt.conf')
        try:
            coderate = self._coderate_config.get('dvbt', 'coderate')
        except:
            coderate = 0
        self.coderate = coderate

        infile = str(sys.argv[1])

        #Constellation QPSK 16QAM 64QAM
        if constellation == "QPSK":
            const = dtv.MOD_QPSK
        elif constellation == "16QAM":
            const = dtv.MOD_16QAM
        elif constellation == "64QAM":
            const = dtv.MOD_64QAM
        else:
            sys.stderr.write(
                "CONSTELLATION IN CONFIG WRONG! Values: QPSK, 16QAM or 64QAM \n"
            )
            sys.exit(1)

# Coderate 1/2 2/3 3/4 5/6 7/8

        if coderate == "1/2":
            codr = dtv.C1_2
        elif coderate == "2/3":
            codr = dtv.C2_3
        elif coderate == "3/4":
            codr = dtv.C3_4
        elif coderate == "5/6":
            codr = dtv.C5_6
        elif coderate == "7/8":
            codr = dtv.C7_8
        else:
            sys.stderr.write(
                "CODERATE IN CONFIG WRONG! Values: 1/2, 2/3, 3/4, 5/6 or 7/8 \n"
            )
            sys.exit(1)

        if mode == "2k":
            factor = 1
            carriers = 2048
            modus = dtv.T2k
        elif mode == "8k":
            factor = 4
            carriers = 8192
            modus = dtv.T8k
        else:
            sys.stderr.write("MODE IN CONFIG WRONG! Values: 2k or 8k \n")
            sys.exit(1)

#guard_interval dtv.GI_1_32 1/4 1/8 1/16 1/32
        if guard_interval == "1/4":
            guardi = dtv.GI_1_4
            gi = carriers / 4
        elif guard_interval == "1/8":
            guardi = dtv.GI_1_8
            gi = carriers / 8
        elif guard_interval == "1/16":
            guardi = dtv.GI_1_16
            gi = carriers / 16
        elif guard_interval == "1/32":
            guardi = dtv.GI_1_32
            gi = carriers / 32
        else:
            sys.stderr.write(
                "GUARD_INTERVAL IN CONFIG WRONG! Values: 1/4, 1/8, 1/16 or 1/32 \n"
            )
            sys.exit(1)

        ##################################################
        # Blocks
        ##################################################
        self.osmosdr_sink_0 = osmosdr.sink(args="numchan=" + str(1) + " " + '')
        self.osmosdr_sink_0.set_sample_rate(samp_rate)
        self.osmosdr_sink_0.set_center_freq(frequency, 0)
        self.osmosdr_sink_0.set_freq_corr(0, 0)
        self.osmosdr_sink_0.set_gain(rf_gain, 0)
        self.osmosdr_sink_0.set_if_gain(if_gain, 0)
        self.osmosdr_sink_0.set_bb_gain(0, 0)
        self.osmosdr_sink_0.set_antenna('', 0)
        self.osmosdr_sink_0.set_bandwidth(0, 0)

        self.fft_vxx_0 = fft.fft_vcc(carriers, False,
                                     (window.rectangular(carriers)), True, 1)
        self.dtv_dvbt_symbol_inner_interleaver_0 = dtv.dvbt_symbol_inner_interleaver(
            (1512 * factor), modus, 1)
        self.dtv_dvbt_reference_signals_0 = dtv.dvbt_reference_signals(
            gr.sizeof_gr_complex, (1512 * factor), carriers, const, dtv.NH,
            codr, codr, guardi, modus, 1, 0)
        self.dtv_dvbt_reed_solomon_enc_0 = dtv.dvbt_reed_solomon_enc(
            2, 8, 0x11d, 255, 239, 8, 51, (8 * factor))
        self.dtv_dvbt_map_0 = dtv.dvbt_map((1512 * factor), const, dtv.NH,
                                           modus, 1)
        self.dtv_dvbt_inner_coder_0 = dtv.dvbt_inner_coder(
            1, (1512 * factor), const, dtv.NH, codr)
        self.dtv_dvbt_energy_dispersal_0 = dtv.dvbt_energy_dispersal(1 *
                                                                     factor)
        self.dtv_dvbt_convolutional_interleaver_0 = dtv.dvbt_convolutional_interleaver(
            (136 * factor), 12, 17)
        self.dtv_dvbt_bit_inner_interleaver_0 = dtv.dvbt_bit_inner_interleaver(
            (1512 * factor), const, dtv.NH, modus)
        self.digital_ofdm_cyclic_prefixer_0 = digital.ofdm_cyclic_prefixer(
            carriers, carriers + (gi), 0, '')
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc(
            (0.0022097087, ))

        if infile == "-":
            self.blocks_file_descriptor_source_0 = blocks.file_descriptor_source(
                gr.sizeof_char * 1, 0, True)
        else:
            self.blocks_file_source_0 = blocks.file_source(
                gr.sizeof_char * 1, infile, True)

        ##################################################
        # Connections
        ##################################################

        if infile == "-":
            self.connect((self.blocks_file_descriptor_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))
        else:
            self.connect((self.blocks_file_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))

        self.connect((self.blocks_multiply_const_vxx_0, 0),
                     (self.osmosdr_sink_0, 0))
        self.connect((self.digital_ofdm_cyclic_prefixer_0, 0),
                     (self.blocks_multiply_const_vxx_0, 0))
        self.connect((self.dtv_dvbt_bit_inner_interleaver_0, 0),
                     (self.dtv_dvbt_symbol_inner_interleaver_0, 0))
        self.connect((self.dtv_dvbt_convolutional_interleaver_0, 0),
                     (self.dtv_dvbt_inner_coder_0, 0))
        self.connect((self.dtv_dvbt_energy_dispersal_0, 0),
                     (self.dtv_dvbt_reed_solomon_enc_0, 0))
        self.connect((self.dtv_dvbt_inner_coder_0, 0),
                     (self.dtv_dvbt_bit_inner_interleaver_0, 0))
        self.connect((self.dtv_dvbt_map_0, 0),
                     (self.dtv_dvbt_reference_signals_0, 0))
        self.connect((self.dtv_dvbt_reed_solomon_enc_0, 0),
                     (self.dtv_dvbt_convolutional_interleaver_0, 0))
        self.connect((self.dtv_dvbt_reference_signals_0, 0),
                     (self.fft_vxx_0, 0))
        self.connect((self.dtv_dvbt_symbol_inner_interleaver_0, 0),
                     (self.dtv_dvbt_map_0, 0))
        self.connect((self.fft_vxx_0, 0),
                     (self.digital_ofdm_cyclic_prefixer_0, 0))
Beispiel #17
0
  def __init__(self):
    gr.top_block.__init__(self)

    bitrate = 8000
    channel_bw = 12500
    chan0_freq = 358400000


    options = get_options()

    self.rfgain = options.gain

    self.channels = [ int(ch) for ch in options.channels.split(',') if ch ]
    self.ch_freqs = [ ch * channel_bw + chan0_freq for ch in self.channels ]
    self.ch_freqs.extend(
            [ int(f) for f in options.channels_by_freq.split(',') if f ])
    while len(self.channels) < len(self.ch_freqs):
        self.channels.append(-1)

    if options.frequency is None:
        self.ifreq = (max(self.ch_freqs) + min(self.ch_freqs)) / 2 / channel_bw * channel_bw
    else:
        self.ifreq = options.frequency

    ch0 = (self.ifreq - chan0_freq ) / channel_bw
    n = options.sample_rate / channel_bw
    s = options.sample_rate / bitrate / 2
    c = ''
    for ch in range(0,len(self.channels)):
        c = c + '%i,'%((self.channels[ch] - ch0)%n)
    c=c[:-1]

    self.src = osmosdr.source(options.args)
    self.src.set_center_freq(self.ifreq)
    self.src.set_sample_rate(options.sample_rate)
    self.src.set_freq_corr(options.ppm, 0)

    fcl_args = ['./fcl', '-n', '%i'%n, '-s', '%i'%s, '-t', '2', '-c', '%s'%c, '-f', './fir.py %i 7900 2000 rcos'%options.sample_rate, '-o', '/dev/stdout']
    sys.stderr.write(string.join(fcl_args))
    self.fcl = subprocess.Popen(fcl_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    self.fcl_in = blocks.file_descriptor_sink(gr.sizeof_gr_complex*1, self.fcl.stdin.fileno())
    self.fcl_out = blocks.file_descriptor_source(gr.sizeof_gr_complex*1, self.fcl.stdout.fileno(), False)
    self.deinterleave = blocks.deinterleave(gr.sizeof_gr_complex*1, 1)

    self.connect((self.src, 0), (self.fcl_in, 0))
    self.connect((self.fcl_out, 0), (self.deinterleave, 0))

    if self.rfgain is None:
        self.src.set_gain_mode(True, 0)
        self.iagc = 1
        self.rfgain = 0
    else:
        self.iagc = 0
        self.src.set_gain_mode(False)
        self.src.set_gain(-9.7)
        self.src.set_gain(self.rfgain)
        self.src.set_if_gain(37)

    # may differ from the requested rate
    sample_rate = int(self.src.get_sample_rate())
    sys.stderr.write("sample rate: %d\n" % (sample_rate))

    first_decim = int(options.sample_rate / bitrate / 2)
    sys.stderr.write("decim: %d\n" % (first_decim))

    out_sample_rate=sample_rate/first_decim
    sys.stderr.write("output sample rate: %d\n" % (out_sample_rate))

    sps=out_sample_rate/bitrate
    sys.stderr.write("samples per symbol: %d\n" % (sps))

    self.tuners = []
    self.afc_probes = []
    if len(self.channels) != 1:
        if options.output_file:
            if options.output_file.find('%%') == -1:
                raise ValueError('Output name template missing "%%".')
        elif options.output_pipe:
            if options.output_pipe.find('%%') == -1:
                raise ValueError('Output name template missing "%%".')
        else:
            raise ValueError('WTF')
    for ch in range(0,len(self.channels)):
        bw = (9200 + options.afc_ppm_threshold)/2
        taps = filter.firdes.low_pass(1.0,out_sample_rate, bw, bw*options.transition_width, filter.firdes.WIN_HANN)
#        offset = self.ch_freqs[ch] - self.ifreq
        offset = 0
        sys.stderr.write("channel[%d]: %d frequency=%d, offset=%d Hz\n" % (ch, self.channels[ch], self.ch_freqs[ch], offset))


        tuner = filter.freq_xlating_fir_filter_ccc(1, taps, offset, out_sample_rate)
        self.tuners.append(tuner)

        demod = digital.gmsk_demod(samples_per_symbol=sps)

        fname = self.channels[ch]
        if fname == -1:
            fname = self.ch_freqs[ch]
        if options.output_pipe is None:
            file = options.output_file.replace('%%', str(fname))
            output = blocks.file_sink(gr.sizeof_char, file)
        else:
            cmd = options.output_pipe.replace('%%', str(fname))
            pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=True)
            fd = pipe.stdin.fileno()
            output = blocks.file_descriptor_sink(gr.sizeof_char, fd)

        self.connect((self.deinterleave, ch), (tuner, 0))
        self.connect((tuner, 0), (demod, 0))
        self.connect((demod, 0), (output, 0))

        afc_decimation = 32000
        afc_demod = analog.quadrature_demod_cf(sample_rate/first_decim/(2*math.pi*afc_decimation))
        integrate = blocks.integrate_ff(afc_decimation)
        afc_probe = blocks.probe_signal_f()
        self.afc_probes.append(afc_probe)

        self.connect((tuner, 0), (afc_demod,0))
        self.connect((afc_demod, 0), (integrate,0))
        self.connect((integrate, 0), (afc_probe, 0))

    def _variable_function_probe_0_probe():
        while True:
            time.sleep(options.afc_period)
            for ch in range(0,len(self.channels)):
                err = self.afc_probes[ch].level()
                if abs(err) < options.afc_ppm_threshold:
                    continue
                freq = self.tuners[ch].center_freq() + err * options.afc_gain
                self.tuners[ch].set_center_freq(freq)
                if self.channels[ch] == -1:
                    sys.stderr.write("Freq %d freq err: %5.0f\tfreq: %f\n" % (self.ch_freqs[ch], err, freq))
                else:
                    sys.stderr.write("Chan %d freq err: %5.0f\tfreq: %f\n" % (self.channels[ch], err, freq))
            sys.stderr.write("\n")
    _variable_function_probe_0_thread = threading.Thread(target=_variable_function_probe_0_probe)
    _variable_function_probe_0_thread.daemon = True
    _variable_function_probe_0_thread.start()
    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'))
Beispiel #19
0
    def __init__(self):
        gr.top_block.__init__(self, "Dvbc Tx Nogui")

        ##################################################
        # Variables
        ##################################################
        self._symrate_config = ConfigParser.ConfigParser()
        self._symrate_config.read('./dvbc.conf')
        try:
            symrate = self._symrate_config.getint('dvbc', 'symbolrate')
        except:
            symrate = 0
        self.symrate = symrate
        self.samp_rate = samp_rate = symrate * 2
        self.rrc_taps = rrc_taps = 100
        self._rf_gain_config = ConfigParser.ConfigParser()
        self._rf_gain_config.read('./dvbc.conf')
        try:
            rf_gain = self._rf_gain_config.getint('hackrf', 'rf-gain')
        except:
            rf_gain = 0
        self.rf_gain = rf_gain
        self._mode_config = ConfigParser.ConfigParser()
        self._mode_config.read('./dvbc.conf')
        try:
            mode = self._mode_config.get('dvbc', 'mode')
        except:
            mode = 0
        self.mode = mode
        self._if_gain_config = ConfigParser.ConfigParser()
        self._if_gain_config.read('./dvbc.conf')
        try:
            if_gain = self._if_gain_config.getint('hackrf', 'if-gain')
        except:
            if_gain = 0
        self.if_gain = if_gain
        self._center_freq_config = ConfigParser.ConfigParser()
        self._center_freq_config.read('./dvbc.conf')
        try:
            center_freq = self._center_freq_config.getint(
                'hackrf', 'frequency')
        except:
            center_freq = 0
        self.center_freq = center_freq

        infile = str(sys.argv[1])

        if mode == "16QAM":
            mod = dvbc.MOD_16QAM
        elif mode == "32QAM":
            mod = dvbc.MOD_32QAM
        elif mode == "64QAM":
            mod = dvbc.MOD_64QAM
        elif mode == "128QAM":
            mod = dvbc.MOD_128QAM
        elif mode == "256QAM":
            mod = dvbc.MOD_256QAM
        else:
            sys.stderr.write(
                "MODE IN CONFIG WRONG! Values: 16QAM, 32QAM, 64QAM, 128QAM or 256QAM \n"
            )
            sys.exit(1)

        print "Frequency: ", center_freq / 1000000, "Mhz / Mode: ", mode, "/ Symbolrate: ", symrate / 1000, "\n"

        ##################################################
        # Blocks
        ##################################################
        self.osmosdr_sink_1 = osmosdr.sink(args="numchan=" + str(1) + " " +
                                           'hackrf,buffers=128,buflen=32768')
        self.osmosdr_sink_1.set_sample_rate(samp_rate)
        self.osmosdr_sink_1.set_center_freq(center_freq, 0)
        self.osmosdr_sink_1.set_freq_corr(0, 0)
        self.osmosdr_sink_1.set_gain(rf_gain, 0)
        self.osmosdr_sink_1.set_if_gain(if_gain, 0)
        self.osmosdr_sink_1.set_bb_gain(0, 0)
        self.osmosdr_sink_1.set_antenna('', 0)
        self.osmosdr_sink_1.set_bandwidth(8750000, 0)

        self.fft_filter_xxx_0 = filter.fft_filter_ccc(
            1, (firdes.root_raised_cosine(0.85, samp_rate, samp_rate / 2, 0.15,
                                          rrc_taps)), 1)
        self.fft_filter_xxx_0.declare_sample_delay(0)
        self.dvbc_symbolmapper_bb_0 = dvbc.symbolmapper_bb(mod)
        self.dvbc_modulator_bc_0 = dvbc.modulator_bc(mod)
        self.dtv_dvbt_reed_solomon_enc_0 = dtv.dvbt_reed_solomon_enc(
            2, 8, 0x11d, 255, 239, 8, 51, 8)
        self.dtv_dvbt_energy_dispersal_0 = dtv.dvbt_energy_dispersal(1)
        self.dtv_dvbt_convolutional_interleaver_0 = dtv.dvbt_convolutional_interleaver(
            136, 12, 17)

        if infile == "-":
            self.blocks_file_descriptor_source_0 = blocks.file_descriptor_source(
                gr.sizeof_char * 1, 0, True)
        else:
            self.blocks_file_source_0 = blocks.file_source(
                gr.sizeof_char * 1, infile, True)

        ##################################################
        # Connections
        ##################################################

        if infile == "-":
            self.connect((self.blocks_file_descriptor_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))
        else:
            self.connect((self.blocks_file_source_0, 0),
                         (self.dtv_dvbt_energy_dispersal_0, 0))

        self.connect((self.dtv_dvbt_convolutional_interleaver_0, 0),
                     (self.dvbc_symbolmapper_bb_0, 0))
        self.connect((self.dtv_dvbt_energy_dispersal_0, 0),
                     (self.dtv_dvbt_reed_solomon_enc_0, 0))
        self.connect((self.dtv_dvbt_reed_solomon_enc_0, 0),
                     (self.dtv_dvbt_convolutional_interleaver_0, 0))
        self.connect((self.dvbc_modulator_bc_0, 0), (self.fft_filter_xxx_0, 0))
        self.connect((self.dvbc_symbolmapper_bb_0, 0),
                     (self.dvbc_modulator_bc_0, 0))
        self.connect((self.fft_filter_xxx_0, 0), (self.osmosdr_sink_1, 0))
Beispiel #20
0
    def __init__(self):
        gr.top_block.__init__(self)

        bitrate = 8000
        channel_bw = 12500
        chan0_freq = 358400000

        options = get_options()

        self.rfgain = options.gain

        self.channels = [int(ch) for ch in options.channels.split(',') if ch]
        self.ch_freqs = [ch * channel_bw + chan0_freq for ch in self.channels]
        self.ch_freqs.extend(
            [int(f) for f in options.channels_by_freq.split(',') if f])
        while len(self.channels) < len(self.ch_freqs):
            self.channels.append(-1)

        if options.frequency is None:
            self.ifreq = (max(self.ch_freqs) +
                          min(self.ch_freqs)) / 2 / channel_bw * channel_bw
        else:
            self.ifreq = options.frequency

        ch0 = (self.ifreq - chan0_freq) / channel_bw
        n = options.sample_rate / channel_bw
        s = options.sample_rate / bitrate / 2
        c = ''
        for ch in range(0, len(self.channels)):
            c = c + '%i,' % ((self.channels[ch] - ch0) % n)
        c = c[:-1]

        self.src = osmosdr.source(options.args)
        self.src.set_center_freq(self.ifreq)
        self.src.set_sample_rate(options.sample_rate)
        self.src.set_freq_corr(options.ppm, 0)

        fcl_args = [
            './fcl', '-n',
            '%i' % n, '-s',
            '%i' % s, '-t', '2', '-c',
            '%s' % c, '-f',
            './fir.py %i 7900 2000 rcos' % options.sample_rate, '-o',
            '/dev/stdout'
        ]
        sys.stderr.write(string.join(fcl_args))
        self.fcl = subprocess.Popen(fcl_args,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
        self.fcl_in = blocks.file_descriptor_sink(gr.sizeof_gr_complex * 1,
                                                  self.fcl.stdin.fileno())
        self.fcl_out = blocks.file_descriptor_source(gr.sizeof_gr_complex * 1,
                                                     self.fcl.stdout.fileno(),
                                                     False)
        self.deinterleave = blocks.deinterleave(gr.sizeof_gr_complex * 1, 1)

        self.connect((self.src, 0), (self.fcl_in, 0))
        self.connect((self.fcl_out, 0), (self.deinterleave, 0))

        if self.rfgain is None:
            self.src.set_gain_mode(True, 0)
            self.iagc = 1
            self.rfgain = 0
        else:
            self.iagc = 0
            self.src.set_gain_mode(False)
            self.src.set_gain(-9.7)
            self.src.set_gain(self.rfgain)
            self.src.set_if_gain(37)

        # may differ from the requested rate
        sample_rate = int(self.src.get_sample_rate())
        sys.stderr.write("sample rate: %d\n" % (sample_rate))

        first_decim = int(options.sample_rate / bitrate / 2)
        sys.stderr.write("decim: %d\n" % (first_decim))

        out_sample_rate = sample_rate / first_decim
        sys.stderr.write("output sample rate: %d\n" % (out_sample_rate))

        sps = out_sample_rate / bitrate
        sys.stderr.write("samples per symbol: %d\n" % (sps))

        self.tuners = []
        self.afc_probes = []
        if len(self.channels) != 1:
            if options.output_file:
                if options.output_file.find('%%') == -1:
                    raise ValueError('Output name template missing "%%".')
            elif options.output_pipe:
                if options.output_pipe.find('%%') == -1:
                    raise ValueError('Output name template missing "%%".')
            else:
                raise ValueError('WTF')
        for ch in range(0, len(self.channels)):
            bw = (9200 + options.afc_ppm_threshold) / 2
            taps = filter.firdes.low_pass(1.0, out_sample_rate, bw,
                                          bw * options.transition_width,
                                          filter.firdes.WIN_HANN)
            #        offset = self.ch_freqs[ch] - self.ifreq
            offset = 0
            sys.stderr.write(
                "channel[%d]: %d frequency=%d, offset=%d Hz\n" %
                (ch, self.channels[ch], self.ch_freqs[ch], offset))

            tuner = filter.freq_xlating_fir_filter_ccc(1, taps, offset,
                                                       out_sample_rate)
            self.tuners.append(tuner)

            demod = digital.gmsk_demod(samples_per_symbol=sps)

            fname = self.channels[ch]
            if fname == -1:
                fname = self.ch_freqs[ch]
            if options.output_pipe is None:
                file = options.output_file.replace('%%', str(fname))
                output = blocks.file_sink(gr.sizeof_char, file)
            else:
                cmd = options.output_pipe.replace('%%', str(fname))
                pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=True)
                fd = pipe.stdin.fileno()
                output = blocks.file_descriptor_sink(gr.sizeof_char, fd)

            self.connect((self.deinterleave, ch), (tuner, 0))
            self.connect((tuner, 0), (demod, 0))
            self.connect((demod, 0), (output, 0))

            afc_decimation = 32000
            afc_demod = analog.quadrature_demod_cf(
                sample_rate / first_decim / (2 * math.pi * afc_decimation))
            integrate = blocks.integrate_ff(afc_decimation)
            afc_probe = blocks.probe_signal_f()
            self.afc_probes.append(afc_probe)

            self.connect((tuner, 0), (afc_demod, 0))
            self.connect((afc_demod, 0), (integrate, 0))
            self.connect((integrate, 0), (afc_probe, 0))

        def _variable_function_probe_0_probe():
            while True:
                time.sleep(options.afc_period)
                for ch in range(0, len(self.channels)):
                    err = self.afc_probes[ch].level()
                    if abs(err) < options.afc_ppm_threshold:
                        continue
                    freq = self.tuners[ch].center_freq(
                    ) + err * options.afc_gain
                    self.tuners[ch].set_center_freq(freq)
                    if self.channels[ch] == -1:
                        sys.stderr.write(
                            "Freq %d freq err: %5.0f\tfreq: %f\n" %
                            (self.ch_freqs[ch], err, freq))
                    else:
                        sys.stderr.write(
                            "Chan %d freq err: %5.0f\tfreq: %f\n" %
                            (self.channels[ch], err, freq))
                sys.stderr.write("\n")

        _variable_function_probe_0_thread = threading.Thread(
            target=_variable_function_probe_0_probe)
        _variable_function_probe_0_thread.daemon = True
        _variable_function_probe_0_thread.start()
    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):
        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 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")

            if self._filename == '/dev/stdin':
                file_source = blocks.file_descriptor_source(itemsize=itemsize,
                                                            fd=0,
                                                            repeat=False)
            else:
                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

        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.
        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._burst_pre_len / decimation),
                    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,
                                                       -self._burst_pre_len,
                                                       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'))