def __init__(self):
        gr.top_block.__init__(self)

        parser = OptionParser(option_class=eng_option)
        parser.add_option(
            "-O",
            "--audio-output",
            type="string",
            default="",
            help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
        parser.add_option("-r",
                          "--sample-rate",
                          type="eng_float",
                          default=48000,
                          help="set sample rate to RATE (48000)")
        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            raise SystemExit, 1

        sample_rate = int(options.sample_rate)
        ampl = 0.1

        src = gr.glfsr_source_b(32)  # Pseudorandom noise source
        b2f = gr.chunks_to_symbols_bf([ampl, -ampl], 1)
        dst = audio.sink(sample_rate, options.audio_output)
        self.connect(src, b2f, dst)
Exemple #2
0
    def __init__(self, output_rate):

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

        symbol_rate = 4800   # P25 baseband symbol rate
        lcm = gru.lcm(symbol_rate, output_rate)
        self._interp_factor = int(lcm // symbol_rate)
        self._decimation = int(lcm // output_rate)
        self._excess_bw =0.2

        mod_map = [1.0/3.0, 1.0, -(1.0/3.0), -1.0]
        self.C2S = gr.chunks_to_symbols_bf(mod_map)

        ntaps = 11 * self._interp_factor
        rrc_taps = gr.firdes.root_raised_cosine(
            self._interp_factor, # gain (since we're interpolating by sps)
            lcm,                 # sampling rate
            symbol_rate,
            self._excess_bw,     # excess bandwidth (roll-off factor)
            ntaps)

        self.rrc_filter = gr.interp_fir_filter_fff(self._interp_factor, rrc_taps)
        
        # FM pre-emphasis filter
        shaping_coeffs = [-0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099, 0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137, -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137, -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099, -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018]
        self.shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        # generate output at appropriate rate
        self.decimator = blks2.rational_resampler_fff(1, self._decimation)

        self.connect(self, self.C2S, self.rrc_filter, self.shaping_filter, self.decimator, self)
Exemple #3
0
    def test_convolutional_encoder(self):
        """
		Tests convolutional encoder
		"""
        src_data = make_transport_stream()
        constellation = [.7, .7, .7, -.7, -.7, .7, -.7, -.7]

        src = gr.vector_source_b(src_data)
        unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        enc = dvb_convolutional_encoder_bb.convolutional_encoder_bb()
        repack1 = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)
        repack2 = gr.packed_to_unpacked_bb(2, gr.GR_MSB_FIRST)
        mapper = gr.chunks_to_symbols_bf(constellation,
                                         dvb_swig.dimensionality)
        viterbi = trellis.viterbi_combined_fb(
            trellis.fsm(dvb_swig.k, dvb_swig.n,
                        dvb_convolutional_encoder_bb.G), dvb_swig.K, -1, -1,
            dvb_swig.dimensionality, constellation, digital.TRELLIS_EUCLIDEAN)
        pack = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)
        dst = gr.vector_sink_b()

        self.tb.connect(src, unpack, enc, repack1, repack2, mapper)
        self.tb.connect(mapper, viterbi, pack, dst)
        self.tb.run()
        result_data = dst.data()
        self.assertEqual(tuple(src_data[:len(result_data)]), result_data)
    def test_002_correlation_b(self):
        for degree in range(1,11):                # Higher degrees take too long to correlate
            src = gr.glfsr_source_b(degree, False)
            b2f = gr.chunks_to_symbols_bf((-1.0,1.0), 1)
            dst = gr.vector_sink_f()
            self.fg.connect(src, b2f, dst)
            self.fg.run()

            actual_result = dst.data()
            R = auto_correlate(actual_result)
            self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin
            for i in range(len(R)-1):
                self.assertEqual(R[i+1], -1.0)    # Auto-correlation minimum everywhere else
Exemple #5
0
    def test_002_correlation_b(self):
        for degree in range(1,11):                # Higher degrees take too long to correlate
            src = gr.glfsr_source_b(degree, False)
            b2f = gr.chunks_to_symbols_bf((-1.0,1.0), 1)
            dst = gr.vector_sink_f()
	    del self.tb # Discard existing top block
	    self.tb = gr.top_block()
            self.tb.connect(src, b2f, dst)
            self.tb.run()
	    self.tb.disconnect_all()
            actual_result = dst.data()
            R = auto_correlate(actual_result)
            self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin
            for i in range(len(R)-1):
                self.assertEqual(R[i+1], -1.0)    # Auto-correlation minimum everywhere else
Exemple #6
0
    def __init__(self, options, queue):
        gr.top_block.__init__(self, "mhp")

        sample_rate = options.sample_rate

        arity = 2
        IN = gr.file_source(gr.sizeof_char, options.input_file, options.repeat)
        B2C = gr.packed_to_unpacked_bb(arity, gr.GR_MSB_FIRST)
        mod_map = [1.0, 3.0, -1.0, -3.0]
        C2S = gr.chunks_to_symbols_bf(mod_map)
        if options.reverse:
            polarity = gr.multiply_const_ff(-1)
        else:
            polarity = gr.multiply_const_ff( 1)

        symbol_rate = 4800
        samples_per_symbol = sample_rate // symbol_rate
        excess_bw = 0.1
        ntaps = 11 * samples_per_symbol
        rrc_taps = gr.firdes.root_raised_cosine(
            samples_per_symbol, # gain  (sps since we're interpolating by sps
            samples_per_symbol, # sampling rate
            1.0,                # symbol rate
            excess_bw,          # excess bandwidth (roll-off factor)
            ntaps)
        rrc_filter = gr.interp_fir_filter_fff(samples_per_symbol, rrc_taps)

        rrc_coeffs = [0, -0.003, -0.006, -0.009, -0.012, -0.014, -0.014, -0.013, -0.01, -0.006, 0, 0.007, 0.014, 0.02, 0.026, 0.029, 0.029, 0.027, 0.021, 0.012, 0, -0.013, -0.027, -0.039, -0.049, -0.054, -0.055, -0.049, -0.038, -0.021, 0, 0.024, 0.048, 0.071, 0.088, 0.098, 0.099, 0.09, 0.07, 0.039, 0, -0.045, -0.091, -0.134, -0.17, -0.193, -0.199, -0.184, -0.147, -0.085, 0, 0.105, 0.227, 0.36, 0.496, 0.629, 0.751, 0.854, 0.933, 0.983, 1, 0.983, 0.933, 0.854, 0.751, 0.629, 0.496, 0.36, 0.227, 0.105, 0, -0.085, -0.147, -0.184, -0.199, -0.193, -0.17, -0.134, -0.091, -0.045, 0, 0.039, 0.07, 0.09, 0.099, 0.098, 0.088, 0.071, 0.048, 0.024, 0, -0.021, -0.038, -0.049, -0.055, -0.054, -0.049, -0.039, -0.027, -0.013, 0, 0.012, 0.021, 0.027, 0.029, 0.029, 0.026, 0.02, 0.014, 0.007, 0, -0.006, -0.01, -0.013, -0.014, -0.014, -0.012, -0.009, -0.006, -0.003, 0]

        # rrc_coeffs work slightly differently: each input sample
        # (from mod_map above) at 4800 rate, then 9 zeros are inserted
        # to bring to a 48000 rate, then this filter is applied:
        # rrc_filter = gr.fir_filter_fff(1, rrc_coeffs)
        # FIXME: how to insert the 9 zero samples using gr ?

        # FM pre-emphasis filter
        shaping_coeffs = [-0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099, 0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137, -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137, -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099, -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018]
        shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        OUT = audio.sink(sample_rate, options.audio_output)
        amp = gr.multiply_const_ff(options.factor)

        self.connect(IN, B2C, C2S, polarity, rrc_filter, shaping_filter, amp)
        # output to both L and R channels
        self.connect(amp, (OUT,0) )
        self.connect(amp, (OUT,1) )
Exemple #7
0
    def __init__(self, output_rate):

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

        symbol_rate = 4800  # P25 baseband symbol rate
        lcm = gru.lcm(symbol_rate, output_rate)
        self._interp_factor = int(lcm // symbol_rate)
        self._decimation = int(lcm // output_rate)
        self._excess_bw = 0.2

        mod_map = [1.0 / 3.0, 1.0, -(1.0 / 3.0), -1.0]
        self.C2S = gr.chunks_to_symbols_bf(mod_map)

        ntaps = 11 * self._interp_factor
        rrc_taps = gr.firdes.root_raised_cosine(
            self._interp_factor,  # gain (since we're interpolating by sps)
            lcm,  # sampling rate
            symbol_rate,
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)

        self.rrc_filter = gr.interp_fir_filter_fff(self._interp_factor,
                                                   rrc_taps)

        # FM pre-emphasis filter
        shaping_coeffs = [
            -0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099,
            0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137,
            -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137,
            -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099,
            -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018
        ]
        self.shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        # generate output at appropriate rate
        self.decimator = blks2.rational_resampler_fff(1, self._decimation)

        self.connect(self, self.C2S, self.rrc_filter, self.shaping_filter,
                     self.decimator, self)
Exemple #8
0
    def __init__(self):
        gr.top_block.__init__(self)

        parser = OptionParser(option_class=eng_option)
        parser.add_option("-O", "--audio-output", type="string", default="",
                          help="pcm output device name.  E.g., hw:0,0 or /dev/dsp")
        parser.add_option("-r", "--sample-rate", type="eng_float", default=48000,
                          help="set sample rate to RATE (48000)")
        (options, args) = parser.parse_args ()
        if len(args) != 0:
            parser.print_help()
            raise SystemExit, 1

        sample_rate = int(options.sample_rate)
        ampl = 0.1

        src = gr.glfsr_source_b(32)     # Pseudorandom noise source
        b2f = gr.chunks_to_symbols_bf([ampl, -ampl], 1)
        dst = audio.sink(sample_rate, options.audio_output)
        self.connect(src, b2f, dst)
Exemple #9
0
	def test_convolutional_encoder(self):
		"""
		Tests convolutional encoder
		"""
		src_data = make_transport_stream()
		constellation = [.7, .7,.7,-.7,-.7,.7,-.7,-.7]

		src = gr.vector_source_b(src_data)
		unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
		enc = dvb_convolutional_encoder_bb.convolutional_encoder_bb()
		repack1 = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)
		repack2 = gr.packed_to_unpacked_bb(2, gr.GR_MSB_FIRST)
		mapper = gr.chunks_to_symbols_bf(constellation, dvb_swig.dimensionality)
		viterbi = trellis.viterbi_combined_fb(trellis.fsm(dvb_swig.k, dvb_swig.n, dvb_convolutional_encoder_bb.G),
				dvb_swig.K, -1, -1, dvb_swig.dimensionality, constellation, trellis.TRELLIS_EUCLIDEAN)
		pack = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)
		dst = gr.vector_sink_b()

		self.tb.connect(src, unpack, enc, repack1, repack2, mapper)
		self.tb.connect(mapper, viterbi, pack, dst)
		self.tb.run()
		result_data = dst.data()
		self.assertEqual(tuple(src_data[:len(result_data)]), result_data)
Exemple #10
0
def run_test(seed, blocksize):
    tb = gr.top_block()

    ##################################################
    # Variables
    ##################################################
    M = 2
    K = 1
    P = 2
    h = (1.0 * K) / P
    L = 3
    Q = 4
    frac = 0.99
    f = trellis.fsm(P, M, L)

    # CPFSK signals
    #p = numpy.ones(Q)/(2.0)
    #q = numpy.cumsum(p)/(1.0*Q)

    # GMSK signals
    BT = 0.3
    tt = numpy.arange(0, L * Q) / (1.0 * Q) - L / 2.0
    #print tt
    p = (0.5 * scipy.stats.erfc(2 * math.pi * BT * (tt - 0.5) / math.sqrt(
        math.log(2.0)) / math.sqrt(2.0)) - 0.5 * scipy.stats.erfc(
            2 * math.pi * BT *
            (tt + 0.5) / math.sqrt(math.log(2.0)) / math.sqrt(2.0))) / 2.0
    p = p / sum(p) * Q / 2.0
    #print p
    q = numpy.cumsum(p) / Q
    q = q / q[-1] / 2.0
    #print q

    (f0T, SS, S, F, Sf, Ff,
     N) = fsm_utils.make_cpm_signals(K, P, M, L, q, frac)
    #print N
    #print Ff
    Ffa = numpy.insert(Ff, Q, numpy.zeros(N), axis=0)
    #print Ffa
    MF = numpy.fliplr(numpy.transpose(Ffa))
    #print MF
    E = numpy.sum(numpy.abs(Sf)**2, axis=0)
    Es = numpy.sum(E) / f.O()
    #print Es

    constellation = numpy.reshape(numpy.transpose(Sf), N * f.O())
    #print Ff
    #print Sf
    #print constellation
    #print numpy.max(numpy.abs(SS - numpy.dot(Ff , Sf)))

    EsN0_db = 10.0
    N0 = Es * 10.0**(-(1.0 * EsN0_db) / 10.0)
    #N0 = 0.0
    #print N0
    head = 4
    tail = 4
    numpy.random.seed(seed * 666)
    data = numpy.random.randint(0, M, head + blocksize + tail + 1)
    #data = numpy.zeros(blocksize+1+head+tail,'int')
    for i in range(head):
        data[i] = 0
    for i in range(tail + 1):
        data[-i] = 0

##################################################
# Blocks
##################################################
    random_source_x_0 = gr.vector_source_b(data.tolist(), False)
    gr_chunks_to_symbols_xx_0 = gr.chunks_to_symbols_bf((-1, 1), 1)
    gr_interp_fir_filter_xxx_0 = gr.interp_fir_filter_fff(Q, p)
    gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(2 * math.pi * h *
                                                            (1.0 / Q))

    gr_add_vxx_0 = gr.add_vcc(1)
    gr_noise_source_x_0 = gr.noise_source_c(gr.GR_GAUSSIAN, (N0 / 2.0)**0.5,
                                            -long(seed))

    gr_multiply_vxx_0 = gr.multiply_vcc(1)
    gr_sig_source_x_0 = gr.sig_source_c(Q, gr.GR_COS_WAVE, -f0T, 1, 0)
    # only works for N=2, do it manually for N>2...
    gr_fir_filter_xxx_0_0 = gr.fir_filter_ccc(Q, MF[0].conjugate())
    gr_fir_filter_xxx_0_0_0 = gr.fir_filter_ccc(Q, MF[1].conjugate())
    gr_streams_to_stream_0 = gr.streams_to_stream(gr.sizeof_gr_complex * 1,
                                                  int(N))
    gr_skiphead_0 = gr.skiphead(gr.sizeof_gr_complex * 1, int(N * (1 + 0)))
    viterbi = trellis.viterbi_combined_cb(f, head + blocksize + tail, 0, -1,
                                          int(N), constellation,
                                          digital.TRELLIS_EUCLIDEAN)

    gr_vector_sink_x_0 = gr.vector_sink_b()

    ##################################################
    # Connections
    ##################################################
    tb.connect((random_source_x_0, 0), (gr_chunks_to_symbols_xx_0, 0))
    tb.connect((gr_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0))
    tb.connect((gr_interp_fir_filter_xxx_0, 0),
               (gr_frequency_modulator_fc_0, 0))
    tb.connect((gr_frequency_modulator_fc_0, 0), (gr_add_vxx_0, 0))
    tb.connect((gr_noise_source_x_0, 0), (gr_add_vxx_0, 1))
    tb.connect((gr_add_vxx_0, 0), (gr_multiply_vxx_0, 0))
    tb.connect((gr_sig_source_x_0, 0), (gr_multiply_vxx_0, 1))
    tb.connect((gr_multiply_vxx_0, 0), (gr_fir_filter_xxx_0_0, 0))
    tb.connect((gr_multiply_vxx_0, 0), (gr_fir_filter_xxx_0_0_0, 0))
    tb.connect((gr_fir_filter_xxx_0_0, 0), (gr_streams_to_stream_0, 0))
    tb.connect((gr_fir_filter_xxx_0_0_0, 0), (gr_streams_to_stream_0, 1))
    tb.connect((gr_streams_to_stream_0, 0), (gr_skiphead_0, 0))
    tb.connect((gr_skiphead_0, 0), (viterbi, 0))
    tb.connect((viterbi, 0), (gr_vector_sink_x_0, 0))

    tb.run()
    dataest = gr_vector_sink_x_0.data()
    #print data
    #print numpy.array(dataest)
    perr = 0
    err = 0
    for i in range(blocksize):
        if data[head + i] != dataest[head + i]:
            #print i
            err += 1
    if err != 0:
        perr = 1
    return (err, perr)
Exemple #11
0
    def __init__(self,
                 output_sample_rate=_def_output_sample_rate,
                 excess_bw=_def_excess_bw,
                 reverse=_def_reverse,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered P25 FM modulation.

	The input is a dibit (P25 symbol) stream (char, not packed) and the
	output is the float "C4FM" signal at baseband, suitable for application
        to an FM modulator stage

        Input is at the base symbol rate (4800), output sample rate is
        typically either 32000 (USRP TX chain) or 48000 (sound card)

	@param output_sample_rate: output sample rate
	@type output_sample_rate: integer
	@param excess_bw: Root-raised cosine filter excess bandwidth
	@type excess_bw: float
        @param reverse: reverse polarity flag
        @type reverse: bool
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modulation data to files?
        @type debug: bool
	"""

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

        input_sample_rate = 4800  # P25 baseband symbol rate
        lcm = gru.lcm(input_sample_rate, output_sample_rate)
        self._interp_factor = int(lcm // input_sample_rate)
        self._decimation = int(lcm // output_sample_rate)
        self._excess_bw = excess_bw

        mod_map = [1.0 / 3.0, 1.0, -(1.0 / 3.0), -1.0]
        self.C2S = gr.chunks_to_symbols_bf(mod_map)
        if reverse:
            self.polarity = gr.multiply_const_ff(-1)
        else:
            self.polarity = gr.multiply_const_ff(1)

        ntaps = 11 * self._interp_factor
        rrc_taps = gr.firdes.root_raised_cosine(
            self._interp_factor,  # gain (since we're interpolating by sps)
            lcm,  # sampling rate
            input_sample_rate,  # symbol rate
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)

        # rrc_coeffs work slightly differently: each input sample
        # (from mod_map above) at 4800 rate, then 9 zeros are inserted
        # to bring to 48000 rate, then this filter is applied:
        # rrc_filter = gr.fir_filter_fff(1, rrc_coeffs)
        # FIXME: how to insert the 9 zero samples using gr ?
        # rrc_coeffs = [0, -0.003, -0.006, -0.009, -0.012, -0.014, -0.014, -0.013, -0.01, -0.006, 0, 0.007, 0.014, 0.02, 0.026, 0.029, 0.029, 0.027, 0.021, 0.012, 0, -0.013, -0.027, -0.039, -0.049, -0.054, -0.055, -0.049, -0.038, -0.021, 0, 0.024, 0.048, 0.071, 0.088, 0.098, 0.099, 0.09, 0.07, 0.039, 0, -0.045, -0.091, -0.134, -0.17, -0.193, -0.199, -0.184, -0.147, -0.085, 0, 0.105, 0.227, 0.36, 0.496, 0.629, 0.751, 0.854, 0.933, 0.983, 1, 0.983, 0.933, 0.854, 0.751, 0.629, 0.496, 0.36, 0.227, 0.105, 0, -0.085, -0.147, -0.184, -0.199, -0.193, -0.17, -0.134, -0.091, -0.045, 0, 0.039, 0.07, 0.09, 0.099, 0.098, 0.088, 0.071, 0.048, 0.024, 0, -0.021, -0.038, -0.049, -0.055, -0.054, -0.049, -0.039, -0.027, -0.013, 0, 0.012, 0.021, 0.027, 0.029, 0.029, 0.026, 0.02, 0.014, 0.007, 0, -0.006, -0.01, -0.013, -0.014, -0.014, -0.012, -0.009, -0.006, -0.003, 0]

        self.rrc_filter = gr.interp_fir_filter_fff(self._interp_factor,
                                                   rrc_taps)

        # FM pre-emphasis filter
        shaping_coeffs = [
            -0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099,
            0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137,
            -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137,
            -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099,
            -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018
        ]
        self.shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

        self.connect(self, self.C2S, self.polarity, self.rrc_filter,
                     self.shaping_filter)
        if (self._decimation > 1):
            self.decimator = blks2.rational_resampler_fff(1, self._decimation)
            self.connect(self.shaping_filter, self.decimator, self)
        else:
            self.connect(self.shaping_filter, self)
Exemple #12
0
    def __init__(self, 
                 samples_per_symbol=_def_samples_per_symbol,
                 bits_per_symbol=_def_bits_per_symbol,
                 h_numerator=_def_h_numerator,
                 h_denominator=_def_h_denominator,
                 cpm_type=_def_cpm_type,
		 bt=_def_bt,
		 symbols_per_pulse=_def_symbols_per_pulse,
                 generic_taps=_def_generic_taps,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for Continuous Phase
	modulation.

	The input is a byte stream (unsigned char) 
        representing packed bits and the
	output is the complex modulated signal at baseband.

        See Proakis for definition of generic CPM signals:
        s(t)=exp(j phi(t))
        phi(t)= 2 pi h int_0^t f(t') dt'
        f(t)=sum_k a_k g(t-kT)
        (normalizing assumption: int_0^infty g(t) dt = 1/2)

	@param samples_per_symbol: samples per baud >= 2
	@type samples_per_symbol: integer
	@param bits_per_symbol: bits per symbol
	@type bits_per_symbol: integer
	@param h_numerator: numerator of modulation index
	@type h_numerator: integer
	@param h_denominator: denominator of modulation index (numerator and denominator must be relative primes)
	@type h_denominator: integer
	@param cpm_type: supported types are: 0=CPFSK, 1=GMSK, 2=RC, 3=GENERAL
	@type cpm_type: integer
        @param bt: bandwidth symbol time product for GMSK
        @type bt: float
	@param symbols_per_pulse: shaping pulse duration in symbols
	@type symbols_per_pulse: integer
	@param generic_taps: define a generic CPM pulse shape (sum = samples_per_symbol/2)
	@type generic_taps: array of floats

        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modulation data to files?
        @type debug: bool       
	"""

	gr.hier_block2.__init__("cpm_mod", 
				gr.io_signature(1, 1, gr.sizeof_char),       # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) #  Output signature

        self._samples_per_symbol = samples_per_symbol
        self._bits_per_symbol = bits_per_symbol
        self._h_numerator = h_numerator
        self._h_denominator = h_denominator
        self._cpm_type = cpm_type
        self._bt=bt
        if cpm_type == 0 or cpm_type == 2 or cpm_type == 3: # CPFSK, RC, Generic
	    self._symbols_per_pulse = symbols_per_pulse
        elif cpm_type == 1: # GMSK
	    self._symbols_per_pulse = 4
        else:
            raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,))

        self._generic_taps=numpy.array(generic_taps)

        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
            raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,))

        self.nsymbols = 2**bits_per_symbol
        self.sym_alphabet=numpy.arange(-(self.nsymbols-1),self.nsymbols,2)


	self.ntaps = self._symbols_per_pulse * samples_per_symbol
	sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol

        # Unpack Bytes into bits_per_symbol groups
        self.B2s = gr.packed_to_unpacked_bb(bits_per_symbol,gr.GR_MSB_FIRST)
 
 
	# Turn it into symmetric PAM data.
        self.pam = gr.chunks_to_symbols_bf(self.sym_alphabet,1)

        # Generate pulse (sum of taps = samples_per_symbol/2)
        if cpm_type == 0: # CPFSK
            self.taps= (1.0/self._symbols_per_pulse/2,) * self.ntaps
        elif cpm_type == 1: # GMSK
            gaussian_taps = gr.firdes.gaussian(
                1.0/2,                     # gain
                samples_per_symbol,    # symbol_rate
                bt,                    # bandwidth * symbol time
                self.ntaps                  # number of taps
                )
	    sqwave = (1,) * samples_per_symbol       # rectangular window
	    self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave))
        elif cpm_type == 2: # Raised Cosine
            # generalize it for arbitrary roll-off factor
            self.taps = (1-numpy.cos(2*pi*numpy.arange(0,self.ntaps)/samples_per_symbol/self._symbols_per_pulse))/(2*self._symbols_per_pulse)
        elif cpm_type == 3: # Generic CPM
            self.taps = generic_taps
        else:
            raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,))

	self.filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)

	# FM modulation
	self.fmmod = gr.frequency_modulator_fc(sensitivity)
		
        if verbose:
            self._print_verbage()
         
        if log:
            self._setup_logging()

	# Connect
	self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self)
Exemple #13
0
def run_test(seed,blocksize):
        tb = gr.top_block()

	##################################################
	# Variables
	##################################################
	M = 2
	K = 1
	P = 2
	h = (1.0*K)/P
	L = 3
	Q = 4
        frac = 0.99
        f = trellis.fsm(P,M,L)

        # CPFSK signals
        #p = numpy.ones(Q)/(2.0)
        #q = numpy.cumsum(p)/(1.0*Q)

        # GMSK signals
        BT=0.3;
        tt=numpy.arange(0,L*Q)/(1.0*Q)-L/2.0;
        #print tt
        p=(0.5*scipy.stats.erfc(2*math.pi*BT*(tt-0.5)/math.sqrt(math.log(2.0))/math.sqrt(2.0))-0.5*scipy.stats.erfc(2*math.pi*BT*(tt+0.5)/math.sqrt(math.log(2.0))/math.sqrt(2.0)))/2.0;
        p=p/sum(p)*Q/2.0;
        #print p
        q=numpy.cumsum(p)/Q;
        q=q/q[-1]/2.0;
        #print q

        (f0T,SS,S,F,Sf,Ff,N) = fsm_utils.make_cpm_signals(K,P,M,L,q,frac)
        #print N
        #print Ff
        Ffa = numpy.insert(Ff,Q,numpy.zeros(N),axis=0)
        #print Ffa
        MF = numpy.fliplr(numpy.transpose(Ffa))
        #print MF
        E = numpy.sum(numpy.abs(Sf)**2,axis=0)
        Es = numpy.sum(E)/f.O()
        #print Es

        constellation = numpy.reshape(numpy.transpose(Sf),N*f.O())
        #print Ff
        #print Sf
        #print constellation
        #print numpy.max(numpy.abs(SS - numpy.dot(Ff , Sf)))

	EsN0_db = 10.0
        N0 =  Es * 10.0**(-(1.0*EsN0_db)/10.0)
        #N0 = 0.0
        #print N0
        head = 4
        tail = 4
        numpy.random.seed(seed*666)
        data = numpy.random.randint(0, M, head+blocksize+tail+1)
        #data = numpy.zeros(blocksize+1+head+tail,'int')
        for i in range(head):
            data[i]=0
        for i in range(tail+1):
            data[-i]=0
      


	##################################################
	# Blocks
	##################################################
	random_source_x_0 = gr.vector_source_b(data, False)
	gr_chunks_to_symbols_xx_0 = gr.chunks_to_symbols_bf((-1, 1), 1)
	gr_interp_fir_filter_xxx_0 = gr.interp_fir_filter_fff(Q, p)
	gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(2*math.pi*h*(1.0/Q))

	gr_add_vxx_0 = gr.add_vcc(1)
	gr_noise_source_x_0 = gr.noise_source_c(gr.GR_GAUSSIAN, (N0/2.0)**0.5, -long(seed))

	gr_multiply_vxx_0 = gr.multiply_vcc(1)
	gr_sig_source_x_0 = gr.sig_source_c(Q, gr.GR_COS_WAVE, -f0T, 1, 0)
        # only works for N=2, do it manually for N>2...
	gr_fir_filter_xxx_0_0 = gr.fir_filter_ccc(Q, MF[0].conjugate())
	gr_fir_filter_xxx_0_0_0 = gr.fir_filter_ccc(Q, MF[1].conjugate())
	gr_streams_to_stream_0 = gr.streams_to_stream(gr.sizeof_gr_complex*1, N)
	gr_skiphead_0 = gr.skiphead(gr.sizeof_gr_complex*1, N*(1+0))
	viterbi = trellis.viterbi_combined_cb(f, head+blocksize+tail, 0, -1, N, constellation, trellis.TRELLIS_EUCLIDEAN)

        gr_vector_sink_x_0 = gr.vector_sink_b()

	##################################################
	# Connections
	##################################################
	tb.connect((random_source_x_0, 0), (gr_chunks_to_symbols_xx_0, 0))
	tb.connect((gr_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0))
	tb.connect((gr_interp_fir_filter_xxx_0, 0), (gr_frequency_modulator_fc_0, 0))
	tb.connect((gr_frequency_modulator_fc_0, 0), (gr_add_vxx_0, 0))
	tb.connect((gr_noise_source_x_0, 0), (gr_add_vxx_0, 1))
	tb.connect((gr_add_vxx_0, 0), (gr_multiply_vxx_0, 0))
	tb.connect((gr_sig_source_x_0, 0), (gr_multiply_vxx_0, 1))
	tb.connect((gr_multiply_vxx_0, 0), (gr_fir_filter_xxx_0_0, 0))
	tb.connect((gr_multiply_vxx_0, 0), (gr_fir_filter_xxx_0_0_0, 0))
	tb.connect((gr_fir_filter_xxx_0_0, 0), (gr_streams_to_stream_0, 0))
	tb.connect((gr_fir_filter_xxx_0_0_0, 0), (gr_streams_to_stream_0, 1))
	tb.connect((gr_streams_to_stream_0, 0), (gr_skiphead_0, 0))
	tb.connect((gr_skiphead_0, 0), (viterbi, 0))
	tb.connect((viterbi, 0), (gr_vector_sink_x_0, 0))
        

        tb.run()
        dataest = gr_vector_sink_x_0.data()
        #print data
        #print numpy.array(dataest)
        perr = 0
        err = 0
        for i in range(blocksize):
          if data[head+i] != dataest[head+i]:
            #print i
            err += 1
        if err != 0 :
          perr = 1
        return (err,perr)
Exemple #14
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 bits_per_symbol=_def_bits_per_symbol,
                 h_numerator=_def_h_numerator,
                 h_denominator=_def_h_denominator,
                 cpm_type=_def_cpm_type,
                 bt=_def_bt,
                 symbols_per_pulse=_def_symbols_per_pulse,
                 generic_taps=_def_generic_taps,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for Continuous Phase
	modulation.

	The input is a byte stream (unsigned char) 
        representing packed bits and the
	output is the complex modulated signal at baseband.

        See Proakis for definition of generic CPM signals:
        s(t)=exp(j phi(t))
        phi(t)= 2 pi h int_0^t f(t') dt'
        f(t)=sum_k a_k g(t-kT)
        (normalizing assumption: int_0^infty g(t) dt = 1/2)

	@param samples_per_symbol: samples per baud >= 2
	@type samples_per_symbol: integer
	@param bits_per_symbol: bits per symbol
	@type bits_per_symbol: integer
	@param h_numerator: numerator of modulation index
	@type h_numerator: integer
	@param h_denominator: denominator of modulation index (numerator and denominator must be relative primes)
	@type h_denominator: integer
	@param cpm_type: supported types are: 0=CPFSK, 1=GMSK, 2=RC, 3=GENERAL
	@type cpm_type: integer
        @param bt: bandwidth symbol time product for GMSK
        @type bt: float
	@param symbols_per_pulse: shaping pulse duration in symbols
	@type symbols_per_pulse: integer
	@param generic_taps: define a generic CPM pulse shape (sum = samples_per_symbol/2)
	@type generic_taps: array of floats

        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modulation data to files?
        @type debug: bool       
	"""

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

        self._samples_per_symbol = samples_per_symbol
        self._bits_per_symbol = bits_per_symbol
        self._h_numerator = h_numerator
        self._h_denominator = h_denominator
        self._cpm_type = cpm_type
        self._bt = bt
        if cpm_type == 0 or cpm_type == 2 or cpm_type == 3:  # CPFSK, RC, Generic
            self._symbols_per_pulse = symbols_per_pulse
        elif cpm_type == 1:  # GMSK
            self._symbols_per_pulse = 4
        else:
            raise TypeError, (
                "cpm_type must be an integer in {0,1,2,3}, is %r" %
                (cpm_type, ))

        self._generic_taps = numpy.array(generic_taps)

        if samples_per_symbol < 2:
            raise TypeError, ("samples_per_symbol must be >= 2, is %r" %
                              (samples_per_symbol, ))

        self.nsymbols = 2**bits_per_symbol
        self.sym_alphabet = numpy.arange(-(self.nsymbols - 1), self.nsymbols,
                                         2).tolist()

        self.ntaps = int(self._symbols_per_pulse * samples_per_symbol)
        sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol

        # Unpack Bytes into bits_per_symbol groups
        self.B2s = gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)

        # Turn it into symmetric PAM data.
        self.pam = gr.chunks_to_symbols_bf(self.sym_alphabet, 1)

        # Generate pulse (sum of taps = samples_per_symbol/2)
        if cpm_type == 0:  # CPFSK
            self.taps = (1.0 / self._symbols_per_pulse / 2, ) * self.ntaps
        elif cpm_type == 1:  # GMSK
            gaussian_taps = gr.firdes.gaussian(
                1.0 / 2,  # gain
                samples_per_symbol,  # symbol_rate
                bt,  # bandwidth * symbol time
                self.ntaps  # number of taps
            )
            sqwave = (1, ) * samples_per_symbol  # rectangular window
            self.taps = numpy.convolve(numpy.array(gaussian_taps),
                                       numpy.array(sqwave))
        elif cpm_type == 2:  # Raised Cosine
            # generalize it for arbitrary roll-off factor
            self.taps = (1 - numpy.cos(
                2 * pi * numpy.arange(0, self.ntaps) / samples_per_symbol /
                self._symbols_per_pulse)) / (2 * self._symbols_per_pulse)
        elif cpm_type == 3:  # Generic CPM
            self.taps = generic_taps
        else:
            raise TypeError, (
                "cpm_type must be an integer in {0,1,2,3}, is %r" %
                (cpm_type, ))

        self.filter = blks2.pfb_arb_resampler_fff(samples_per_symbol,
                                                  self.taps)

        # FM modulation
        self.fmmod = gr.frequency_modulator_fc(sensitivity)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

# Connect
        self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self)
Exemple #15
0
    def __init__(self,
                 output_sample_rate=_def_output_sample_rate,
                 excess_bw=_def_excess_bw,
                 reverse=_def_reverse,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered P25 FM modulation.

	The input is a dibit (P25 symbol) stream (char, not packed) and the
	output is the float "C4FM" signal at baseband, suitable for application
        to an FM modulator stage

        Input is at the base symbol rate (4800), output sample rate is
        typically either 32000 (USRP TX chain) or 48000 (sound card)

	@param output_sample_rate: output sample rate
	@type output_sample_rate: integer
	@param excess_bw: Root-raised cosine filter excess bandwidth
	@type excess_bw: float
        @param reverse: reverse polarity flag
        @type reverse: bool
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modulation data to files?
        @type debug: bool
	"""

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

        input_sample_rate = 4800   # P25 baseband symbol rate
        lcm = gru.lcm(input_sample_rate, output_sample_rate)
        self._interp_factor = int(lcm // input_sample_rate)
        self._decimation = int(lcm // output_sample_rate)
        self._excess_bw = excess_bw

        mod_map = [1.0/3.0, 1.0, -(1.0/3.0), -1.0]
        self.C2S = gr.chunks_to_symbols_bf(mod_map)
        if reverse:
            self.polarity = gr.multiply_const_ff(-1)
        else:
            self.polarity = gr.multiply_const_ff( 1)

        ntaps = 11 * self._interp_factor
        rrc_taps = gr.firdes.root_raised_cosine(
            self._interp_factor, # gain (since we're interpolating by sps)
            lcm,                      # sampling rate
            input_sample_rate,        # symbol rate
            self._excess_bw,          # excess bandwidth (roll-off factor)
            ntaps)

        # rrc_coeffs work slightly differently: each input sample
        # (from mod_map above) at 4800 rate, then 9 zeros are inserted
        # to bring to 48000 rate, then this filter is applied:
        # rrc_filter = gr.fir_filter_fff(1, rrc_coeffs)
        # FIXME: how to insert the 9 zero samples using gr ?
        # rrc_coeffs = [0, -0.003, -0.006, -0.009, -0.012, -0.014, -0.014, -0.013, -0.01, -0.006, 0, 0.007, 0.014, 0.02, 0.026, 0.029, 0.029, 0.027, 0.021, 0.012, 0, -0.013, -0.027, -0.039, -0.049, -0.054, -0.055, -0.049, -0.038, -0.021, 0, 0.024, 0.048, 0.071, 0.088, 0.098, 0.099, 0.09, 0.07, 0.039, 0, -0.045, -0.091, -0.134, -0.17, -0.193, -0.199, -0.184, -0.147, -0.085, 0, 0.105, 0.227, 0.36, 0.496, 0.629, 0.751, 0.854, 0.933, 0.983, 1, 0.983, 0.933, 0.854, 0.751, 0.629, 0.496, 0.36, 0.227, 0.105, 0, -0.085, -0.147, -0.184, -0.199, -0.193, -0.17, -0.134, -0.091, -0.045, 0, 0.039, 0.07, 0.09, 0.099, 0.098, 0.088, 0.071, 0.048, 0.024, 0, -0.021, -0.038, -0.049, -0.055, -0.054, -0.049, -0.039, -0.027, -0.013, 0, 0.012, 0.021, 0.027, 0.029, 0.029, 0.026, 0.02, 0.014, 0.007, 0, -0.006, -0.01, -0.013, -0.014, -0.014, -0.012, -0.009, -0.006, -0.003, 0]

        self.rrc_filter = gr.interp_fir_filter_fff(self._interp_factor, rrc_taps)


        # FM pre-emphasis filter
        shaping_coeffs = [-0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099, 0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137, -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137, -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099, -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018]
        self.shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        if verbose:
            self._print_verbage()
        
        if log:
            self._setup_logging()

        self.connect(self, self.C2S, self.polarity, self.rrc_filter, self.shaping_filter)
        if (self._decimation > 1):
            self.decimator = blks2.rational_resampler_fff(1, self._decimation)
            self.connect(self.shaping_filter, self.decimator, self)
        else:
            self.connect(self.shaping_filter, self)
Exemple #16
0
    def __init__(self, options, queue):
        gr.top_block.__init__(self, "mhp")

        sample_rate = options.sample_rate

        arity = 2
        IN = gr.file_source(gr.sizeof_char, options.input_file, options.repeat)
        B2C = gr.packed_to_unpacked_bb(arity, gr.GR_MSB_FIRST)
        mod_map = [1.0, 3.0, -1.0, -3.0]
        C2S = gr.chunks_to_symbols_bf(mod_map)
        if options.reverse:
            polarity = gr.multiply_const_ff(-1)
        else:
            polarity = gr.multiply_const_ff(1)

        symbol_rate = 4800
        samples_per_symbol = sample_rate // symbol_rate
        excess_bw = 0.1
        ntaps = 11 * samples_per_symbol
        rrc_taps = gr.firdes.root_raised_cosine(
            samples_per_symbol,  # gain  (sps since we're interpolating by sps
            samples_per_symbol,  # sampling rate
            1.0,  # symbol rate
            excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)
        rrc_filter = gr.interp_fir_filter_fff(samples_per_symbol, rrc_taps)

        rrc_coeffs = [
            0, -0.003, -0.006, -0.009, -0.012, -0.014, -0.014, -0.013, -0.01,
            -0.006, 0, 0.007, 0.014, 0.02, 0.026, 0.029, 0.029, 0.027, 0.021,
            0.012, 0, -0.013, -0.027, -0.039, -0.049, -0.054, -0.055, -0.049,
            -0.038, -0.021, 0, 0.024, 0.048, 0.071, 0.088, 0.098, 0.099, 0.09,
            0.07, 0.039, 0, -0.045, -0.091, -0.134, -0.17, -0.193, -0.199,
            -0.184, -0.147, -0.085, 0, 0.105, 0.227, 0.36, 0.496, 0.629, 0.751,
            0.854, 0.933, 0.983, 1, 0.983, 0.933, 0.854, 0.751, 0.629, 0.496,
            0.36, 0.227, 0.105, 0, -0.085, -0.147, -0.184, -0.199, -0.193,
            -0.17, -0.134, -0.091, -0.045, 0, 0.039, 0.07, 0.09, 0.099, 0.098,
            0.088, 0.071, 0.048, 0.024, 0, -0.021, -0.038, -0.049, -0.055,
            -0.054, -0.049, -0.039, -0.027, -0.013, 0, 0.012, 0.021, 0.027,
            0.029, 0.029, 0.026, 0.02, 0.014, 0.007, 0, -0.006, -0.01, -0.013,
            -0.014, -0.014, -0.012, -0.009, -0.006, -0.003, 0
        ]

        # rrc_coeffs work slightly differently: each input sample
        # (from mod_map above) at 4800 rate, then 9 zeros are inserted
        # to bring to a 48000 rate, then this filter is applied:
        # rrc_filter = gr.fir_filter_fff(1, rrc_coeffs)
        # FIXME: how to insert the 9 zero samples using gr ?

        # FM pre-emphasis filter
        shaping_coeffs = [
            -0.018, 0.0347, 0.0164, -0.0064, -0.0344, -0.0522, -0.0398, 0.0099,
            0.0798, 0.1311, 0.121, 0.0322, -0.113, -0.2499, -0.3007, -0.2137,
            -0.0043, 0.2825, 0.514, 0.604, 0.514, 0.2825, -0.0043, -0.2137,
            -0.3007, -0.2499, -0.113, 0.0322, 0.121, 0.1311, 0.0798, 0.0099,
            -0.0398, -0.0522, -0.0344, -0.0064, 0.0164, 0.0347, -0.018
        ]
        shaping_filter = gr.fir_filter_fff(1, shaping_coeffs)

        OUT = audio.sink(sample_rate, options.audio_output)
        amp = gr.multiply_const_ff(options.factor)

        self.connect(IN, B2C, C2S, polarity, rrc_filter, shaping_filter, amp)
        # output to both L and R channels
        self.connect(amp, (OUT, 0))
        self.connect(amp, (OUT, 1))