Esempio n. 1
0
def make_prs(sample_rate=2048000):
    dp = parameters.dab_parameters(1, sample_rate)
    prs = dp.prn

    def write(file_name, signal):
        if type(signal) != numpy.complex64:
            signal = numpy.asarray(signal, dtype=numpy.complex64)
        signal.tofile(file_name)

    def interleave(symbol):
        return [symbol[i] for i in dp.frequency_interleaving_sequence_array]

    def pad(symbol):
        zeros_on_left = (dp.fft_length - dp.num_carriers) / 2
        zeros_on_right = dp.fft_length - zeros_on_left - dp.num_carriers - 1
        return [0] * zeros_on_left + symbol[0:dp.num_carriers / 2] + [
            0
        ] + symbol[dp.num_carriers / 2:] + [0] * zeros_on_right

    #print prs
    interleaved_prs = interleave(prs)

    #padded_prs = pad(interleaved_prs)
    padded_prs = pad(prs)
    return padded_prs
Esempio n. 2
0
	def __init__(self):
		gr.top_block.__init__(self)
		
		usage = "%prog: [options] samples_file"
		parser = OptionParser(option_class=eng_option, usage=usage)
		(options, args) = parser.parse_args ()
		if len(args)<1:
			# print "using gaussian noise as source"
			# self.sigsrc = gr.noise_source_c(gr.GR_GAUSSIAN,10e6)
			print "using repeating random vector as source"
			self.sigsrc = blocks.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True)
			self.src = blocks.throttle( gr.sizeof_gr_complex,2048000)
			self.connect(self.sigsrc, self.src)
		else:
			filename = args[0]
			print "using samples from file " + filename
			self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False)

		dp = parameters.dab_parameters(1)
		rp = parameters.receiver_parameters(1)
		self.sync_dab = ofdm_sync_dab(dp, rp, False)
		self.nop0 = blocks.nop(gr.sizeof_gr_complex)
		self.nop1 = blocks.nop(gr.sizeof_char)
		self.connect(self.src, self.sync_dab, self.nop0)
		self.connect((self.sync_dab,1), self.nop1)
Esempio n. 3
0
    def __init__(self):
        gr.sync_block.__init__(self,
                               name="dab_sync",
                               in_sig=[numpy.complex64],
                               out_sig=[numpy.complex64])

        self.sample_rate = 2048000
        self.step = 1

        self.dp = parameters.dab_parameters(1, self.sample_rate)
        self.prs = make_prs.modulate_prs(self.sample_rate, True)
        self.frame_length = int(self.sample_rate * 96e-3)
        self.prs_len = len(self.prs)
        print "PRS length", self.prs_len

        self.correlator = correlate.Correlator(self.prs, self.sample_rate)
        self.P = 0.2 * 3
        self.I = 0.2 * 3

        self.fract = 1000
        self.integer_offset = 0
        self.fract_offset = 0

        self.state = INIT

        self.set_history(self.prs_len + 1)
Esempio n. 4
0
    def __init__(self):
        gr.top_block.__init__(self)

        usage = "%prog: [options] samples_file"
        parser = OptionParser(option_class=eng_option, usage=usage)
        (options, args) = parser.parse_args()
        if len(args) < 1:
            # print "using gaussian noise as source"
            # self.sigsrc = gr.noise_source_c(gr.GR_GAUSSIAN,10e6)
            print "using repeating random vector as source"
            self.sigsrc = blocks.vector_source_c([
                10e6 * (random.random() + 1j * random.random())
                for i in range(0, 100000)
            ], True)
            self.src = blocks.throttle(gr.sizeof_gr_complex, 2048000)
            self.connect(self.sigsrc, self.src)
        else:
            filename = args[0]
            print "using samples from file " + filename
            self.src = blocks.file_source(gr.sizeof_gr_complex, filename,
                                          False)

        dp = parameters.dab_parameters(1)
        rp = parameters.receiver_parameters(1)
        self.sync_dab = ofdm_sync_dab(dp, rp, False)
        self.nop0 = blocks.nop(gr.sizeof_gr_complex)
        self.nop1 = blocks.nop(gr.sizeof_char)
        self.connect(self.src, self.sync_dab, self.nop0)
        self.connect((self.sync_dab, 1), self.nop1)
Esempio n. 5
0
    def test_001_t (self):
        self.symbol_length = 32*4
        self.dab_params = dab_parameters(1, 208.064e6, True)

        # source
        self.dp = dab_parameters(1, 208.064e6, True)
        self.fib_src = dab.fib_source_b_make(1, 1, 1, "ensemble1", "service1        ", "musicmix", 4, [2], [15], [1])

        # encoder
        self.fib_enc = fic_encode(self.dab_params)
        self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST)

        # mapper
        self.map = dab.mapper_bc_make(self.dp.num_carriers)

        # demapper
        self.s2v = blocks.stream_to_vector_make(gr.sizeof_gr_complex, self.dp.num_carriers)
        self.soft_interleaver = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers)

        # decode
        self.fic_decoder = fic_decode(self.dab_params)

        # control stream
        self.trigger_src = blocks.vector_source_b([1] + [0]*74, True)

        self.tb.connect(self.fib_src,
                        blocks.head_make(gr.sizeof_char, 100000),
                        self.fib_enc,
                        self.unpack,
                        self.map,
                        self.s2v,
                        self.soft_interleaver,
                        self.fic_decoder
                        )
        self.tb.connect(self.trigger_src, (self.fic_decoder, 1))


        self.tb.run ()
        pass
Esempio n. 6
0
	def __init__(self):
		gr.top_block.__init__(self)
		

		usage = "%prog: [options] samples_file"
		parser = OptionParser(option_class=eng_option, usage=usage)
  		parser.add_option("-m", "--dab-mode", type="int", default=1,
        	     	help="DAB mode [default=%default]")
		parser.add_option("-F", "--filter-input", action="store_true", default=False,
                          help="Enable FFT filter at input")
  		parser.add_option("-s", "--resample-fixed", type="float", default=1,
			help="resample by a fixed factor (fractional interpolation)")
		parser.add_option("-S", "--autocorrect-sample-rate", action="store_true", default=False,
                          help="Estimate sample rate offset and resample (dynamic fractional interpolation)")
  		parser.add_option('-r', '--sample-rate', type="int", default=2048000,
	     		help="Use non-standard sample rate (default=%default)")
  		parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False,
	     		help="Enable individual carrier magnitude equalizer")
  		parser.add_option('-d', '--debug', action="store_true", default=False,
	     		help="Write output to files")
  		parser.add_option('-v', '--verbose', action="store_true", default=False,
	     		help="Print status messages")
		(options, args) = parser.parse_args ()
	
		dp = parameters.dab_parameters(options.dab_mode, verbose=options.verbose, sample_rate=options.sample_rate)

		rp = parameters.receiver_parameters(options.dab_mode, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, equalize_magnitude=options.equalize_magnitude, verbose=options.verbose)

		if len(args)<1:
			if options.verbose: print "-> using repeating random vector as source"
			self.sigsrc = gr.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True)
			self.ns_simulate = gr.vector_source_c([0.01]*dp.ns_length+[1]*dp.symbols_per_frame*dp.symbol_length,1)
			self.mult = gr.multiply_cc() # simulate null symbols ...
			self.src = gr.throttle( gr.sizeof_gr_complex,2048000)
			self.connect(self.sigsrc, (self.mult, 0))
			self.connect(self.ns_simulate, (self.mult, 1))
			self.connect(self.mult, self.src)
		else:
			filename = args[0]
			if options.verbose: print "-> using samples from file " + filename
			self.src = gr.file_source(gr.sizeof_gr_complex, filename, False)

		self.dab_demod = ofdm.ofdm_demod(dp, rp, debug=options.debug, verbose=options.verbose)
		
		self.connect(self.src, self.dab_demod)

		# sink output to nowhere 
		self.nop0 = gr.nop(gr.sizeof_char*dp.num_carriers/4)
		self.nop1 = gr.nop(gr.sizeof_char)
		self.connect((self.dab_demod,0),self.nop0)
		self.connect((self.dab_demod,1),self.nop1)
Esempio n. 7
0
    def init(self):
        self.sample_rate = 2048000
        self.step = 1

        self.dp = parameters.dab_parameters(1, self.sample_rate)
        self.prs = make_prs.modulate_prs(self.sample_rate, True)
        self.frame_length = int(self.sample_rate * 96e-3)
        self.prs_len = len(self.prs)

        self.P = 0.2 * 3
        self.I = 0.2 * 3

        self.fract = 1000
        self.integer_offset = 0
        self.fract_offset = 0

        self.state = get_samples
        self.get_samples_count = self.frame_length
        self.next_state = find_start
Esempio n. 8
0
def modulate_prs(sample_rate=2048000, cp=True):
    dp = parameters.dab_parameters(1, sample_rate)
    padded_prs = make_prs(sample_rate)

    #plt.plot(numpy.abs(padded_prs))
    #plt.show()
    #plt.plot(numpy.angle(padded_prs))
    #plt.show()

    shifted_prs = numpy.fft.fftshift(padded_prs)

    #plt.plot(numpy.abs(shifted_prs))
    #plt.show()

    ifft_prs = numpy.fft.ifft(shifted_prs)

    if cp:
        print "CP length", dp.cp_length
        cycled_prs = numpy.concatenate((ifft_prs[-dp.cp_length:], ifft_prs))
        return cycled_prs
    else:
        return ifft_prs
Esempio n. 9
0
if __name__ == "__main__":

    #sample_rate = 2048000
    sample_rate = 2000000
    cycled_prs = modulate_prs(sample_rate)
    iq.write("/tmp/generated.cfile", cycled_prs)

    signal = numpy.concatenate(([0] * 2048, cycled_prs))
    #signal = numpy.concatenate(([0] * 2048, cycled_prs, [0] * 2048, cycled_prs))
    #signal = numpy.concatenate(([0] * 2048, prs, [0] * 2048, prs))

    iq.write("/tmp/foo.cfile", signal)
    #print dp.frequency_interleaving_sequence_array

    dp = parameters.dab_parameters(1, sample_rate)
    Tu = dp.fft_length

    offset = 600
    shift_signal = numpy.exp(
        complex(0, -1) * numpy.arange(len(signal)) * 2 * numpy.pi * offset /
        float(sample_rate))
    signal = signal * shift_signal

    time_shifted_signal = signal[Tu:]

    auto_correlated = [0] * len(time_shifted_signal)
    for i in range(len(time_shifted_signal)):
        auto_correlated[i] = numpy.angle(signal[i] * numpy.conj(
            time_shifted_signal[i])) / 2 / 3.14 / (2048. / sample_rate)
Esempio n. 10
0
    def __init__(self):
        gr.top_block.__init__(self)

        usage = "%prog: [options] samples_file"
        parser = OptionParser(option_class=eng_option, usage=usage)
        parser.add_option("-m",
                          "--dab-mode",
                          type="int",
                          default=1,
                          help="DAB mode [default=%default]")
        parser.add_option("-F",
                          "--filter-input",
                          action="store_true",
                          default=False,
                          help="Enable FFT filter at input")
        parser.add_option(
            "-s",
            "--resample-fixed",
            type="float",
            default=1,
            help="resample by a fixed factor (fractional interpolation)")
        parser.add_option(
            "-S",
            "--autocorrect-sample-rate",
            action="store_true",
            default=False,
            help=
            "Estimate sample rate offset and resample (dynamic fractional interpolation)"
        )
        parser.add_option(
            '-r',
            '--sample-rate',
            type="int",
            default=2048000,
            help="Use non-standard sample rate (default=%default)")
        parser.add_option('-e',
                          '--equalize-magnitude',
                          action="store_true",
                          default=False,
                          help="Enable individual carrier magnitude equalizer")
        parser.add_option('-d',
                          '--debug',
                          action="store_true",
                          default=False,
                          help="Write output to files")
        parser.add_option('-v',
                          '--verbose',
                          action="store_true",
                          default=False,
                          help="Print status messages")
        (options, args) = parser.parse_args()

        dp = parameters.dab_parameters(options.dab_mode,
                                       verbose=options.verbose,
                                       sample_rate=options.sample_rate)

        rp = parameters.receiver_parameters(
            options.dab_mode,
            input_fft_filter=options.filter_input,
            autocorrect_sample_rate=options.autocorrect_sample_rate,
            sample_rate_correction_factor=options.resample_fixed,
            equalize_magnitude=options.equalize_magnitude,
            verbose=options.verbose)

        if len(args) < 1:
            if options.verbose:
                print "-> using repeating random vector as source"
            self.sigsrc = blocks.vector_source_c([
                10e6 * (random.random() + 1j * random.random())
                for i in range(0, 100000)
            ], True)
            self.ns_simulate = blocks.vector_source_c(
                [0.01] * dp.ns_length +
                [1] * dp.symbols_per_frame * dp.symbol_length, 1)
            self.mult = blocks.multiply_cc()  # simulate null symbols ...
            self.src = blocks.throttle(gr.sizeof_gr_complex, 2048000)
            self.connect(self.sigsrc, (self.mult, 0))
            self.connect(self.ns_simulate, (self.mult, 1))
            self.connect(self.mult, self.src)
        else:
            filename = args[0]
            if options.verbose: print "-> using samples from file " + filename
            self.src = blocks.file_source(gr.sizeof_gr_complex, filename,
                                          False)

        self.dab_demod = ofdm.ofdm_demod(dp,
                                         rp,
                                         debug=options.debug,
                                         verbose=options.verbose)

        self.connect(self.src, self.dab_demod)

        # sink output to nowhere
        self.nop0 = blocks.nop(gr.sizeof_char * dp.num_carriers / 4)
        self.nop1 = blocks.nop(gr.sizeof_char)
        self.connect((self.dab_demod, 0), self.nop0)
        self.connect((self.dab_demod, 1), self.nop1)
Esempio n. 11
0
    def __init__(self, mode, debug=False):
        """
		OFDM time and coarse frequency synchronisation for DAB

		@param mode DAB mode (1-4)
		@param debug if True: write data streams out to files
		"""

        if mode < 1 or mode > 4:
            raise ValueError, "Invalid DAB mode: " + str(
                mode) + " (modes 1-4 exist)"

        # get the correct DAB parameters
        dp = parameters.dab_parameters(mode)
        rp = parameters.receiver_parameters(mode)

        gr.hier_block2.__init__(
            self,
            "ofdm_sync_dab",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # input signature
            gr.io_signature2(2, 2, gr.sizeof_gr_complex,
                             gr.sizeof_char))  # output signature

        # workaround for a problem that prevents connecting more than one block directly (see trac ticket #161)
        self.input = gr.kludge_copy(gr.sizeof_gr_complex)
        self.connect(self, self.input)

        #
        # null-symbol detection
        #
        # (outsourced to detect_zero.py)

        self.ns_detect = detect_null.detect_null(dp.ns_length, debug)
        self.connect(self.input, self.ns_detect)

        #
        # fine frequency synchronisation
        #

        # the code for fine frequency synchronisation is adapted from
        # ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine
        # frequency error, as suggested in "ML Estimation of Timing and
        # Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek,
        # Magnus Sandell, Per Ola Börjesson, see
        # http://www.sm.luth.se/csee/sp/research/report/bsb96r.html

        self.ffs_delay = gr.delay(gr.sizeof_gr_complex, dp.fft_length)
        self.ffs_conj = gr.conjugate_cc()
        self.ffs_mult = gr.multiply_cc()
        # self.ffs_moving_sum = gr.fir_filter_ccf(1, [1]*dp.cp_length)
        self.ffs_moving_sum = dab_swig.moving_sum_cc(dp.cp_length)
        self.ffs_angle = gr.complex_to_arg()
        self.ffs_angle_scale = gr.multiply_const_ff(1. / dp.fft_length)
        self.ffs_delay_sample_and_hold = gr.delay(
            gr.sizeof_char,
            dp.symbol_length)  # sample the value at the end of the symbol ..
        self.ffs_sample_and_hold = gr.sample_and_hold_ff()
        self.ffs_delay_input_for_correction = gr.delay(
            gr.sizeof_gr_complex, dp.symbol_length
        )  # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself
        self.ffs_nco = gr.frequency_modulator_fc(
            1)  # ffs_sample_and_hold directly outputs phase error per sample
        self.ffs_mixer = gr.multiply_cc()

        # calculate fine frequency error
        self.connect(self.input, self.ffs_conj, self.ffs_mult)
        self.connect(self.input, self.ffs_delay, (self.ffs_mult, 1))
        self.connect(self.ffs_mult, self.ffs_moving_sum, self.ffs_angle)
        # only use the value from the first half of the first symbol
        self.connect(self.ffs_angle, self.ffs_angle_scale,
                     (self.ffs_sample_and_hold, 0))
        self.connect(self.ns_detect, self.ffs_delay_sample_and_hold,
                     (self.ffs_sample_and_hold, 1))
        # do the correction
        self.connect(self.ffs_sample_and_hold, self.ffs_nco,
                     (self.ffs_mixer, 0))
        self.connect(self.input, self.ffs_delay_input_for_correction,
                     (self.ffs_mixer, 1))

        # output - corrected signal and start of DAB frames
        self.connect(self.ffs_mixer, (self, 0))
        self.connect(self.ffs_delay_sample_and_hold, (self, 1))

        if debug:
            self.connect(
                self.ffs_angle,
                gr.file_sink(gr.sizeof_float,
                             "debug/ofdm_sync_dab_ffs_angle.dat"))
            self.connect(
                self.ffs_sample_and_hold,
                gr.multiply_const_ff(1. / (dp.T * 2 * pi)),
                gr.file_sink(gr.sizeof_float,
                             "debug/ofdm_sync_dab_fine_freq_err_f.dat"))
            self.connect(
                self.ffs_mixer,
                gr.file_sink(gr.sizeof_gr_complex,
                             "debug/ofdm_sync_dab_fine_freq_corrected_c.dat"))
Esempio n. 12
0
	def __init__(self, mode, debug=False):
		"""
		OFDM time and coarse frequency synchronisation for DAB

		@param mode DAB mode (1-4)
		@param debug if True: write data streams out to files
		"""

		if mode<1 or mode>4:
			raise ValueError, "Invalid DAB mode: "+str(mode)+" (modes 1-4 exist)"

		# get the correct DAB parameters
		dp = parameters.dab_parameters(mode)
		rp = parameters.receiver_parameters(mode)
		
		gr.hier_block2.__init__(self,"ofdm_sync_dab",
		                        gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature
					gr.io_signature2(2, 2, gr.sizeof_gr_complex, gr.sizeof_char)) # output signature

		# workaround for a problem that prevents connecting more than one block directly (see trac ticket #161)
		self.input = gr.kludge_copy(gr.sizeof_gr_complex)
		self.connect(self, self.input)

		#
		# null-symbol detection
		#
		# (outsourced to detect_zero.py)
		
		self.ns_detect = detect_null.detect_null(dp.ns_length, debug)
		self.connect(self.input, self.ns_detect)

		#
		# fine frequency synchronisation
		#

		# the code for fine frequency synchronisation is adapted from
		# ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine
		# frequency error, as suggested in "ML Estimation of Timing and
		# Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek,
		# Magnus Sandell, Per Ola Börjesson, see
		# http://www.sm.luth.se/csee/sp/research/report/bsb96r.html

		self.ffs_delay = gr.delay(gr.sizeof_gr_complex, dp.fft_length)
		self.ffs_conj = gr.conjugate_cc()
		self.ffs_mult = gr.multiply_cc()
		# self.ffs_moving_sum = gr.fir_filter_ccf(1, [1]*dp.cp_length)
		self.ffs_moving_sum = dab_swig.moving_sum_cc(dp.cp_length)
		self.ffs_angle = gr.complex_to_arg()
		self.ffs_angle_scale = gr.multiply_const_ff(1./dp.fft_length)
		self.ffs_delay_sample_and_hold = gr.delay(gr.sizeof_char, dp.symbol_length) # sample the value at the end of the symbol ..
		self.ffs_sample_and_hold = gr.sample_and_hold_ff()
		self.ffs_delay_input_for_correction = gr.delay(gr.sizeof_gr_complex, dp.symbol_length) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself
		self.ffs_nco = gr.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample
		self.ffs_mixer = gr.multiply_cc()

		# calculate fine frequency error
		self.connect(self.input, self.ffs_conj, self.ffs_mult)
		self.connect(self.input, self.ffs_delay, (self.ffs_mult, 1))
		self.connect(self.ffs_mult, self.ffs_moving_sum, self.ffs_angle)
		# only use the value from the first half of the first symbol
		self.connect(self.ffs_angle, self.ffs_angle_scale, (self.ffs_sample_and_hold, 0))
		self.connect(self.ns_detect, self.ffs_delay_sample_and_hold, (self.ffs_sample_and_hold, 1))
		# do the correction
		self.connect(self.ffs_sample_and_hold, self.ffs_nco, (self.ffs_mixer, 0))
		self.connect(self.input, self.ffs_delay_input_for_correction, (self.ffs_mixer, 1))

		# output - corrected signal and start of DAB frames
		self.connect(self.ffs_mixer, (self, 0))
		self.connect(self.ffs_delay_sample_and_hold, (self, 1))

		if debug:
			self.connect(self.ffs_angle, gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_ffs_angle.dat"))
			self.connect(self.ffs_sample_and_hold, gr.multiply_const_ff(1./(dp.T*2*pi)), gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat"))
			self.connect(self.ffs_mixer, gr.file_sink(gr.sizeof_gr_complex, "debug/ofdm_sync_dab_fine_freq_corrected_c.dat"))