Esempio n. 1
0
    def __init__(self, samplerate, bits_per_sec, fftlen):
        gr.hier_block2.__init__(
            self,
            "gmsk_sync",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        #this is just the old square-and-fft method
        #ais.freqest is simply looking for peaks spaced bits-per-sec apart
        self.square = gr.multiply_cc(1)
        self.fftvect = gr.stream_to_vector(gr.sizeof_gr_complex, fftlen)
        self.fft = gr.fft_vcc(fftlen, True, window.rectangular(fftlen), True)
        self.freqest = ais.freqest(int(samplerate), int(bits_per_sec), fftlen)
        self.repeat = gr.repeat(gr.sizeof_float, fftlen)
        self.fm = gr.frequency_modulator_fc(-1.0 / (float(samplerate) /
                                                    (2 * pi)))
        self.mix = gr.multiply_cc(1)

        self.connect(self, (self.square, 0))
        self.connect(self, (self.square, 1))
        #this is the feedforward branch
        self.connect(self, (self.mix, 0))
        #this is the feedback branch
        self.connect(self.square, self.fftvect, self.fft, self.freqest,
                     self.repeat, self.fm, (self.mix, 1))
        #and this is the output
        self.connect(self.mix, self)
Esempio n. 2
0
    def __init__(self, bt=0.3, samples_per_symbol=2):
        gr.hier_block2.__init__(
            self, "msk_demod", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)
        )

        ntaps = 4 * samples_per_symbol  # up to 3 bits in filter at once
        sensitivity = (pi / 2) / samples_per_symbol  # phase change per bit = pi / 2

        # Turn it into NRZ data.
        self.unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        self.nrz = digital.chunks_to_symbols_bf([-1, 1], 1)  # note could also invert bits here

        # Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
        self.gaussian_taps = gr.firdes.gaussian(1, samples_per_symbol, bt, ntaps)

        self.sqwave = (1,) * samples_per_symbol  # rectangular window
        self.taps = numpy.convolve(numpy.array(self.gaussian_taps), numpy.array(self.sqwave))
        self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps)

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

        # TODO: this is hardcoded, how to figure out this value?
        self.offset = gr.add_const_vff((-0.5,))

        # CC430 RF core is inverted with respect to USRP for some reason
        self.invert = gr.multiply_const_vff((-1,))

        # Connect & Initialize base class
        self.connect(self, self.unpack, self.nrz, self.invert, self.offset, self.gaussian_filter, self.fmmod, self)
Esempio n. 3
0
    def set_waveform(self, type):
        self.lock()
        self.disconnect_all()
        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
            self._src = gr.sig_source_c(
                self[SAMP_RATE_KEY],  # Sample rate
                type,  # Waveform type
                self[WAVEFORM_FREQ_KEY],  # Waveform frequency
                self[AMPLITUDE_KEY],  # Waveform amplitude
                self[WAVEFORM_OFFSET_KEY])  # Waveform offset
        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
            self._src = gr.noise_source_c(type, self[AMPLITUDE_KEY])
        elif type == "2tone":
            self._src1 = gr.sig_source_c(self[SAMP_RATE_KEY], gr.GR_SIN_WAVE,
                                         self[WAVEFORM_FREQ_KEY],
                                         self[AMPLITUDE_KEY] / 2.0, 0)
            if (self[WAVEFORM2_FREQ_KEY] is None):
                self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]

            self._src2 = gr.sig_source_c(self[SAMP_RATE_KEY], gr.GR_SIN_WAVE,
                                         self[WAVEFORM2_FREQ_KEY],
                                         self[AMPLITUDE_KEY] / 2.0, 0)
            self._src = gr.add_cc()
            self.connect(self._src1, (self._src, 0))
            self.connect(self._src2, (self._src, 1))
        elif type == "sweep":
            # rf freq is center frequency
            # waveform_freq is total swept width
            # waveform2_freq is sweep rate
            # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
            if self[WAVEFORM2_FREQ_KEY] is None:
                self[WAVEFORM2_FREQ_KEY] = 0.1

            self._src1 = gr.sig_source_f(self[SAMP_RATE_KEY], gr.GR_TRI_WAVE,
                                         self[WAVEFORM2_FREQ_KEY], 1.0, -0.5)
            self._src2 = gr.frequency_modulator_fc(
                self[WAVEFORM_FREQ_KEY] * 2 * math.pi / self[SAMP_RATE_KEY])
            self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
            self.connect(self._src1, self._src2, self._src)
        else:
            raise RuntimeError("Unknown waveform type")

        self.connect(self._src, self._u)
        self.unlock()

        if self._verbose:
            print "Set baseband modulation to:", waveforms[type]
            if type == gr.GR_SIN_WAVE:
                print "Modulation frequency: %sHz" % (n2s(
                    self[WAVEFORM_FREQ_KEY]), )
                print "Initial phase:", self[WAVEFORM_OFFSET_KEY]
            elif type == "2tone":
                print "Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]), )
                print "Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]), )
            elif type == "sweep":
                print "Sweeping across %sHz to %sHz" % (n2s(
                    -self[WAVEFORM_FREQ_KEY] /
                    2.0), n2s(self[WAVEFORM_FREQ_KEY] / 2.0))
                print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]), )
            print "TX amplitude:", self[AMPLITUDE_KEY]
Esempio n. 4
0
    def __init__(self, vocoder, lo_freq, audio_rate, if_rate):

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

        c4fm = op25_c4fm_mod.p25_mod_bf(output_sample_rate=audio_rate,
                                 log=False,
                                 verbose=True)
        interp_factor = if_rate / audio_rate

        low_pass = 2.88e3
        interp_taps = gr.firdes.low_pass(1.0, if_rate, low_pass, low_pass * 0.1, gr.firdes.WIN_HANN)

        interpolator = gr.interp_fir_filter_fff (int(interp_factor), interp_taps)

        max_dev = 12.5e3
        k = 2 * math.pi * max_dev / if_rate

        adjustment = 1.5   # adjust for proper c4fm deviation level

        modulator = gr.frequency_modulator_fc (k * adjustment)

        # Local oscillator
        lo = gr.sig_source_c (if_rate,        # sample rate
                              gr.GR_SIN_WAVE, # waveform type
                              lo_freq,        #frequency
                              1.0,            # amplitude
                              0)              # DC Offset
        mixer = gr.multiply_cc ()

        self.connect (vocoder, c4fm, interpolator, modulator, (mixer, 0))
        self.connect (lo, (mixer, 1))
        self.connect (mixer, self)
Esempio n. 5
0
    def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
        """
        Narrow Band FM Transmitter.

        Takes a single float input stream of audio samples in the range [-1,+1]
        and produces a single FM modulated complex baseband output.

        @param audio_rate: sample rate of audio stream, >= 16k
        @type audio_rate: integer
        @param quad_rate: sample rate of output stream
        @type quad_rate: integer
        @param tau: preemphasis time constant (default 75e-6)
        @type tau: float
        @param max_dev: maximum deviation in Hz (default 5e3)
        @type max_dev: float

        quad_rate must be an integer multiple of audio_rate.
        """

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

        # FIXME audio_rate and quad_rate ought to be exact rationals
        audio_rate = int(audio_rate)
        quad_rate = int(quad_rate)

        if quad_rate % audio_rate != 0:
            raise ValueError, "quad_rate is not an integer multiple of audio_rate"

        do_interp = audio_rate != quad_rate

        if do_interp:
            interp_factor = quad_rate / audio_rate
            interp_taps = optfir.low_pass(
                interp_factor,  # gain
                quad_rate,  # Fs
                4500,  # passband cutoff
                7000,  # stopband cutoff
                0.1,  # passband ripple dB
                40)  # stopband atten dB

            #print "len(interp_taps) =", len(interp_taps)
            self.interpolator = gr.interp_fir_filter_fff(
                interp_factor, interp_taps)

        self.preemph = fm_preemph(quad_rate, tau=tau)

        k = 2 * math.pi * max_dev / quad_rate
        self.modulator = gr.frequency_modulator_fc(k)

        if do_interp:
            self.connect(self, self.interpolator, self.preemph, self.modulator,
                         self)
        else:
            self.connect(self, self.preemph, self.modulator, self)
Esempio n. 6
0
    def __init__(self, subdev_spec, freq, subdev_gain, filename, delay):

        gr.top_block.__init__(self)

        # data sink and sink rate
        u = usrp.sink_c()

        # important vars (to be calculated from USRP when available
        dac_rate = u.dac_rate()
        usrp_rate = 320e3
        usrp_interp = int(dac_rate // usrp_rate)
        channel_rate = 32e3
        interp_factor = int(usrp_rate // channel_rate)

        # open the pcap source
        pcap = op25.pcap_source_b(filename, delay)
        #        pcap = gr.glfsr_source_b(16)

        # convert octets into dibits
        bits_per_symbol = 2
        unpack = gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)

        # modulator
        c4fm = p25_mod_bf(output_rate=channel_rate)

        # setup low pass filter + interpolator
        low_pass = 2.88e3
        interp_taps = gr.firdes.low_pass(1.0, channel_rate, low_pass,
                                         low_pass * 0.1, gr.firdes.WIN_HANN)
        interpolator = gr.interp_fir_filter_fff(int(interp_factor),
                                                interp_taps)

        # frequency modulator
        max_dev = 12.5e3
        k = 2 * math.pi * max_dev / usrp_rate
        adjustment = 1.5  # adjust for proper c4fm deviation level
        fm = gr.frequency_modulator_fc(k * adjustment)

        # signal gain
        gain = gr.multiply_const_cc(4000)

        # configure USRP
        if subdev_spec is None:
            subdev_spec = usrp.pick_tx_subdevice(u)
        u.set_mux(usrp.determine_tx_mux_value(u, subdev_spec))
        self.db = usrp.selected_subdev(u, subdev_spec)
        print "Using TX d'board %s" % (self.db.side_and_name(), )
        u.set_interp_rate(usrp_interp)

        if gain is None:
            g = self.db.gain_range()
            gain = float(g[0] + g[1]) / 2
        self.db.set_gain(self.db.gain_range()[0])
        u.tune(self.db.which(), self.db, freq)
        self.db.set_enable(True)

        self.connect(pcap, unpack, c4fm, interpolator, fm, gain, u)
Esempio n. 7
0
    def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3):
        """
        Wide Band FM Transmitter.

        Takes a single float input stream of audio samples in the range [-1,+1]
        and produces a single FM modulated complex baseband output.

        @param audio_rate: sample rate of audio stream, >= 16k
        @type audio_rate: integer
        @param quad_rate: sample rate of output stream
        @type quad_rate: integer
        @param tau: preemphasis time constant (default 75e-6)
        @type tau: float
        @param max_dev: maximum deviation in Hz (default 75e3)
        @type max_dev: float

        quad_rate must be an integer multiple of audio_rate.
        """
        gr.hier_block2.__init__(
            self,
            "wfm_tx",
            gr.io_signature(1, 1, gr.sizeof_float),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        # FIXME audio_rate and quad_rate ought to be exact rationals
        audio_rate = int(audio_rate)
        quad_rate = int(quad_rate)

        if quad_rate % audio_rate != 0:
            raise ValueError, "quad_rate is not an integer multiple of audio_rate"

        do_interp = audio_rate != quad_rate

        if do_interp:
            interp_factor = quad_rate / audio_rate
            interp_taps = optfir.low_pass(
                interp_factor,  # gain
                quad_rate,  # Fs
                16000,  # passband cutoff
                18000,  # stopband cutoff
                0.1,  # passband ripple dB
                40)  # stopband atten dB

            print "len(interp_taps) =", len(interp_taps)
            self.interpolator = gr.interp_fir_filter_fff(
                interp_factor, interp_taps)

        self.preemph = fm_preemph(quad_rate, tau=tau)

        k = 2 * math.pi * max_dev / quad_rate
        self.modulator = gr.frequency_modulator_fc(k)

        if do_interp:
            self.connect(self, self.interpolator, self.preemph, self.modulator,
                         self)
        else:
            self.connect(self, self.preemph, self.modulator, self)
Esempio n. 8
0
def test_freqmod() :
    from cmath import phase, pi, rect
    tb = gr.top_block()
    src = gr.vector_source_f((1,)*1000)
    mod = gr.frequency_modulator_fc(pi)
    sink = gr.vector_sink_c()
    tb.connect(src, mod, sink)
    tb.run()
    d = sink.data()
    print "\n".join(["% 1.3f % 1.3f"%((i*1j).real, (i*1j).imag) for i in d])
Esempio n. 9
0
    def __init__(self, subdev_spec, freq, subdev_gain, filename, delay):

        gr.top_block.__init__ (self)

        # data sink and sink rate
        u = usrp.sink_c()

        # important vars (to be calculated from USRP when available
        dac_rate = u.dac_rate()
        usrp_rate = 320e3
        usrp_interp = int(dac_rate // usrp_rate)
        channel_rate = 32e3
        interp_factor = int(usrp_rate // channel_rate)

        # open the pcap source
        pcap = op25.pcap_source_b(filename, delay)
#        pcap = gr.glfsr_source_b(16)

        # convert octets into dibits
        bits_per_symbol = 2
        unpack = gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST)

        # modulator
        c4fm = p25_mod_bf(output_rate=channel_rate)

        # setup low pass filter + interpolator
        low_pass = 2.88e3
        interp_taps = gr.firdes.low_pass(1.0, channel_rate, low_pass, low_pass * 0.1, gr.firdes.WIN_HANN)
        interpolator = gr.interp_fir_filter_fff (int(interp_factor), interp_taps)

        # frequency modulator
        max_dev = 12.5e3
        k = 2 * math.pi * max_dev / usrp_rate
        adjustment = 1.5   # adjust for proper c4fm deviation level
        fm = gr.frequency_modulator_fc(k * adjustment)

        # signal gain
        gain = gr.multiply_const_cc(4000)

        # configure USRP
        if subdev_spec is None:
            subdev_spec = usrp.pick_tx_subdevice(u)
        u.set_mux(usrp.determine_tx_mux_value(u, subdev_spec))
        self.db = usrp.selected_subdev(u, subdev_spec)
        print "Using TX d'board %s" % (self.db.side_and_name(),)
        u.set_interp_rate(usrp_interp)

        if gain is None:
            g = self.db.gain_range()
            gain = float(g[0] + g[1]) / 2
        self.db.set_gain(self.db.gain_range()[0])
        u.tune(self.db.which(), self.db, freq)
        self.db.set_enable(True)

        self.connect(pcap, unpack, c4fm, interpolator, fm, gain, u)
Esempio n. 10
0
def test_freqmod():
    from cmath import phase, pi, rect
    tb = gr.top_block()
    src = gr.vector_source_f((1, ) * 1000)
    mod = gr.frequency_modulator_fc(pi)
    sink = gr.vector_sink_c()
    tb.connect(src, mod, sink)
    tb.run()
    d = sink.data()
    print "\n".join(
        ["% 1.3f % 1.3f" % ((i * 1j).real, (i * 1j).imag) for i in d])
Esempio n. 11
0
 def test_fm_001 (self):
     pi = math.pi
     sensitivity = pi/4
     src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0)
     running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0)
     expected_result = tuple ([sincos (x) for x in running_sum])
     src = gr.vector_source_f (src_data)
     op = gr.frequency_modulator_fc (sensitivity)
     dst = gr.vector_sink_c ()
     self.tb.connect (src, op)
     self.tb.connect (op, dst)
     self.tb.run ()
     result_data = dst.data ()
     self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5)
Esempio n. 12
0
    def __init__(self, bt = 0.3, samples_per_symbol = 2, ti_adj=False):
        gr.hier_block2.__init__(self, "msk_demod",
                gr.io_signature(1, 1, gr.sizeof_char),
                gr.io_signature(1, 1, gr.sizeof_gr_complex))

        self.sps = 2
        self.bt = 0.35
        self.mu = 0.5
        self.gain_mu = 0.175
        self.freq_error = 0.0
        self.omega_relative_limit = 0.005

        self.omega = self.sps * (1 + self.freq_error)
        self.gain_omega = .25 * self.gain_mu * self.gain_mu        # critically damped

        ntaps = 4 * samples_per_symbol              # up to 3 bits in filter at once
        sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2

        # Turn it into NRZ data.
        self.unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        self.nrz = digital.chunks_to_symbols_bf([-1, 1], 1) # note could also invert bits here

        # Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
        self.gaussian_taps = gr.firdes.gaussian(1, samples_per_symbol, bt, ntaps)

        self.sqwave = (1,) * samples_per_symbol       # rectangular window
        self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
        self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps)

        # the clock recovery block tracks the symbol clock and resamples as needed.
        # the output of the block is a stream of soft symbols (float)
        self.clock_recovery = digital.clock_recovery_mm_ff(self.omega, self.gain_omega,
                                                               self.mu, self.gain_mu,
                                                               self.omega_relative_limit)

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

        # TODO: this is hardcoded, how to figure out this value?
        self.offset = gr.add_const_vff((-.5, ))

        # CC430 RF core is inverted with respect to USRP for some reason
        self.invert = gr.multiply_const_vff((-1, ))

        # Connect & Initialize base class
        if ti_adj:
            self.connect(self, self.unpack, self.nrz, self.invert, self.offset, self.gaussian_filter, self.fmmod, self)
        else:
            self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self)
Esempio n. 13
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 bt=_def_bt,
                 verbose=_def_verbose,
                 log=_def_log):

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

        samples_per_symbol = int(samples_per_symbol)
        self._samples_per_symbol = samples_per_symbol
        self._bt = bt
        self._differential = False

        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,))

	ntaps = 4 * samples_per_symbol			# up to 3 bits in filter at once
	sensitivity = (pi / 2) / samples_per_symbol	# phase change per bit = pi / 2

	# Turn it into NRZ data.
	#self.nrz = digital.bytes_to_syms()
        self.unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        self.nrz = digital.chunks_to_symbols_bf([-1, 1], 1)

	# Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
	self.gaussian_taps = gr.firdes.gaussian(
		1,		       # gain
		samples_per_symbol,    # symbol_rate
		bt,		       # bandwidth * symbol time
		ntaps	               # number of taps
		)

	self.sqwave = (1,) * samples_per_symbol       # rectangular window
	self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
	self.gaussian_filter = filter.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 & Initialize base class
	self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self)
 def test_fm_001 (self):
     pi = math.pi
     sensitivity = pi/4
     src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0)
     running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0)
     expected_result = tuple ([sincos (x) for x in running_sum])
     src = gr.vector_source_f (src_data)
     op = gr.frequency_modulator_fc (sensitivity)
     dst = gr.vector_sink_c ()
     self.tb.connect (src, op)
     self.tb.connect (op, dst)
     self.tb.run ()
     result_data = dst.data ()
     self.assertComplexTuplesAlmostEqual (expected_result, result_data)
Esempio n. 15
0
    def __init__(self, fg, spb=8, bt=0.3):
        """
	Hierarchical block for cc1k FSK modulation.

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

	@param fg: flow graph
	@type fg: flow graph
	@param spb: samples per baud >= 2
	@type spb: integer
	@param bt: Gaussian filter bandwidth * symbol time
	@type bt: float
	"""
        if not isinstance(spb, int) or spb < 2:
            raise TypeError, "sbp must be an integer >= 2"
        self.spb = spb

        #sensitivity = (pi / 2) / spb	# phase change per bit = pi / 2
        sensitivity = 3.5 * pi / spb

        # Turn it into NRZ data.
        self.nrz = gr.bytes_to_syms()

        # Manchester Encode the whole thing and upsample by 8
        self.manchester = ucla.manchester_ff()

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

        # Connect
        fg.connect(self.nrz, self.manchester)
        fg.connect(self.manchester, self.fmmod)

        #filesink1 = gr.file_sink(gr.sizeof_float, 'nrz.dat')
        #fg.connect(self.nrz, filesink1)
        #filesink = gr.file_sink(gr.sizeof_float, 'manchester.dat')
        #fg.connect(self.manchester, filesink)

        # Initialize base class
        gr.hier_block.__init__(self, fg, self.nrz, self.fmmod)
Esempio n. 16
0
    def __init__(self, fg, spb = 8, bt = 0.3):
        """
	Hierarchical block for cc1k FSK modulation.

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

	@param fg: flow graph
	@type fg: flow graph
	@param spb: samples per baud >= 2
	@type spb: integer
	@param bt: Gaussian filter bandwidth * symbol time
	@type bt: float
	"""
        if not isinstance(spb, int) or spb < 2:
            raise TypeError, "sbp must be an integer >= 2"
        self.spb = spb

	#sensitivity = (pi / 2) / spb	# phase change per bit = pi / 2
        sensitivity = 3.5*pi / spb
        
	# Turn it into NRZ data.
	self.nrz = gr.bytes_to_syms()

        # Manchester Encode the whole thing and upsample by 8
        self.manchester = ucla.manchester_ff()

	# FM modulation
	self.fmmod = gr.frequency_modulator_fc(sensitivity)
		
	# Connect
	fg.connect(self.nrz, self.manchester)
        fg.connect(self.manchester, self.fmmod)

        #filesink1 = gr.file_sink(gr.sizeof_float, 'nrz.dat')
        #fg.connect(self.nrz, filesink1)
        #filesink = gr.file_sink(gr.sizeof_float, 'manchester.dat')
        #fg.connect(self.manchester, filesink)
        
	# Initialize base class
	gr.hier_block.__init__(self, fg, self.nrz, self.fmmod)
Esempio n. 17
0
    def __init__(self, vocoder, lo_freq, audio_rate, if_rate):

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

        c4fm = op25_c4fm_mod.p25_mod_bf(output_sample_rate=audio_rate,
                                        log=False,
                                        verbose=True)
        interp_factor = if_rate / audio_rate

        low_pass = 2.88e3
        interp_taps = gr.firdes.low_pass(1.0, if_rate, low_pass,
                                         low_pass * 0.1, gr.firdes.WIN_HANN)

        interpolator = gr.interp_fir_filter_fff(int(interp_factor),
                                                interp_taps)

        max_dev = 12.5e3
        k = 2 * math.pi * max_dev / if_rate

        adjustment = 1.5  # adjust for proper c4fm deviation level

        modulator = gr.frequency_modulator_fc(k * adjustment)

        # Local oscillator
        lo = gr.sig_source_c(
            if_rate,  # sample rate
            gr.GR_SIN_WAVE,  # waveform type
            lo_freq,  #frequency
            1.0,  # amplitude
            0)  # DC Offset
        mixer = gr.multiply_cc()

        self.connect(vocoder, c4fm, interpolator, modulator, (mixer, 0))
        self.connect(lo, (mixer, 1))
        self.connect(mixer, self)
Esempio n. 18
0
    def __init__(self, samplerate, bits_per_sec, fftlen):
		gr.hier_block2.__init__(self, "gmsk_sync",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

		#this is just the old square-and-fft method
		#ais.freqest is simply looking for peaks spaced bits-per-sec apart
		self.square = gr.multiply_cc(1)
		self.fftvect = gr.stream_to_vector(gr.sizeof_gr_complex, fftlen)
		self.fft = gr.fft_vcc(fftlen, True, window.rectangular(fftlen), True)
		self.freqest = ais.freqest(int(samplerate), int(bits_per_sec), fftlen)
		self.repeat = gr.repeat(gr.sizeof_float, fftlen)
		self.fm = gr.frequency_modulator_fc(-1.0/(float(samplerate)/(2*pi)))
		self.mix = gr.multiply_cc(1)

		self.connect(self, (self.square, 0))
		self.connect(self, (self.square, 1))
		#this is the feedforward branch
		self.connect(self, (self.mix, 0))
		#this is the feedback branch
		self.connect(self.square, self.fftvect, self.fft, self.freqest, self.repeat, self.fm, (self.mix, 1))
		#and this is the output
		self.connect(self.mix, self)
Esempio n. 19
0
  def __init__(self, noise_voltage, sensitivity):
    gr.hier_block2.__init__(self, "variable_awgn_channel", 
        gr.io_signature(1,1,gr.sizeof_gr_complex),
        gr.io_signature(1,1,gr.sizeof_gr_complex))

    self.noise_adder = gr.add_cc()
    self.noise = gr.noise_source_c(gr.GR_GAUSSIAN,noise_voltage)
    self.noise_amp = gr.multiply_cc()
    self.offset = gr.frequency_modulator_fc(sensitivity)
    self.mixer_offset = gr.multiply_cc()

    self.connect(self, (self.mixer_offset,0))
    self.connect(self.offset,(self.mixer_offset,1))
    self.connect(self.mixer_offset, (self.noise_adder,1))
    self.connect(self.noise, (self.noise_amp,0))
    self.connect(self.noise_amp, (self.noise_adder,0))
    self.connect(self.noise_adder, self)

    try:
        gr.hier_block.update_var_names(self, "var_awgn_channel", vars())
        gr.hier_block.update_var_names(self, "var_awgn_channel", vars(self))
    except:
        pass
Esempio n. 20
0
    def __init__(self, bt=0.3, samples_per_symbol=2):
        gr.hier_block2.__init__(self, "msk_demod",
                                gr.io_signature(1, 1, gr.sizeof_char),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex))

        ntaps = 4 * samples_per_symbol  # up to 3 bits in filter at once
        sensitivity = (pi /
                       2) / samples_per_symbol  # phase change per bit = pi / 2

        # Turn it into NRZ data.
        self.unpack = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        self.nrz = digital.chunks_to_symbols_bf(
            [-1, 1], 1)  # note could also invert bits here

        # Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
        self.gaussian_taps = gr.firdes.gaussian(1, samples_per_symbol, bt,
                                                ntaps)

        self.sqwave = (1, ) * samples_per_symbol  # rectangular window
        self.taps = numpy.convolve(numpy.array(self.gaussian_taps),
                                   numpy.array(self.sqwave))
        self.gaussian_filter = filter.interp_fir_filter_fff(
            samples_per_symbol, self.taps)

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

        # TODO: this is hardcoded, how to figure out this value?
        self.offset = gr.add_const_vff((-.5, ))

        # CC430 RF core is inverted with respect to USRP for some reason
        self.invert = gr.multiply_const_vff((-1, ))

        # Connect & Initialize base class
        self.connect(self, self.unpack, self.nrz, self.invert, self.offset,
                     self.gaussian_filter, self.fmmod, self)
Esempio n. 21
0
    def __init__(self, noise_voltage, sensitivity):
        gr.hier_block2.__init__(self, "variable_awgn_channel",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex))

        self.noise_adder = gr.add_cc()
        self.noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_voltage)
        self.noise_amp = gr.multiply_cc()
        self.offset = gr.frequency_modulator_fc(sensitivity)
        self.mixer_offset = gr.multiply_cc()

        self.connect(self, (self.mixer_offset, 0))
        self.connect(self.offset, (self.mixer_offset, 1))
        self.connect(self.mixer_offset, (self.noise_adder, 1))
        self.connect(self.noise, (self.noise_amp, 0))
        self.connect(self.noise_amp, (self.noise_adder, 0))
        self.connect(self.noise_adder, self)

        try:
            gr.hier_block.update_var_names(self, "var_awgn_channel", vars())
            gr.hier_block.update_var_names(self, "var_awgn_channel",
                                           vars(self))
        except:
            pass
Esempio n. 22
0
	def __init__(self, dab_params, rx_params, 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
		"""

		dp = dab_params
		rp = rx_params
		
		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 = dab_swig.moving_sum_cc(dp.cp_length)
		self.ffs_arg = gr.complex_to_arg()
		self.ffs_sample_and_average = dab_swig.ofdm_ffs_sample(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, dp.sample_rate)
		if rp.correct_ffe:
			self.ffs_delay_input_for_correction = gr.delay(gr.sizeof_gr_complex, dp.symbol_length*rp.symbols_for_ffs_estimation) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself
			self.ffs_delay_frame_start = gr.delay(gr.sizeof_char, dp.symbol_length*rp.symbols_for_ffs_estimation) # sample the value at the end of the symbol ..
			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_arg, (self.ffs_sample_and_average, 0))
		self.connect(self.ns_detect, (self.ffs_sample_and_average, 1))

		if rp.correct_ffe: 
			# do the correction
			self.connect(self.ffs_sample_and_average, 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.ns_detect, self.ffs_delay_frame_start, (self, 1))
		else: 
			# just patch the signal through
			self.connect(self.ffs_sample_and_average, gr.null_sink(gr.sizeof_float))
			self.connect(self.input, (self,0))
			# frame start still needed ..
			self.connect(self.ns_detect, (self,1))

		if debug:
			self.connect(self.ffs_sample_and_average, 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"))
    def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, carrier_map_bin, nc_filter, logging=False):
        gr.hier_block2.__init__(self, "ofdm_receiver",
                        gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                        gr.io_signature4(4, 4, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char, gr.sizeof_char, gr.sizeof_float)) # Output signature

        self._fft_length = fft_length
        self._occupied_tones = occupied_tones
        self._cp_length = cp_length
        self._nc_filter = nc_filter
        self._carrier_map_bin = carrier_map_bin

        win = [1 for i in range(self._fft_length)]

        self.initialize(ks, self._carrier_map_bin)

        SYNC = "pn"
        if SYNC == "ml":
            nco_sensitivity = -1.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, self._ks0time, logging)
        elif SYNC == "pn":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pn.ofdm_sync_pn(fft_length, cp_length, logging)
        elif SYNC == "pnac":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, self._ks0time, logging)
        elif SYNC == "fixed":                                             # for testing only; do not user over the air
            self.chan_filt = gr.multiply_const_cc(1.0)                    # remove filter and filter delay for this
            nsymbols = 18                                                 # enter the number of symbols per packet
            freq_offset = 0.0                                             # if you use a frequency offset, enter it here
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, freq_offset, logging)

        self.reset_filter()


        # TODO: why? Create a delay line, linklab
        self.delay = gr.delay(gr.sizeof_gr_complex, fft_length)

        self.nco = gr.frequency_modulator_fc(nco_sensitivity)         # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = flex.ofdm_sampler(fft_length, fft_length+cp_length)
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
        self.ofdm_frame_acq = flex.ofdm_frame_acquisition(self._occupied_tones, self._fft_length,
                                                                                                        self._cp_length, self._ks[0], 1)

        if self._nc_filter:
            print '\nMulti-band Filter Turned ON!'
            self.ncofdm_filt = ncofdm_filt(self._fft_length, self._occupied_tones, self._carrier_map_bin)
            self.connect(self, self.chan_filt, self.ncofdm_filt)
            self.connect(self.ncofdm_filt, self.ofdm_sync)             # into the synchronization alg.
            self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1))   # use sync freq. offset output to derotate input signal
            self.connect(self.ncofdm_filt, self.delay, (self.sigmix,0))                 # signal to be derotated
        else :
            print '\nMulti-band Filter Turned OFF!'
            self.connect(self, self.chan_filt)
            self.connect(self.chan_filt, self.ofdm_sync)             # into the synchronization alg.
            self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1))   # use sync freq. offset output to derotate input signal
            self.connect(self.chan_filt, self.delay, (self.sigmix,0))                 # signal to be derotated

        self.connect(self.sigmix, (self.sampler,0))                   # sample off timing signal detected in sync alg
        self.connect((self.ofdm_sync,1), (self.sampler,1))            # timing signal to sample at

        self.connect((self.sampler,0), self.fft_demod)                # send derotated sampled signal to FFT
        self.connect(self.fft_demod, (self.ofdm_frame_acq,0))         # find frame start and equalize signal
        # TODO: do we need a char delay for the timing signal?
        self.connect((self.sampler,1), (self.ofdm_frame_acq,1))       # send timing signal to signal frame start

        # TODO: reconnect properly
        self.connect((self.ofdm_frame_acq,0), (self,0))               # finished with fine/coarse freq correction,
        self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char,1), (self,1))

        self.connect((self.ofdm_frame_acq,1), (self,2))               # frame and symbol timing, and equalization
        self.connect((self.ofdm_frame_acq,2), (self,3))               # snr estimates

        if logging:
            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-chan_filt_c.dat"))
            self.connect(self.ncofdm_filt, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-ncofdm_filt_c.dat"))
            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-nco_c.dat"))
            self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-fft_out_c.dat"))
            self.connect(self.ofdm_frame_acq, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "flex_ofdm_recv-frame_acq_data_c.dat"))
            self.connect((self.ofdm_frame_acq,3), gr.keep_one_in_n(gr.sizeof_float*occupied_tones, 32), gr.file_sink(gr.sizeof_float*occupied_tones, "flex_ofdm_recv-frame_acq_gain_f.dat"))
            self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "flex_ofdm_recv-frame_acq_signal_b.dat"))
            self.connect((self.ofdm_frame_acq,2), gr.file_sink(gr.sizeof_float, "flex_ofdm_recv-frame_acq_snr_f.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-sampler_data_c.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "flex_ofdm_recv-sampler_data_c.dat"))
            self.connect((self.sampler, 1), gr.file_sink(1*fft_length, "flex_ofdm_recv-sampler_signal_b.dat"))
            self.connect((self.ofdm_sync, 1), gr.file_sink(1, "flex_ofdm_recv-sync_b.dat"))
            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "flex_ofdm_recv-sigmix_c.dat"))
        else:
            self.connect((self.ofdm_frame_acq,3), gr.null_sink(gr.sizeof_float*self._occupied_tones))
Esempio n. 24
0
  def __init__(self, p, logging=False):
    """
    Hierarchical block for receiving OFDM symbols.

    The input is the complex modulated signal at baseband.
    Synchronized packets are sent back to the demodulator.

    @param params: Raw OFDM parameters
    @type  params: ofdm_params
    @param logging: turn file logging on or off
    @type  logging: bool
    """
    from numpy import fft

    gr.hier_block2.__init__(self, "ofdm_receiver",
      gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
      gr.io_signature2(2, 2, gr.sizeof_gr_complex*p.occupied_tones, gr.sizeof_char)) # Output signature

    # low-pass filter the input channel
    bw = (float(p.occupied_tones) / float(p.fft_length)) / 2.0
    tb = bw*0.08
    lpf_coeffs = gr.firdes.low_pass (1.0,                     # gain
                                     1.0,                     # sampling rate
                                     bw+tb,                   # midpoint of trans. band
                                     tb,                      # width of trans. band
                                     gr.firdes.WIN_HAMMING)   # filter type
    lpf = gr.fft_filter_ccc(1, lpf_coeffs)
    #lpf = gr.add_const_cc(0.0)  ## no-op low-pass-filter
    self.connect(self, lpf)

    # to the synchronization algorithm
    #from gnuradio import blks2impl
    #from gnuradio.blks2impl.ofdm_sync_pn import ofdm_sync_pn
    sync = ofdm_sync(p.fft_length, p.cp_length, p.half_sync, logging)
    self.connect(lpf, sync)

    # correct for fine frequency offset computed in sync (up to +-pi/fft_length)
    # NOTE: frame_acquisition can correct coarse freq offset (i.e. kpi/fft_length)
    if p.half_sync:
      nco_sensitivity = 2.0/p.fft_length
    else:
      nco_sensitivity = 1.0/(p.fft_length + p.cp_length)
    #nco_sensitivity = 0

    nco = gr.frequency_modulator_fc(nco_sensitivity)
    sigmix = gr.multiply_cc()

    self.connect((sync,0), (sigmix,0))
    self.connect((sync,1), nco, (sigmix,1))

    # sample at symbol boundaries
    # NOTE: (sync,2) indicates the first sample of the symbol!
    sampler = raw.ofdm_sampler(p.fft_length, p.fft_length+p.cp_length, timeout=100)
    self.connect(sigmix, (sampler,0))
    self.connect((sync,2), (sampler,1))  # timing signal to sample at

    # fft on the symbols
    win = [1 for i in range(p.fft_length)]
    # see gr_fft_vcc_fftw that it works differently if win = []
    fft = gr.fft_vcc(p.fft_length, True, win, True)
    self.connect((sampler,0), fft)

    # use the preamble to correct the coarse frequency offset and initial equalizer
    frame_acq = raw.ofdm_frame_acquisition(p.fft_length, p.cp_length, p.preambles)

    self.frame_acq = frame_acq
    self.connect(fft, (frame_acq,0))
    self.connect((sampler,1), (frame_acq,1))

    self.connect((frame_acq,0), (self,0))  # finished with fine/coarse freq correction
    self.connect((frame_acq,1), (self,1))  # frame and symbol timing

    if logging:
      self.connect(lpf,
                   gr.file_sink(gr.sizeof_gr_complex, "rx-filt.dat"))
      self.connect(fft,
                   gr.file_sink(gr.sizeof_gr_complex*p.fft_length, "rx-fft.dat"))
      self.connect((frame_acq,0),
                   gr.file_sink(gr.sizeof_gr_complex*p.occupied_tones, "rx-acq.dat"))
      self.connect((frame_acq,1),
                   gr.file_sink(1, "rx-detect.datb"))
      self.connect(sampler,
                   gr.file_sink(gr.sizeof_gr_complex*p.fft_length, "rx-sampler.dat"))
      self.connect(sigmix,
                   gr.file_sink(gr.sizeof_gr_complex, "rx-sigmix.dat"))
      self.connect(nco,
                   gr.file_sink(gr.sizeof_gr_complex, "rx-nco.dat"))
    def __init__(self, fg,
                 samples_per_symbol=_def_samples_per_symbol,
                 bt=_def_bt,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for Gaussian Minimum Shift Key (GMSK)
	modulation.

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

	@param fg: flow graph
	@type fg: flow graph
	@param samples_per_symbol: samples per baud >= 2
	@type samples_per_symbol: integer
	@param bt: Gaussian filter bandwidth * symbol time
	@type bt: float
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modualtion data to files?
        @type debug: bool       
	"""

        self._fg = fg
        self._samples_per_symbol = samples_per_symbol
        self._bt = bt

        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,))

	ntaps = 4 * samples_per_symbol			# up to 3 bits in filter at once
	sensitivity = (pi / 2) / samples_per_symbol	# phase change per bit = pi / 2

	# Turn it into NRZ data.
	self.nrz = gr.bytes_to_syms()

	# Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
	self.gaussian_taps = gr.firdes.gaussian(
		1,		       # gain
		samples_per_symbol,    # symbol_rate
		bt,		       # bandwidth * symbol time
		ntaps	               # number of taps
		)

	self.sqwave = (1,) * samples_per_symbol       # rectangular window
	self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
	self.gaussian_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 & Initialize base class
	self._fg.connect(self.nrz, self.gaussian_filter, self.fmmod)
	gr.hier_block.__init__(self, self._fg, self.nrz, self.fmmod)
Esempio n. 26
0
    def __init__(self, frame, panel, vbox, argv):
        stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)

        parser = OptionParser(option_class=eng_option)
        parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, help="select USRP Tx side A or B")
        parser.add_option(
            "-f",
            "--freq",
            type="eng_float",
            default=107.2e6,
            help="set Tx frequency to FREQ [required]",
            metavar="FREQ",
        )
        parser.add_option("--wavfile", type="string", default=None, help="open .wav audio file FILE")
        parser.add_option("--xml", type="string", default="rds_data.xml", help="open .xml RDS data FILE")
        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            sys.exit(1)

        usrp_interp = 500
        self.u = usrp.sink_c(0, usrp_interp)
        print "USRP Serial: ", self.u.serial_number()
        usrp_rate = self.u.dac_rate() / usrp_interp  # 256 kS/s

        # determine the daughterboard subdevice we're using
        if options.tx_subdev_spec is None:
            options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
        self.u.set_mux(usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec))
        self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
        print "Using d'board", self.subdev.side_and_name()

        # set max Tx gain, tune frequency and enable transmitter
        gain = self.subdev.gain_range()[1]
        self.subdev.set_gain(gain)
        print "Gain set to", gain
        if self.u.tune(self.subdev.which(), self.subdev, options.freq):
            print "Tuned to", options.freq / 1e6, "MHz"
        else:
            sys.exit(1)
        self.subdev.set_enable(True)

        # open wav file containing floats in the [-1, 1] range, repeat
        if options.wavfile is None:
            print "Please provide a wavfile to transmit! Exiting\n"
            sys.exit(1)
        self.src = gr.wavfile_source(options.wavfile, True)
        nchans = self.src.channels()
        sample_rate = self.src.sample_rate()
        bits_per_sample = self.src.bits_per_sample()
        print nchans, "channels,", sample_rate, "samples/sec,", bits_per_sample, "bits/sample"

        # resample to usrp rate
        self.resample_left = blks2.rational_resampler_fff(usrp_rate, sample_rate)
        self.resample_right = blks2.rational_resampler_fff(usrp_rate, sample_rate)
        self.connect((self.src, 0), self.resample_left)
        self.connect((self.src, 1), self.resample_right)

        # create L+R (mono) and L-R (stereo)
        self.audio_lpr = gr.add_ff()
        self.audio_lmr = gr.sub_ff()
        self.connect(self.resample_left, (self.audio_lpr, 0))
        self.connect(self.resample_left, (self.audio_lmr, 0))
        self.connect(self.resample_right, (self.audio_lpr, 1))
        self.connect(self.resample_right, (self.audio_lmr, 1))

        # low-pass filter for L+R
        audio_lpr_taps = gr.firdes.low_pass(
            0.5,  # gain
            usrp_rate,  # sampling rate
            15e3,  # passband cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING,
        )
        self.audio_lpr_filter = gr.fir_filter_fff(1, audio_lpr_taps)
        self.connect(self.audio_lpr, self.audio_lpr_filter)

        # create pilot tone at 19 kHz
        self.pilot = gr.sig_source_f(
            usrp_rate, gr.GR_SIN_WAVE, 19e3, 5e-2  # sampling rate  # waveform  # frequency
        )  # amplitude

        # upconvert L-R to 38 kHz and band-pass
        self.mix_stereo = gr.multiply_ff()
        audio_lmr_taps = gr.firdes.band_pass(
            80,  # gain
            usrp_rate,  # sampling rate
            38e3 - 15e3,  # low cutoff
            38e3 + 15e3,  # high cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING,
        )
        self.audio_lmr_filter = gr.fir_filter_fff(1, audio_lmr_taps)
        self.connect(self.audio_lmr, (self.mix_stereo, 0))
        self.connect(self.pilot, (self.mix_stereo, 1))
        self.connect(self.pilot, (self.mix_stereo, 2))
        self.connect(self.mix_stereo, self.audio_lmr_filter)

        # create RDS bitstream
        # diff-encode, manchester-emcode, NRZ
        # enforce the 1187.5bps rate
        # pulse shaping filter (matched with receiver)
        # mix with 57kHz carrier (equivalent to BPSK)
        self.rds_enc = rds.data_encoder("rds_data.xml")
        self.diff_enc = gr.diff_encoder_bb(2)
        self.manchester1 = gr.map_bb([1, 2])
        self.manchester2 = gr.unpack_k_bits_bb(2)
        self.nrz = gr.map_bb([-1, 1])
        self.c2f = gr.char_to_float()
        self.rate_enforcer = rds.rate_enforcer(usrp_rate)
        pulse_shaping_taps = gr.firdes.low_pass(
            1,  # gain
            usrp_rate,  # sampling rate
            1.5e3,  # passband cutoff
            2e3,  # transition width
            gr.firdes.WIN_HAMMING,
        )
        self.pulse_shaping = gr.fir_filter_fff(1, pulse_shaping_taps)
        self.bpsk_mod = gr.multiply_ff()
        self.connect(self.rds_enc, self.diff_enc, self.manchester1, self.manchester2, self.nrz, self.c2f)
        self.connect(self.c2f, (self.rate_enforcer, 0))
        self.connect(self.pilot, (self.rate_enforcer, 1))
        self.connect(self.rate_enforcer, (self.bpsk_mod, 0))
        self.connect(self.pilot, (self.bpsk_mod, 1))
        self.connect(self.pilot, (self.bpsk_mod, 2))
        self.connect(self.pilot, (self.bpsk_mod, 3))

        # RDS band-pass filter
        rds_filter_taps = gr.firdes.band_pass(
            50,  # gain
            usrp_rate,  # sampling rate
            57e3 - 3e3,  # low cutoff
            57e3 + 3e3,  # high cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING,
        )
        self.rds_filter = gr.fir_filter_fff(1, rds_filter_taps)
        self.connect(self.bpsk_mod, self.rds_filter)

        # mix L+R, pilot, L-R and RDS
        self.mixer = gr.add_ff()
        self.connect(self.audio_lpr_filter, (self.mixer, 0))
        self.connect(self.pilot, (self.mixer, 1))
        self.connect(self.audio_lmr_filter, (self.mixer, 2))
        self.connect(self.rds_filter, (self.mixer, 3))

        # fm modulation, gain & TX
        max_dev = 75e3
        k = 2 * math.pi * max_dev / usrp_rate  # modulator sensitivity
        self.modulator = gr.frequency_modulator_fc(k)
        self.gain = gr.multiply_const_cc(5e3)
        self.connect(self.mixer, self.modulator, self.gain, self.u)

        # plot an FFT to verify we are sending what we want
        if 1:
            self.fft = fftsink2.fft_sink_f(
                panel, title="Pre FM modulation", fft_size=512 * 4, sample_rate=usrp_rate, y_per_div=20, ref_level=-20
            )
            self.connect(self.mixer, self.fft)
            vbox.Add(self.fft.win, 1, wx.EXPAND)
        if 0:
            self.scope = scopesink2.scope_sink_f(panel, title="RDS encoder output", sample_rate=usrp_rate)
            self.connect(self.rds_enc, self.scope)
            vbox.Add(self.scope.win, 1, wx.EXPAND)
Esempio n. 27
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 sensitivity=_def_sensitivity,
                 bt=_def_bt,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for Gaussian Frequency Shift Key (GFSK)
	modulation.

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

	@param samples_per_symbol: samples per baud >= 2
	@type samples_per_symbol: integer
	@param bt: Gaussian filter bandwidth * symbol time
	@type bt: float
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modualtion data to files?
        @type debug: bool       
	"""

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

        samples_per_symbol = int(samples_per_symbol)
        self._samples_per_symbol = samples_per_symbol
        self._bt = bt
        self._differential = False

        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,))

	ntaps = 4 * samples_per_symbol			# up to 3 bits in filter at once
	#sensitivity = (pi / 2) / samples_per_symbol	# phase change per bit = pi / 2

	# Turn it into NRZ data.
	self.nrz = gr.bytes_to_syms()

	# Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
	self.gaussian_taps = gr.firdes.gaussian(
		1.0,		       # gain
		samples_per_symbol,    # symbol_rate
		bt,		       # bandwidth * symbol time
		ntaps	               # number of taps
		)

	self.sqwave = (1,) * samples_per_symbol       # rectangular window
	self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave))
	self.gaussian_filter = gr.interp_fir_filter_fff(samples_per_symbol, self.taps)

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

	# small amount of output attenuation to prevent clipping USRP sink
	self.amp = gr.multiply_const_cc(0.999)
		
        if verbose:
            self._print_verbage()
         
        if log:
            self._setup_logging()

	# Connect & Initialize base class
	self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self)
Esempio n. 28
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)
Esempio n. 29
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)
Esempio n. 30
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. 31
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)
Esempio n. 32
0
    def __init__(self, freq, subdev_spec, which_USRP, audio_input, debug):
        #gr.hier_block2.__init__(self, "analog_transmit_path",
        #                        gr.io_signature(0, 0, 0), #input signature
        #                        gr.io_signature(0, 0, 0)) #output signature
        
        gr.top_block.__init__(self)
        self.DEBUG = debug
        self.freq = freq
        #self.freq = 462562500
        # audio_input="hw:0"

        #Formerly from XML
        self.tx_usrp_pga_gain_scaling = 1.0
        self.tx_power = 1
        self.tx_mod_type = 'fm'
        self.tx_freq_deviation = 2.5e3
        self.tx_base_band_bw = 5e3
           
        ##################  USRP settings  ###################
        r = gr.enable_realtime_scheduling ()
        # acquire USRP via USB 2.0

        #self.u = usrp.sink_c(fusb_block_size=1024,
        #                     fusb_nblocks=4,
        #                     which=which_USRP)
	self.u = uhd.single_usrp_sink(
			device_addr="",
			io_type=uhd.io_type_t.COMPLEX_FLOAT32,
			num_channels=1,
			)
                                             
        # get D/A converter sampling rate
        #self.dac_rate = self.u.dac_rate()          #128 MS/s
        self.dac_rate = 128e6          #128 MS/s
        if self.DEBUG:
            print "    Tx Path DAC rate:      %d" %(self.dac_rate)
 
        #System digital sample rate setting
        self.audio_rate = 16e3
        self._gr_interp = 16
        self.max_gr_interp_rate = 40
        self._usrp_interp = 500
        self.gr_rate = self.dac_rate / self._usrp_interp
        self._gr_decim = 1

        if self.DEBUG:
            print "    usrp interp: ", self._usrp_interp
            print "    gr interp: ", self._gr_interp
            print "    gr rate1:  ", self.gr_rate
            print "    gr decim: ", self._gr_decim
            print "    audio rate: ", self.audio_rate

        # set USRP interplation ratio
        #self.u.set_interp_rate(self._usrp_interp)   
        self.u.set_samp_rate(self.gr_rate)

        # set USRP daughterboard subdevice
        #if subdev_spec is None:
        #    subdev_spec = usrp.pick_tx_subdevice(self.u)
        #self.u.set_mux(usrp.determine_tx_mux_value(self.u, subdev_spec))
        #self.subdev = usrp.selected_subdev(self.u, subdev_spec)
	self.u.set_antenna("TX/RX")

        #if self.DEBUG:
        #    print "    TX Path use daughterboard:  %s"    % (self.subdev.side_and_name())
       
         
        # Set center frequency of USRP
        """
        Set the center frequency we're interested in.
        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital up converter.
        """
        assert(self.freq != None)
        #r = self.u.tune(self.subdev.which(), self.subdev, self.freq)
        r = self.u.set_center_freq(self.freq, 0)

        if self.DEBUG:
            if r:
                print "    Tx Frequency: %s" %(eng_notation.num_to_str(self.freq))
            else:
                print "----Failed to set Tx frequency to %s" % (eng_notation.num_to_str(self.freq),)
                raise ValueError
        
            
        # Set the USRP Tx PGA gain, (Note that on the RFX cards this is a nop.)  
        # subdev.set_gain(subdev.gain_range()[1])    # set max Tx gain      
        #g = self.subdev.gain_range()
        g = self.u.get_gain_range(0)
        #_tx_usrp_gain_range = g[1]-g[0]
        _tx_usrp_gain_range = g
        #_tx_usrp_gain = g[0] + _tx_usrp_gain_range * self.tx_usrp_pga_gain_scaling
        #_tx_usrp_gain = g + _tx_usrp_gain_range * self.tx_usrp_pga_gain_scaling

        #self.subdev.set_gain(_tx_usrp_gain)        
        #self.u.set_gain(_tx_usrp_gain, 0)
        self.u.set_gain(10, 0)

        #if self.DEBUG:
        #    print "    USRP Tx PGA Gain Range: min = %g, max = %g, step size = %g" \
        #                    %(g[0], g[1], g[2])
        #    print "    USRP Tx PGA gain set to: %g" %(_tx_usrp_gain)


        # Set the transmit amplitude sent to the USRP (param: ampl 0 <= ampl < 16384.)
        """
        Convert tx_power(mW) in waveform.xml to amplitude in gnu radio
        """
        ampl= 1638.3*pow(self.tx_power, 0.5) 
        self.tx_amplitude = max(0.0, min(ampl, 16383.0))
        if self.DEBUG:
            print "tx amplitude:", self.tx_amplitude

        #gr digital amplifier
	self.tx_amplitude = 1.0
        self.gr_amp = gr.multiply_const_cc (int(self.tx_amplitude))   # software amplifier (scaler)
        print "GR amp= ", int(self.tx_amplitude)
        if self.DEBUG:
            print "    Tx power acquired from waveform configuration XML file is: %f between (0, 100.0mW)" %(self.tx_power)
            print "    Tx Path initial software signal amplitude to USRP: %f / 16383.0" %(ampl)
            print "    Tx Path actual software signal amplitude to USRP: %f / 16383.0"  %(self.tx_amplitude)
            

        ##################  Choose the corresponding analog modem ################### 
        if self.DEBUG:
            print "----Tx path modulation: %s"  % (self.tx_mod_type)


        chan_filter_coeffs_fixed = (        
            0.000457763671875,
            0.000946044921875,
            0.00067138671875, 
            0.001068115234375,
            0.00091552734375, 
            0.0008544921875,  
            0.000518798828125,
            0.0001220703125,  
            -0.000396728515625,
            -0.0008544921875,  
            -0.00128173828125, 
            -0.00146484375,    
            -0.001434326171875,
            -0.0010986328125,  
            -0.000518798828125,
            0.000274658203125,
            0.001129150390625,
            0.00189208984375, 
            0.00238037109375, 
            0.00250244140625, 
            0.002166748046875,
            0.0013427734375,  
            0.000152587890625,
            -0.001220703125,   
            -0.002532958984375,
            -0.0035400390625,  
            -0.003997802734375,
            -0.003753662109375,
            -0.002777099609375,
            -0.0010986328125,  
            0.000946044921875,
            0.00311279296875, 
            0.00494384765625, 
            0.00604248046875, 
            0.006103515625,   
            0.005035400390625,
            0.00286865234375, 
            -0.0001220703125,  
            -0.00347900390625, 
            -0.006561279296875,
            -0.008758544921875,
            -0.00958251953125, 
            -0.008636474609375,
            -0.005950927734375,
            -0.001739501953125,
            0.00335693359375, 
            0.00848388671875, 
            0.0126953125,     
            0.01507568359375, 
            0.014862060546875,
            0.01171875,       
            0.00579833984375, 
            -0.002227783203125,
            -0.01123046875,    
            -0.0196533203125,  
            -0.02587890625,    
            -0.028228759765625,
            -0.025421142578125,
            -0.016754150390625,
            -0.002166748046875,
            0.017608642578125,
            0.041015625,      
            0.0660400390625,  
            0.090240478515625,
            0.111083984375,   
            0.12640380859375, 
            0.134490966796875,
            0.134490966796875,
            0.12640380859375, 
            0.111083984375,   
            0.090240478515625,
            0.0660400390625,  
            0.041015625,      
            0.017608642578125,
            -0.002166748046875,
            -0.016754150390625,
            -0.025421142578125,
            -0.028228759765625,
            -0.02587890625,    
            -0.0196533203125,  
            -0.01123046875,    
            -0.002227783203125,
            0.00579833984375, 
            0.01171875,       
            0.014862060546875,
            0.01507568359375, 
            0.0126953125,     
            0.00848388671875, 
            0.00335693359375, 
            -0.001739501953125,
            -0.005950927734375,
            -0.008636474609375,
            -0.00958251953125, 
            -0.008758544921875,
            -0.006561279296875,
            -0.00347900390625, 
            -0.0001220703125,  
            0.00286865234375, 
            0.005035400390625,
            0.006103515625,   
            0.00604248046875, 
            0.00494384765625, 
            0.00311279296875, 
            0.000946044921875,
            -0.0010986328125,  
            -0.002777099609375,
            -0.003753662109375,
            -0.003997802734375,
            -0.0035400390625,  
            -0.002532958984375,
            -0.001220703125,   
            0.000152587890625,
            0.0013427734375,  
            0.002166748046875,
            0.00250244140625, 
            0.00238037109375, 
            0.00189208984375, 
            0.001129150390625,
            0.000274658203125,
            -0.000518798828125,
            -0.0010986328125,  
            -0.001434326171875,
            -0.00146484375,    
            -0.00128173828125, 
            -0.0008544921875,  
            -0.000396728515625,
            0.0001220703125,  
            0.000518798828125,
            0.0008544921875,  
            0.00091552734375, 
            0.001068115234375,
            0.00067138671875, 
            0.000946044921875,
            0.000457763671875)	

        #chan_filter = gr.interp_fir_filter_ccf(self._gr_interp, chan_filter_coeffs_fixed)
        #chan_filter_dsp = gr.dsp_fir_ccf (chan_filter_coeffs_fixed, 14, self._gr_interp, 0, 0, 0, 1)
        #r = gr.enable_realtime_scheduling ()
        if self.DEBUG:
            print "interpolation rate = ", self._gr_interp

        # FM modulator
        k = 2 * math.pi * self.tx_freq_deviation / self.gr_rate
        
        modulator = gr.frequency_modulator_fc(k)
 
        # Pre-emphasis for FM modulation	
        """
        tau is preemphasis time constant, inverse proportional to channel bandwidth 
        """
        chan_bw = 2.0*(self.tx_base_band_bw + \
                            self.tx_freq_deviation)# Carson's rule of FM channel bandwidth 
        
        tau = 1/(chan_bw * 0.5)
        if self.DEBUG:
            print "    channel bandwidth: ", chan_bw
            print "    tau: ", tau
        preemph = fm_preemph (self.gr_rate, tau)           
       

#        audio_coeffs = (
# 0.00058729130373770002,
# 0.0016584444738215582,
# 0.0015819269921330031,
# 0.0014607862142637573,
# 0.00020681278261230754,
#-0.0013001097961560814,
#-0.00249802658603143,  
#-0.0024276134129972843,
#-0.00083069749014258953,
# 0.0017562878158492619,
# 0.003963761120687582,  
# 0.0043075911442784871,
# 0.0020710872871114866,
#-0.0020172640629268932,
#-0.005882026963765212,  
#-0.0070692053073845166,
#-0.0041954626649490937,
# 0.0019311082705710714,
# 0.0082980827342646387,
# 0.011045923787287403,  
# 0.0076530405054369872,
#-0.0012102332109476402,
#-0.011372099802214802,  
#-0.016910189774436514,  
#-0.013347352799620162,  
#-0.00068013535845177706,
# 0.015578754320259895,  
# 0.026379517186832846,  
# 0.023618496101893545,  
# 0.0051085800414948012,
#-0.022608534445133374,  
#-0.045529642916534545,  
#-0.047580556152787695,  
#-0.018048092177406189,  
# 0.042354392363985506,  
# 0.11988807809069109,  
# 0.19189052073753335,  
# 0.2351677633079737,    
# 0.2351677633079737,    
# 0.19189052073753335,  
# 0.11988807809069109,  
# 0.042354392363985506,  
#-0.018048092177406189,  
#-0.047580556152787695,  
#-0.045529642916534545,  
#-0.022608534445133374,  
# 0.0051085800414948012,
# 0.023618496101893545,  
# 0.026379517186832846,  
# 0.015578754320259895,  
#-0.00068013535845177706,
#-0.013347352799620162,  
#-0.016910189774436514,  
#-0.011372099802214802,  
#-0.0012102332109476402,
# 0.0076530405054369872,
# 0.011045923787287403,  
# 0.0082980827342646387,
# 0.0019311082705710714,
#-0.0041954626649490937,
#-0.0070692053073845166,
#-0.005882026963765212,  
#-0.0020172640629268932,
# 0.0020710872871114866,
# 0.0043075911442784871,
# 0.003963761120687582,  
# 0.0017562878158492619,
#-0.00083069749014258953,
#-0.0024276134129972843,
#-0.00249802658603143,  
#-0.0013001097961560814,
# 0.00020681278261230754,
# 0.0014607862142637573,
# 0.0015819269921330031,
# 0.0016584444738215582,
# 0.00058729130373770002)
        

        audio_coeffs = (
            -0.021392822265625,
             -0.0194091796875,                      
             0.02972412109375,                      
             -0.018341064453125,                    
             -0.025299072265625,                    
             0.07745361328125,                      
             -0.08251953125,                        
             -0.033905029296875,                    
             0.56634521484375,                      
             0.56634521484375,                      
             -0.033905029296875,                    
             -0.08251953125,                        
             0.07745361328125,                      
             -0.025299072265625,                    
             -0.018341064453125,                    
             0.02972412109375,                      
             -0.0194091796875,                      
             -0.021392822265625) 

        #audio_coeffs = (
        #    -0.21392822265625,
        #     -0.194091796875,                      
        #     0.2972412109375,                      
        #     -0.18341064453125,                    
        #     -0.25299072265625,                    
        #     0.7745361328125,                      
        #     -0.8251953125,                        
        #     -0.33905029296875,                    
        #     5.6634521484375,                      
        #     5.6634521484375,                      
        #     -0.33905029296875,                    
        #     -0.8251953125,                        
        #     0.7745361328125,                      
        #     -0.25299072265625,                    
        #     -0.18341064453125,                    
        #     0.2972412109375,                      
        #     -0.194091796875,                      
        #     -0.21392822265625) 
        self.audio_filter = gr.interp_fir_filter_fff(self._gr_interp, audio_coeffs)
 
        #Source audio Low-pass Filter
        #self.audio_throt = gr.multiply_const_ff(50)
        self.audio_throt = gr.multiply_const_ff(5)

        if self.DEBUG:
            print "audio decim FIR filter tap length:", len(audio_coeffs)
     
        # Setup audio source 
        src = audio.source(int(self.audio_rate), audio_input)
            
        # Wiring up
        #self.connect(src, self.audio_throt, interpolator, preemph, modulator, chan_filter_dsp, self.gr_amp, self.u)
        

        self.connect(src, self.audio_throt, self.audio_filter, modulator, self.gr_amp, self.u)
Esempio n. 33
0
    def __init__(self, frame, panel, vbox, argv):
        stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)

        parser = OptionParser(option_class=eng_option)
        parser.add_option("-T",
                          "--tx-subdev-spec",
                          type="subdev",
                          default=None,
                          help="select USRP Tx side A or B")
        parser.add_option("-f",
                          "--freq",
                          type="eng_float",
                          default=107.2e6,
                          help="set Tx frequency to FREQ [required]",
                          metavar="FREQ")
        parser.add_option("--wavfile",
                          type="string",
                          default="",
                          help="read input from FILE")
        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            sys.exit(1)

        self.usrp_interp = 200
        self.u = usrp.sink_c(0, self.usrp_interp)
        print "USRP Serial: ", self.u.serial_number()
        self.dac_rate = self.u.dac_rate()  # 128 MS/s
        self.usrp_rate = self.dac_rate / self.usrp_interp  # 640 kS/s
        self.sw_interp = 5
        self.audio_rate = self.usrp_rate / self.sw_interp  # 128 kS/s

        # determine the daughterboard subdevice we're using
        if options.tx_subdev_spec is None:
            options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
        self.u.set_mux(
            usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec))
        self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
        print "Using d'board: ", self.subdev.side_and_name()

        # set max Tx gain, tune frequency and enable transmitter
        self.subdev.set_gain(self.subdev.gain_range()[1])
        if self.u.tune(self.subdev.which(), self.subdev, options.freq):
            print "Tuned to", options.freq / 1e6, "MHz"
        else:
            sys.exit(1)
        self.subdev.set_enable(True)

        # open wav file containing floats in the [-1, 1] range, repeat
        if options.wavfile is None:
            print "Please provide a wavfile to transmit! Exiting\n"
            sys.exit(1)
        self.src = gr.wavfile_source(options.wavfile, True)
        nchans = self.src.channels()
        sample_rate = self.src.sample_rate()
        bits_per_sample = self.src.bits_per_sample()
        print nchans, "channels,", sample_rate, "kS/s,", bits_per_sample, "bits/sample"

        # resample to 128kS/s
        if sample_rate == 44100:
            self.resample_left = blks2.rational_resampler_fff(32, 11)
            self.resample_right = blks2.rational_resampler_fff(32, 11)
        elif sample_rate == 48000:
            self.resample_left == blks2.rational_resampler_fff(8, 3)
            self.resample_right == blks2.rational_resampler_fff(8, 3)
        elif sample_rate == 8000:
            self.resample_left == blks2.rational_resampler_fff(16, 1)
            self.resample_right == blks2.rational_resampler_fff(16, 1)
        else:
            print sample_rate, "is an unsupported sample rate"
            sys.exit(1)
        self.connect((self.src, 0), self.resample_left)
        self.connect((self.src, 1), self.resample_right)

        # create L+R (mono) and L-R (stereo)
        self.audio_lpr = gr.add_ff()
        self.audio_lmr = gr.sub_ff()
        self.connect(self.resample_left, (self.audio_lpr, 0))
        self.connect(self.resample_left, (self.audio_lmr, 0))
        self.connect(self.resample_right, (self.audio_lpr, 1))
        self.connect(self.resample_right, (self.audio_lmr, 1))

        # low-pass filter for L+R
        audio_lpr_taps = gr.firdes.low_pass(
            0.3,  # gain
            self.audio_rate,  # sampling rate
            15e3,  # passband cutoff
            2e3,  # transition width
            gr.firdes.WIN_HANN)
        self.audio_lpr_filter = gr.fir_filter_fff(1, audio_lpr_taps)
        self.connect(self.audio_lpr, self.audio_lpr_filter)

        # create pilot tone at 19 kHz
        self.pilot = gr.sig_source_f(
            self.audio_rate,  # sampling freq
            gr.GR_SIN_WAVE,  # waveform
            19e3,  # frequency
            3e-2)  # amplitude

        # create the L-R signal carrier at 38 kHz, high-pass to remove 0Hz tone
        self.stereo_carrier = gr.multiply_ff()
        self.connect(self.pilot, (self.stereo_carrier, 0))
        self.connect(self.pilot, (self.stereo_carrier, 1))
        stereo_carrier_taps = gr.firdes.high_pass(
            1,  # gain
            self.audio_rate,  # sampling rate
            1e4,  # cutoff freq
            2e3,  # transition width
            gr.firdes.WIN_HANN)
        self.stereo_carrier_filter = gr.fir_filter_fff(1, stereo_carrier_taps)
        self.connect(self.stereo_carrier, self.stereo_carrier_filter)

        # upconvert L-R to 23-53 kHz and band-pass
        self.mix_stereo = gr.multiply_ff()
        audio_lmr_taps = gr.firdes.band_pass(
            3e3,  # gain
            self.audio_rate,  # sampling rate
            23e3,  # low cutoff
            53e3,  # high cuttof
            2e3,  # transition width
            gr.firdes.WIN_HANN)
        self.audio_lmr_filter = gr.fir_filter_fff(1, audio_lmr_taps)
        self.connect(self.audio_lmr, (self.mix_stereo, 0))
        self.connect(self.stereo_carrier_filter, (self.mix_stereo, 1))
        self.connect(self.mix_stereo, self.audio_lmr_filter)

        # mix L+R, pilot and L-R
        self.mixer = gr.add_ff()
        self.connect(self.audio_lpr_filter, (self.mixer, 0))
        self.connect(self.pilot, (self.mixer, 1))
        self.connect(self.audio_lmr_filter, (self.mixer, 2))

        # interpolation & pre-emphasis
        interp_taps = gr.firdes.low_pass(
            self.sw_interp,  # gain
            self.audio_rate,  # Fs
            60e3,  # cutoff freq
            5e3,  # transition width
            gr.firdes.WIN_HAMMING)
        self.interpolator = gr.interp_fir_filter_fff(self.sw_interp,
                                                     interp_taps)
        self.pre_emph = blks2.fm_preemph(self.usrp_rate, tau=50e-6)
        self.connect(self.mixer, self.interpolator, self.pre_emph)

        # fm modulation, gain & TX
        max_dev = 100e3
        k = 2 * math.pi * max_dev / self.usrp_rate  # modulator sensitivity
        self.modulator = gr.frequency_modulator_fc(k)
        self.gain = gr.multiply_const_cc(1e3)
        self.connect(self.pre_emph, self.modulator, self.gain, self.u)

        # plot an FFT to verify we are sending what we want
        pre_mod = fftsink2.fft_sink_f(panel,
                                      title="Before Interpolation",
                                      fft_size=512,
                                      sample_rate=self.audio_rate,
                                      y_per_div=20,
                                      ref_level=20)
        self.connect(self.mixer, pre_mod)
        vbox.Add(pre_mod.win, 1, wx.EXPAND)
Esempio n. 34
0
def main():
    parser = OptionParser(option_class=eng_option)
    parser.add_option("-f",
                      "--freq",
                      type="eng_float",
                      default=144.800e6,
                      help="set frequency to FREQ",
                      metavar="FREQ")
    parser.add_option("-m",
                      "--message",
                      type="string",
                      default=":ALL      :this is a test",
                      help="message to send",
                      metavar="MESSAGE")
    parser.add_option("-c",
                      "--mycall",
                      type="string",
                      default="MYCALL",
                      help="source callsign",
                      metavar="CALL")
    parser.add_option("-t",
                      "--tocall",
                      type="string",
                      default="CQ",
                      help="recipient callsign",
                      metavar="CALL")
    parser.add_option("-v",
                      "--via",
                      type="string",
                      default="RELAY",
                      help="digipeater callsign",
                      metavar="CALL")
    parser.add_option("-d",
                      "--do-logging",
                      action="store_true",
                      default=False,
                      help="enable logging on datafiles")
    parser.add_option("-s",
                      "--use-datafile",
                      action="store_true",
                      default=False,
                      help="use usrp.dat (256kbps) as output")
    (options, args) = parser.parse_args()
    if len(args) != 0:
        parser.print_help()
        sys.exit(1)

    bitrate = 9600
    dac_rate = 128e6
    usrp_interp = 500
    cordic_freq = options.freq - dac_rate
    sf = 153600
    syminterp = sf / bitrate  #16
    nbfmdev = 3e3
    fmsens = 2 * pi * nbfmdev / (sf * 5 / 3)
    bit_oversampling = 8
    sw_interp = int(sf / bitrate / bit_oversampling)  #2

    fg = gr.flow_graph()

    p = buildpacket(options.mycall, 0, options.tocall, 0, options.via, 0, 0x03,
                    0xf0, options.message)
    if options.do_logging:
        dumppackettofile(p, "packet.dat")
    v = bits2syms(nrziencode(scrambler(hdlcpacket(p, 100, 1000))))
    src = gr.vector_source_f(v)
    gaussian_taps = gr.firdes.gaussian(
        1,  # gain
        bit_oversampling,  # symbol_rate
        0.3,  # bandwidth * symbol time
        4 * bit_oversampling  # number of taps
    )
    sqwave = (1, ) * syminterp  #rectangular window
    taps = Numeric.convolve(Numeric.array(gaussian_taps),
                            Numeric.array(sqwave))
    gaussian = gr.interp_fir_filter_fff(syminterp, taps)  #9600*16=153600

    res_taps = blks.design_filter(5, 3, 0.4)
    res = blks.rational_resampler_fff(fg, 5, 3, res_taps)  #153600*5/3=256000
    fmmod = gr.frequency_modulator_fc(fmsens)
    amp = gr.multiply_const_cc(32000)

    if options.use_datafile:
        dst = gr.file_sink(gr.sizeof_gr_complex, "usrp.dat")
    else:
        u = usrp.sink_c(0, usrp_interp)  #256000*500=128000000
        tx_subdev_spec = usrp.pick_tx_subdevice(u)
        m = usrp.determine_tx_mux_value(u, tx_subdev_spec)
        print "mux = %#04x" % (m, )
        u.set_mux(m)
        subdev = usrp.selected_subdev(u, tx_subdev_spec)
        print "Using TX d'board %s" % (subdev.side_and_name(), )
        u.set_tx_freq(0, cordic_freq)
        u.set_pga(0, 0)
        print "Actual frequency: ", u.tx_freq(0)
        dst = u

    fg.connect(src, gaussian, res, fmmod, amp, dst)

    fg.start()
    fg.wait()
Esempio n. 35
0
    def __init__(self, frame, panel, vbox, argv):
        stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)

        parser = OptionParser(option_class=eng_option)
        parser.add_option("-T",
                          "--tx-subdev-spec",
                          type="subdev",
                          default=None,
                          help="select USRP Tx side A or B")
        parser.add_option("-f",
                          "--freq",
                          type="eng_float",
                          default=107.2e6,
                          help="set Tx frequency to FREQ [required]",
                          metavar="FREQ")
        parser.add_option("--wavfile",
                          type="string",
                          default=None,
                          help="open .wav audio file FILE")
        parser.add_option("--xml",
                          type="string",
                          default="rds_data.xml",
                          help="open .xml RDS data FILE")
        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            sys.exit(1)

        usrp_interp = 500
        self.u = usrp.sink_c(0, usrp_interp)
        print "USRP Serial: ", self.u.serial_number()
        usrp_rate = self.u.dac_rate() / usrp_interp  # 256 kS/s

        # determine the daughterboard subdevice we're using
        if options.tx_subdev_spec is None:
            options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
        self.u.set_mux(
            usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec))
        self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
        print "Using d'board", self.subdev.side_and_name()

        # set max Tx gain, tune frequency and enable transmitter
        gain = self.subdev.gain_range()[1]
        self.subdev.set_gain(gain)
        print "Gain set to", gain
        if self.u.tune(self.subdev.which(), self.subdev, options.freq):
            print "Tuned to", options.freq / 1e6, "MHz"
        else:
            sys.exit(1)
        self.subdev.set_enable(True)

        # open wav file containing floats in the [-1, 1] range, repeat
        if options.wavfile is None:
            print "Please provide a wavfile to transmit! Exiting\n"
            sys.exit(1)
        self.src = gr.wavfile_source(options.wavfile, True)
        nchans = self.src.channels()
        sample_rate = self.src.sample_rate()
        bits_per_sample = self.src.bits_per_sample()
        print nchans, "channels,", sample_rate, "samples/sec,", \
         bits_per_sample, "bits/sample"

        # resample to usrp rate
        self.resample_left = blks2.rational_resampler_fff(
            usrp_rate, sample_rate)
        self.resample_right = blks2.rational_resampler_fff(
            usrp_rate, sample_rate)
        self.connect((self.src, 0), self.resample_left)
        self.connect((self.src, 1), self.resample_right)

        # create L+R (mono) and L-R (stereo)
        self.audio_lpr = gr.add_ff()
        self.audio_lmr = gr.sub_ff()
        self.connect(self.resample_left, (self.audio_lpr, 0))
        self.connect(self.resample_left, (self.audio_lmr, 0))
        self.connect(self.resample_right, (self.audio_lpr, 1))
        self.connect(self.resample_right, (self.audio_lmr, 1))

        # low-pass filter for L+R
        audio_lpr_taps = gr.firdes.low_pass(
            0.5,  # gain
            usrp_rate,  # sampling rate
            15e3,  # passband cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING)
        self.audio_lpr_filter = gr.fir_filter_fff(1, audio_lpr_taps)
        self.connect(self.audio_lpr, self.audio_lpr_filter)

        # create pilot tone at 19 kHz
        self.pilot = gr.sig_source_f(
            usrp_rate,  # sampling rate
            gr.GR_SIN_WAVE,  # waveform
            19e3,  # frequency
            5e-2)  # amplitude

        # upconvert L-R to 38 kHz and band-pass
        self.mix_stereo = gr.multiply_ff()
        audio_lmr_taps = gr.firdes.band_pass(
            80,  # gain
            usrp_rate,  # sampling rate
            38e3 - 15e3,  # low cutoff
            38e3 + 15e3,  # high cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING)
        self.audio_lmr_filter = gr.fir_filter_fff(1, audio_lmr_taps)
        self.connect(self.audio_lmr, (self.mix_stereo, 0))
        self.connect(self.pilot, (self.mix_stereo, 1))
        self.connect(self.pilot, (self.mix_stereo, 2))
        self.connect(self.mix_stereo, self.audio_lmr_filter)

        # create RDS bitstream
        # diff-encode, manchester-emcode, NRZ
        # enforce the 1187.5bps rate
        # pulse shaping filter (matched with receiver)
        # mix with 57kHz carrier (equivalent to BPSK)
        self.rds_enc = rds.data_encoder('rds_data.xml')
        self.diff_enc = gr.diff_encoder_bb(2)
        self.manchester1 = gr.map_bb([1, 2])
        self.manchester2 = gr.unpack_k_bits_bb(2)
        self.nrz = gr.map_bb([-1, 1])
        self.c2f = gr.char_to_float()
        self.rate_enforcer = rds.rate_enforcer(usrp_rate)
        pulse_shaping_taps = gr.firdes.low_pass(
            1,  # gain
            usrp_rate,  # sampling rate
            1.5e3,  # passband cutoff
            2e3,  # transition width
            gr.firdes.WIN_HAMMING)
        self.pulse_shaping = gr.fir_filter_fff(1, pulse_shaping_taps)
        self.bpsk_mod = gr.multiply_ff()
        self.connect (self.rds_enc, self.diff_enc, self.manchester1, \
         self.manchester2, self.nrz, self.c2f)
        self.connect(self.c2f, (self.rate_enforcer, 0))
        self.connect(self.pilot, (self.rate_enforcer, 1))
        self.connect(self.rate_enforcer, (self.bpsk_mod, 0))
        self.connect(self.pilot, (self.bpsk_mod, 1))
        self.connect(self.pilot, (self.bpsk_mod, 2))
        self.connect(self.pilot, (self.bpsk_mod, 3))

        # RDS band-pass filter
        rds_filter_taps = gr.firdes.band_pass(
            50,  # gain
            usrp_rate,  # sampling rate
            57e3 - 3e3,  # low cutoff
            57e3 + 3e3,  # high cutoff
            1e3,  # transition width
            gr.firdes.WIN_HAMMING)
        self.rds_filter = gr.fir_filter_fff(1, rds_filter_taps)
        self.connect(self.bpsk_mod, self.rds_filter)

        # mix L+R, pilot, L-R and RDS
        self.mixer = gr.add_ff()
        self.connect(self.audio_lpr_filter, (self.mixer, 0))
        self.connect(self.pilot, (self.mixer, 1))
        self.connect(self.audio_lmr_filter, (self.mixer, 2))
        self.connect(self.rds_filter, (self.mixer, 3))

        # fm modulation, gain & TX
        max_dev = 75e3
        k = 2 * math.pi * max_dev / usrp_rate  # modulator sensitivity
        self.modulator = gr.frequency_modulator_fc(k)
        self.gain = gr.multiply_const_cc(5e3)
        self.connect(self.mixer, self.modulator, self.gain, self.u)

        # plot an FFT to verify we are sending what we want
        if 1:
            self.fft = fftsink2.fft_sink_f(panel,
                                           title="Pre FM modulation",
                                           fft_size=512 * 4,
                                           sample_rate=usrp_rate,
                                           y_per_div=20,
                                           ref_level=-20)
            self.connect(self.mixer, self.fft)
            vbox.Add(self.fft.win, 1, wx.EXPAND)
        if 0:
            self.scope = scopesink2.scope_sink_f(panel,
                                                 title="RDS encoder output",
                                                 sample_rate=usrp_rate)
            self.connect(self.rds_enc, self.scope)
            vbox.Add(self.scope.win, 1, wx.EXPAND)
Esempio n. 36
0
    def __init__(self,
                 fft_length,
                 cp_length,
                 occupied_tones,
                 snr,
                 ks,
                 threshold,
                 options,
                 logging=False):
        """
	Hierarchical block for receiving OFDM symbols.

	The input is the complex modulated signal at baseband.
        Synchronized packets are sent back to the demodulator.

        @param fft_length: total number of subcarriers
        @type  fft_length: int
        @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length)
        @type  cp_length: int
        @param occupied_tones: number of subcarriers used for data
        @type  occupied_tones: int
        @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer
        @type  snr: float
        @param ks: known symbols used as preambles to each packet
        @type  ks: list of lists
        @param logging: turn file logging on or off
        @type  logging: bool
	"""

        gr.hier_block2.__init__(
            self,
            "ofdm_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            #gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature apurv--
            gr.io_signature3(3, 3, gr.sizeof_gr_complex * occupied_tones,
                             gr.sizeof_char,
                             gr.sizeof_gr_complex * occupied_tones
                             ))  # apurv++, goes into frame sink for hestimates
        #gr.io_signature4(4, 4, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_gr_complex*fft_length))     # apurv++, goes into frame sink for hestimates

        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw * 0.08
        chan_coeffs = gr.firdes.low_pass(
            1.0,  # gain
            1.0,  # sampling rate
            bw + tb,  # midpoint of trans. band
            tb,  # width of trans. band
            gr.firdes.WIN_HAMMING)  # filter type
        self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs)

        win = [1 for i in range(fft_length)]

        zeros_on_left = int(math.ceil((fft_length - occupied_tones) / 2.0))
        ks0 = fft_length * [
            0,
        ]
        ks0[zeros_on_left:zeros_on_left + occupied_tones] = ks[0]

        ks0 = fft.ifftshift(ks0)
        ks0time = fft.ifft(ks0)
        # ADD SCALING FACTOR
        ks0time = ks0time.tolist()

        nco_sensitivity = -2.0 / fft_length  # correct for fine frequency
        self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, ks0time,
                                      threshold, options.threshold_type,
                                      options.threshold_gap,
                                      logging)  # apurv++

        # Set up blocks

        self.nco = gr.frequency_modulator_fc(
            nco_sensitivity
        )  # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = digital_swig.ofdm_sampler(
            fft_length, fft_length + cp_length,
            len(ks) + 1, 100
        )  # 1 for the extra preamble which ofdm_rx doesn't know about (check frame_sink)
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
        self.ofdm_frame_acq = digital_swig.ofdm_frame_acquisition(
            occupied_tones, fft_length, cp_length, ks)

        if options.verbose:
            self._print_verbage(options)

# apurv++ modified to allow collected time domain data to artifically pass through the rx chain #

# to replay the input manually, use this #
#self.connect(self, gr.null_sink(gr.sizeof_gr_complex))
#self.connect(gr.file_source(gr.sizeof_gr_complex, "input.dat"), self.chan_filt)

############# input -> chan_filt ##############
        self.connect(self, self.chan_filt)

        use_chan_filt = options.use_chan_filt
        correct_freq_offset = 0

        if use_chan_filt == 1:
            ##### chan_filt -> SYNC, chan_filt -> SIGMIX ####
            self.connect(self.chan_filt, self.ofdm_sync)
            if correct_freq_offset == 1:
                # enable if frequency offset correction is required #
                self.connect(self.chan_filt,
                             gr.delay(gr.sizeof_gr_complex, (fft_length)),
                             (self.sigmix, 0))  # apurv++ follow freq offset
            else:
                self.connect(self.chan_filt, (self.sampler, 0))
                ###self.connect(self.chan_filt, gr.delay(gr.sizeof_gr_complex, (fft_length)), (self.sampler, 0))		## extra delay

                #self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
        elif use_chan_filt == 2:
            #### alternative: chan_filt-> NULL, file_source -> SYNC, file_source -> SIGMIX ####
            self.connect(self.chan_filt, gr.null_sink(gr.sizeof_gr_complex))
            if correct_freq_offset == 1:
                self.connect(
                    gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"),
                    self.ofdm_sync)
                self.connect(
                    gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"),
                    gr.delay(gr.sizeof_gr_complex, (fft_length)),
                    (self.sigmix, 0))
            else:
                self.connect(
                    gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"),
                    self.ofdm_sync)
                self.connect(
                    gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"),
                    (self.sampler, 0))
        else:
            # chan_filt->NULL #
            self.connect(self.chan_filt, gr.null_sink(gr.sizeof_gr_complex))

        method = options.method
        if method == -1:
            ################## for offline analysis, dump sampler input till the frame_sink, using io_signature4 #################
            if correct_freq_offset == 1:
                # enable if frequency offset correction is required #
                self.connect((self.ofdm_sync, 0), self.nco,
                             (self.sigmix, 1))  # freq offset (0'ed :/)
                self.connect(self.sigmix,
                             (self.sampler, 0))  # corrected output (0'ed FF)
                self.connect((self.ofdm_sync, 1),
                             gr.delay(gr.sizeof_char, fft_length),
                             (self.sampler, 1))  # timing signal

            else:
                # disable frequency offset correction completely #
                self.connect((self.ofdm_sync, 0),
                             gr.null_sink(gr.sizeof_float))
                self.connect((self.ofdm_sync, 1),
                             (self.sampler, 1))  # timing signal,

                #self.connect((self.ofdm_sync,0), (self.sampler, 2))						##added
                ##self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char, fft_length+cp_length), (self.sampler, 1))           # timing signal, ##extra delay

                # route received time domain to sink (all-the-way) for offline analysis #
            self.connect((self.sampler, 0), (self.ofdm_frame_acq, 2))
            #self.connect((self.sampler, 1), gr.file_sink(gr.sizeof_char*fft_length, "sampler_timing.dat"))

        elif method == 0:
            # NORMAL functioning #
            if correct_freq_offset == 1:
                self.connect(
                    (self.ofdm_sync, 0), self.nco, (self.sigmix, 1)
                )  # use sync freq. offset output to derotate input signal
                self.connect(
                    self.sigmix,
                    (self.sampler,
                     0))  # sample off timing signal detected in sync alg
                self.connect((self.ofdm_sync, 1),
                             gr.delay(gr.sizeof_char, fft_length),
                             (self.sampler, 1))  # delay?
            else:
                self.connect((self.ofdm_sync, 1), (self.sampler, 1))

#self.connect((self.sampler, 2), (self.ofdm_frame_acq, 2))
#######################################################################

        use_default = options.use_default
        if use_default == 0:  #(set method == 0)
            # sampler-> NULL, replay trace->fft_demod, ofdm_frame_acq (time domain) #
            #self.connect((self.sampler, 0), gr.null_sink(gr.sizeof_gr_complex*fft_length))
            #self.connect((self.sampler, 1), gr.null_sink(gr.sizeof_char*fft_length))

            self.connect(
                gr.file_source(gr.sizeof_gr_complex * fft_length,
                               "symbols_src.dat"), self.fft_demod)
            self.connect(
                gr.file_source(gr.sizeof_char * fft_length, "timing_src.dat"),
                (self.ofdm_frame_acq, 1))
            self.connect(self.fft_demod, (self.ofdm_frame_acq, 0))
        elif use_default == 1:  #(set method == -1)
            # normal functioning #
            self.connect(
                (self.sampler, 0),
                self.fft_demod)  # send derotated sampled signal to FFT
            self.connect((self.sampler, 1),
                         (self.ofdm_frame_acq,
                          1))  # send timing signal to signal frame start
            self.connect(self.fft_demod, (self.ofdm_frame_acq, 0))
        elif use_default == 2:
            # replay directly to ofdm_frame_acq (frequency domain) #
            self.connect(
                gr.file_source(gr.sizeof_gr_complex * fft_length,
                               "symbols_src.dat"), (self.ofdm_frame_acq, 0))
            self.connect(
                gr.file_source(gr.sizeof_char * fft_length, "timing_src.dat"),
                (self.ofdm_frame_acq, 1))

########################### some logging start ##############################
#self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char, fft_length), gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
#self.connect((self.sampler, 0), gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat"))
#self.connect((self.sampler, 1), gr.file_sink(gr.sizeof_char*fft_length, "ofdm_timing_sampler_c.dat"))
############################ some logging end ###############################

        self.connect((self.ofdm_frame_acq, 0),
                     (self, 0))  # finished with fine/coarse freq correction,
        self.connect((self.ofdm_frame_acq, 1),
                     (self, 1))  # frame and symbol timing, and equalization
        self.connect((self.ofdm_frame_acq, 2),
                     (self, 2))  # equalizer: hestimates

        #self.connect((self.ofdm_frame_acq,3), (self,3))           # ref sampler above

        # apurv++ ends #

        #self.connect(self.ofdm_frame_acq, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat"))
        #self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat"))

        # apurv++ log the fine frequency offset corrected symbols #
        #self.connect((self.ofdm_frame_acq, 1), gr.file_sink(gr.sizeof_char, "ofdm_timing_frame_acq_c.dat"))
        #self.connect((self.ofdm_frame_acq, 2), gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_hestimates_c.dat"))
        #self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat"))
        #self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
        #self.connect(self, gr.file_sink(gr.sizeof_gr_complex, "ofdm_input_c.dat"))
        # apurv++ end #

        if logging:
            self.connect(
                self.chan_filt,
                gr.file_sink(gr.sizeof_gr_complex,
                             "ofdm_receiver-chan_filt_c.dat"))
            self.connect(
                self.fft_demod,
                gr.file_sink(gr.sizeof_gr_complex * fft_length,
                             "ofdm_receiver-fft_out_c.dat"))
            self.connect(
                self.ofdm_frame_acq,
                gr.file_sink(gr.sizeof_gr_complex * occupied_tones,
                             "ofdm_receiver-frame_acq_c.dat"))
            self.connect((self.ofdm_frame_acq, 1),
                         gr.file_sink(1, "ofdm_receiver-found_corr_b.dat"))
            self.connect(
                self.sampler,
                gr.file_sink(gr.sizeof_gr_complex * fft_length,
                             "ofdm_receiver-sampler_c.dat"))
            #self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat"))
            self.connect(
                self.nco,
                gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
Esempio n. 37
0
    def __init__(self):
        grc_wxgui.top_block_gui.__init__(self, title="Fm Stereo Tx")

        ##################################################
        # Variables
        ##################################################
        self.st_gain = st_gain = 10
        self.samp_rate = samp_rate = 195.312e3
        self.pilot_gain = pilot_gain = 80e-3
        self.mpx_rate = mpx_rate = 160e3
        self.Mono_gain = Mono_gain = 300e-3
        self.FM_freq = FM_freq = 96.5e6

        ##################################################
        # Blocks
        ##################################################
        _st_gain_sizer = wx.BoxSizer(wx.VERTICAL)
        self._st_gain_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_st_gain_sizer,
            value=self.st_gain,
            callback=self.set_st_gain,
            label='st_gain',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._st_gain_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_st_gain_sizer,
            value=self.st_gain,
            callback=self.set_st_gain,
            minimum=0,
            maximum=100,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.Add(_st_gain_sizer)
        _pilot_gain_sizer = wx.BoxSizer(wx.VERTICAL)
        self._pilot_gain_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_pilot_gain_sizer,
            value=self.pilot_gain,
            callback=self.set_pilot_gain,
            label='pilot_gain',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._pilot_gain_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_pilot_gain_sizer,
            value=self.pilot_gain,
            callback=self.set_pilot_gain,
            minimum=0,
            maximum=1,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.Add(_pilot_gain_sizer)
        self.notebook_0 = self.notebook_0 = wx.Notebook(self.GetWin(),
                                                        style=wx.NB_TOP)
        self.notebook_0.AddPage(grc_wxgui.Panel(self.notebook_0), "FM")
        self.notebook_0.AddPage(grc_wxgui.Panel(self.notebook_0), "audio")
        self.Add(self.notebook_0)
        _Mono_gain_sizer = wx.BoxSizer(wx.VERTICAL)
        self._Mono_gain_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_Mono_gain_sizer,
            value=self.Mono_gain,
            callback=self.set_Mono_gain,
            label='Mono_gain',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._Mono_gain_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_Mono_gain_sizer,
            value=self.Mono_gain,
            callback=self.set_Mono_gain,
            minimum=0,
            maximum=1,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.Add(_Mono_gain_sizer)
        _FM_freq_sizer = wx.BoxSizer(wx.VERTICAL)
        self._FM_freq_text_box = forms.text_box(
            parent=self.GetWin(),
            sizer=_FM_freq_sizer,
            value=self.FM_freq,
            callback=self.set_FM_freq,
            label='FM_freq',
            converter=forms.float_converter(),
            proportion=0,
        )
        self._FM_freq_slider = forms.slider(
            parent=self.GetWin(),
            sizer=_FM_freq_sizer,
            value=self.FM_freq,
            callback=self.set_FM_freq,
            minimum=88e6,
            maximum=108e6,
            num_steps=100,
            style=wx.SL_HORIZONTAL,
            cast=float,
            proportion=1,
        )
        self.Add(_FM_freq_sizer)
        self.wxgui_fftsink2_1 = fftsink2.fft_sink_f(
            self.notebook_0.GetPage(1).GetWin(),
            baseband_freq=0,
            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.notebook_0.GetPage(1).Add(self.wxgui_fftsink2_1.win)
        self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
            self.notebook_0.GetPage(0).GetWin(),
            baseband_freq=FM_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.notebook_0.GetPage(0).Add(self.wxgui_fftsink2_0.win)
        self.uhd_usrp_sink_0 = uhd.usrp_sink(
            device_addr="addr=192.168.10.2",
            stream_args=uhd.stream_args(
                cpu_format="fc32",
                channels=range(1),
            ),
        )
        self.uhd_usrp_sink_0.set_samp_rate(samp_rate)
        self.uhd_usrp_sink_0.set_center_freq(FM_freq, 0)
        self.uhd_usrp_sink_0.set_gain(0, 0)
        self.uhd_usrp_sink_0.set_antenna("TX/RX", 0)
        self.low_pass_filter_0 = gr.fir_filter_fff(
            1,
            firdes.low_pass(Mono_gain, mpx_rate, 15000, 2000,
                            firdes.WIN_HAMMING, 6.76))
        self.gr_vector_to_streams_0 = gr.vector_to_streams(
            gr.sizeof_short * 1, 2)
        self.gr_sub_xx_0 = gr.sub_ff(1)
        self.gr_sig_source_x_1 = gr.sig_source_f(160000, gr.GR_SIN_WAVE, 19000,
                                                 pilot_gain, 0)
        self.gr_sig_source_x_0 = gr.sig_source_f(160000, gr.GR_SIN_WAVE, 38000,
                                                 30e-3, 0)
        self.gr_short_to_float_1 = gr.short_to_float(1, 1)
        self.gr_short_to_float_0 = gr.short_to_float(1, 1)
        self.gr_multiply_xx_0 = gr.multiply_vff(1)
        self.gr_multiply_const_vxx_2 = gr.multiply_const_vcc((32.768e3, ))
        self.gr_multiply_const_vxx_1 = gr.multiply_const_vff((30e-6, ))
        self.gr_multiply_const_vxx_0 = gr.multiply_const_vff((30e-6, ))
        self.gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(980e-3)
        self.gr_file_source_0 = gr.file_source(
            gr.sizeof_short * 2,
            "/home/kranthi/Documents/project/FM Transceiver/FM Transmitter/test.raw",
            True)
        self.gr_add_xx_1 = gr.add_vff(1)
        self.gr_add_xx_0 = gr.add_vff(1)
        self.blks2_rational_resampler_xxx_2 = blks2.rational_resampler_fff(
            interpolation=4,
            decimation=1,
            taps=None,
            fractional_bw=None,
        )
        self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_fff(
            interpolation=5,
            decimation=1,
            taps=None,
            fractional_bw=None,
        )
        self.blks2_rational_resampler_xxx_0 = blks2.rational_resampler_fff(
            interpolation=5,
            decimation=1,
            taps=None,
            fractional_bw=None,
        )
        self.blks2_fm_preemph_0 = blks2.fm_preemph(fs=mpx_rate, tau=50e-6)
        self.band_pass_filter_0 = gr.fir_filter_fff(
            1,
            firdes.band_pass(st_gain, mpx_rate, 23000, 53000, 2000,
                             firdes.WIN_HAMMING, 6.76))

        ##################################################
        # Connections
        ##################################################
        self.connect((self.gr_file_source_0, 0),
                     (self.gr_vector_to_streams_0, 0))
        self.connect((self.gr_vector_to_streams_0, 0),
                     (self.gr_short_to_float_0, 0))
        self.connect((self.gr_vector_to_streams_0, 1),
                     (self.gr_short_to_float_1, 0))
        self.connect((self.gr_short_to_float_0, 0),
                     (self.gr_multiply_const_vxx_0, 0))
        self.connect((self.gr_short_to_float_1, 0),
                     (self.gr_multiply_const_vxx_1, 0))
        self.connect((self.gr_multiply_const_vxx_0, 0),
                     (self.blks2_rational_resampler_xxx_0, 0))
        self.connect((self.gr_multiply_const_vxx_1, 0),
                     (self.blks2_rational_resampler_xxx_1, 0))
        self.connect((self.blks2_rational_resampler_xxx_0, 0),
                     (self.gr_add_xx_0, 1))
        self.connect((self.blks2_rational_resampler_xxx_0, 0),
                     (self.gr_sub_xx_0, 1))
        self.connect((self.blks2_rational_resampler_xxx_1, 0),
                     (self.gr_sub_xx_0, 0))
        self.connect((self.blks2_rational_resampler_xxx_1, 0),
                     (self.gr_add_xx_0, 0))
        self.connect((self.gr_add_xx_0, 0), (self.low_pass_filter_0, 0))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 0))
        self.connect((self.gr_sub_xx_0, 0), (self.gr_multiply_xx_0, 1))
        self.connect((self.gr_multiply_xx_0, 0), (self.band_pass_filter_0, 0))
        self.connect((self.gr_sig_source_x_1, 0), (self.gr_add_xx_1, 0))
        self.connect((self.band_pass_filter_0, 0), (self.gr_add_xx_1, 1))
        self.connect((self.low_pass_filter_0, 0), (self.gr_add_xx_1, 2))
        self.connect((self.gr_add_xx_1, 0), (self.blks2_fm_preemph_0, 0))
        self.connect((self.blks2_fm_preemph_0, 0),
                     (self.blks2_rational_resampler_xxx_2, 0))
        self.connect((self.blks2_rational_resampler_xxx_2, 0),
                     (self.gr_frequency_modulator_fc_0, 0))
        self.connect((self.gr_frequency_modulator_fc_0, 0),
                     (self.gr_multiply_const_vxx_2, 0))
        self.connect((self.gr_multiply_const_vxx_2, 0),
                     (self.uhd_usrp_sink_0, 0))
        self.connect((self.gr_multiply_const_vxx_2, 0),
                     (self.wxgui_fftsink2_0, 0))
        self.connect((self.gr_multiply_const_vxx_1, 0),
                     (self.wxgui_fftsink2_1, 0))
Esempio n. 38
0
    def __init__(self, freq, subdev_spec, which_USRP, audio_input, debug):
        #gr.hier_block2.__init__(self, "analog_transmit_path",
        #                        gr.io_signature(0, 0, 0), #input signature
        #                        gr.io_signature(0, 0, 0)) #output signature

        gr.top_block.__init__(self)
        self.DEBUG = debug
        self.freq = freq
        #self.freq = 462562500
        # audio_input="hw:0"

        #Formerly from XML
        self.tx_usrp_pga_gain_scaling = 1.0
        self.tx_power = 1
        self.tx_mod_type = 'fm'
        self.tx_freq_deviation = 2.5e3
        self.tx_base_band_bw = 5e3

        ##################  USRP settings  ###################
        r = gr.enable_realtime_scheduling()
        # acquire USRP via USB 2.0

        #self.u = usrp.sink_c(fusb_block_size=1024,
        #                     fusb_nblocks=4,
        #                     which=which_USRP)
        self.u = uhd.single_usrp_sink(
            device_addr="",
            io_type=uhd.io_type_t.COMPLEX_FLOAT32,
            num_channels=1,
        )

        # get D/A converter sampling rate
        #self.dac_rate = self.u.dac_rate()          #128 MS/s
        self.dac_rate = 128e6  #128 MS/s
        if self.DEBUG:
            print "    Tx Path DAC rate:      %d" % (self.dac_rate)

        #System digital sample rate setting
        self.audio_rate = 16e3
        self._gr_interp = 16
        self.max_gr_interp_rate = 40
        self._usrp_interp = 500
        self.gr_rate = self.dac_rate / self._usrp_interp
        self._gr_decim = 1

        if self.DEBUG:
            print "    usrp interp: ", self._usrp_interp
            print "    gr interp: ", self._gr_interp
            print "    gr rate1:  ", self.gr_rate
            print "    gr decim: ", self._gr_decim
            print "    audio rate: ", self.audio_rate

        # set USRP interplation ratio
        #self.u.set_interp_rate(self._usrp_interp)
        self.u.set_samp_rate(self.gr_rate)

        # set USRP daughterboard subdevice
        #if subdev_spec is None:
        #    subdev_spec = usrp.pick_tx_subdevice(self.u)
        #self.u.set_mux(usrp.determine_tx_mux_value(self.u, subdev_spec))
        #self.subdev = usrp.selected_subdev(self.u, subdev_spec)
        self.u.set_antenna("TX/RX")

        #if self.DEBUG:
        #    print "    TX Path use daughterboard:  %s"    % (self.subdev.side_and_name())

        # Set center frequency of USRP
        """
        Set the center frequency we're interested in.
        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital up converter.
        """
        assert (self.freq != None)
        #r = self.u.tune(self.subdev.which(), self.subdev, self.freq)
        r = self.u.set_center_freq(self.freq, 0)

        if self.DEBUG:
            if r:
                print "    Tx Frequency: %s" % (eng_notation.num_to_str(
                    self.freq))
            else:
                print "----Failed to set Tx frequency to %s" % (
                    eng_notation.num_to_str(self.freq), )
                raise ValueError

        # Set the USRP Tx PGA gain, (Note that on the RFX cards this is a nop.)
        # subdev.set_gain(subdev.gain_range()[1])    # set max Tx gain
        #g = self.subdev.gain_range()
        g = self.u.get_gain_range(0)
        #_tx_usrp_gain_range = g[1]-g[0]
        _tx_usrp_gain_range = g
        #_tx_usrp_gain = g[0] + _tx_usrp_gain_range * self.tx_usrp_pga_gain_scaling
        #_tx_usrp_gain = g + _tx_usrp_gain_range * self.tx_usrp_pga_gain_scaling

        #self.subdev.set_gain(_tx_usrp_gain)
        #self.u.set_gain(_tx_usrp_gain, 0)
        self.u.set_gain(10, 0)

        #if self.DEBUG:
        #    print "    USRP Tx PGA Gain Range: min = %g, max = %g, step size = %g" \
        #                    %(g[0], g[1], g[2])
        #    print "    USRP Tx PGA gain set to: %g" %(_tx_usrp_gain)

        # Set the transmit amplitude sent to the USRP (param: ampl 0 <= ampl < 16384.)
        """
        Convert tx_power(mW) in waveform.xml to amplitude in gnu radio
        """
        ampl = 1638.3 * pow(self.tx_power, 0.5)
        self.tx_amplitude = max(0.0, min(ampl, 16383.0))
        if self.DEBUG:
            print "tx amplitude:", self.tx_amplitude

        #gr digital amplifier
        self.tx_amplitude = 1.0
        self.gr_amp = gr.multiply_const_cc(int(
            self.tx_amplitude))  # software amplifier (scaler)
        print "GR amp= ", int(self.tx_amplitude)
        if self.DEBUG:
            print "    Tx power acquired from waveform configuration XML file is: %f between (0, 100.0mW)" % (
                self.tx_power)
            print "    Tx Path initial software signal amplitude to USRP: %f / 16383.0" % (
                ampl)
            print "    Tx Path actual software signal amplitude to USRP: %f / 16383.0" % (
                self.tx_amplitude)

        ##################  Choose the corresponding analog modem ###################
        if self.DEBUG:
            print "----Tx path modulation: %s" % (self.tx_mod_type)

        chan_filter_coeffs_fixed = (
            0.000457763671875, 0.000946044921875, 0.00067138671875,
            0.001068115234375, 0.00091552734375, 0.0008544921875,
            0.000518798828125, 0.0001220703125, -0.000396728515625,
            -0.0008544921875, -0.00128173828125, -0.00146484375,
            -0.001434326171875, -0.0010986328125, -0.000518798828125,
            0.000274658203125, 0.001129150390625, 0.00189208984375,
            0.00238037109375, 0.00250244140625, 0.002166748046875,
            0.0013427734375, 0.000152587890625, -0.001220703125,
            -0.002532958984375, -0.0035400390625, -0.003997802734375,
            -0.003753662109375, -0.002777099609375, -0.0010986328125,
            0.000946044921875, 0.00311279296875, 0.00494384765625,
            0.00604248046875, 0.006103515625, 0.005035400390625,
            0.00286865234375, -0.0001220703125, -0.00347900390625,
            -0.006561279296875, -0.008758544921875, -0.00958251953125,
            -0.008636474609375, -0.005950927734375, -0.001739501953125,
            0.00335693359375, 0.00848388671875, 0.0126953125, 0.01507568359375,
            0.014862060546875, 0.01171875, 0.00579833984375,
            -0.002227783203125, -0.01123046875, -0.0196533203125,
            -0.02587890625, -0.028228759765625, -0.025421142578125,
            -0.016754150390625, -0.002166748046875, 0.017608642578125,
            0.041015625, 0.0660400390625, 0.090240478515625, 0.111083984375,
            0.12640380859375, 0.134490966796875, 0.134490966796875,
            0.12640380859375, 0.111083984375, 0.090240478515625,
            0.0660400390625, 0.041015625, 0.017608642578125,
            -0.002166748046875, -0.016754150390625, -0.025421142578125,
            -0.028228759765625, -0.02587890625, -0.0196533203125,
            -0.01123046875, -0.002227783203125, 0.00579833984375, 0.01171875,
            0.014862060546875, 0.01507568359375, 0.0126953125,
            0.00848388671875, 0.00335693359375, -0.001739501953125,
            -0.005950927734375, -0.008636474609375, -0.00958251953125,
            -0.008758544921875, -0.006561279296875, -0.00347900390625,
            -0.0001220703125, 0.00286865234375, 0.005035400390625,
            0.006103515625, 0.00604248046875, 0.00494384765625,
            0.00311279296875, 0.000946044921875, -0.0010986328125,
            -0.002777099609375, -0.003753662109375, -0.003997802734375,
            -0.0035400390625, -0.002532958984375, -0.001220703125,
            0.000152587890625, 0.0013427734375, 0.002166748046875,
            0.00250244140625, 0.00238037109375, 0.00189208984375,
            0.001129150390625, 0.000274658203125, -0.000518798828125,
            -0.0010986328125, -0.001434326171875, -0.00146484375,
            -0.00128173828125, -0.0008544921875, -0.000396728515625,
            0.0001220703125, 0.000518798828125, 0.0008544921875,
            0.00091552734375, 0.001068115234375, 0.00067138671875,
            0.000946044921875, 0.000457763671875)

        #chan_filter = gr.interp_fir_filter_ccf(self._gr_interp, chan_filter_coeffs_fixed)
        #chan_filter_dsp = gr.dsp_fir_ccf (chan_filter_coeffs_fixed, 14, self._gr_interp, 0, 0, 0, 1)
        #r = gr.enable_realtime_scheduling ()
        if self.DEBUG:
            print "interpolation rate = ", self._gr_interp

        # FM modulator
        k = 2 * math.pi * self.tx_freq_deviation / self.gr_rate

        modulator = gr.frequency_modulator_fc(k)

        # Pre-emphasis for FM modulation
        """
        tau is preemphasis time constant, inverse proportional to channel bandwidth 
        """
        chan_bw = 2.0*(self.tx_base_band_bw + \
                            self.tx_freq_deviation)# Carson's rule of FM channel bandwidth

        tau = 1 / (chan_bw * 0.5)
        if self.DEBUG:
            print "    channel bandwidth: ", chan_bw
            print "    tau: ", tau
        preemph = fm_preemph(self.gr_rate, tau)

        #        audio_coeffs = (
        # 0.00058729130373770002,
        # 0.0016584444738215582,
        # 0.0015819269921330031,
        # 0.0014607862142637573,
        # 0.00020681278261230754,
        #-0.0013001097961560814,
        #-0.00249802658603143,
        #-0.0024276134129972843,
        #-0.00083069749014258953,
        # 0.0017562878158492619,
        # 0.003963761120687582,
        # 0.0043075911442784871,
        # 0.0020710872871114866,
        #-0.0020172640629268932,
        #-0.005882026963765212,
        #-0.0070692053073845166,
        #-0.0041954626649490937,
        # 0.0019311082705710714,
        # 0.0082980827342646387,
        # 0.011045923787287403,
        # 0.0076530405054369872,
        #-0.0012102332109476402,
        #-0.011372099802214802,
        #-0.016910189774436514,
        #-0.013347352799620162,
        #-0.00068013535845177706,
        # 0.015578754320259895,
        # 0.026379517186832846,
        # 0.023618496101893545,
        # 0.0051085800414948012,
        #-0.022608534445133374,
        #-0.045529642916534545,
        #-0.047580556152787695,
        #-0.018048092177406189,
        # 0.042354392363985506,
        # 0.11988807809069109,
        # 0.19189052073753335,
        # 0.2351677633079737,
        # 0.2351677633079737,
        # 0.19189052073753335,
        # 0.11988807809069109,
        # 0.042354392363985506,
        #-0.018048092177406189,
        #-0.047580556152787695,
        #-0.045529642916534545,
        #-0.022608534445133374,
        # 0.0051085800414948012,
        # 0.023618496101893545,
        # 0.026379517186832846,
        # 0.015578754320259895,
        #-0.00068013535845177706,
        #-0.013347352799620162,
        #-0.016910189774436514,
        #-0.011372099802214802,
        #-0.0012102332109476402,
        # 0.0076530405054369872,
        # 0.011045923787287403,
        # 0.0082980827342646387,
        # 0.0019311082705710714,
        #-0.0041954626649490937,
        #-0.0070692053073845166,
        #-0.005882026963765212,
        #-0.0020172640629268932,
        # 0.0020710872871114866,
        # 0.0043075911442784871,
        # 0.003963761120687582,
        # 0.0017562878158492619,
        #-0.00083069749014258953,
        #-0.0024276134129972843,
        #-0.00249802658603143,
        #-0.0013001097961560814,
        # 0.00020681278261230754,
        # 0.0014607862142637573,
        # 0.0015819269921330031,
        # 0.0016584444738215582,
        # 0.00058729130373770002)

        audio_coeffs = (-0.021392822265625, -0.0194091796875, 0.02972412109375,
                        -0.018341064453125, -0.025299072265625,
                        0.07745361328125, -0.08251953125, -0.033905029296875,
                        0.56634521484375, 0.56634521484375, -0.033905029296875,
                        -0.08251953125, 0.07745361328125, -0.025299072265625,
                        -0.018341064453125, 0.02972412109375, -0.0194091796875,
                        -0.021392822265625)

        #audio_coeffs = (
        #    -0.21392822265625,
        #     -0.194091796875,
        #     0.2972412109375,
        #     -0.18341064453125,
        #     -0.25299072265625,
        #     0.7745361328125,
        #     -0.8251953125,
        #     -0.33905029296875,
        #     5.6634521484375,
        #     5.6634521484375,
        #     -0.33905029296875,
        #     -0.8251953125,
        #     0.7745361328125,
        #     -0.25299072265625,
        #     -0.18341064453125,
        #     0.2972412109375,
        #     -0.194091796875,
        #     -0.21392822265625)
        self.audio_filter = gr.interp_fir_filter_fff(self._gr_interp,
                                                     audio_coeffs)

        #Source audio Low-pass Filter
        #self.audio_throt = gr.multiply_const_ff(50)
        self.audio_throt = gr.multiply_const_ff(5)

        if self.DEBUG:
            print "audio decim FIR filter tap length:", len(audio_coeffs)

        # Setup audio source
        src = audio.source(int(self.audio_rate), audio_input)

        # Wiring up
        #self.connect(src, self.audio_throt, interpolator, preemph, modulator, chan_filter_dsp, self.gr_amp, self.u)

        self.connect(src, self.audio_throt, self.audio_filter, modulator,
                     self.gr_amp, self.u)
Esempio n. 39
0
    def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, threshold, options, logging=False):
        """
	Hierarchical block for receiving OFDM symbols.

	The input is the complex modulated signal at baseband.
        Synchronized packets are sent back to the demodulator.

        @param fft_length: total number of subcarriers
        @type  fft_length: int
        @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length)
        @type  cp_length: int
        @param occupied_tones: number of subcarriers used for data
        @type  occupied_tones: int
        @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer
        @type  snr: float
        @param ks: known symbols used as preambles to each packet
        @type  ks: list of lists
        @param logging: turn file logging on or off
        @type  logging: bool
	"""

        gr.hier_block2.__init__(
            self,
            "ofdm_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            # gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature apurv--
            gr.io_signature3(
                3, 3, gr.sizeof_gr_complex * occupied_tones, gr.sizeof_char, gr.sizeof_gr_complex * occupied_tones
            ),
        )  # apurv++, goes into frame sink for hestimates
        # gr.io_signature4(4, 4, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_gr_complex*fft_length))     # apurv++, goes into frame sink for hestimates

        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw * 0.08
        chan_coeffs = gr.firdes.low_pass(
            1.0,  # gain
            1.0,  # sampling rate
            bw + tb,  # midpoint of trans. band
            tb,  # width of trans. band
            gr.firdes.WIN_HAMMING,
        )  # filter type
        self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs)

        win = [1 for i in range(fft_length)]

        zeros_on_left = int(math.ceil((fft_length - occupied_tones) / 2.0))
        ks0 = fft_length * [0]
        ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0]

        ks0 = fft.ifftshift(ks0)
        ks0time = fft.ifft(ks0)
        # ADD SCALING FACTOR
        ks0time = ks0time.tolist()

        nco_sensitivity = -2.0 / fft_length  # correct for fine frequency
        self.ofdm_sync = ofdm_sync_pn(
            fft_length, cp_length, ks0time, threshold, options.threshold_type, options.threshold_gap, logging
        )  # apurv++

        # Set up blocks

        self.nco = gr.frequency_modulator_fc(
            nco_sensitivity
        )  # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = digital_swig.ofdm_sampler(
            fft_length, fft_length + cp_length, len(ks) + 1, 100
        )  # 1 for the extra preamble which ofdm_rx doesn't know about (check frame_sink)
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
        self.ofdm_frame_acq = digital_swig.ofdm_frame_acquisition(occupied_tones, fft_length, cp_length, ks)

        if options.verbose:
            self._print_verbage(options)

        # apurv++ modified to allow collected time domain data to artifically pass through the rx chain #

        # to replay the input manually, use this #
        # self.connect(self, gr.null_sink(gr.sizeof_gr_complex))
        # self.connect(gr.file_source(gr.sizeof_gr_complex, "input.dat"), self.chan_filt)

        ############# input -> chan_filt ##############
        self.connect(self, self.chan_filt)

        use_chan_filt = options.use_chan_filt
        correct_freq_offset = 0

        if use_chan_filt == 1:
            ##### chan_filt -> SYNC, chan_filt -> SIGMIX ####
            self.connect(self.chan_filt, self.ofdm_sync)
            if correct_freq_offset == 1:
                # enable if frequency offset correction is required #
                self.connect(
                    self.chan_filt, gr.delay(gr.sizeof_gr_complex, (fft_length)), (self.sigmix, 0)
                )  # apurv++ follow freq offset
            else:
                self.connect(self.chan_filt, (self.sampler, 0))
                ###self.connect(self.chan_filt, gr.delay(gr.sizeof_gr_complex, (fft_length)), (self.sampler, 0))		## extra delay

                # self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
        elif use_chan_filt == 2:
            #### alternative: chan_filt-> NULL, file_source -> SYNC, file_source -> SIGMIX ####
            self.connect(self.chan_filt, gr.null_sink(gr.sizeof_gr_complex))
            if correct_freq_offset == 1:
                self.connect(gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"), self.ofdm_sync)
                self.connect(
                    gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"),
                    gr.delay(gr.sizeof_gr_complex, (fft_length)),
                    (self.sigmix, 0),
                )
            else:
                self.connect(gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"), self.ofdm_sync)
                self.connect(gr.file_source(gr.sizeof_gr_complex, "chan_filt.dat"), (self.sampler, 0))
        else:
            # chan_filt->NULL #
            self.connect(self.chan_filt, gr.null_sink(gr.sizeof_gr_complex))

        method = options.method
        if method == -1:
            ################## for offline analysis, dump sampler input till the frame_sink, using io_signature4 #################
            if correct_freq_offset == 1:
                # enable if frequency offset correction is required #
                self.connect((self.ofdm_sync, 0), self.nco, (self.sigmix, 1))  # freq offset (0'ed :/)
                self.connect(self.sigmix, (self.sampler, 0))  # corrected output (0'ed FF)
                self.connect(
                    (self.ofdm_sync, 1), gr.delay(gr.sizeof_char, fft_length), (self.sampler, 1)
                )  # timing signal

            else:
                # disable frequency offset correction completely #
                self.connect((self.ofdm_sync, 0), gr.null_sink(gr.sizeof_float))
                self.connect((self.ofdm_sync, 1), (self.sampler, 1))  # timing signal,

                # self.connect((self.ofdm_sync,0), (self.sampler, 2))						##added
                ##self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char, fft_length+cp_length), (self.sampler, 1))           # timing signal, ##extra delay

                # route received time domain to sink (all-the-way) for offline analysis #
            self.connect((self.sampler, 0), (self.ofdm_frame_acq, 2))
            # self.connect((self.sampler, 1), gr.file_sink(gr.sizeof_char*fft_length, "sampler_timing.dat"))

        elif method == 0:
            # NORMAL functioning #
            if correct_freq_offset == 1:
                self.connect(
                    (self.ofdm_sync, 0), self.nco, (self.sigmix, 1)
                )  # use sync freq. offset output to derotate input signal
                self.connect(self.sigmix, (self.sampler, 0))  # sample off timing signal detected in sync alg
                self.connect((self.ofdm_sync, 1), gr.delay(gr.sizeof_char, fft_length), (self.sampler, 1))  # delay?
            else:
                self.connect((self.ofdm_sync, 1), (self.sampler, 1))

                # self.connect((self.sampler, 2), (self.ofdm_frame_acq, 2))
                #######################################################################

        use_default = options.use_default
        if use_default == 0:  # (set method == 0)
            # sampler-> NULL, replay trace->fft_demod, ofdm_frame_acq (time domain) #
            # self.connect((self.sampler, 0), gr.null_sink(gr.sizeof_gr_complex*fft_length))
            # self.connect((self.sampler, 1), gr.null_sink(gr.sizeof_char*fft_length))

            self.connect(gr.file_source(gr.sizeof_gr_complex * fft_length, "symbols_src.dat"), self.fft_demod)
            self.connect(gr.file_source(gr.sizeof_char * fft_length, "timing_src.dat"), (self.ofdm_frame_acq, 1))
            self.connect(self.fft_demod, (self.ofdm_frame_acq, 0))
        elif use_default == 1:  # (set method == -1)
            # normal functioning #
            self.connect((self.sampler, 0), self.fft_demod)  # send derotated sampled signal to FFT
            self.connect((self.sampler, 1), (self.ofdm_frame_acq, 1))  # send timing signal to signal frame start
            self.connect(self.fft_demod, (self.ofdm_frame_acq, 0))
        elif use_default == 2:
            # replay directly to ofdm_frame_acq (frequency domain) #
            self.connect(gr.file_source(gr.sizeof_gr_complex * fft_length, "symbols_src.dat"), (self.ofdm_frame_acq, 0))
            self.connect(gr.file_source(gr.sizeof_char * fft_length, "timing_src.dat"), (self.ofdm_frame_acq, 1))

        ########################### some logging start ##############################
        # self.connect((self.ofdm_sync,1), gr.delay(gr.sizeof_char, fft_length), gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
        # self.connect((self.sampler, 0), gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat"))
        # self.connect((self.sampler, 1), gr.file_sink(gr.sizeof_char*fft_length, "ofdm_timing_sampler_c.dat"))
        ############################ some logging end ###############################

        self.connect((self.ofdm_frame_acq, 0), (self, 0))  # finished with fine/coarse freq correction,
        self.connect((self.ofdm_frame_acq, 1), (self, 1))  # frame and symbol timing, and equalization
        self.connect((self.ofdm_frame_acq, 2), (self, 2))  # equalizer: hestimates

        # self.connect((self.ofdm_frame_acq,3), (self,3))           # ref sampler above

        # apurv++ ends #

        # self.connect(self.ofdm_frame_acq, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat"))
        # self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat"))

        # apurv++ log the fine frequency offset corrected symbols #
        # self.connect((self.ofdm_frame_acq, 1), gr.file_sink(gr.sizeof_char, "ofdm_timing_frame_acq_c.dat"))
        # self.connect((self.ofdm_frame_acq, 2), gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_hestimates_c.dat"))
        # self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat"))
        # self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
        # self.connect(self, gr.file_sink(gr.sizeof_gr_complex, "ofdm_input_c.dat"))
        # apurv++ end #

        if logging:
            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
            self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex * fft_length, "ofdm_receiver-fft_out_c.dat"))
            self.connect(
                self.ofdm_frame_acq,
                gr.file_sink(gr.sizeof_gr_complex * occupied_tones, "ofdm_receiver-frame_acq_c.dat"),
            )
            self.connect((self.ofdm_frame_acq, 1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex * fft_length, "ofdm_receiver-sampler_c.dat"))
            # self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat"))
            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
Esempio n. 40
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)
Esempio n. 41
0
	def __init__(self, frame, panel, vbox, argv):
		stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv)

		parser = OptionParser (option_class=eng_option)
		parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None,
						help="select USRP Tx side A or B")
		parser.add_option("-f", "--freq", type="eng_float", default=107.2e6,
						help="set Tx frequency to FREQ [required]", metavar="FREQ")
		parser.add_option("--wavfile", type="string", default="",
						help="read input from FILE")
		(options, args) = parser.parse_args()
		if len(args) != 0:
			parser.print_help()
			sys.exit(1)

		self.usrp_interp = 200
		self.u = usrp.sink_c (0, self.usrp_interp)
		print "USRP Serial: ", self.u.serial_number()
		self.dac_rate = self.u.dac_rate()					# 128 MS/s
		self.usrp_rate = self.dac_rate / self.usrp_interp	# 640 kS/s
		self.sw_interp = 5
		self.audio_rate = self.usrp_rate / self.sw_interp	# 128 kS/s

		# determine the daughterboard subdevice we're using
		if options.tx_subdev_spec is None:
			options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
		self.u.set_mux(usrp.determine_tx_mux_value(self.u, options.tx_subdev_spec))
		self.subdev = usrp.selected_subdev(self.u, options.tx_subdev_spec)
		print "Using d'board: ", self.subdev.side_and_name()

		# set max Tx gain, tune frequency and enable transmitter
		self.subdev.set_gain(self.subdev.gain_range()[1])
		if self.u.tune(self.subdev.which(), self.subdev, options.freq):
			print "Tuned to", options.freq/1e6, "MHz"
		else:
			sys.exit(1)
		self.subdev.set_enable(True)

		# open wav file containing floats in the [-1, 1] range, repeat
		if options.wavfile is None:
			print "Please provide a wavfile to transmit! Exiting\n"
			sys.exit(1)
		self.src = gr.wavfile_source (options.wavfile, True)
		nchans = self.src.channels()
		sample_rate = self.src.sample_rate()
		bits_per_sample = self.src.bits_per_sample()
		print nchans, "channels,", sample_rate, "kS/s,", bits_per_sample, "bits/sample"

		# resample to 128kS/s
		if sample_rate == 44100:
			self.resample_left = blks2.rational_resampler_fff(32,11)
			self.resample_right = blks2.rational_resampler_fff(32,11)
		elif sample_rate == 48000:
			self.resample_left == blks2.rational_resampler_fff(8,3)
			self.resample_right == blks2.rational_resampler_fff(8,3)
		elif sample_rate == 8000:
			self.resample_left == blks2.rational_resampler_fff(16,1)
			self.resample_right == blks2.rational_resampler_fff(16,1)
		else:
			print sample_rate, "is an unsupported sample rate"
			sys.exit(1)
		self.connect ((self.src, 0), self.resample_left)
		self.connect ((self.src, 1), self.resample_right)

		# create L+R (mono) and L-R (stereo)
		self.audio_lpr = gr.add_ff()
		self.audio_lmr = gr.sub_ff()
		self.connect (self.resample_left, (self.audio_lpr, 0))
		self.connect (self.resample_left, (self.audio_lmr, 0))
		self.connect (self.resample_right, (self.audio_lpr, 1))
		self.connect (self.resample_right, (self.audio_lmr, 1))

		# low-pass filter for L+R
		audio_lpr_taps = gr.firdes.low_pass (0.3,	# gain
											self.audio_rate,	# sampling rate
											15e3,				# passband cutoff
											2e3,				# transition width
											gr.firdes.WIN_HANN)
		self.audio_lpr_filter = gr.fir_filter_fff (1, audio_lpr_taps)
		self.connect (self.audio_lpr, self.audio_lpr_filter)

		# create pilot tone at 19 kHz
		self.pilot = gr.sig_source_f(self.audio_rate,	# sampling freq
									gr.GR_SIN_WAVE,		# waveform
									19e3,				# frequency
									3e-2)				# amplitude

		# create the L-R signal carrier at 38 kHz, high-pass to remove 0Hz tone
		self.stereo_carrier = gr.multiply_ff()
		self.connect (self.pilot, (self.stereo_carrier, 0))
		self.connect (self.pilot, (self.stereo_carrier, 1))
		stereo_carrier_taps = gr.firdes.high_pass (1,			# gain
											self.audio_rate,	# sampling rate
											1e4,				# cutoff freq
											2e3,				# transition width
											gr.firdes.WIN_HANN)
		self.stereo_carrier_filter = gr.fir_filter_fff(1, stereo_carrier_taps)
		self.connect (self.stereo_carrier, self.stereo_carrier_filter)

		# upconvert L-R to 23-53 kHz and band-pass
		self.mix_stereo = gr.multiply_ff()
		audio_lmr_taps = gr.firdes.band_pass (3e3,				# gain
											self.audio_rate,	# sampling rate
											23e3,				# low cutoff
											53e3,				# high cuttof
											2e3,				# transition width
											gr.firdes.WIN_HANN)
		self.audio_lmr_filter = gr.fir_filter_fff (1, audio_lmr_taps)
		self.connect (self.audio_lmr, (self.mix_stereo, 0))
		self.connect (self.stereo_carrier_filter, (self.mix_stereo, 1))
		self.connect (self.mix_stereo, self.audio_lmr_filter)

		# mix L+R, pilot and L-R
		self.mixer = gr.add_ff()
		self.connect (self.audio_lpr_filter, (self.mixer, 0))
		self.connect (self.pilot, (self.mixer, 1))
		self.connect (self.audio_lmr_filter, (self.mixer, 2))

		# interpolation & pre-emphasis
		interp_taps = gr.firdes.low_pass (self.sw_interp,	# gain
										self.audio_rate,	# Fs
										60e3,				# cutoff freq
										5e3,				# transition width
										gr.firdes.WIN_HAMMING)
		self.interpolator = gr.interp_fir_filter_fff (self.sw_interp, interp_taps)
		self.pre_emph = blks2.fm_preemph(self.usrp_rate, tau=50e-6)
		self.connect (self.mixer, self.interpolator, self.pre_emph)

		# fm modulation, gain & TX
		max_dev = 100e3
		k = 2 * math.pi * max_dev / self.usrp_rate		# modulator sensitivity
		self.modulator = gr.frequency_modulator_fc (k)
		self.gain = gr.multiply_const_cc (1e3)
		self.connect (self.pre_emph, self.modulator, self.gain, self.u)

		# plot an FFT to verify we are sending what we want
		pre_mod = fftsink2.fft_sink_f(panel, title="Before Interpolation",
			fft_size=512, sample_rate=self.audio_rate, y_per_div=20, ref_level=20)
		self.connect (self.mixer, pre_mod)
		vbox.Add (pre_mod.win, 1, wx.EXPAND)
Esempio n. 42
0
    def set_waveform(self, type):
        self.lock()
        self.disconnect_all()
        if type == gr.GR_SIN_WAVE or type == gr.GR_CONST_WAVE:
            self._src = gr.sig_source_c(self[SAMP_RATE_KEY],      # Sample rate
                                        type,                # Waveform type
                                        self[WAVEFORM_FREQ_KEY], # Waveform frequency
                                        self[AMPLITUDE_KEY],     # Waveform amplitude
                                        self[WAVEFORM_OFFSET_KEY])        # Waveform offset
        elif type == gr.GR_GAUSSIAN or type == gr.GR_UNIFORM:
            self._src = gr.noise_source_c(type, self[AMPLITUDE_KEY])
        elif type == "2tone":
            self._src1 = gr.sig_source_c(self[SAMP_RATE_KEY],
                                         gr.GR_SIN_WAVE,
                                         self[WAVEFORM_FREQ_KEY],
                                         self[AMPLITUDE_KEY]/2.0,
                                         0)
            if(self[WAVEFORM2_FREQ_KEY] is None):
                self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY]

            self._src2 = gr.sig_source_c(self[SAMP_RATE_KEY],
                                         gr.GR_SIN_WAVE,
                                         self[WAVEFORM2_FREQ_KEY],
                                         self[AMPLITUDE_KEY]/2.0,
                                         0)
            self._src = gr.add_cc()
            self.connect(self._src1,(self._src,0))
            self.connect(self._src2,(self._src,1))
        elif type == "sweep":
            # rf freq is center frequency
            # waveform_freq is total swept width
            # waveform2_freq is sweep rate
            # will sweep from (rf_freq-waveform_freq/2) to (rf_freq+waveform_freq/2)
            if self[WAVEFORM2_FREQ_KEY] is None:
                self[WAVEFORM2_FREQ_KEY] = 0.1

            self._src1 = gr.sig_source_f(self[SAMP_RATE_KEY],
                                         gr.GR_TRI_WAVE,
                                         self[WAVEFORM2_FREQ_KEY],
                                         1.0,
                                         -0.5)
            self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
            self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
            self.connect(self._src1,self._src2,self._src)
        else:
            raise RuntimeError("Unknown waveform type")

        self.connect(self._src, self._u)
        self.unlock()

        if self._verbose:
            print "Set baseband modulation to:", waveforms[type]
            if type == gr.GR_SIN_WAVE:
                print "Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)
                print "Initial phase:", self[WAVEFORM_OFFSET_KEY]
            elif type == "2tone":
                print "Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)
                print "Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)
            elif type == "sweep":
                print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))
                print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)
            print "TX amplitude:", self[AMPLITUDE_KEY]
Esempio n. 43
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):

	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 = digital_swig.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 = filter.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)
Esempio n. 44
0
	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Fm Stereo Tx")

		##################################################
		# Variables
		##################################################
		self.st_gain = st_gain = 10
		self.samp_rate = samp_rate = 195.312e3
		self.pilot_gain = pilot_gain = 80e-3
		self.mpx_rate = mpx_rate = 160e3
		self.Mono_gain = Mono_gain = 300e-3
		self.FM_freq = FM_freq = 96.5e6

		##################################################
		# Blocks
		##################################################
		_st_gain_sizer = wx.BoxSizer(wx.VERTICAL)
		self._st_gain_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_st_gain_sizer,
			value=self.st_gain,
			callback=self.set_st_gain,
			label='st_gain',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._st_gain_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_st_gain_sizer,
			value=self.st_gain,
			callback=self.set_st_gain,
			minimum=0,
			maximum=100,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_st_gain_sizer)
		_pilot_gain_sizer = wx.BoxSizer(wx.VERTICAL)
		self._pilot_gain_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_pilot_gain_sizer,
			value=self.pilot_gain,
			callback=self.set_pilot_gain,
			label='pilot_gain',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._pilot_gain_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_pilot_gain_sizer,
			value=self.pilot_gain,
			callback=self.set_pilot_gain,
			minimum=0,
			maximum=1,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_pilot_gain_sizer)
		self.notebook_0 = self.notebook_0 = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
		self.notebook_0.AddPage(grc_wxgui.Panel(self.notebook_0), "FM")
		self.notebook_0.AddPage(grc_wxgui.Panel(self.notebook_0), "audio")
		self.Add(self.notebook_0)
		_Mono_gain_sizer = wx.BoxSizer(wx.VERTICAL)
		self._Mono_gain_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_Mono_gain_sizer,
			value=self.Mono_gain,
			callback=self.set_Mono_gain,
			label='Mono_gain',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._Mono_gain_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_Mono_gain_sizer,
			value=self.Mono_gain,
			callback=self.set_Mono_gain,
			minimum=0,
			maximum=1,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_Mono_gain_sizer)
		_FM_freq_sizer = wx.BoxSizer(wx.VERTICAL)
		self._FM_freq_text_box = forms.text_box(
			parent=self.GetWin(),
			sizer=_FM_freq_sizer,
			value=self.FM_freq,
			callback=self.set_FM_freq,
			label='FM_freq',
			converter=forms.float_converter(),
			proportion=0,
		)
		self._FM_freq_slider = forms.slider(
			parent=self.GetWin(),
			sizer=_FM_freq_sizer,
			value=self.FM_freq,
			callback=self.set_FM_freq,
			minimum=88e6,
			maximum=108e6,
			num_steps=100,
			style=wx.SL_HORIZONTAL,
			cast=float,
			proportion=1,
		)
		self.Add(_FM_freq_sizer)
		self.wxgui_fftsink2_1 = fftsink2.fft_sink_f(
			self.notebook_0.GetPage(1).GetWin(),
			baseband_freq=0,
			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.notebook_0.GetPage(1).Add(self.wxgui_fftsink2_1.win)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_c(
			self.notebook_0.GetPage(0).GetWin(),
			baseband_freq=FM_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.notebook_0.GetPage(0).Add(self.wxgui_fftsink2_0.win)
		self.uhd_usrp_sink_0 = uhd.usrp_sink(
			device_addr="addr=192.168.10.2",
			stream_args=uhd.stream_args(
				cpu_format="fc32",
				channels=range(1),
			),
		)
		self.uhd_usrp_sink_0.set_samp_rate(samp_rate)
		self.uhd_usrp_sink_0.set_center_freq(FM_freq, 0)
		self.uhd_usrp_sink_0.set_gain(0, 0)
		self.uhd_usrp_sink_0.set_antenna("TX/RX", 0)
		self.low_pass_filter_0 = gr.fir_filter_fff(1, firdes.low_pass(
			Mono_gain, mpx_rate, 15000, 2000, firdes.WIN_HAMMING, 6.76))
		self.gr_vector_to_streams_0 = gr.vector_to_streams(gr.sizeof_short*1, 2)
		self.gr_sub_xx_0 = gr.sub_ff(1)
		self.gr_sig_source_x_1 = gr.sig_source_f(160000, gr.GR_SIN_WAVE, 19000, pilot_gain, 0)
		self.gr_sig_source_x_0 = gr.sig_source_f(160000, gr.GR_SIN_WAVE, 38000, 30e-3, 0)
		self.gr_short_to_float_1 = gr.short_to_float(1, 1)
		self.gr_short_to_float_0 = gr.short_to_float(1, 1)
		self.gr_multiply_xx_0 = gr.multiply_vff(1)
		self.gr_multiply_const_vxx_2 = gr.multiply_const_vcc((32.768e3, ))
		self.gr_multiply_const_vxx_1 = gr.multiply_const_vff((30e-6, ))
		self.gr_multiply_const_vxx_0 = gr.multiply_const_vff((30e-6, ))
		self.gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(980e-3)
		self.gr_file_source_0 = gr.file_source(gr.sizeof_short*2, "/home/kranthi/Documents/project/FM Transceiver/FM Transmitter/test.raw", True)
		self.gr_add_xx_1 = gr.add_vff(1)
		self.gr_add_xx_0 = gr.add_vff(1)
		self.blks2_rational_resampler_xxx_2 = blks2.rational_resampler_fff(
			interpolation=4,
			decimation=1,
			taps=None,
			fractional_bw=None,
		)
		self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_fff(
			interpolation=5,
			decimation=1,
			taps=None,
			fractional_bw=None,
		)
		self.blks2_rational_resampler_xxx_0 = blks2.rational_resampler_fff(
			interpolation=5,
			decimation=1,
			taps=None,
			fractional_bw=None,
		)
		self.blks2_fm_preemph_0 = blks2.fm_preemph(fs=mpx_rate, tau=50e-6)
		self.band_pass_filter_0 = gr.fir_filter_fff(1, firdes.band_pass(
			st_gain, mpx_rate, 23000, 53000, 2000, firdes.WIN_HAMMING, 6.76))

		##################################################
		# Connections
		##################################################
		self.connect((self.gr_file_source_0, 0), (self.gr_vector_to_streams_0, 0))
		self.connect((self.gr_vector_to_streams_0, 0), (self.gr_short_to_float_0, 0))
		self.connect((self.gr_vector_to_streams_0, 1), (self.gr_short_to_float_1, 0))
		self.connect((self.gr_short_to_float_0, 0), (self.gr_multiply_const_vxx_0, 0))
		self.connect((self.gr_short_to_float_1, 0), (self.gr_multiply_const_vxx_1, 0))
		self.connect((self.gr_multiply_const_vxx_0, 0), (self.blks2_rational_resampler_xxx_0, 0))
		self.connect((self.gr_multiply_const_vxx_1, 0), (self.blks2_rational_resampler_xxx_1, 0))
		self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_add_xx_0, 1))
		self.connect((self.blks2_rational_resampler_xxx_0, 0), (self.gr_sub_xx_0, 1))
		self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.gr_sub_xx_0, 0))
		self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.gr_add_xx_0, 0))
		self.connect((self.gr_add_xx_0, 0), (self.low_pass_filter_0, 0))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 0))
		self.connect((self.gr_sub_xx_0, 0), (self.gr_multiply_xx_0, 1))
		self.connect((self.gr_multiply_xx_0, 0), (self.band_pass_filter_0, 0))
		self.connect((self.gr_sig_source_x_1, 0), (self.gr_add_xx_1, 0))
		self.connect((self.band_pass_filter_0, 0), (self.gr_add_xx_1, 1))
		self.connect((self.low_pass_filter_0, 0), (self.gr_add_xx_1, 2))
		self.connect((self.gr_add_xx_1, 0), (self.blks2_fm_preemph_0, 0))
		self.connect((self.blks2_fm_preemph_0, 0), (self.blks2_rational_resampler_xxx_2, 0))
		self.connect((self.blks2_rational_resampler_xxx_2, 0), (self.gr_frequency_modulator_fc_0, 0))
		self.connect((self.gr_frequency_modulator_fc_0, 0), (self.gr_multiply_const_vxx_2, 0))
		self.connect((self.gr_multiply_const_vxx_2, 0), (self.uhd_usrp_sink_0, 0))
		self.connect((self.gr_multiply_const_vxx_2, 0), (self.wxgui_fftsink2_0, 0))
		self.connect((self.gr_multiply_const_vxx_1, 0), (self.wxgui_fftsink2_1, 0))
Esempio n. 45
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. 46
0
    def __init__(
        self, fft_length, cp_length, occupied_tones, snr, ks, threshold, options, logging=False
    ):  # apurv++: added num_symbols, use_chan_filt
        """
    Hierarchical block for receiving OFDM symbols.

    The input is the complex modulated signal at baseband.
    Synchronized packets are sent back to the demodulator.

    @param params: Raw OFDM parameters
    @type  params: ofdm_params
    @param logging: turn file logging on or off
    @type  logging: bool
    """

        gr.hier_block2.__init__(
            self,
            "ofdm_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature3(
                3, 3, gr.sizeof_gr_complex * occupied_tones, gr.sizeof_char, gr.sizeof_gr_complex * occupied_tones
            ),
        )  # Output signature

        # low-pass filter the input channel
        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw * 0.08
        lpf_coeffs = gr.firdes.low_pass(
            1.0,  # gain
            1.0,  # sampling rate
            bw + tb,  # midpoint of trans. band
            tb,  # width of trans. band
            gr.firdes.WIN_HAMMING,
        )  # filter type
        self.chan_filt = gr.fft_filter_ccc(1, lpf_coeffs)
        self.connect(self, self.chan_filt)
        self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "rx-filt.dat"))

        zeros_on_left = int(math.ceil((fft_length - occupied_tones) / 2.0))
        ks0 = fft_length * [0]
        ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0]
        ks0 = fft.ifftshift(ks0)
        ks0time = fft.ifft(ks0)
        ks0time = ks0time.tolist()

        ks1 = fft_length * [0]
        ks1[zeros_on_left : zeros_on_left + occupied_tones] = ks[1]
        ks1 = fft.ifftshift(ks1)
        ks1time = fft.ifft(ks1)
        ks1time = ks1time.tolist()

        # sync = ofdm_sync_pn(fft_length, cp_length, True, logging)		# raw
        sync = ofdm_sync_pn(fft_length, cp_length, True, ks0time, ks1time, threshold, logging)  # crosscorr version

        use_chan_filt = 1
        if use_chan_filt == 0:
            self.connect(gr.file_source(gr.sizeof_gr_complex, "chan-filt.dat"), sync)
        else:
            self.connect(self.chan_filt, sync)

        # correct for fine frequency offset computed in sync (up to +-pi/fft_length)
        nco_sensitivity = 2.0 / fft_length

        nco = gr.frequency_modulator_fc(nco_sensitivity)
        sigmix = gr.multiply_cc()

        # sample at symbol boundaries
        # NOTE: (sync,2) indicates the first sample of the symbol!
        sampler = digital_swig.ofdm_sampler(fft_length, fft_length + cp_length, len(ks) + 1, timeout=100)  # apurv--

        # frequency offset correction #
        self.connect((sync, 0), (sigmix, 0))
        self.connect((sync, 1), nco, (sigmix, 1))
        self.connect(sigmix, (sampler, 0))
        self.connect((sync, 2), (sampler, 1))

        """
    self.connect((sync,0), (sampler,0))
    self.connect((sync,2), (sampler,1))  # timing signal to sample at
    self.connect((sync,1), gr.file_sink(gr.sizeof_float, "offset.dat"))
    """

        self.connect((sampler, 1), gr.file_sink(gr.sizeof_char, "sampler_timing.dat"))
        # self.connect((sampler, 2), gr.file_sink(gr.sizeof_char*fft_length, "sampler_timing_fft.dat"))

        # fft on the symbols
        win = [1 for i in range(fft_length)]
        # see gr_fft_vcc_fftw that it works differently if win = []
        fft1 = gr.fft_vcc(fft_length, True, win, True)
        self.connect((sampler, 0), fft1)

        # use the preamble to correct the coarse frequency offset and initial equalizer
        ###frame_acq = raw.ofdm_frame_acquisition(fft_length, cp_length, preambles_raw, carriers)
        frame_acq = digital_swig.ofdm_frame_acquisition(occupied_tones, fft_length, cp_length, ks)

        self.frame_acq = frame_acq

        # normal operation #
        self.connect((fft1, 0), gr.file_sink(gr.sizeof_gr_complex * options.fft_length, "fft-out.dat"))
        self.connect((sampler, 1), gr.file_sink(gr.sizeof_char, "sampler_timing.dat"))
        self.connect(fft1, (frame_acq, 0))
        self.connect((sampler, 1), (frame_acq, 1))

        """ 
    # enable to have manual input to frame_acq # 
    self.connect(fft1, gr.null_sink(gr.sizeof_gr_complex*options.fft_length))
    self.connect(gr.file_source(gr.sizeof_gr_complex*options.fft_length, "combined.dat"), (frame_acq,0))
    self.connect(gr.file_source(gr.sizeof_char, "combined_t.dat"), (frame_acq,1))
    """

        # self.connect(fft, gr.null_sink(gr.sizeof_gr_complex*options.fft_length))
        # self.connect((sampler, 1), gr.null_sink(gr.sizeof_char))
        # self.connect(gr.file_source(gr.sizeof_gr_complex*options.fft_length, "symbols_src.dat"), (frame_acq, 0))
        # self.connect(gr.file_source(gr.sizeof_char, "timing.dat"), (frame_acq, 1))

        self.connect((frame_acq, 0), (self, 0))  # finished with fine/coarse freq correction
        self.connect((frame_acq, 1), (self, 1))  # frame and symbol timing
        self.connect((frame_acq, 2), (self, 2))  # hestimates

        self.connect((frame_acq, 0), gr.file_sink(gr.sizeof_gr_complex * occupied_tones, "rx-acq.dat"))
        self.connect((frame_acq, 1), gr.file_sink(gr.sizeof_char, "timing-acq.dat"))

        if logging:
            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "rx-filt.dat"))
            self.connect(fft1, gr.file_sink(gr.sizeof_gr_complex * fft_length, "rx-fft.dat"))
            self.connect((frame_acq, 0), gr.file_sink(gr.sizeof_gr_complex * occupied_tones, "rx-acq.dat"))
            self.connect((frame_acq, 1), gr.file_sink(1, "rx-detect.datb"))
            self.connect(sampler, gr.file_sink(gr.sizeof_gr_complex * fft_length, "rx-sampler.dat"))
            self.connect(sigmix, gr.file_sink(gr.sizeof_gr_complex, "rx-sigmix.dat"))
            self.connect(nco, gr.file_sink(gr.sizeof_gr_complex, "rx-nco.dat"))
Esempio n. 47
0
	def __init__(self):
		grc_wxgui.top_block_gui.__init__(self, title="Rds Tx")
		_icon_path = "/home/azimout/.local/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
		self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

		##################################################
		# Variables
		##################################################
		self.usrp_interp = usrp_interp = 500
		self.dac_rate = dac_rate = 128e6
		self.wav_rate = wav_rate = 44100
		self.usrp_rate = usrp_rate = int(dac_rate/usrp_interp)
		self.fm_max_dev = fm_max_dev = 120e3

		##################################################
		# Blocks
		##################################################
		self.band_pass_filter_0 = gr.interp_fir_filter_fff(1, firdes.band_pass(
			1, usrp_rate, 54e3, 60e3, 3e3, firdes.WIN_HAMMING, 6.76))
		self.band_pass_filter_1 = gr.interp_fir_filter_fff(1, firdes.band_pass(
			1, usrp_rate, 23e3, 53e3, 2e3, firdes.WIN_HAMMING, 6.76))
		self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_fff(
			interpolation=usrp_rate,
			decimation=wav_rate,
			taps=None,
			fractional_bw=None,
		)
		self.blks2_rational_resampler_xxx_1_0 = blks2.rational_resampler_fff(
			interpolation=usrp_rate,
			decimation=wav_rate,
			taps=None,
			fractional_bw=None,
		)
		self.gr_add_xx_0 = gr.add_vff(1)
		self.gr_add_xx_1 = gr.add_vff(1)
		self.gr_char_to_float_0 = gr.char_to_float()
		self.gr_diff_encoder_bb_0 = gr.diff_encoder_bb(2)
		self.gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(2*math.pi*fm_max_dev/usrp_rate)
		self.gr_map_bb_0 = gr.map_bb(([-1,1]))
		self.gr_map_bb_1 = gr.map_bb(([1,2]))
		self.gr_multiply_xx_0 = gr.multiply_vff(1)
		self.gr_multiply_xx_1 = gr.multiply_vff(1)
		self.gr_rds_data_encoder_0 = rds.data_encoder("/media/dimitris/mywork/gr/dimitris/rds/trunk/src/test/rds_data.xml")
		self.gr_rds_rate_enforcer_0 = rds.rate_enforcer(256000)
		self.gr_sig_source_x_0 = gr.sig_source_f(usrp_rate, gr.GR_COS_WAVE, 19e3, 0.3, 0)
		self.gr_sub_xx_0 = gr.sub_ff(1)
		self.gr_unpack_k_bits_bb_0 = gr.unpack_k_bits_bb(2)
		self.gr_wavfile_source_0 = gr.wavfile_source("/media/dimitris/mywork/gr/dimitris/rds/trunk/src/python/limmenso_stereo.wav", True)
		self.low_pass_filter_0 = gr.interp_fir_filter_fff(1, firdes.low_pass(
			1, usrp_rate, 1.5e3, 2e3, firdes.WIN_HAMMING, 6.76))
		self.low_pass_filter_0_0 = gr.interp_fir_filter_fff(1, firdes.low_pass(
			1, usrp_rate, 15e3, 2e3, firdes.WIN_HAMMING, 6.76))
		self.usrp_simple_sink_x_0 = grc_usrp.simple_sink_c(which=0, side="A")
		self.usrp_simple_sink_x_0.set_interp_rate(500)
		self.usrp_simple_sink_x_0.set_frequency(107.2e6, verbose=True)
		self.usrp_simple_sink_x_0.set_gain(0)
		self.usrp_simple_sink_x_0.set_enable(True)
		self.usrp_simple_sink_x_0.set_auto_tr(True)
		self.wxgui_fftsink2_0 = fftsink2.fft_sink_f(
			self.GetWin(),
			baseband_freq=0,
			y_per_div=20,
			y_divs=10,
			ref_level=0,
			ref_scale=2.0,
			sample_rate=usrp_rate,
			fft_size=1024,
			fft_rate=30,
			average=False,
			avg_alpha=None,
			title="FFT Plot",
			peak_hold=False,
		)
		self.Add(self.wxgui_fftsink2_0.win)

		##################################################
		# Connections
		##################################################
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_rds_rate_enforcer_0, 1))
		self.connect((self.gr_char_to_float_0, 0), (self.gr_rds_rate_enforcer_0, 0))
		self.connect((self.gr_map_bb_0, 0), (self.gr_char_to_float_0, 0))
		self.connect((self.gr_frequency_modulator_fc_0, 0), (self.usrp_simple_sink_x_0, 0))
		self.connect((self.gr_add_xx_1, 0), (self.gr_frequency_modulator_fc_0, 0))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_add_xx_1, 1))
		self.connect((self.gr_sub_xx_0, 0), (self.gr_multiply_xx_1, 2))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_1, 1))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_1, 0))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 3))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 2))
		self.connect((self.blks2_rational_resampler_xxx_1_0, 0), (self.gr_add_xx_0, 1))
		self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.gr_add_xx_0, 0))
		self.connect((self.blks2_rational_resampler_xxx_1_0, 0), (self.gr_sub_xx_0, 1))
		self.connect((self.blks2_rational_resampler_xxx_1, 0), (self.gr_sub_xx_0, 0))
		self.connect((self.gr_wavfile_source_0, 1), (self.blks2_rational_resampler_xxx_1_0, 0))
		self.connect((self.gr_wavfile_source_0, 0), (self.blks2_rational_resampler_xxx_1, 0))
		self.connect((self.gr_rds_data_encoder_0, 0), (self.gr_diff_encoder_bb_0, 0))
		self.connect((self.gr_diff_encoder_bb_0, 0), (self.gr_map_bb_1, 0))
		self.connect((self.gr_map_bb_1, 0), (self.gr_unpack_k_bits_bb_0, 0))
		self.connect((self.gr_unpack_k_bits_bb_0, 0), (self.gr_map_bb_0, 0))
		self.connect((self.gr_rds_rate_enforcer_0, 0), (self.low_pass_filter_0, 0))
		self.connect((self.low_pass_filter_0, 0), (self.gr_multiply_xx_0, 0))
		self.connect((self.gr_multiply_xx_0, 0), (self.band_pass_filter_0, 0))
		self.connect((self.band_pass_filter_0, 0), (self.gr_add_xx_1, 0))
		self.connect((self.gr_multiply_xx_1, 0), (self.band_pass_filter_1, 0))
		self.connect((self.band_pass_filter_1, 0), (self.gr_add_xx_1, 3))
		self.connect((self.gr_add_xx_1, 0), (self.wxgui_fftsink2_0, 0))
		self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 1))
		self.connect((self.gr_add_xx_0, 0), (self.low_pass_filter_0_0, 0))
		self.connect((self.low_pass_filter_0_0, 0), (self.gr_add_xx_1, 2))
Esempio n. 48
0
    def __init__(self, p, logging=False):
        """
    Hierarchical block for receiving OFDM symbols.

    The input is the complex modulated signal at baseband.
    Synchronized packets are sent back to the demodulator.

    @param params: Raw OFDM parameters
    @type  params: ofdm_params
    @param logging: turn file logging on or off
    @type  logging: bool
    """
        from numpy import fft

        gr.hier_block2.__init__(
            self,
            "ofdm_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature2(2, 2, gr.sizeof_gr_complex * p.occupied_tones,
                             gr.sizeof_char))  # Output signature

        # low-pass filter the input channel
        bw = (float(p.occupied_tones) / float(p.fft_length)) / 2.0
        tb = bw * 0.08
        lpf_coeffs = gr.firdes.low_pass(
            1.0,  # gain
            1.0,  # sampling rate
            bw + tb,  # midpoint of trans. band
            tb,  # width of trans. band
            gr.firdes.WIN_HAMMING)  # filter type
        lpf = gr.fft_filter_ccc(1, lpf_coeffs)
        #lpf = gr.add_const_cc(0.0)  ## no-op low-pass-filter
        self.connect(self, lpf)

        # to the synchronization algorithm
        #from gnuradio import blks2impl
        #from gnuradio.blks2impl.ofdm_sync_pn import ofdm_sync_pn
        sync = ofdm_sync(p.fft_length, p.cp_length, p.half_sync, logging)
        self.connect(lpf, sync)

        # correct for fine frequency offset computed in sync (up to +-pi/fft_length)
        # NOTE: frame_acquisition can correct coarse freq offset (i.e. kpi/fft_length)
        if p.half_sync:
            nco_sensitivity = 2.0 / p.fft_length
        else:
            nco_sensitivity = 1.0 / (p.fft_length + p.cp_length)
        #nco_sensitivity = 0

        nco = gr.frequency_modulator_fc(nco_sensitivity)
        sigmix = gr.multiply_cc()

        self.connect((sync, 0), (sigmix, 0))
        self.connect((sync, 1), nco, (sigmix, 1))

        # sample at symbol boundaries
        # NOTE: (sync,2) indicates the first sample of the symbol!
        sampler = raw.ofdm_sampler(p.fft_length,
                                   p.fft_length + p.cp_length,
                                   timeout=100)
        self.connect(sigmix, (sampler, 0))
        self.connect((sync, 2), (sampler, 1))  # timing signal to sample at

        # fft on the symbols
        win = [1 for i in range(p.fft_length)]
        # see gr_fft_vcc_fftw that it works differently if win = []
        fft = gr.fft_vcc(p.fft_length, True, win, True)
        self.connect((sampler, 0), fft)

        # use the preamble to correct the coarse frequency offset and initial equalizer
        frame_acq = raw.ofdm_frame_acquisition(p.fft_length, p.cp_length,
                                               p.preambles)

        self.frame_acq = frame_acq
        self.connect(fft, (frame_acq, 0))
        self.connect((sampler, 1), (frame_acq, 1))

        self.connect((frame_acq, 0),
                     (self, 0))  # finished with fine/coarse freq correction
        self.connect((frame_acq, 1), (self, 1))  # frame and symbol timing

        if logging:
            self.connect(lpf, gr.file_sink(gr.sizeof_gr_complex,
                                           "rx-filt.dat"))
            self.connect(
                fft,
                gr.file_sink(gr.sizeof_gr_complex * p.fft_length,
                             "rx-fft.dat"))
            self.connect((frame_acq, 0),
                         gr.file_sink(gr.sizeof_gr_complex * p.occupied_tones,
                                      "rx-acq.dat"))
            self.connect((frame_acq, 1), gr.file_sink(1, "rx-detect.datb"))
            self.connect(
                sampler,
                gr.file_sink(gr.sizeof_gr_complex * p.fft_length,
                             "rx-sampler.dat"))
            self.connect(sigmix,
                         gr.file_sink(gr.sizeof_gr_complex, "rx-sigmix.dat"))
            self.connect(nco, gr.file_sink(gr.sizeof_gr_complex, "rx-nco.dat"))
Esempio n. 49
0
    def __init__(self, bandwidth, fft_length, cp_length, occupied_tones, snr, ks, logging=False, mode='benchmark'):
        """
	Hierarchical block for receiving OFDM symbols.

	The input is the complex modulated signal at baseband.
        Synchronized packets are sent back to the demodulator.

        @param fft_length: total number of subcarriers
        @type  fft_length: int
        @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length)
        @type  cp_length: int
        @param occupied_tones: number of subcarriers used for data
        @type  occupied_tones: int
        @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer
        @type  snr: float
        @param ks: known symbols used as preambles to each packet
        @type  ks: list of lists
        @param logging: turn file logging on or off
        @type  logging: bool
	"""

	gr.hier_block2.__init__(self, "ofdm_receiver",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature
        
        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw*0.08
        chan_coeffs = gr.firdes.low_pass (1.0,                     # gain
                                          1.0,                     # sampling rate
                                          bw+tb,                   # midpoint of trans. band
                                          tb,                      # width of trans. band
                                          gr.firdes.WIN_HAMMING)   # filter type
        self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs)
        
        win = [1 for i in range(fft_length)]

        zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0))
        ks0 = fft_length*[0,]
        ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0]
        
        ks0 = fft.ifftshift(ks0)
        ks0time = fft.ifft(ks0)
        # ADD SCALING FACTOR
        ks0time = ks0time.tolist()

        SYNC = "pn"
        if SYNC == "ml":
            nco_sensitivity = -1.0/fft_length   # correct for fine frequency
            self.ofdm_sync = ofdm_sync_ml(fft_length,
                                          cp_length,
                                          snr,
                                          ks0time,
                                          logging)
        elif SYNC == "pn":
            nco_sensitivity = -2.0/fft_length   # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pn(fft_length,
                                          cp_length,
                                          logging, mode)
        elif SYNC == "pnac":
            nco_sensitivity = -2.0/fft_length   # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pnac(fft_length,
                                            cp_length,
                                            ks0time,
                                            logging)
        # for testing only; do not user over the air
        # remove filter and filter delay for this
        elif SYNC == "fixed":
            self.chan_filt = gr.multiply_const_cc(1.0) 
            nsymbols = 18      # enter the number of symbols per packet
            freq_offset = 0.0  # if you use a frequency offset, enter it here
            nco_sensitivity = -2.0/fft_length   # correct for fine frequency
            self.ofdm_sync = ofdm_sync_fixed(fft_length,
                                             cp_length,
                                             nsymbols,
                                             freq_offset,
                                             logging)

        # Set up blocks

        self.nco = gr.frequency_modulator_fc(nco_sensitivity)         # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = digital_swig.ofdm_sampler(fft_length, fft_length+cp_length, long(bandwidth))
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)
        self.ofdm_frame_acq = digital_swig.ofdm_frame_acquisition(occupied_tones,
                                                                  fft_length,
                                                                  cp_length, ks[0])

        self.connect(self, self.chan_filt)                            # filter the input channel
        self.connect(self.chan_filt, self.ofdm_sync)                  # into the synchronization alg.
        self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1))   # use sync freq. offset output to derotate input signal
        self.connect(self.chan_filt, (self.sigmix,0))                 # signal to be derotated
        self.connect(self.sigmix, (self.sampler,0))                   # sample off timing signal detected in sync alg
        self.connect((self.ofdm_sync,1), (self.sampler,1))            # timing signal to sample at

        self.connect((self.sampler,0), self.fft_demod)                # send derotated sampled signal to FFT
        self.connect(self.fft_demod, (self.ofdm_frame_acq,0))         # find frame start and equalize signal
        self.connect((self.sampler,1), (self.ofdm_frame_acq,1))       # send timing signal to signal frame start
        self.connect((self.ofdm_frame_acq,0), (self,0))               # finished with fine/coarse freq correction,
        self.connect((self.ofdm_frame_acq,1), (self,1))               # frame and symbol timing, and equalization

        # for debugging
        self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))

        if logging:
            self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat"))
            self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat"))
            self.connect(self.ofdm_frame_acq,
                         gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat"))
            self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat"))
            self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat"))
            self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat"))
            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
    def __init__(self, ntxchans, nrxchans, fft_length, cp_length, occupied_tones, snr, ks, logging=False):
        """
	Hierarchical block for receiving OFDM symbols.

	The input is the complex modulated signal at baseband.
        Synchronized packets are sent back to the demodulator.

        @param ntxchans: Number of transmitter MIMO channels (antennas)
        @type  ntxchans: int
        @param nrxchans: Number of reciever MIMO channels (antennas)
        @type  nrxchans: int
        @param fft_length: total number of subcarriers
        @type  fft_length: int
        @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length)
        @type  cp_length: int
        @param occupied_tones: number of subcarriers used for data
        @type  occupied_tones: int
        @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer
        @type  snr: float
        @param ks: known symbols used as preambles to each packet
        @type  ks: list of lists
        @param logging: turn file logging on or off
        @type  logging: bool
	"""

	gr.hier_block2.__init__(self, "ofdm_mimo_receiver",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature
        
        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw*0.08
        chan_coeffs = gr.firdes.low_pass (1.0,                     # gain
                                          1.0,                     # sampling rate
                                          bw+tb,                   # midpoint of trans. band
                                          tb,                      # width of trans. band
                                          gr.firdes.WIN_HAMMING)   # filter type

        # For starters, run Sync on channel 0 and use it to clock and retime all channels
        win = [1 for i in range(fft_length)]

        zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0))
        ks0 = fft_length*[0,]
        ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0][0:]
        
        ks0 = fft.ifftshift(ks0)
        ks0time = fft.ifft(ks0)
        # ADD SCALING FACTOR
        ks0time = ks0time.tolist()

        SYNC = "pn"
        if SYNC == "ml":
            nco_sensitivity = -1.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, ks0time, logging)
        elif SYNC == "pn":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging)
        elif SYNC == "pnac":
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time, logging)
        elif SYNC == "fixed":                                             # for testing only; do not user over the air
            self.chan_filt = gr.multiply_const_cc(1.0)                    # remove filter and filter delay for this
            nsymbols = 18                                                 # enter the number of symbols per packet
            freq_offset = 0.0                                             # if you use a frequency offset, enter it here
            nco_sensitivity = -2.0/fft_length                             # correct for fine frequency
            self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, freq_offset, logging)

        # Set up blocks
        self.chan_filt = list()
        self.sigmix = list()
        self.sampler = list()
        self.fft_demod = list()

        # Deinterleave the incoming stream into separate channels
        self.deint = gr.deinterleave(gr.sizeof_gr_complex)

        # generate a signal proportional to frequency error of sync block
        self.nco = gr.frequency_modulator_fc(nco_sensitivity)

        # Manage and combine all channels
        if 0:
            self.ofdm_frame_acq = gr.ofdm_mrc_frame_acquisition(nrxchans, occupied_tones, fft_length,
                                                                cp_length, ks[0])
        else:
            print "Transmitter using ", ntxchans
            print "Receiver using    ", nrxchans
            if(ntxchans == 1):
                self.ofdm_frame_acq = gr.ofdm_alamouti_frame_acquisition(ntxchans, occupied_tones, fft_length,
                                                                         cp_length, ks[0], occupied_tones*[0,])
            else:
                self.ofdm_frame_acq = gr.ofdm_alamouti_frame_acquisition(ntxchans, occupied_tones, fft_length,
                                                                         cp_length, ks[0], ks[1])

        self.connect(self, self.deint)               # deinterleave channels
        self.connect((self.ofdm_sync,0), self.nco)   # use sync freq. offset to derotate signal

        for i in xrange(nrxchans):
            self.chan_filt.append(gr.fft_filter_ccc(1, chan_coeffs))
            self.sigmix.append(gr.multiply_cc())
            self.sampler.append(gr.ofdm_sampler(fft_length, fft_length+cp_length))
            self.fft_demod.append(gr.fft_vcc(fft_length, True, win, True))
            

            self.connect((self.deint, i), self.chan_filt[i])              # filter the input channel
            self.connect(self.nco, (self.sigmix[i],1))                    # use sync freq. offset to derotate signal
            self.connect(self.chan_filt[i], (self.sigmix[i],0))           # signal to be derotated
            self.connect(self.sigmix[i], (self.sampler[i],0))             # sample off timing signal detected in sync alg
            self.connect((self.ofdm_sync,1), (self.sampler[i],1))         # timing signal to sample at
            
            self.connect((self.sampler[i],0), self.fft_demod[i])          # send derotated sampled signal to FFT
            self.connect(self.fft_demod[i], (self.ofdm_frame_acq,1+i))    # find frame start and equalize signal

            if logging:
                self.connect(self.chan_filt[i],
                             gr.file_sink(gr.sizeof_gr_complex, ("ofdm_mimo-receiver-chan%02d-chan_filt_c.dat" % i)))
                self.connect(self.fft_demod[i],
                             gr.file_sink(gr.sizeof_gr_complex*fft_length, ("ofdm_mimo-receiver-chan%02d-fft_out_c.dat" % i)))
                self.connect(self.sampler[i],
                             gr.file_sink(gr.sizeof_gr_complex*fft_length, ("ofdm_mimo-receiver-chan%02d-sampler_c.dat" % i)))
                self.connect(self.sigmix[i],
                             gr.file_sink(gr.sizeof_gr_complex, ("ofdm_mimo-receiver-chan%02d-sigmix_c.dat" % i)))
                
        if logging:
            self.connect((self.ofdm_frame_acq,0),
                         gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_mimo-receiver-frame_acq_c.dat"))
            self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_mimo-receiver-found_corr_b.dat"))
            self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_mimo-receiver-nco_c.dat"))
            
        self.connect(self.chan_filt[0], self.ofdm_sync)               # into the synchronization alg.
        self.connect((self.sampler[0],1), (self.ofdm_frame_acq,0))    # send timing signal to signal frame start
        self.connect((self.sampler[i],1), gr.null_sink(fft_length*gr.sizeof_char))
        self.connect((self.ofdm_frame_acq,0), (self,0))               # finished with fine/coarse freq correction,
        self.connect((self.ofdm_frame_acq,1), (self,1))               # frame and symbol timing, and equalization
Esempio n. 51
0
    def __init__(self,
                 fft_length,
                 cp_length,
                 occupied_tones,
                 snr,
                 logging=False):
        """
	Hierarchical block for receiving OFDM symbols.

	The input is the complex modulated signal at baseband.
        Synchronized packets are sent back to the demodulator.

        @param fft_length: total number of subcarriers
        @type  fft_length: int
        @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length)
        @type  cp_length: int
        @param occupied_tones: number of subcarriers used for data
        @type  occupied_tones: int
        @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer
        @type  snr: float
        @param logging: turn file logging on or off
        @type  logging: bool
	"""

        gr.hier_block2.__init__(
            self,
            "ofdm_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature2(2, 2, gr.sizeof_gr_complex * fft_length,
                             gr.sizeof_char * fft_length))  # Output signature

        bw = (float(occupied_tones) / float(fft_length)) / 2.0
        tb = bw * 0.08
        chan_coeffs = gr.firdes.low_pass(
            1.0,  # gain
            1.0,  # sampling rate
            bw + tb,  # midpoint of trans. band
            tb,  # width of trans. band
            gr.firdes.WIN_HAMMING)  # filter type
        #self.chan_filt = gr.fft_filter_ccc(1, chan_coeffs)
        self.chan_filt = gr.multiply_cc(1)

        win = [1 for i in range(fft_length)]

        ks0time = fft_length * (0, )

        SYNC = "ml"
        if SYNC == "ml":
            #TODO -1.0/...
            nco_sensitivity = -1.0 / fft_length  # correct for fine frequency
            self.ofdm_sync = ofdm_sync_ml.ofdm_sync_ml(fft_length, cp_length,
                                                       snr, ks0time, logging)
        elif SYNC == "pn":
            nco_sensitivity = -2.0 / fft_length  # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pn.ofdm_sync_pn(fft_length, cp_length,
                                                       logging)
        elif SYNC == "pnac":
            nco_sensitivity = -2.0 / fft_length  # correct for fine frequency
            self.ofdm_sync = ofdm_sync_pnac.ofdm_sync_pnac(
                fft_length, cp_length, ks0time, logging)
        # for testing only; do not user over the air
        # remove filter and filter delay for this
        elif SYNC == "fixed":
            self.chan_filt = gr.multiply_const_cc(1.0)
            nsymbols = 18  # enter the number of symbols per packet
            freq_offset = 0.0  # if you use a frequency offset, enter it here
            nco_sensitivity = -2.0 / fft_length  # correct for fine frequency
            self.ofdm_sync = ofdm_sync_fixed.ofdm_sync_fixed(
                fft_length, cp_length, nsymbols, freq_offset, logging)
        # Set up blocks
        #self.grnull = gr.null_sink(4);

        self.nco = gr.frequency_modulator_fc(
            nco_sensitivity
        )  # generate a signal proportional to frequency error of sync block
        self.sigmix = gr.multiply_cc()
        self.sampler = digital_swig.ofdm_sampler(fft_length,
                                                 fft_length + cp_length)
        self.fft_demod = gr.fft_vcc(fft_length, True, win, True)

        self.connect(self, self.chan_filt)  # filter the input channel
        self.connect(self.chan_filt,
                     self.ofdm_sync)  # into the synchronization alg.

        self.connect(
            (self.ofdm_sync, 0), self.nco,
            (self.sigmix,
             1))  # use sync freq. offset output to derotate input signal
        self.connect(self.chan_filt,
                     (self.sigmix, 0))  # signal to be derotated

        self.connect(
            self.sigmix,
            (self.sampler, 0))  # sample off timing signal detected in sync alg
        #self.connect(self.chan_filt, (self.sampler,0))                   # sample off timing signal detected in sync alg

        self.connect((self.ofdm_sync, 1),
                     (self.sampler, 1))  # timing signal to sample at
        self.connect((self.sampler, 0),
                     self.fft_demod)  # send derotated sampled signal to FFT
        self.connect(self.fft_demod,
                     (self, 0))  # frequency domain signal sent to output 0
        self.connect((self.sampler, 1), (self, 1))  # timing sent to output 1
        print "setup OK"

        logging = 0

        if logging:
            self.connect(
                self.chan_filt,
                gr.file_sink(gr.sizeof_gr_complex,
                             "ofdm_receiver-chan_filt_c.dat"))
            self.connect((self.ofdm_sync, 0),
                         gr.file_sink(gr.sizeof_float,
                                      "ofdm_receiver-sync_0.dat"))
            self.connect((self.ofdm_sync, 1),
                         gr.file_sink(gr.sizeof_char,
                                      "ofdm_receiver-sync_1.dat"))
            self.connect(
                self.nco,
                gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
            self.connect(
                self.sigmix,
                gr.file_sink(gr.sizeof_gr_complex,
                             "ofdm_receiver-sigmix_c.dat"))
            self.connect((self.sampler, 0),
                         gr.file_sink(gr.sizeof_gr_complex * fft_length,
                                      "ofdm_receiver-sampler_0.dat"))
            self.connect((self.sampler, 1),
                         gr.file_sink(gr.sizeof_char * fft_length,
                                      "ofdm_receiver-sampler_1.dat"))
            self.connect(
                self.fft_demod,
                gr.file_sink(gr.sizeof_gr_complex * fft_length,
                             "ofdm_receiver-fft_out_c.dat"))
Esempio n. 52
0
    def __init__(self):
        grc_wxgui.top_block_gui.__init__(self, title="Rds Tx")
        _icon_path = "/home/azimout/.local/share/icons/hicolor/32x32/apps/gnuradio-grc.png"
        self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY))

        ##################################################
        # Variables
        ##################################################
        self.usrp_interp = usrp_interp = 500
        self.dac_rate = dac_rate = 128e6
        self.wav_rate = wav_rate = 44100
        self.usrp_rate = usrp_rate = int(dac_rate / usrp_interp)
        self.fm_max_dev = fm_max_dev = 120e3

        ##################################################
        # Blocks
        ##################################################
        self.band_pass_filter_0 = gr.interp_fir_filter_fff(
            1,
            firdes.band_pass(1, usrp_rate, 54e3, 60e3, 3e3, firdes.WIN_HAMMING,
                             6.76))
        self.band_pass_filter_1 = gr.interp_fir_filter_fff(
            1,
            firdes.band_pass(1, usrp_rate, 23e3, 53e3, 2e3, firdes.WIN_HAMMING,
                             6.76))
        self.blks2_rational_resampler_xxx_1 = blks2.rational_resampler_fff(
            interpolation=usrp_rate,
            decimation=wav_rate,
            taps=None,
            fractional_bw=None,
        )
        self.blks2_rational_resampler_xxx_1_0 = blks2.rational_resampler_fff(
            interpolation=usrp_rate,
            decimation=wav_rate,
            taps=None,
            fractional_bw=None,
        )
        self.gr_add_xx_0 = gr.add_vff(1)
        self.gr_add_xx_1 = gr.add_vff(1)
        self.gr_char_to_float_0 = gr.char_to_float()
        self.gr_diff_encoder_bb_0 = gr.diff_encoder_bb(2)
        self.gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(
            2 * math.pi * fm_max_dev / usrp_rate)
        self.gr_map_bb_0 = gr.map_bb(([-1, 1]))
        self.gr_map_bb_1 = gr.map_bb(([1, 2]))
        self.gr_multiply_xx_0 = gr.multiply_vff(1)
        self.gr_multiply_xx_1 = gr.multiply_vff(1)
        self.gr_rds_data_encoder_0 = rds.data_encoder(
            "/media/dimitris/mywork/gr/dimitris/rds/trunk/src/test/rds_data.xml"
        )
        self.gr_rds_rate_enforcer_0 = rds.rate_enforcer(256000)
        self.gr_sig_source_x_0 = gr.sig_source_f(usrp_rate, gr.GR_COS_WAVE,
                                                 19e3, 0.3, 0)
        self.gr_sub_xx_0 = gr.sub_ff(1)
        self.gr_unpack_k_bits_bb_0 = gr.unpack_k_bits_bb(2)
        self.gr_wavfile_source_0 = gr.wavfile_source(
            "/media/dimitris/mywork/gr/dimitris/rds/trunk/src/python/limmenso_stereo.wav",
            True)
        self.low_pass_filter_0 = gr.interp_fir_filter_fff(
            1,
            firdes.low_pass(1, usrp_rate, 1.5e3, 2e3, firdes.WIN_HAMMING,
                            6.76))
        self.low_pass_filter_0_0 = gr.interp_fir_filter_fff(
            1,
            firdes.low_pass(1, usrp_rate, 15e3, 2e3, firdes.WIN_HAMMING, 6.76))
        self.usrp_simple_sink_x_0 = grc_usrp.simple_sink_c(which=0, side="A")
        self.usrp_simple_sink_x_0.set_interp_rate(500)
        self.usrp_simple_sink_x_0.set_frequency(107.2e6, verbose=True)
        self.usrp_simple_sink_x_0.set_gain(0)
        self.usrp_simple_sink_x_0.set_enable(True)
        self.usrp_simple_sink_x_0.set_auto_tr(True)
        self.wxgui_fftsink2_0 = fftsink2.fft_sink_f(
            self.GetWin(),
            baseband_freq=0,
            y_per_div=20,
            y_divs=10,
            ref_level=0,
            ref_scale=2.0,
            sample_rate=usrp_rate,
            fft_size=1024,
            fft_rate=30,
            average=False,
            avg_alpha=None,
            title="FFT Plot",
            peak_hold=False,
        )
        self.Add(self.wxgui_fftsink2_0.win)

        ##################################################
        # Connections
        ##################################################
        self.connect((self.gr_sig_source_x_0, 0),
                     (self.gr_rds_rate_enforcer_0, 1))
        self.connect((self.gr_char_to_float_0, 0),
                     (self.gr_rds_rate_enforcer_0, 0))
        self.connect((self.gr_map_bb_0, 0), (self.gr_char_to_float_0, 0))
        self.connect((self.gr_frequency_modulator_fc_0, 0),
                     (self.usrp_simple_sink_x_0, 0))
        self.connect((self.gr_add_xx_1, 0),
                     (self.gr_frequency_modulator_fc_0, 0))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_add_xx_1, 1))
        self.connect((self.gr_sub_xx_0, 0), (self.gr_multiply_xx_1, 2))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_1, 1))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_1, 0))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 3))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 2))
        self.connect((self.blks2_rational_resampler_xxx_1_0, 0),
                     (self.gr_add_xx_0, 1))
        self.connect((self.blks2_rational_resampler_xxx_1, 0),
                     (self.gr_add_xx_0, 0))
        self.connect((self.blks2_rational_resampler_xxx_1_0, 0),
                     (self.gr_sub_xx_0, 1))
        self.connect((self.blks2_rational_resampler_xxx_1, 0),
                     (self.gr_sub_xx_0, 0))
        self.connect((self.gr_wavfile_source_0, 1),
                     (self.blks2_rational_resampler_xxx_1_0, 0))
        self.connect((self.gr_wavfile_source_0, 0),
                     (self.blks2_rational_resampler_xxx_1, 0))
        self.connect((self.gr_rds_data_encoder_0, 0),
                     (self.gr_diff_encoder_bb_0, 0))
        self.connect((self.gr_diff_encoder_bb_0, 0), (self.gr_map_bb_1, 0))
        self.connect((self.gr_map_bb_1, 0), (self.gr_unpack_k_bits_bb_0, 0))
        self.connect((self.gr_unpack_k_bits_bb_0, 0), (self.gr_map_bb_0, 0))
        self.connect((self.gr_rds_rate_enforcer_0, 0),
                     (self.low_pass_filter_0, 0))
        self.connect((self.low_pass_filter_0, 0), (self.gr_multiply_xx_0, 0))
        self.connect((self.gr_multiply_xx_0, 0), (self.band_pass_filter_0, 0))
        self.connect((self.band_pass_filter_0, 0), (self.gr_add_xx_1, 0))
        self.connect((self.gr_multiply_xx_1, 0), (self.band_pass_filter_1, 0))
        self.connect((self.band_pass_filter_1, 0), (self.gr_add_xx_1, 3))
        self.connect((self.gr_add_xx_1, 0), (self.wxgui_fftsink2_0, 0))
        self.connect((self.gr_sig_source_x_0, 0), (self.gr_multiply_xx_0, 1))
        self.connect((self.gr_add_xx_0, 0), (self.low_pass_filter_0_0, 0))
        self.connect((self.low_pass_filter_0_0, 0), (self.gr_add_xx_1, 2))