def __init__(self): gr.top_block.__init__(self, "GPS Simulator Playback - 10Msps") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 10e6 self.freq = freq = 1575.42e6 ################################################## # Blocks ################################################## self.uhd_usrp_sink_0 = uhd.usrp_sink( ",".join(("", "")), uhd.stream_args( cpu_format="fc32", args='', channels=list(range(0, 1)), ), '', ) self.uhd_usrp_sink_0.set_clock_source('external', 0) self.uhd_usrp_sink_0.set_center_freq(freq, 0) self.uhd_usrp_sink_0.set_gain(0, 0) self.uhd_usrp_sink_0.set_antenna('TX/RX', 0) self.uhd_usrp_sink_0.set_samp_rate(samp_rate) # No synchronization enforced. self.blocks_multiply_const_vxx_1_1 = blocks.multiply_const_cc(1.0) self.blocks_multiply_const_vxx_1_0 = blocks.multiply_const_cc(0.25) self.blocks_multiply_const_vxx_1 = blocks.multiply_const_cc(1.0 / (2**12)) self.blocks_interleaved_short_to_complex_0 = blocks.interleaved_short_to_complex( False, False) self.blocks_file_source_0 = blocks.file_source( gr.sizeof_short * 1, '/home/damien/bitbucket/gnss-sim/gpssim.bin', False, 0, 0) self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL) self.blocks_add_xx_0 = blocks.add_vcc(1) self.analog_noise_source_x_0 = analog.noise_source_c( analog.GR_GAUSSIAN, 1.0, 0) ################################################## # Connections ################################################## self.connect((self.analog_noise_source_x_0, 0), (self.blocks_add_xx_0, 1)) self.connect((self.blocks_add_xx_0, 0), (self.blocks_multiply_const_vxx_1_0, 0)) self.connect((self.blocks_file_source_0, 0), (self.blocks_interleaved_short_to_complex_0, 0)) self.connect((self.blocks_interleaved_short_to_complex_0, 0), (self.blocks_multiply_const_vxx_1, 0)) self.connect((self.blocks_multiply_const_vxx_1, 0), (self.blocks_multiply_const_vxx_1_1, 0)) self.connect((self.blocks_multiply_const_vxx_1_0, 0), (self.uhd_usrp_sink_0, 0)) self.connect((self.blocks_multiply_const_vxx_1_1, 0), (self.blocks_add_xx_0, 0))
def __init__(self): gr.hier_block2.__init__( self, "BER Computation", gr.io_signaturev( 2, 2, [gr.sizeof_gr_complex * 1, gr.sizeof_gr_complex * 1]), gr.io_signaturev(2, 2, [gr.sizeof_float * 1, gr.sizeof_float * 1]), ) ################################################## # Variables ################################################## self.samp_rate = samp_rate = 32000 ################################################## # Blocks ################################################## self.iir_filter_xxx_0_0 = filter.iir_filter_ffd([1], [1, 1], True) self.iir_filter_xxx_0 = filter.iir_filter_ffd([1], [1, 1], True) self.blocks_tag_gate_0 = blocks.tag_gate(gr.sizeof_gr_complex * 1, False) self.blocks_tag_gate_0.set_single_key("") self.blocks_sub_xx_0 = blocks.sub_cc(1) self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_cc(0) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(0.5) self.blocks_max_xx_0_0 = blocks.max_ff(1, 1) self.blocks_max_xx_0 = blocks.max_ff(1, 1) self.blocks_divide_xx_0 = blocks.divide_ff(1) self.blocks_complex_to_mag_0_0 = blocks.complex_to_mag(1) self.blocks_complex_to_mag_0 = blocks.complex_to_mag(1) self.blocks_add_const_vxx_0 = blocks.add_const_cc(1) ################################################## # Connections ################################################## self.connect((self.blocks_add_const_vxx_0, 0), (self.blocks_complex_to_mag_0_0, 0)) self.connect((self.blocks_complex_to_mag_0, 0), (self.iir_filter_xxx_0, 0)) self.connect((self.blocks_complex_to_mag_0_0, 0), (self.iir_filter_xxx_0_0, 0)) self.connect((self.blocks_divide_xx_0, 0), (self, 0)) self.connect((self.blocks_max_xx_0, 0), (self.blocks_divide_xx_0, 1)) self.connect((self.blocks_max_xx_0_0, 0), (self.blocks_divide_xx_0, 0)) self.connect((self.blocks_max_xx_0_0, 0), (self, 1)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_complex_to_mag_0, 0)) self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.blocks_add_const_vxx_0, 0)) self.connect((self.blocks_sub_xx_0, 0), (self.blocks_tag_gate_0, 0)) self.connect((self.blocks_tag_gate_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.blocks_tag_gate_0, 0), (self.blocks_multiply_const_vxx_0_0, 0)) self.connect((self.iir_filter_xxx_0, 0), (self.blocks_max_xx_0_0, 0)) self.connect((self.iir_filter_xxx_0_0, 0), (self.blocks_max_xx_0, 0)) self.connect((self, 0), (self.blocks_sub_xx_0, 0)) self.connect((self, 1), (self.blocks_sub_xx_0, 1))
def __init__(self, sample_rate, amplitude): gr.hier_block2.__init__(self, "gsm_source_c", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._symb_rate = 13e6 / 48; self._samples_per_symbol = 2 self._data = blocks.vector_source_b(self.gen_gsm_seq(), True, 2) self._split = blocks.vector_to_streams(gr.sizeof_char*1, 2) self._pack = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) self._mod = digital.gmsk_mod(self._samples_per_symbol, bt=0.35) self._pwr_f = blocks.char_to_float(1, 1) self._pwr_c = blocks.float_to_complex(1) self._pwr_w = blocks.repeat(gr.sizeof_gr_complex*1, self._samples_per_symbol) self._mul = blocks.multiply_vcc(1) self._interpolate = filter.fractional_resampler_cc( 0, (self._symb_rate * self._samples_per_symbol) / sample_rate ) self._scale = blocks.multiply_const_cc(amplitude) self.connect(self._data, self._split) self.connect((self._split, 0), self._pack, self._mod, (self._mul, 0)) self.connect((self._split, 1), self._pwr_f, self._pwr_c, self._pwr_w, (self._mul, 1)) self.connect(self._mul, self._interpolate, self._scale, self)
def __init__(self, constellation, differential, rotation): if constellation.arity() > 256: # If this becomes limiting some of the blocks should be generalised so # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") gr.hier_block2.__init__( self, "mod_demod", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, gr.sizeof_char), ) # Output signature arity = constellation.arity() # TX self.constellation = constellation self.differential = differential import weakref self.blocks = [weakref.proxy(self)] # We expect a stream of unpacked bits. # First step is to pack them. self.blocks.append(blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)) # Second step we unpack them such that we have k bits in each byte where # each constellation symbol hold k bits. self.blocks.append(blocks.packed_to_unpacked_bb(self.constellation.bits_per_symbol(), gr.GR_MSB_FIRST)) # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(digital.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: self.blocks.append(digital.diff_encoder_bb(arity)) # Convert to constellation symbols. self.blocks.append( digital.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality()) ) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: self.blocks.append(blocks.multiply_const_cc(rotation)) # RX # Convert the constellation symbols back to binary values. self.blocks.append(digital.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: self.blocks.append(digital.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(digital.map_bb(mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(blocks.unpack_k_bits_bb(self.constellation.bits_per_symbol())) # connect to block output check_index = len(self.blocks) self.blocks = self.blocks[:check_index] self.blocks.append(weakref.proxy(self)) self.connect(*self.blocks)
def __init__(self, modulator_class, options): ''' See below for what options should hold ''' gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) options = copy.copy( options) # make a copy so we can destructively modify self._verbose = options.verbose self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP self._bitrate = options.bitrate # desired bit rate self._mod_class = modulator_class # the modulator_class we are using # Get mod_kwargs mod_kwargs = self._mod_class.extract_kwargs_from_options(options) # Transmitter self.modulator = self._mod_class(**mod_kwargs) self.packet_transmitter = digital.mod_pkts(self.modulator, access_code=None, msgq_limit=4) self.amp = blocks.multiply_const_cc(1) self.set_tx_amplitude(self._tx_amplitude) # Display some information about the setup #if self._verbose: # self._print_verbage() # Connect components in the flowgraph self.connect(self.packet_transmitter, self.amp, self)
def __init__(self, ifile, ofile, options): gr.top_block.__init__(self) SNR = 10.0**(options.snr / 10.0) time_offset = options.time_offset phase_offset = options.phase_offset*(math.pi / 180.0) # calculate noise voltage from SNR power_in_signal = abs(options.tx_amplitude)**2 noise_power = power_in_signal / SNR noise_voltage = math.sqrt(noise_power) print("Noise voltage: ", noise_voltage) frequency_offset = options.frequency_offset / options.fft_length self.src = blocks.file_source(gr.sizeof_gr_complex, ifile) #self.throttle = blocks.throttle(gr.sizeof_gr_complex, options.sample_rate) self.channel = channels.channel_model(noise_voltage, frequency_offset, time_offset, noise_seed=-random.randint(0,100000)) self.phase = blocks.multiply_const_cc(complex(math.cos(phase_offset), math.sin(phase_offset))) self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk)
def __init__(self, ifile, ofile, options): gr.top_block.__init__(self) SNR = 10.0 ** (options.snr / 10.0) time_offset = options.time_offset phase_offset = options.phase_offset * (math.pi / 180.0) # calculate noise voltage from SNR power_in_signal = abs(options.tx_amplitude) ** 2 noise_power = power_in_signal / SNR noise_voltage = math.sqrt(noise_power) print "Noise voltage: ", noise_voltage frequency_offset = options.frequency_offset / options.fft_length self.src = blocks.file_source(gr.sizeof_gr_complex, ifile) # self.throttle = blocks.throttle(gr.sizeof_gr_complex, options.sample_rate) self.channel = filter.channel_model( noise_voltage, frequency_offset, time_offset, noise_seed=-random.randint(0, 100000) ) self.phase = blocks.multiply_const_cc(complex(math.cos(phase_offset), math.sin(phase_offset))) self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk)
def __init__(self, options): ''' See below for what options should hold ''' gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) options = copy.copy( options) # make a copy so we can destructively modify self._verbose = options.verbose # turn verbose mode on/off self._tx_amplitude = options.tx_amplitude # digital amp sent to radio self.ofdm_tx = digital.ofdm_mod(options, msgq_limit=1, pad_for_usrp=True) #msgq_limit=4, #pad_for_usrp=False) self.amp = blocks.multiply_const_cc(1) self.set_tx_amplitude(self._tx_amplitude) # Display some information about the setup if self._verbose: self._print_verbage() # Create and setup transmit path flow graph self.connect(self.ofdm_tx, self.amp, self)
def __set_rx_from_file(self, filename, capture_rate): file = blocks.file_source(gr.sizeof_gr_complex, filename, True) gain = blocks.multiply_const_cc(self.options.gain) throttle = blocks.throttle(gr.sizeof_gr_complex, capture_rate) self.__connect([[file, gain, throttle]]) print("__set_rx_from_file") self.__build_graph(throttle, capture_rate)
def __init__(self, samples_per_symbol=_def_samples_per_symbol, sensitivity=_def_sensitivity, bt=_def_bt, verbose=_def_verbose, log=_def_log, do_unpack=_def_do_unpack): 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 = digital.bytes_to_syms() self.nrz = digital.chunks_to_symbols_bf([-1, 1]) # Form Gaussian filter # Generate Gaussian response (Needs to be convolved with window below). self.gaussian_taps = filter.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 = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) # FM modulation self.fmmod = analog.frequency_modulator_fc(sensitivity) # small amount of output attenuation to prevent clipping USRP sink self.amp = blocks.multiply_const_cc(0.999) if verbose: self._print_verbage() if log: self._setup_logging() # Connect & Initialize base class if do_unpack: self.unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self) else: self.connect(self, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self)
def __init__(self, modulator, audio_rate, rf_rate, freq): modulator = IModulator(modulator) gr.hier_block2.__init__( self, 'SimulatedChannel', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__freq = freq self.__rf_rate = rf_rate self.__modulator = modulator modulator_input_type = modulator.get_input_type() if modulator_input_type.get_kind() == 'MONO': audio_resampler = make_resampler( audio_rate, modulator_input_type.get_sample_rate()) self.connect(self, audio_resampler, modulator) elif modulator_input_type.get_kind() == 'NONE': self.connect(self, blocks.null_sink(gr.sizeof_float)) else: raise Exception('don\'t know how to supply input of type %s' % modulator_input_type) rf_resampler = rational_resampler.rational_resampler_ccf( interpolation=int(rf_rate), decimation=int(modulator.get_output_type().get_sample_rate())) self.__rotator = blocks.rotator_cc( rotator_inc(rate=rf_rate, shift=freq)) self.__mult = blocks.multiply_const_cc(dB(-10)) self.connect(modulator, rf_resampler, self.__rotator, self.__mult, self)
def __init__(self, sample_rate, amplitude): gr.hier_block2.__init__( self, "gsm_source_c", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._symb_rate = 13e6 / 48 self._samples_per_symbol = 2 self._data = blocks.vector_source_b(self.gen_gsm_seq(), True, 2) self._split = blocks.vector_to_streams(gr.sizeof_char * 1, 2) self._pack = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) self._mod = digital.gmsk_mod(self._samples_per_symbol, bt=0.35) self._pwr_f = blocks.char_to_float(1, 1) self._pwr_c = blocks.float_to_complex(1) self._pwr_w = blocks.repeat(gr.sizeof_gr_complex * 1, self._samples_per_symbol) self._mul = blocks.multiply_vcc(1) self._interpolate = filter.fractional_resampler_cc( 0, (self._symb_rate * self._samples_per_symbol) / sample_rate) self._scale = blocks.multiply_const_cc(amplitude) self.connect(self._data, self._split) self.connect((self._split, 0), self._pack, self._mod, (self._mul, 0)) self.connect((self._split, 1), self._pwr_f, self._pwr_c, self._pwr_w, (self._mul, 1)) self.connect(self._mul, self._interpolate, self._scale, self)
def test_qpsk_channel(self): upper_bound = tuple(50.0 * numpy.ones((self.num_data, ))) lower_bound = tuple(0.0 * numpy.zeros((self.num_data, ))) self.cons = cons = digital.constellation_qpsk().base() self.data = data = [ random.randrange(len(cons.points())) for x in range(self.num_data) ] self.symbols = symbols = numpy.squeeze( [cons.map_to_points_v(i) for i in data]) chan = channels.channel_model(noise_voltage=0.1, frequency_offset=0.0, epsilon=1.0, taps=[1.0 + 0.0j], noise_seed=0, block_tags=False) evm = digital.meas_evm_cc(cons, digital.evm_measurement_t_EVM_PERCENT) vso = blocks.vector_source_c(symbols, False, 1, []) mc = blocks.multiply_const_cc(3.0 + 2.0j) vsi = blocks.vector_sink_f() self.tb.connect(vso, chan, evm, vsi) self.tb.run() # check data output_data = vsi.data() self.assertLess(output_data, upper_bound) self.assertGreater(output_data, lower_bound)
def __init__(self): global fileSource global fileSink gr.top_block.__init__(self, "Gain Correction") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 100e6 ################################################## # Blocks ################################################## self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex * 1, samp_rate, True) self.blocks_multiply_const_xx_0 = blocks.multiply_const_cc(0.0001, 1) self.blocks_file_source_0 = blocks.file_source( gr.sizeof_gr_complex * 1, fileSource, False, 0, 0) self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL) self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_gr_complex * 1, fileSink, False) self.blocks_file_sink_0.set_unbuffered(False) ################################################## # Connections ################################################## self.connect((self.blocks_file_source_0, 0), (self.blocks_multiply_const_xx_0, 0)) self.connect((self.blocks_multiply_const_xx_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.blocks_throttle_0, 0), (self.blocks_file_sink_0, 0))
def __init__(self, options): ''' See below for what options should hold ''' gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) options = copy.copy(options) # make a copy so we can destructively modify self._verbose = options.verbose # turn verbose mode on/off self._tx_amplitude = options.tx_amplitude # digital amp sent to radio self.ofdm_tx = digital.ofdm_mod(options, msgq_limit=4, pad_for_usrp=False) self.amp = blocks.multiply_const_cc(1) self.set_tx_amplitude(self._tx_amplitude) # Display some information about the setup if self._verbose: self._print_verbage() # Create and setup transmit path flow graph self.connect(self.ofdm_tx, self.amp, self)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset") parser.add_option("-g", "--gain", type="eng_float", default=1) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-r", "--new-sample-rate", type="int", default=96000, help="output sample rate") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") (options, args) = parser.parse_args() sample_rate = options.sample_rate new_sample_rate = options.new_sample_rate IN = blocks.file_source(gr.sizeof_gr_complex, options.input_file) OUT = blocks.file_sink(gr.sizeof_gr_complex, options.output_file) LO = analog.sig_source_c(sample_rate, analog.GR_COS_WAVE, options.calibration, 1.0, 0) MIXER = blocks.multiply_cc() AMP = blocks.multiply_const_cc(options.gain) nphases = 32 frac_bw = 0.05 p1 = frac_bw p2 = frac_bw rs_taps = filter.firdes.low_pass(nphases, nphases, p1, p2) RESAMP = filter.pfb_arb_resampler_ccf(float(new_sample_rate) / float(sample_rate), (rs_taps), nphases, ) self.connect(IN, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, AMP, RESAMP, OUT)
def __init__(self, modulator, audio_rate, rf_rate, freq): modulator = IModulator(modulator) gr.hier_block2.__init__( self, 'SimulatedChannel', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__freq = freq self.__rf_rate = rf_rate self.__modulator = modulator modulator_input_type = modulator.get_input_type() if modulator_input_type.get_kind() == 'MONO': audio_resampler = make_resampler(audio_rate, modulator_input_type.get_sample_rate()) self.connect(self, audio_resampler, modulator) elif modulator_input_type.get_kind() == 'NONE': self.connect(self, blocks.null_sink(gr.sizeof_float)) else: raise Exception('don\'t know how to supply input of type %s' % modulator_input_type) rf_resampler = rational_resampler.rational_resampler_ccf( interpolation=int(rf_rate), decimation=int(modulator.get_output_type().get_sample_rate())) self.__rotator = blocks.rotator_cc(rotator_inc(rate=rf_rate, shift=freq)) self.__mult = blocks.multiply_const_cc(dB(-10)) self.connect(modulator, rf_resampler, self.__rotator, self.__mult, self)
def test_001_t (self): """AGC on random noisy QPSK symbols""" # Parameters snr_db = 0.0 const_mult = 1.5 agc_rate = 1e-4 agc_ref = 1.0 agc_gain = 1.0 N_last = 1000 # analyze the last symbols # Constants n_symbols = int(10*(1/agc_rate)) noise_v = 1/sqrt((10**(float(snr_db)/10))) rndm = random.Random() # Input data in_vec = tuple([rndm.randint(0,1) for i in range(0, n_symbols)]) # Flowgraph src = blocks.vector_source_b(in_vec) pack = blocks.repack_bits_bb(1, 2, "", False, gr.GR_MSB_FIRST) const = digital.constellation_qpsk().base() cmap = digital.chunks_to_symbols_bc(const.points()) mult = blocks.multiply_const_cc(const_mult) nadder = blocks.add_cc() noise = analog.noise_source_c(analog.GR_GAUSSIAN, noise_v, 0) agc = blocksat.agc_cc(agc_rate, agc_ref, agc_gain) snk = blocks.vector_sink_c() snk2 = blocks.vector_sink_c() # Reference AGC approach rms_cf = blocks.rms_cf(0.0001) f2c = blocks.float_to_complex() div = blocks.divide_cc() snk3 = blocks.vector_sink_c() self.tb.connect(src, pack, cmap, mult) self.tb.connect(mult, (nadder, 0)) self.tb.connect(noise, (nadder, 1)) self.tb.connect(nadder, agc, snk) self.tb.connect(nadder, snk2) self.tb.connect(nadder, (div, 0)) self.tb.connect(nadder, rms_cf, (f2c, 0), (div, 1)) self.tb.connect(div, snk3) self.tb.run() # Collect results agc_syms = snk.data() pre_agc_syms = snk2.data() ref_agc_syms = snk3.data() rms_agc = self.rms(agc_syms, N_last) rms_pre_agc = self.rms(pre_agc_syms, N_last) rms_agc_ref = self.rms(ref_agc_syms, N_last) print('RMS before AGC: %f' %(rms_pre_agc)) print('RMS after AGC: %f' %(rms_agc)) print('RMS after reference AGC: %f' %(rms_agc_ref)) # Check results self.assertAlmostEqual(rms_agc, 1.0, places=1)
def __init__(self, constellation, differential, rotation): if constellation.arity() > 256: # If this becomes limiting some of the blocks should be generalised so # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") gr.hier_block2.__init__(self, "mod_demod", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature arity = constellation.arity() # TX self.constellation = constellation self.differential = differential import weakref self.blocks = [weakref.proxy(self)] # We expect a stream of unpacked bits. # First step is to pack them. self.blocks.append(blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)) # Second step we unpack them such that we have k bits in each byte where # each constellation symbol hold k bits. self.blocks.append( blocks.packed_to_unpacked_bb(self.constellation.bits_per_symbol(), gr.GR_MSB_FIRST)) # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(digital.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: self.blocks.append(digital.diff_encoder_bb(arity)) # Convert to constellation symbols. self.blocks.append(digital.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: self.blocks.append(blocks.multiply_const_cc(rotation)) # RX # Convert the constellation symbols back to binary values. self.blocks.append(digital.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: self.blocks.append(digital.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(digital.map_bb( mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(blocks.unpack_k_bits_bb( self.constellation.bits_per_symbol())) # connect to block output check_index = len(self.blocks) self.blocks = self.blocks[:check_index] self.blocks.append(weakref.proxy(self)) self.connect(*self.blocks)
def test_multiply_const_cc(): top = gr.top_block() src = blocks.null_source(gr.sizeof_gr_complex) mul = blocks.multiply_const_cc(complex(random.random(), random.random())) probe = blocks.probe_rate(gr.sizeof_gr_complex) top.connect(src, mul, probe) return top, probe
def BuildConjMult(self,scope=True): ## Compute angle difference #self.conj = blocks.conjugate_cc() self.mult = blocks.multiply_conjugate_cc() self.connect(self.rx0, blocks.multiply_const_cc(10000), (self.mult,0)) self.connect(self.rx1, blocks.multiply_const_cc(10000), (self.mult,1)) self.histo = qtgui.histogram_sink_f(1000,360,-179,180,"Histogram") #self.histo.enable_autoscale(False) self.histo.enable_accumulate(True) self.histo.enable_grid(True) #self.histo.enable_menu(True) self.connect(self.mult,blocks.complex_to_arg(), blocks.multiply_const_ff(180.0/np.pi),self.histo) self.pyobj = sip.wrapinstance(self.histo.pyqwidget(), QtGui.QWidget) self.pyobj.show()
def __init__(self, filename, dev_addrs, onebit, gain, digital_gain, fs, fc, sync_pps): gr.top_block.__init__(self) if onebit: raise NotImplementedError("TODO: 1-bit mode not implemented.") uhd_srcs = [ uhd.usrp_source(",".join( [addr, "num_recv_frames=256,recv_frame_size=16384"]), uhd.stream_args( cpu_format="fc32", otwformat="sc16", channels=[0])) for addr in dev_addrs] str2vec = blocks.streams_to_vector(2, len(uhd_srcs)) self.connect(str2vec, blocks.stream_to_vector(2 * len(uhd_srcs), 16*1024*1024), blocks.file_sink(2 * len(uhd_srcs) * 16 * 1024 * 1024, filename, False)) for ix, src in enumerate(uhd_srcs): src.set_clock_rate(fs*2, uhd.ALL_MBOARDS) src.set_samp_rate(fs) src.set_center_freq(uhd.tune_request(fc, 3e6)) src.set_gain(gain, 0) # TODO Use offset tuning? if sync_pps: src.set_clock_source("external") # 10 MHz src.set_time_source("external") # PPS self.connect(src, # [-1.0, 1.0] blocks.multiply_const_cc(32767 * digital_gain[ix]), # [-32767.0, 32767.0] blocks.complex_to_interleaved_short(), #[-32768, 32767] blocks.short_to_char(), #[-128, 127] blocks.stream_to_vector(1, 2), # I,Q,I,Q -> IQ, IQ (str2vec, ix)) print "Setting clocks..." if sync_pps: time.sleep(1.1) # Ensure there's been an edge. TODO: necessary? last_pps_time = uhd_srcs[0].get_time_last_pps() while last_pps_time == uhd_srcs[0].get_time_last_pps(): time.sleep(0.1) print "Got edge" [src.set_time_next_pps(uhd.time_spec(round(time.time())+1)) for src in uhd_srcs] time.sleep(1.0) # Wait for edge to set the clocks else: # No external PPS/10 MHz. Just set each clock and accept some skew. t = time.time() [src.set_time_now(uhd.time_spec(time.time())) for src in uhd_srcs] if len(uhd_srcs) > 1: print "Uncabled; loosely synced only. Initial skew ~ %.1f ms" % ( (time.time()-t) * 1000) t_start = uhd.time_spec(time.time() + 1.5) [src.set_start_time(t_start) for src in uhd_srcs] print "ready"
def __init__(self): gr.top_block.__init__(self, "Hd Tx Rtl File") ################################################## # Blocks ################################################## self.rational_resampler_xxx_1 = filter.rational_resampler_ccc( interpolation=2, decimation=1, taps=None, fractional_bw=None) self.nrsc5_sis_encoder_0 = nrsc5.sis_encoder('ABCD') self.nrsc5_psd_encoder_0 = nrsc5.psd_encoder(0, 'Title', 'Artist') self.nrsc5_l2_encoder_0 = nrsc5.l2_encoder(1, 0, 146176) self.nrsc5_l1_fm_encoder_mp1_0 = nrsc5.l1_fm_encoder(1) self.nrsc5_hdc_encoder_0 = nrsc5.hdc_encoder(2, 64000) self.fft_vxx_0 = fft.fft_vcc(2048, False, window.rectangular(2048), True, 1) self.blocks_wavfile_source_0 = blocks.wavfile_source('sample.wav', True) self.blocks_vector_to_stream_0 = blocks.vector_to_stream(gr.sizeof_gr_complex*1, 2048) self.blocks_vector_source_x_0 = blocks.vector_source_c([math.sin(math.pi / 2 * i / 112) for i in range(112)] + [1] * (2048-112) + [math.cos(math.pi / 2 * i / 112) for i in range(112)], True, 1, []) self.blocks_repeat_0 = blocks.repeat(gr.sizeof_gr_complex*2048, 2) self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(0.5) self.blocks_keep_m_in_n_0 = blocks.keep_m_in_n(gr.sizeof_gr_complex, 2160, 4096, 0) self.blocks_interleave_0 = blocks.interleave(gr.sizeof_float*1, 1) self.blocks_float_to_uchar_0 = blocks.float_to_uchar() self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, 'hd-generated.raw', False) self.blocks_file_sink_0.set_unbuffered(False) self.blocks_conjugate_cc_0 = blocks.conjugate_cc() self.blocks_complex_to_float_0 = blocks.complex_to_float(1) self.blocks_add_const_vxx_0_0 = blocks.add_const_ff(127.5) ################################################## # Connections ################################################## self.connect((self.blocks_add_const_vxx_0_0, 0), (self.blocks_float_to_uchar_0, 0)) self.connect((self.blocks_complex_to_float_0, 0), (self.blocks_interleave_0, 0)) self.connect((self.blocks_complex_to_float_0, 1), (self.blocks_interleave_0, 1)) self.connect((self.blocks_conjugate_cc_0, 0), (self.rational_resampler_xxx_1, 0)) self.connect((self.blocks_float_to_uchar_0, 0), (self.blocks_file_sink_0, 0)) self.connect((self.blocks_interleave_0, 0), (self.blocks_add_const_vxx_0_0, 0)) self.connect((self.blocks_keep_m_in_n_0, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_complex_to_float_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.blocks_conjugate_cc_0, 0)) self.connect((self.blocks_repeat_0, 0), (self.blocks_vector_to_stream_0, 0)) self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.blocks_vector_to_stream_0, 0), (self.blocks_keep_m_in_n_0, 0)) self.connect((self.blocks_wavfile_source_0, 1), (self.nrsc5_hdc_encoder_0, 1)) self.connect((self.blocks_wavfile_source_0, 0), (self.nrsc5_hdc_encoder_0, 0)) self.connect((self.fft_vxx_0, 0), (self.blocks_repeat_0, 0)) self.connect((self.nrsc5_hdc_encoder_0, 0), (self.nrsc5_l2_encoder_0, 0)) self.connect((self.nrsc5_l1_fm_encoder_mp1_0, 0), (self.fft_vxx_0, 0)) self.connect((self.nrsc5_l2_encoder_0, 0), (self.nrsc5_l1_fm_encoder_mp1_0, 0)) self.connect((self.nrsc5_psd_encoder_0, 0), (self.nrsc5_l2_encoder_0, 1)) self.connect((self.nrsc5_sis_encoder_0, 0), (self.nrsc5_l1_fm_encoder_mp1_0, 1)) self.connect((self.rational_resampler_xxx_1, 0), (self.blocks_multiply_const_vxx_0, 0))
def __init__(self): grc_wxgui.top_block_gui.__init__(self, title="Onoff Bare Test") ################################################## # Variables ################################################## self.samp_rate = samp_rate = 200000 self.onoff = onoff = 1 ################################################## # Blocks ################################################## self.sinusoid = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, 1000, 10, 0) self.throttle = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate) # This is the ON block (a very CPU intensive block) self.ONblock = filter.interp_fir_filter_ccc(1, 5000*(1,) ) # This is the OFF block (a low CPU intensity block) self.OFFblock=blocks.multiply_const_cc(1.0) # null sink self.null_sink = blocks.null_sink(gr.sizeof_gr_complex*1) # An auxiliary null source+header 0 to connect the disconnected blocks self.nsa=blocks.null_source(gr.sizeof_gr_complex*1) self.head_aux=blocks.head(gr.sizeof_gr_complex*1, 0) self.connect(self.nsa, self.head_aux) # An auxiliary null sink to connect the disconnected blocks self.nullsink_aux=blocks.null_sink(gr.sizeof_gr_complex*1) self._onoff_chooser = forms.button( parent=self.GetWin(), value=self.onoff, callback=self.set_onoff, label="On/Off", choices=[0,1], labels=['Off', 'On'], ) self.Add(self._onoff_chooser) ################################################## # Connections ################################################## self.connect((self.sinusoid, 0), (self.throttle, 0)) if self.onoff==1: self.connect(self.throttle, self.ONblock) self.connect(self.ONblock, self.null_sink) self.connect(self.head_aux,self.OFFblock) self.connect(self.OFFblock,self.nullsink_aux) else: self.connect(self.throttle, self.OFFblock) self.connect(self.OFFblock, self.null_sink) self.connect(self.head_aux,self.ONblock) self.connect(self.ONblock,self.nullsink_aux)
def __init__(self, alpha=0.5, center_freq=3560e6, degree=8, gain=31.5, samp_rate=24e6): gr.top_block.__init__(self, "Spread Spectrum Tx") ################################################## # Parameters ################################################## self.alpha = alpha self.center_freq = center_freq self.degree = degree self.gain = gain self.samp_rate = samp_rate ################################################## # Blocks ################################################## self.uhd_usrp_sink_0 = uhd.usrp_sink( ",".join(("", "")), uhd.stream_args( cpu_format="fc32", args='', channels=list(range(0, 1)), ), '', ) self.uhd_usrp_sink_0.set_clock_source('external', 0) self.uhd_usrp_sink_0.set_center_freq(center_freq, 0) self.uhd_usrp_sink_0.set_gain(gain, 0) self.uhd_usrp_sink_0.set_antenna('TX/RX', 0) self.uhd_usrp_sink_0.set_samp_rate(samp_rate) self.uhd_usrp_sink_0.set_time_unknown_pps(uhd.time_spec()) self.root_raised_cosine_filter_0 = filter.interp_fir_filter_fff( 1, firdes.root_raised_cosine(1, samp_rate, samp_rate, 0.5, 64)) self.digital_glfsr_source_x_0 = digital.glfsr_source_f( degree, True, 0, 1) self.blocks_null_source_0 = blocks.null_source(gr.sizeof_float * 1) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_cc(10) self.blocks_float_to_complex_0 = blocks.float_to_complex(1) ################################################## # Connections ################################################## self.connect((self.blocks_float_to_complex_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.uhd_usrp_sink_0, 0)) self.connect((self.blocks_null_source_0, 0), (self.blocks_float_to_complex_0, 1)) self.connect((self.digital_glfsr_source_x_0, 0), (self.root_raised_cosine_filter_0, 0)) self.connect((self.root_raised_cosine_filter_0, 0), (self.blocks_float_to_complex_0, 0))
def __init__(self, context, mode, angle=0.0): gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__angle = 0.0 # dummy statically visible value will be overwritten # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE, self.__vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect( self, blocks.multiply_const_ff(audio_modulation_index), # M_i (vor_audio, 1)) # Carrier component self.connect(analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.__delay = blocks.delay(gr.sizeof_gr_complex, 0) # configured by set_angle self.connect( vor_audio, make_resampler(self.__audio_rate, self.__rf_rate ), # TODO make a complex version and do this last blocks.float_to_complex(1), self.__delay, (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(self.__rf_rate, analog.GR_COS_WAVE, fm_subcarrier, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, make_resampler(self.__audio_rate, self.__rf_rate), analog.frequency_modulator_fc(2 * math.pi * fm_deviation / self.__rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect(vor_add, self) # calculate and initialize delay self.set_angle(angle)
def open_ifile(self, capture_rate, gain, input_filename, file_seek): speed = 96000 # TODO: fixme ifile = blocks.file_source(gr.sizeof_gr_complex, input_filename, 1) if file_seek > 0: rc = ifile.seek(file_seek * 1024, gr.SEEK_SET) assert rc == True throttle = blocks.throttle(gr.sizeof_gr_complex, speed) self.source = blocks.multiply_const_cc(gain) self.connect(ifile, throttle, self.source) self.__set_rx_from_audio(speed)
def __init__(self, context, mode, angle=0.0): gr.hier_block2.__init__( self, 'SimulatedDevice VOR modulator', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__angle = 0.0 # dummy statically visible value will be overwritten # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE, self.__vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect( self, blocks.multiply_const_ff(audio_modulation_index), # M_i (vor_audio, 1)) # Carrier component self.connect( analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.__delay = blocks.delay(gr.sizeof_gr_complex, 0) # configured by set_angle self.connect( vor_audio, make_resampler(self.__audio_rate, self.__rf_rate), # TODO make a complex version and do this last blocks.float_to_complex(1), self.__delay, (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(self.__rf_rate, analog.GR_COS_WAVE, fm_subcarrier, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, make_resampler(self.__audio_rate, self.__rf_rate), analog.frequency_modulator_fc(2 * math.pi * fm_deviation / self.__rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect( vor_add, self) # calculate and initialize delay self.set_angle(angle)
def __init__(self, scale_factor=1.0 / C2IS_SCALE_FACTOR): gr.hier_block2.__init__(self, self.__class__.__name__, gr.io_signature(1, 1, gr.sizeof_short), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.is2c = blocks.interleaved_short_to_complex(vector_input=False, swap=False) self.scaler = blocks.multiply_const_cc(scale_factor) self.connect(self, self.is2c, self.scaler, self)
def __init__(self, options): gr.top_block.__init__(self) if(options.tx_freq is not None): self.sink = UHDTransmitter(options) elif(options.to_file is not None): self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) else: self.sink = blocks.null_sink(gr.sizeof_gr_complex) # Do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) #self.txpath = blocks.message_burst_source(gr.sizeof_gr_complex, 10) self.tx_source_blk1 = raw.message_tag_source(gr.sizeof_gr_complex, 10) self.tx_source_blk2 = raw.message_tag_source(gr.sizeof_gr_complex, 10) self.amp1 = blocks.multiply_const_cc(options.amp) self.amp2 = blocks.multiply_const_cc(options.amp) self.connect(self.tx_source_blk1, self.amp1, (self.sink, 0)) self.connect(self.tx_source_blk2, self.amp2, (self.sink, 1))
def __init__(self): gr.hier_block2.__init__(self, self.__class__.__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_short)) self.clipper = Clipper(-1.0, 1.0) self.scaler = blocks.multiply_const_cc(C2IS_SCALE_FACTOR) self.c2is = blocks.complex_to_interleaved_short(vector=False) self.connect(self, self.clipper, self.scaler, self.c2is, self)
def __init__(self): args = get_args() gr.top_block.__init__(self) self._usrp = None self._channels_id_list = None self._m_board = 0 # Init and configure USRP self.init_usrp(self._m_board, args.ip_address, args.clock_rate, args.sampling_rate, args.number_of_channels, args.internal_clock) # Configure front-ends if args.pa_gain > 0 and args.disable_safety: self.configure_front_ends(args.pa_gain) else: print('Safety engaged, will not increase the PA gain.') self.configure_front_ends(0) # Tune self.tune_front_ends(args.center_frequency, args.no_dsp_offset, self._m_board) # Load files or activate sine-wave if args.sine_frequency is None: ntaps = args.K * args.samples_per_symbol self._tx_rrc_taps = filter.firdes.root_raised_cosine( args.samples_per_symbol, args.samples_per_symbol, 1.0, args.rolloff_factor, ntaps) print( 'Number of taps for pulse-shaping: {:d} ({:d} sps, alpha {:f})' .format(ntaps, args.samples_per_symbol, args.rolloff_factor)) # Load binary file for k in np.arange(len(args.filename)): print('Load file {:s} on channel {:d}'.format( args.filename[k], self._channels_id_list[k])) print('Scaling:', args.scaling) self.connect( blocks.file_source(gr.sizeof_gr_complex, args.filename[k], repeat=True), blocks.multiply_const_cc(args.scaling[k]), filter.interp_fir_filter_ccf(args.samples_per_symbol, self._tx_rrc_taps), (self._usrp, self._channels_id_list[k])) else: self._signal_source = analog.sig_source_c(args.sampling_rate, analog.GR_SIN_WAVE, args.sine_frequency, args.scaling[0]) # Connect all blocks and run for channel_id in self._channels_id_list: self.connect(self._signal_source, (self._usrp, channel_id)) print('Transmission setup completed.')
def __init__(self, dtype="discrete", limit=10000, randomize=False): if dtype == "discrete": gr.hier_block2.__init__(self, "source_alphabet", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_char)) self.src = blocks.file_source( gr.sizeof_char, "source_material/gutenberg_shakespeare.txt") self.convert = blocks.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST) # self.convert = blocks.packed_to_unpacked_bb(8, gr.GR_LSB_FIRST); self.limit = blocks.head(gr.sizeof_char, limit) self.connect(self.src, self.convert) last = self.convert # whiten our sequence with a random block scrambler (optionally) if randomize: rand_len = 256 rand_bits = np.random.randint(2, size=rand_len) self.rand_src = blocks.vector_source_b(rand_bits, True) self.xor = blocks.xor_bb() self.connect(self.rand_src, (self.xor, 1)) self.connect(last, self.xor) last = self.xor elif dtype == "continuous": # continuous gr.hier_block2.__init__(self, "source_alphabet", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_float)) self.src = blocks.wavfile_source( "source_material/serial-s01-e01.mp3", True) self.float_short = blocks.float_to_short(1, 1) self.convert2 = blocks.interleaved_short_to_complex() self.convert3 = blocks.multiply_const_cc(1.0 / 65535) self.convert = blocks.complex_to_float() self.limit = blocks.head(gr.sizeof_float, limit) self.connect(self.src, self.convert2, self.convert3, self.convert) last = self.convert else: # noise gr.hier_block2.__init__( self, "source_alphabet", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.src = analog.fastnoise_source_c(analog.GR_GAUSSIAN, 1e-4, 0, 8192) self.limit = blocks.head(gr.sizeof_gr_complex, limit) last = self.src # connect head or not, and connect to output if limit is None: self.connect(last, self) else: self.connect(last, self.limit, self)
def open_audio_c(self, capture_rate, gain, audio_input_filename): self.info = { "capture-rate": capture_rate, "center-freq": 0, "source-dev": "AUDIO", "source-decim": 1 } self.audio_source = audio.source(capture_rate, audio_input_filename) self.audio_cvt = blocks.float_to_complex() self.connect((self.audio_source, 0), (self.audio_cvt, 0)) self.connect((self.audio_source, 1), (self.audio_cvt, 1)) self.source = blocks.multiply_const_cc(gain) self.connect(self.audio_cvt, self.source) self.__set_rx_from_audio(capture_rate)
def __init__(self, dtype="discrete", limit=10000, randomize=False, repeat=False): if (dtype == "discrete"): gr.hier_block2.__init__(self, "source_alphabet", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_char)) self.src = blocks.file_source( gr.sizeof_char, "source_material/gutenberg_shakespeare.txt", repeat=repeat) self.convert = blocks.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST) #self.convert = blocks.packed_to_unpacked_bb(8, gr.GR_LSB_FIRST); if limit is not None: self.limit = blocks.head(gr.sizeof_char, limit) self.connect(self.src, self.convert) last = self.convert # whiten our sequence with a random block scrambler (optionally) if (randomize): rand_len = 256 rand_bits = np.random.randint(2, size=rand_len) self.randsrc = blocks.vector_source_b(rand_bits, True) self.xor = blocks.xor_bb() self.connect(self.randsrc, (self.xor, 1)) self.connect(last, self.xor) last = self.xor else: # "type_continuous" gr.hier_block2.__init__(self, "source_alphabet", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_float)) self.src = mediatools.audiosource_s( ["source_material/serial-s01-e01.mp3"]) self.convert2 = blocks.interleaved_short_to_complex() self.convert3 = blocks.multiply_const_cc(1.0 / 65535) self.convert = blocks.complex_to_float() if limit is not None: self.limit = blocks.head(gr.sizeof_float, limit) self.connect(self.src, self.convert2, self.convert3, self.convert) last = self.convert # connect head or not, and connect to output if (limit is None): self.connect(last, self) else: self.connect(last, self.limit, self)
def __init__(self): gr.hier_block2.__init__(self, "transmitter_am", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.rate = 44.1e3 / 200e3 self.interp = filter.fractional_interpolator_ff(0.0, self.rate) self.cnv = blocks.float_to_complex() self.mul = blocks.multiply_const_cc(1.0) self.add = blocks.add_const_cc(1.0) self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 0e3, 1.0) self.mod = blocks.multiply_cc() self.connect(self, self.interp, self.cnv, self.mul, self.add, self.mod, self) self.connect(self.src, (self.mod, 1))
def __init__(self, byte_size, mod_type, samples_per_symbol, blk_num=-1): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.mod_type = mod_type # bpsk or qpsk if (self.mod_type == "bpsk"): self.block_size = (byte_size + 9) * 8 else: self.block_size = (byte_size + 9) * 4 self.cp_size = 32 self.db_num = 1 self.eb_num = 1 self.samples_per_symbol = samples_per_symbol self.excess_bw = 0.35 self.amp = 2.0 self.src = scfde.modulate_message_c(block_size=self.block_size, mod_type=self.mod_type, msgq_limit=4, block_num=blk_num) self.insert_esti = scfde.insert_esti_block_ccb( block_size=self.block_size, db_num=self.db_num, eb_num=self.eb_num) self.insert_sync = scfde.insert_sync_block_cbc( block_size=self.block_size) self.insert_cp = scfde.insert_cp_cc(block_size=self.block_size, cp_size=self.cp_size) self.p_to_s = scfde.parallel_to_serial_cc(ratio=self.block_size + self.cp_size) #pulse shaping nfilts = 32 ntaps = nfilts * 11 * int(self.samples_per_symbol) self.rrc_taps = filter.firdes.root_raised_cosine( nfilts, nfilts, 1.0, self.excess_bw, ntaps) self.rrc_filter = filter.pfb_arb_resampler_ccf(self.samples_per_symbol, self.rrc_taps) self.amplifier = blocks.multiply_const_cc(self.amp) self.connect(self.src, self.insert_esti) self.connect((self.insert_esti, 0), (self.insert_sync, 0)) self.connect((self.insert_esti, 1), (self.insert_sync, 1)) self.connect(self.insert_sync, self.insert_cp) self.connect(self.insert_cp, self.p_to_s, self.rrc_filter, self.amplifier, self)
def __init__(self, xsource, linear_att, awgn_sigma, freq_offset, outputfile): self.tb = gr.top_block() print 'final SNRdB:', 10 * np.log10(linear_att**2 / awgn_sigma**2) v = np.array(xsource, np.complex128) self.source = blocks.vector_source_c(v, False) self.attenuation = blocks.multiply_const_cc(linear_att + 0 * 1j) self.channel = channels.channel_model(awgn_sigma, freq_offset) self.fsink = blocks.file_sink(gr.sizeof_gr_complex, outputfile) self.tb.connect(self.source, self.attenuation) self.tb.connect(self.attenuation, self.channel) self.tb.connect(self.channel, self.fsink)
def add_vor(freq, angle): compensation = math.pi / 180 * -6.5 # empirical, calibrated against VOR receiver (and therefore probably wrong) angle = angle + compensation angle = angle % (2 * math.pi) vor_sig_freq = 30 phase_shift = int(rf_rate / vor_sig_freq * (angle / (2 * math.pi))) vor_dev = 480 vor_channel = make_channel(freq) vor_30 = analog.sig_source_f(audio_rate, analog.GR_COS_WAVE, vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect(audio_signal, blocks.multiply_const_ff(0.07), # M_i (vor_audio, 1)) # Carrier component self.connect( analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.connect( vor_audio, blocks.float_to_complex(1), make_interpolator(), blocks.delay(gr.sizeof_gr_complex, phase_shift), (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(rf_rate, analog.GR_COS_WAVE, 9960, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, filter.interp_fir_filter_fff(interp, interp_taps), # float not complex analog.frequency_modulator_fc(2 * math.pi * vor_dev / rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect( vor_add, vor_channel) signals.append(vor_channel)
def __init__(self,byte_size,mod_type,samples_per_symbol,blk_num=-1): gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0,0,0), gr.io_signature(1,1,gr.sizeof_gr_complex)) self.mod_type = mod_type # bpsk or qpsk if(self.mod_type == "bpsk"): self.block_size = (byte_size+9)*8 else: self.block_size = (byte_size+9)*4 self.cp_size = 32 self.db_num = 1 self.eb_num = 1 self.samples_per_symbol = samples_per_symbol self.excess_bw = 0.35 self.amp = 2.0 self.src = scfde.modulate_message_c(block_size=self.block_size, mod_type=self.mod_type, msgq_limit=4, block_num=blk_num) self.insert_esti = scfde.insert_esti_block_ccb( block_size=self.block_size, db_num=self.db_num, eb_num=self.eb_num) self.insert_sync = scfde.insert_sync_block_cbc(block_size=self.block_size) self.insert_cp = scfde.insert_cp_cc(block_size=self.block_size, cp_size=self.cp_size) self.p_to_s = scfde.parallel_to_serial_cc(ratio=self.block_size+self.cp_size) #pulse shaping nfilts = 32 ntaps = nfilts*11*int(self.samples_per_symbol) self.rrc_taps = filter.firdes.root_raised_cosine( nfilts,nfilts,1.0,self.excess_bw,ntaps) self.rrc_filter = filter.pfb_arb_resampler_ccf(self.samples_per_symbol, self.rrc_taps) self.amplifier = blocks.multiply_const_cc(self.amp) self.connect(self.src,self.insert_esti) self.connect((self.insert_esti,0),(self.insert_sync,0)) self.connect((self.insert_esti,1),(self.insert_sync,1)) self.connect(self.insert_sync,self.insert_cp) self.connect(self.insert_cp,self.p_to_s,self.rrc_filter,self.amplifier,self)
def __init__(self, item_size_in, item_size_out, onoff,ts,factor,alpha): gr.hier_block2.__init__(self, "myselector", gr.io_signature(1,1, item_size_in), # Input signature gr.io_signature(1,1, item_size_out), # Output signature ) self.item_size_in = item_size_in self.item_size_out = item_size_out self.onoff=onoff #print self.item_size_in, self.item_size_out, self.onoff # Define blocks and connect them # This is the BIG block self.A=cdma.timing_estimator_hier(ts,factor,alpha) #self.Ab=blocks.multiply_const_cc(2.0+0j) #self.Ab=filter.interp_fir_filter_ccc(1,ts) #self.A1=blocks.complex_to_mag_squared() #self.Ae=blocks.float_to_char() #self.Ae=blocks.complex_to_mag_squared() #self.connect(self.Ab, self.A1, self.Ae) #self.connect(self.Ab, self.Ae) # This is the SMALL block self.Ob=blocks.multiply_const_cc(0.0) self.O1=blocks.complex_to_mag_squared() self.Oe=blocks.float_to_char() #self.Oe=blocks.complex_to_mag_squared() self.connect(self.Ob, self.O1, self.Oe) #self.connect(self.Ob, self.Oe) # null sources/sinks for connecting inactive block self.nso=blocks.null_source(item_size_in) self.h=blocks.head(item_size_in, 0) self.connect(self.nso, self.h) self.nsi=blocks.null_sink(item_size_out) if self.onoff==0: self._connect_off() else: self._connect_on()
def __init__(self, modulator, audio_rate, rf_rate, freq): modulator = IModulator(modulator) gr.hier_block2.__init__( self, 'SimulatedChannel', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__freq = freq self.__rf_rate = rf_rate self.modulator = modulator # exported audio_resampler = make_resampler(audio_rate, modulator.get_input_type().get_sample_rate()) rf_resampler = rational_resampler.rational_resampler_ccf( interpolation=int(rf_rate), decimation=int(modulator.get_output_type().get_sample_rate())) self.__rotator = blocks.rotator_cc(rotator_inc(rate=rf_rate, shift=freq)) self.__mult = blocks.multiply_const_cc(10.0 ** -1) self.connect(self, audio_resampler, modulator, rf_resampler, self.__rotator, self.__mult, self)
def __init__(self, mod, options): gr.top_block.__init__(self, "tx_mpsk") self._modulator_class = mod # Get mod_kwargs mod_kwargs = self._modulator_class.extract_kwargs_from_options(options) # transmitter self._modulator = self._modulator_class(**mod_kwargs) if(options.tx_freq is not None): symbol_rate = options.bitrate / self._modulator.bits_per_symbol() self._sink = uhd_transmitter(options.args, symbol_rate, options.samples_per_symbol, options.tx_freq, options.tx_gain, options.spec, options.antenna, options.verbose) options.samples_per_symbol = self._sink._sps elif(options.to_file is not None): self._sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) else: self._sink = blocks.null_sink(gr.sizeof_gr_complex) self._transmitter = bert_transmit(self._modulator._constellation, options.samples_per_symbol, options.differential, options.excess_bw, gray_coded=True, verbose=options.verbose, log=options.log) self.amp = blocks.multiply_const_cc(options.amplitude) self.connect(self._transmitter, self.amp, self._sink)
def __init__(self, modulator_class, options): ''' See below for what options should hold ''' gr.hier_block2.__init__(self, "transmit_path", gr.io_signature(0,0,0), gr.io_signature(1,1,gr.sizeof_gr_complex)) options = copy.copy(options) # make a copy so we can destructively modify self._verbose = options.verbose self._tx_amplitude = options.tx_amplitude # digital amplitude sent to USRP self._bitrate = options.bitrate # desired bit rate self._modulator_class = modulator_class # the modulator_class we are using # Get mod_kwargs mod_kwargs = self._modulator_class.extract_kwargs_from_options(options) # transmitter self.modulator = self._modulator_class(**mod_kwargs) self.packet_transmitter = \ digital.mod_pkts(self.modulator, access_code=None, msgq_limit=4, pad_for_usrp=True) self.amp = blocks.multiply_const_cc(1) self.set_tx_amplitude(self._tx_amplitude) # Display some information about the setup if self._verbose: self._print_verbage() # Connect components in the flowgraph self.connect(self.packet_transmitter, self.amp, self)
def multiply_const_cc(N): k = 3.3 op = blocks.multiply_const_cc(k) tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1) return tb
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.input = blocks.multiply_const_cc(1) # FIXME self.connect(self, self.input) # # null-symbol detection # # (outsourced to detect_zero.py) self.ns_detect = dab.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.ffe = dab.ofdm_ffe_all_in_one(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, int(dp.sample_rate)) if rp.correct_ffe: self.ffs_delay_input_for_correction = blocks.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 = blocks.delay(gr.sizeof_char, dp.symbol_length*rp.symbols_for_ffs_estimation) # sample the value at the end of the symbol .. self.ffs_nco = analog.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample self.ffs_mixer = blocks.multiply_cc() # calculate fine frequency error self.connect(self.input, (self.ffe, 0)) self.connect(self.ns_detect, (self.ffe, 1)) if rp.correct_ffe: # do the correction self.connect(self.ffe, 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.ffe, blocks.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.ffe, blocks.multiply_const_ff(1./(dp.T*2*pi)), blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat"))
def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. Args: options: pass modulation options from higher layers (fft length, occupied tones, etc.) msgq_limit: maximum number of messages in message queue (int) pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ gr.hier_block2.__init__(self, "ofdm_mod", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length self._occupied_tones = options.occupied_tones self._cp_length = options.cp_length win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 # hard-coded known symbols preambles = (ksfreq,) padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) symbol_length = options.fft_length + options.cp_length mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} arity = mods[self._modulation] rot = 1 if self._modulation == "qpsk": rot = (0.707+0.707j) # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("psk") >= 0): constel = psk.psk_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) elif(self._modulation.find("qam") >= 0): constel = qam.qam_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) #print rotated_const self._pkt_input = digital.ofdm_mapper_bcv(rotated_const, msgq_limit, options.occupied_tones, options.fft_length) self.preambles = digital.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = fft.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = blocks.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) self.connect((self._pkt_input, 0), (self.preambles, 0)) self.connect((self._pkt_input, 1), (self.preambles, 1)) self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self)
def __init__(self, filenames, dev_addrs, onebit, iq, noise, mix, gain, fs, fc, unint, sync_pps): gr.top_block.__init__(self) if mix: raise NotImplementedError("TODO: Hilbert remix mode not implemented.") uhd_sinks = [ uhd.usrp_sink(",".join( [addr, "send_frame_size=32768,num_send_frames=128"]), uhd.stream_args( cpu_format="fc32", otwformat="sc8", channels=[0])) for addr in dev_addrs] for sink in uhd_sinks: sink.set_clock_rate(fs*2, uhd.ALL_MBOARDS) sink.set_samp_rate(fs) sink.set_center_freq(fc, 0) sink.set_gain(gain, 0) # TODO Use offset tuning? if sync_pps: sink.set_clock_source("external") # 10 MHz sink.set_time_source("external") # PPS if unint: if noise or onebit or not iq: raise NotImplementedError("TODO: RX channel-interleaved mode only " "supported for noiseless 8-bit complex.") BLOCK_N=16*1024*1024 demux = blocks.vector_to_streams(2, len(uhd_sinks)) self.connect(blocks.file_source(2*len(uhd_sinks)*BLOCK_N, filenames[0], False), blocks.vector_to_stream(2*len(uhd_sinks), BLOCK_N), demux) for ix, sink in enumerate(uhd_sinks): self.connect((demux, ix), blocks.vector_to_stream(1, 2), blocks.interleaved_char_to_complex(), # [-128.0, +127.0] blocks.multiply_const_cc(1.0/1024), # [-0.125, 0.125) # blocks.vector_to_stream(8, 16*1024), sink) else: file_srcs = [blocks.file_source(gr.sizeof_char*1, f, False) for f in filenames] for src, sink in zip(file_srcs, uhd_sinks): if iq: node = blocks.multiply_const_cc(1.0/1024) if onebit: self.connect(src, blocks.unpack_k_bits_bb(8), blocks.char_to_short(), # [0, 1] -> [0, 256] blocks.add_const_ss(-128), # [-128, +128], blocks.interleaved_short_to_complex(), # [ -128.0, +128.0] node) # [-0.125, +0.125] else: self.connect(src, # [-128..127] blocks.interleaved_char_to_complex(), # [-128.0, +127.0] node) # [-0.125, +0.125) else: node = blocks.float_to_complex(1) if onebit: self.connect(src, blocks.unpack_k_bits_bb(8), # [0, 1] -> [-0.125, +0.125] blocks.char_to_float(vlen=1, scale=4), blocks.add_const_vff((-0.125, )), node) else: self.connect(src, # [-128..127] -> [-0.125, +0.125) blocks.char_to_float(vlen=1, scale=1024), node) if noise: combiner = blocks.add_vcc(1) self.connect(node, combiner, sink) self.connect(analog.fastnoise_source_c(analog.GR_GAUSSIAN, noise, -222, 8192), (combiner, 1)) else: self.connect(node, sink) print "Setting clocks..." if sync_pps: time.sleep(1.1) # Ensure there's been an edge. TODO: necessary? last_pps_time = uhd_sinks[0].get_time_last_pps() while last_pps_time == uhd_sinks[0].get_time_last_pps(): time.sleep(0.1) print "Got edge" [sink.set_time_next_pps(uhd.time_spec(round(time.time())+1)) for sink in uhd_sinks] time.sleep(1.0) # Wait for edge to set the clocks else: # No external PPS/10 MHz. Just set each clock and accept some skew. t = time.time() [sink.set_time_now(uhd.time_spec(time.time())) for sink in uhd_sinks] if len(uhd_sinks) > 1: print "Uncabled; loosely synced only. Initial skew ~ %.1f ms" % ( (time.time()-t) * 1000) t_start = uhd.time_spec(time.time() + 1.5) [sink.set_start_time(t_start) for sink in uhd_sinks] print "ready"
def __init__(self, dab_params, rx_params, verbose=False, debug=False): """ Hierarchical block for OFDM demodulation @param dab_params DAB parameter object (dab.parameters.dab_parameters) @param rx_params RX parameter object (dab.parameters.receiver_parameters) @param debug enables debug output to files @param verbose whether to produce verbose messages """ self.dp = dp = dab_params self.rp = rp = rx_params self.verbose = verbose if self.rp.softbits: gr.hier_block2.__init__(self,"ofdm_demod", gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_float*self.dp.num_carriers*2, gr.sizeof_char)) # output signature else: gr.hier_block2.__init__(self,"ofdm_demod", gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature2(2, 2, gr.sizeof_char*self.dp.num_carriers/4, 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.input = blocks.multiply_const_cc(1.0) # FIXME self.connect(self, self.input) # input filtering if self.rp.input_fft_filter: if verbose: print "--> RX filter enabled" lowpass_taps = filter.firdes_low_pass(1.0, # gain dp.sample_rate, # sampling rate rp.filt_bw, # cutoff frequency rp.filt_tb, # width of transition band filter.firdes.WIN_HAMMING) # Hamming window self.fft_filter = filter.fft_filter_ccc(1, lowpass_taps) # correct sample rate offset, if enabled if self.rp.autocorrect_sample_rate: if verbose: print "--> dynamic sample rate correction enabled" self.rate_detect_ns = dab.detect_null(dp.ns_length, False) self.rate_estimator = dab.estimate_sample_rate_bf(dp.sample_rate, dp.frame_length) self.rate_prober = blocks.probe_signal_f() self.connect(self.input, self.rate_detect_ns, self.rate_estimator, self.rate_prober) # self.resample = gr.fractional_interpolator_cc(0, 1) self.resample = dab.fractional_interpolator_triggered_update_cc(0,1) self.connect(self.rate_detect_ns, (self.resample,1)) self.updater = Timer(0.1,self.update_correction) # self.updater = threading.Thread(target=self.update_correction) self.run_interpolater_update_thread = True self.updater.setDaemon(True) self.updater.start() else: self.run_interpolater_update_thread = False if self.rp.sample_rate_correction_factor != 1: if verbose: print "--> static sample rate correction enabled" self.resample = gr.fractional_interpolator_cc(0, self.rp.sample_rate_correction_factor) # timing and fine frequency synchronisation self.sync = dab.ofdm_sync_dab2(self.dp, self.rp, debug) # ofdm symbol sampler self.sampler = dab.ofdm_sampler(dp.fft_length, dp.cp_length, dp.symbols_per_frame, rp.cp_gap) # fft for symbol vectors self.fft = fft.fft_vcc(dp.fft_length, True, [], True) # coarse frequency synchronisation self.cfs = dab.ofdm_coarse_frequency_correct(dp.fft_length, dp.num_carriers, dp.cp_length) # diff phasor self.phase_diff = dab.diff_phasor_vcc(dp.num_carriers) # remove pilot symbol self.remove_pilot = dab.ofdm_remove_first_symbol_vcc(dp.num_carriers) # magnitude equalisation if self.rp.equalize_magnitude: if verbose: print "--> magnitude equalization enabled" self.equalizer = dab.magnitude_equalizer_vcc(dp.num_carriers, rp.symbols_for_magnitude_equalization) # frequency deinterleaving self.deinterleave = dab.frequency_interleaver_vcc(dp.frequency_deinterleaving_sequence_array) # symbol demapping self.demapper = dab.qpsk_demapper_vcb(dp.num_carriers) # # connect everything # if self.rp.autocorrect_sample_rate or self.rp.sample_rate_correction_factor != 1: self.connect(self.input, self.resample) self.input2 = self.resample else: self.input2 = self.input if self.rp.input_fft_filter: self.connect(self.input2, self.fft_filter, self.sync) else: self.connect(self.input2, self.sync) # data stream self.connect((self.sync, 0), (self.sampler, 0), self.fft, (self.cfs, 0), self.phase_diff, (self.remove_pilot,0)) if self.rp.equalize_magnitude: self.connect((self.remove_pilot,0), (self.equalizer,0), self.deinterleave) else: self.connect((self.remove_pilot,0), self.deinterleave) if self.rp.softbits: if verbose: print "--> using soft bits" self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) self.connect(self.deinterleave, self.softbit_interleaver, (self,0)) else: self.connect(self.deinterleave, self.demapper, (self,0)) # control stream self.connect((self.sync, 1), (self.sampler, 1), (self.cfs, 1), (self.remove_pilot,1)) if self.rp.equalize_magnitude: self.connect((self.remove_pilot,1), (self.equalizer,1), (self,1)) else: self.connect((self.remove_pilot,1), (self,1)) # calculate an estimate of the SNR self.phase_var_decim = blocks.keep_one_in_n(gr.sizeof_gr_complex*self.dp.num_carriers, self.rp.phase_var_estimate_downsample) self.phase_var_arg = blocks.complex_to_arg(dp.num_carriers) self.phase_var_v2s = blocks.vector_to_stream(gr.sizeof_float, dp.num_carriers) self.phase_var_mod = dab.modulo_ff(pi/2) self.phase_var_avg_mod = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) self.phase_var_sub_avg = blocks.sub_ff() self.phase_var_sqr = blocks.multiply_ff() self.phase_var_avg = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) self.probe_phase_var = blocks.probe_signal_f() self.connect((self.remove_pilot,0), self.phase_var_decim, self.phase_var_arg, self.phase_var_v2s, self.phase_var_mod, (self.phase_var_sub_avg,0), (self.phase_var_sqr,0)) self.connect(self.phase_var_mod, self.phase_var_avg_mod, (self.phase_var_sub_avg,1)) self.connect(self.phase_var_sub_avg, (self.phase_var_sqr,1)) self.connect(self.phase_var_sqr, self.phase_var_avg, self.probe_phase_var) # measure processing rate self.measure_rate = dab.measure_processing_rate(gr.sizeof_gr_complex, 2000000) self.connect(self.input, self.measure_rate) # debugging if debug: self.connect(self.fft, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/ofdm_after_fft.dat")) self.connect((self.cfs,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_after_cfs.dat")) self.connect(self.phase_diff, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_diff_phasor.dat")) self.connect((self.remove_pilot,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_pilot_removed.dat")) self.connect((self.remove_pilot,1), blocks.file_sink(gr.sizeof_char, "debug/ofdm_after_cfs_trigger.dat")) self.connect(self.deinterleave, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_deinterleaved.dat")) if self.rp.equalize_magnitude: self.connect(self.equalizer, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_equalizer.dat")) if self.rp.softbits: self.connect(self.softbit_interleaver, blocks.file_sink(gr.sizeof_float*dp.num_carriers*2, "debug/softbits.dat"))
def set_waveform(self, type): self.vprint("Selecting waveform...") self.lock() self.disconnect_all() if type == analog.GR_SIN_WAVE or type == analog.GR_CONST_WAVE: self._src = analog.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 == analog.GR_GAUSSIAN or type == analog.GR_UNIFORM: self._src = analog.noise_source_c(type, self[AMPLITUDE_KEY]) elif type == "2tone": self._src1 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.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 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.GR_SIN_WAVE, self[WAVEFORM2_FREQ_KEY], self[AMPLITUDE_KEY]/2.0, 0) self._src = blocks.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 = analog.sig_source_f(self[SAMP_RATE_KEY], analog.GR_TRI_WAVE, self[WAVEFORM2_FREQ_KEY], 1.0, -0.5) self._src2 = analog.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) self._src = blocks.multiply_const_cc(self[AMPLITUDE_KEY]) self.connect(self._src1, self._src2, self._src) else: raise RuntimeError("[UHD-SIGGEN] Unknown waveform type") for c in xrange(len(self.channels)): self.connect(self._src, (self.usrp, c)) if self.extra_sink is not None: self.connect(self._src, self.extra_sink) self.unlock() self.vprint("Set baseband modulation to:", waveforms[type]) if type == analog.GR_SIN_WAVE: self.vprint("Modulation frequency: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Initial phase:", self[WAVEFORM_OFFSET_KEY]) elif type == "2tone": self.vprint("Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) elif type == "sweep": self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))) self.vprint("Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) self.vprint("TX amplitude:", self[AMPLITUDE_KEY])
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. Args: samples_per_symbol: samples per baud >= 2 (integer) bt: Gaussian filter bandwidth * symbol time (float) verbose: Print information about modulator? (bool) debug: Print modualtion data to files? (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 = digital.bytes_to_syms() self.unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) self.nrz = digital.chunks_to_symbols_bf([-1, 1]) # Form Gaussian filter # Generate Gaussian response (Needs to be convolved with window below). self.gaussian_taps = filter.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 = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) # FM modulation self.fmmod = analog.frequency_modulator_fc(sensitivity) # small amount of output attenuation to prevent clipping USRP sink self.amp = blocks.multiply_const_cc(0.999) 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.amp, self)
def __init__(self, frame, panel, vbox, argv): MAX_CHANNELS = 7 stdgui2.std_top_block.__init__ (self, frame, panel, vbox, argv) parser = OptionParser (option_class=eng_option) parser.add_option("-a", "--args", type="string", default="", help="UHD device address args [default=%default]") parser.add_option("", "--spec", type="string", default=None, help="Subdevice of UHD device where appropriate") parser.add_option("-A", "--antenna", type="string", default=None, help="select Rx Antenna where appropriate") parser.add_option("-s", "--samp-rate", type="eng_float", default=400e3, help="set sample rate (bandwidth) [default=%default]") parser.add_option("-f", "--freq", type="eng_float", default=None, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-n", "--nchannels", type="int", default=4, help="number of Tx channels [1,4]") #parser.add_option("","--debug", action="store_true", default=False, # help="Launch Tx debugger") (options, args) = parser.parse_args () if len(args) != 0: parser.print_help() sys.exit(1) if options.nchannels < 1 or options.nchannels > MAX_CHANNELS: sys.stderr.write ("fm_tx4: nchannels out of range. Must be in [1,%d]\n" % MAX_CHANNELS) sys.exit(1) if options.freq is None: sys.stderr.write("fm_tx4: must specify frequency with -f FREQ\n") parser.print_help() sys.exit(1) # ---------------------------------------------------------------- # Set up constants and parameters self.u = uhd.usrp_sink(device_addr=options.args, stream_args=uhd.stream_args('fc32')) # Set the subdevice spec if(options.spec): self.u.set_subdev_spec(options.spec, 0) # Set the antenna if(options.antenna): self.u.set_antenna(options.antenna, 0) self.usrp_rate = options.samp_rate self.u.set_samp_rate(self.usrp_rate) self.usrp_rate = self.u.get_samp_rate() self.sw_interp = 10 self.audio_rate = self.usrp_rate / self.sw_interp # 32 kS/s if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() options.gain = float(g.start()+g.stop())/2 self.set_gain(options.gain) self.set_freq(options.freq) self.sum = blocks.add_cc () # Instantiate N NBFM channels step = 25e3 offset = (0 * step, 1 * step, -1 * step, 2 * step, -2 * step, 3 * step, -3 * step) for i in range (options.nchannels): t = pipeline("audio-%d.dat" % (i % 4), offset[i], self.audio_rate, self.usrp_rate) self.connect(t, (self.sum, i)) self.gain = blocks.multiply_const_cc (1.0 / options.nchannels) # connect it all self.connect (self.sum, self.gain) self.connect (self.gain, self.u) # plot an FFT to verify we are sending what we want if 1: post_mod = fftsink2.fft_sink_c(panel, title="Post Modulation", fft_size=512, sample_rate=self.usrp_rate, y_per_div=20, ref_level=40) self.connect (self.gain, post_mod) vbox.Add (post_mod.win, 1, wx.EXPAND)
def __init__(self, *args, **kwds): # begin wxGlade: MyFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) # Menu Bar self.frame_1_menubar = wx.MenuBar() self.SetMenuBar(self.frame_1_menubar) wxglade_tmp_menu = wx.Menu() self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendItem(self.Exit) self.frame_1_menubar.Append(wxglade_tmp_menu, "File") # Menu Bar end self.panel_1 = wx.Panel(self, -1) self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB") self.button_2 = wx.Button(self, ID_BUTTON_2, "USB") self.button_3 = wx.Button(self, ID_BUTTON_3, "AM") self.button_4 = wx.Button(self, ID_BUTTON_4, "CW") self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper") self.slider_fcutoff_hi = wx.Slider(self, ID_SLIDER_1, 0, -15798, 15799, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower") self.slider_fcutoff_lo = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15798, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_5 = wx.Panel(self, -1) self.label_1 = wx.StaticText(self, -1, " Band\nCenter") self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "") self.panel_6 = wx.Panel(self, -1) self.panel_7 = wx.Panel(self, -1) self.panel_2 = wx.Panel(self, -1) self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq") self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000) self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100) self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol") self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500) self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20) self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time") self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew") self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd") self.panel_3 = wx.Panel(self, -1) self.label_2 = wx.StaticText(self, -1, "PGA ") self.panel_4 = wx.Panel(self, -1) self.panel_8 = wx.Panel(self, -1) self.panel_9 = wx.Panel(self, -1) self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier") self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.label_4 = wx.StaticText(self, -1, "Antenna Tune") self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL | wx.SL_LABELS) self.panel_10 = wx.Panel(self, -1) self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune") self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate") self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset") self.panel_11 = wx.Panel(self, -1) self.panel_12 = wx.Panel(self, -1) self.__set_properties() self.__do_layout() # end wxGlade parser = OptionParser(option_class=eng_option) parser.add_option( "", "--address", type="string", default="addr=192.168.10.2", help="Address of UHD device, [default=%default]", ) parser.add_option( "-c", "--ddc-freq", type="eng_float", default=3.9e6, help="set Rx DDC frequency to FREQ", metavar="FREQ" ) parser.add_option( "-s", "--samp-rate", type="eng_float", default=256e3, help="set sample rate (bandwidth) [default=%default]" ) parser.add_option("-a", "--audio_file", default="", help="audio output file", metavar="FILE") parser.add_option("-r", "--radio_file", default="", help="radio output file", metavar="FILE") parser.add_option("-i", "--input_file", default="", help="radio input file", metavar="FILE") parser.add_option( "-O", "--audio-output", type="string", default="", help="audio output device name. E.g., hw:0,0, /dev/dsp, or pulse", ) (options, args) = parser.parse_args() self.usrp_center = options.ddc_freq input_rate = options.samp_rate self.slider_range = input_rate * 0.9375 self.f_lo = self.usrp_center - (self.slider_range / 2) self.f_hi = self.usrp_center + (self.slider_range / 2) self.af_sample_rate = 32000 fir_decim = long(input_rate / self.af_sample_rate) # data point arrays for antenna tuner self.xdata = [] self.ydata = [] self.tb = gr.top_block() # radio variables, initial conditions self.frequency = self.usrp_center # these map the frequency slider (0-6000) to the actual range self.f_slider_offset = self.f_lo self.f_slider_scale = 10000 self.spin_ctrl_1.SetRange(self.f_lo, self.f_hi) self.text_ctrl_1.SetValue(str(int(self.usrp_center))) self.slider_5.SetValue(0) self.AM_mode = False self.slider_3.SetValue((self.frequency - self.f_slider_offset) / self.f_slider_scale) self.spin_ctrl_1.SetValue(int(self.frequency)) POWERMATE = True try: self.pm = powermate.powermate(self) except: sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") POWERMATE = False if POWERMATE: powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate) powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton) self.active_button = 7 # command line options if options.audio_file == "": SAVE_AUDIO_TO_FILE = False else: SAVE_AUDIO_TO_FILE = True if options.radio_file == "": SAVE_RADIO_TO_FILE = False else: SAVE_RADIO_TO_FILE = True if options.input_file == "": self.PLAY_FROM_USRP = True else: self.PLAY_FROM_USRP = False if self.PLAY_FROM_USRP: self.src = uhd.usrp_source(device_addr=options.address, io_type=uhd.io_type.COMPLEX_FLOAT32, num_channels=1) self.src.set_samp_rate(input_rate) input_rate = self.src.get_samp_rate() self.src.set_center_freq(self.usrp_center, 0) self.tune_offset = 0 else: self.src = blocks.file_source(gr.sizeof_short, options.input_file) self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band # convert rf data in interleaved short int form to complex s2ss = blocks.stream_to_streams(gr.sizeof_short, 2) s2f1 = blocks.short_to_float() s2f2 = blocks.short_to_float() src_f2c = blocks.float_to_complex() self.tb.connect(self.src, s2ss) self.tb.connect((s2ss, 0), s2f1) self.tb.connect((s2ss, 1), s2f2) self.tb.connect(s2f1, (src_f2c, 0)) self.tb.connect(s2f2, (src_f2c, 1)) # save radio data to a file if SAVE_RADIO_TO_FILE: radio_file = blocks.file_sink(gr.sizeof_short, options.radio_file) self.tb.connect(self.src, radio_file) # 2nd DDC xlate_taps = filter.firdes.low_pass(1.0, input_rate, 16e3, 4e3, filter.firdes.WIN_HAMMING) self.xlate = filter.freq_xlating_fir_filter_ccf(fir_decim, xlate_taps, self.tune_offset, input_rate) # Complex Audio filter audio_coeffs = filter.firdes.complex_band_pass( 1.0, # gain self.af_sample_rate, # sample rate -3000, # low cutoff 0, # high cutoff 100, # transition filter.firdes.WIN_HAMMING, ) # window self.slider_fcutoff_hi.SetValue(0) self.slider_fcutoff_lo.SetValue(-3000) self.audio_filter = filter.fir_filter_ccc(1, audio_coeffs) # Main +/- 16Khz spectrum display self.fft = fftsink2.fft_sink_c( self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240) ) # AM Sync carrier if AM_SYNC_DISPLAY: self.fft2 = fftsink.fft_sink_c( self.tb, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640, 240), ) c2f = blocks.complex_to_float() # AM branch self.sel_am = blocks.multiply_const_cc(0) # the following frequencies turn out to be in radians/sample # analog.pll_refout_cc(alpha,beta,min_freq,max_freq) # suggested alpha = X, beta = .25 * X * X pll = analog.pll_refout_cc( 0.5, 0.0625, (2.0 * math.pi * 7.5e3 / self.af_sample_rate), (2.0 * math.pi * 6.5e3 / self.af_sample_rate) ) self.pll_carrier_scale = blocks.multiply_const_cc(complex(10, 0)) am_det = blocks.multiply_cc() # these are for converting +7.5kHz to -7.5kHz # for some reason blocks.conjugate_cc() adds noise ?? c2f2 = blocks.complex_to_float() c2f3 = blocks.complex_to_float() f2c = blocks.float_to_complex() phaser1 = blocks.multiply_const_ff(1) phaser2 = blocks.multiply_const_ff(-1) # filter for pll generated carrier pll_carrier_coeffs = filter.firdes.complex_band_pass( 2.0, # gain self.af_sample_rate, # sample rate 7400, # low cutoff 7600, # high cutoff 100, # transition filter.firdes.WIN_HAMMING, ) # window self.pll_carrier_filter = filter.fir_filter_ccc(1, pll_carrier_coeffs) self.sel_sb = blocks.multiply_const_ff(1) combine = blocks.add_ff() # AGC sqr1 = blocks.multiply_ff() intr = filter.iir_filter_ffd([0.004, 0], [0, 0.999]) offset = blocks.add_const_ff(1) agc = blocks.divide_ff() self.scale = blocks.multiply_const_ff(0.00001) dst = audio.sink(long(self.af_sample_rate), options.audio_output) if self.PLAY_FROM_USRP: self.tb.connect(self.src, self.xlate, self.fft) else: self.tb.connect(src_f2c, self.xlate, self.fft) self.tb.connect(self.xlate, self.audio_filter, self.sel_am, (am_det, 0)) self.tb.connect(self.sel_am, pll, self.pll_carrier_scale, self.pll_carrier_filter, c2f3) self.tb.connect((c2f3, 0), phaser1, (f2c, 0)) self.tb.connect((c2f3, 1), phaser2, (f2c, 1)) self.tb.connect(f2c, (am_det, 1)) self.tb.connect(am_det, c2f2, (combine, 0)) self.tb.connect(self.audio_filter, c2f, self.sel_sb, (combine, 1)) if AM_SYNC_DISPLAY: self.tb.connect(self.pll_carrier_filter, self.fft2) self.tb.connect(combine, self.scale) self.tb.connect(self.scale, (sqr1, 0)) self.tb.connect(self.scale, (sqr1, 1)) self.tb.connect(sqr1, intr, offset, (agc, 1)) self.tb.connect(self.scale, (agc, 0)) self.tb.connect(agc, dst) if SAVE_AUDIO_TO_FILE: f_out = blocks.file_sink(gr.sizeof_short, options.audio_file) sc1 = blocks.multiply_const_ff(64000) f2s1 = blocks.float_to_short() self.tb.connect(agc, sc1, f2s1, f_out) self.tb.start() # for mouse position reporting on fft display self.fft.win.Bind(wx.EVT_LEFT_UP, self.Mouse) # and left click to re-tune self.fft.win.Bind(wx.EVT_LEFT_DOWN, self.Click) # start a timer to check for web commands if WEB_CONTROL: self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec wx.EVT_BUTTON(self, ID_BUTTON_1, self.set_lsb) wx.EVT_BUTTON(self, ID_BUTTON_2, self.set_usb) wx.EVT_BUTTON(self, ID_BUTTON_3, self.set_am) wx.EVT_BUTTON(self, ID_BUTTON_4, self.set_cw) wx.EVT_BUTTON(self, ID_BUTTON_10, self.fwd) wx.EVT_BUTTON(self, ID_BUTTON_11, self.rew) wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate) wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_5, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_6, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_7, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_8, self.on_button) wx.EVT_TOGGLEBUTTON(self, ID_BUTTON_9, self.on_button) wx.EVT_SLIDER(self, ID_SLIDER_1, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_2, self.set_filter) wx.EVT_SLIDER(self, ID_SLIDER_3, self.slide_tune) wx.EVT_SLIDER(self, ID_SLIDER_4, self.set_volume) wx.EVT_SLIDER(self, ID_SLIDER_5, self.set_pga) wx.EVT_SLIDER(self, ID_SLIDER_6, self.am_carrier) wx.EVT_SLIDER(self, ID_SLIDER_7, self.antenna_tune) wx.EVT_SPINCTRL(self, ID_SPIN_1, self.spin_tune) wx.EVT_MENU(self, ID_EXIT, self.TimeToQuit)
def __init__(self, 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. Args: fft_length: total number of subcarriers (int) cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length) (int) occupied_tones: number of subcarriers used for data (int) snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer (float) ks: known symbols used as preambles to each packet (list of lists) logging: turn file logging on or off (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 = filter.firdes.low_pass (1.0, # gain 1.0, # sampling rate bw+tb, # midpoint of trans. band tb, # width of trans. band filter.firdes.WIN_HAMMING) # filter type self.chan_filt = filter.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) 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 = blocks.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 = analog.frequency_modulator_fc(nco_sensitivity) # generate a signal proportional to frequency error of sync block self.sigmix = blocks.multiply_cc() self.sampler = digital.ofdm_sampler(fft_length, fft_length+cp_length) self.fft_demod = gr_fft.fft_vcc(fft_length, True, win, True) self.ofdm_frame_acq = digital.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 if logging: self.connect(self.chan_filt, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) self.connect(self.fft_demod, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) self.connect(self.ofdm_frame_acq, blocks.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) self.connect((self.ofdm_frame_acq,1), blocks.file_sink(1, "ofdm_receiver-found_corr_b.dat")) self.connect(self.sampler, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) self.connect(self.sigmix, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) self.connect(self.nco, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
def __init__(self, frame, panel, vbox, argv): MAX_CHANNELS = 7 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("-e","--enable-fft", action="store_true", default=False, help="enable spectrum plot (and use more CPU)") parser.add_option("-f", "--freq", type="eng_float", default=None, help="set Tx frequency to FREQ [required]", metavar="FREQ") parser.add_option("-i","--file-input", action="store_true", default=False, help="input from baseband-0.dat, baseband-1.dat ...") parser.add_option("-g", "--audio-gain", type="eng_float", default=1.0, help="input audio gain multiplier") parser.add_option("-n", "--nchannels", type="int", default=1, help="number of Tx channels [1,4]") parser.add_option("-a", "--udp-addr", type="string", default="127.0.0.1", help="UDP host IP address") parser.add_option("--args", type="string", default="", help="device args") parser.add_option("--gains", type="string", default="", help="gains") parser.add_option("-p", "--udp-port", type="int", default=0, help="UDP port number") parser.add_option("-r","--repeat", action="store_true", default=False, help="continuously replay input file") parser.add_option("-S", "--stretch", type="int", default=0, help="elastic buffer trigger value") parser.add_option("-v","--verbose", action="store_true", default=False, help="print out stats") parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp") (options, args) = parser.parse_args () if len(args) != 0: parser.print_help() sys.exit(1) if options.nchannels < 1 or options.nchannels > MAX_CHANNELS: sys.stderr.write ("op25_tx: nchannels out of range. Must be in [1,%d]\n" % MAX_CHANNELS) sys.exit(1) if options.freq is None: sys.stderr.write("op25_tx: must specify frequency with -f FREQ\n") parser.print_help() sys.exit(1) # ---------------------------------------------------------------- # Set up constants and parameters self.u = osmosdr.sink (options.args) # the USRP sink (consumes samples) gain_names = self.u.get_gain_names() for name in gain_names: gain_range = self.u.get_gain_range(name) print "gain: name: %s range: start %d stop %d step %d" % (name, gain_range[0].start(), gain_range[0].stop(), gain_range[0].step()) if options.gains: for tuple in options.gains.split(","): name, gain = tuple.split(":") gain = int(gain) print "setting gain %s to %d" % (name, gain) self.u.set_gain(gain, name) self.usrp_rate = 320000 print 'setting sample rate' self.u.set_sample_rate(self.usrp_rate) self.u.set_center_freq(int(options.freq)) #self.u.set_bandwidth(self.usrp_rate) #self.u = blocks.file_sink(gr.sizeof_gr_complex, 'usrp-samp.dat') #self.dac_rate = self.u.dac_rate() # 128 MS/s #self.usrp_interp = 400 #self.u.set_interp_rate(self.usrp_interp) #self.usrp_rate = self.dac_rate / self.usrp_interp # 320 kS/s #self.sw_interp = 10 #self.audio_rate = self.usrp_rate / self.sw_interp # 32 kS/s self.audio_rate = 32000 # if not self.set_freq(options.freq): # freq_range = self.subdev.freq_range() # print "Failed to set frequency to %s. Daughterboard supports %s to %s" % ( # eng_notation.num_to_str(options.freq), # eng_notation.num_to_str(freq_range[0]), # eng_notation.num_to_str(freq_range[1])) # raise SystemExit # self.subdev.set_enable(True) # enable transmitter # instantiate vocoders self.vocoders = [] if options.file_input: i = 0 t = blocks.file_source(gr.sizeof_char, "baseband-%d.dat" % i, options.repeat) self.vocoders.append(t) elif options.udp_port > 0: self.udp_sources = [] for i in range (options.nchannels): t = gr.udp_source(1, options.udp_addr, options.udp_port + i, 216) self.udp_sources.append(t) arity = 2 t = gr.packed_to_unpacked_bb(arity, gr.GR_MSB_FIRST) self.vocoders.append(t) self.connect(self.udp_sources[i], self.vocoders[i]) if 1: # else: input_audio_rate = 8000 #self.audio_input = audio.source(input_audio_rate, options.audio_input) af = 1333 audio_input = analog.sig_source_s( input_audio_rate, analog.GR_SIN_WAVE, af, 15000) t = op25_repeater.vocoder(True, # 0=Decode,True=Encode options.verbose, # Verbose flag options.stretch, # flex amount "", # udp ip address 0, # udp port False) # dump raw u vectors self.connect(audio_input, t) self.vocoders.append(t) sum = blocks.add_cc () # Instantiate N NBFM channels step = 100e3 offset = (0 * step, -1 * step, +1 * step, 2 * step, -2 * step, 3 * step, -3 * step) for i in range (options.nchannels): t = pipeline(self.vocoders[i], offset[i], self.audio_rate, self.usrp_rate) self.connect(t, (sum, i)) t = file_pipeline(offset[2], self.usrp_rate, '2013-320k-filt.dat') self.connect(t, (sum, options.nchannels)) gain = blocks.multiply_const_cc (0.75 / (options.nchannels+1)) # connect it all self.connect (sum, gain) self.connect (gain, self.u) # plot an FFT to verify we are sending what we want if options.enable_fft: post_mod = fftsink2.fft_sink_c(panel, title="Post Modulation", fft_size=512, sample_rate=self.usrp_rate, y_per_div=20, ref_level=40) self.connect (sum, post_mod) vbox.Add (post_mod.win, 1, wx.EXPAND)
def __init__(self, samples_per_symbol=_def_samples_per_symbol, excess_bw=_def_excess_bw, costas_alpha=_def_costas_alpha, gain_mu=_def_gain_mu, mu=_def_mu, omega_relative_limit=_def_omega_relative_limit, gray_code=_def_gray_code, verbose=_def_verbose, log=_def_log): """ Hierarchical block for RRC-filtered CQPSK demodulation The input is the complex modulated signal at baseband. The output is a stream of floats in [ -3 / -1 / +1 / +3 ] @param samples_per_symbol: samples per symbol >= 2 @type samples_per_symbol: float @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float @param costas_alpha: loop filter gain @type costas_alphas: float @param gain_mu: for M&M block @type gain_mu: float @param mu: for M&M block @type mu: float @param omega_relative_limit: for M&M block @type omega_relative_limit: float @param gray_code: Tell modulator to Gray code the bits @type gray_code: bool @param verbose: Print information about modulator? @type verbose: bool @param debug: Print modualtion data to files? @type debug: bool """ gr.hier_block2.__init__(self, "cqpsk_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._costas_alpha = costas_alpha self._mm_gain_mu = gain_mu self._mm_mu = mu self._mm_omega_relative_limit = omega_relative_limit self._gray_code = gray_code if samples_per_symbol < 2: raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol arity = pow(2,self.bits_per_symbol()) # Automatic gain control scale = (1.0/16384.0) self.pre_scaler = blocks.multiply_const_cc(scale) # scale the signal from full-range to +-1 #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) self.agc = analog.feedforward_agc_cc(16, 2.0) # RRC data filter ntaps = 11 * samples_per_symbol self.rrc_taps = filter.firdes.root_raised_cosine( 1.0, # gain self._samples_per_symbol, # sampling rate 1.0, # symbol rate self._excess_bw, # excess bandwidth (roll-off factor) ntaps) self.rrc_filter=filter.interp_fir_filter_ccf(1, self.rrc_taps) if not self._mm_gain_mu: sbs_to_mm = {2: 0.050, 3: 0.075, 4: 0.11, 5: 0.125, 6: 0.15, 7: 0.15} self._mm_gain_mu = sbs_to_mm[samples_per_symbol] self._mm_omega = self._samples_per_symbol self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha fmin = -0.025 fmax = 0.025 self.receiver=digital.mpsk_receiver_cc(arity, pi/4.0, 2*pi/150, fmin, fmax, self._mm_mu, self._mm_gain_mu, self._mm_omega, self._mm_gain_omega, self._mm_omega_relative_limit) self.receiver.set_alpha(self._costas_alpha) self.receiver.set_beta(self._costas_beta) # Perform Differential decoding on the constellation self.diffdec = digital.diff_phasor_cc() # take angle of the difference (in radians) self.to_float = blocks.complex_to_arg() # convert from radians such that signal is in -3/-1/+1/+3 self.rescale = blocks.multiply_const_ff( 1 / (pi / 4) ) if verbose: self._print_verbage() if log: self._setup_logging() # Connect & Initialize base class self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver, self.diffdec, self.to_float, self.rescale, self)
def __init__(self, rx_channels, 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. Args: fft_length: total number of subcarriers (int) cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length) (int) occupied_tones: number of subcarriers used for data (int) snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer (float) ks: known symbols used as preambles to each packet (list of lists) logging: turn file logging on or off (bool) """ self.rx_channels = rx_channels gr.hier_block2.__init__(self, "ofdm_receiver", gr.io_signaturev(self.rx_channels, self.rx_channels, gen_multiple_ios(self.rx_channels)), # Input signature gr.io_signaturev(self.rx_channels*2, self.rx_channels*2, gen_multiple_ios_out(self.rx_channels-1,occupied_tones,fft_length) )) # Output signature bw = (float(occupied_tones) / float(fft_length)) / 2.0 tb = bw*0.08 chan_coeffs = filter.firdes.low_pass (1.0, # gain 1.0, # sampling rate bw+tb, # midpoint of trans. band tb, # width of trans. band filter.firdes.WIN_HAMMING) # filter type self.chan_filt = filter.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": # Schmidl & Cox Method 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) # for testing only; do not user over the air # remove filter and filter delay for this elif SYNC == "fixed": self.chan_filt = blocks.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 = analog.frequency_modulator_fc(nco_sensitivity) # generate a signal proportional to frequency error of sync block self.sigmix = blocks.multiply_cc() self.sampler = digital.ofdm_sampler(fft_length, fft_length+cp_length) self.fft_demod = gr_fft.fft_vcc(fft_length, True, win, True) self.ofdm_frame_acq = digital.ofdm_frame_acquisition(occupied_tones,fft_length,cp_length, ks[0]) # Setup Connections for synchronization path self.connect((self,0), 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 # Debugging # self.connect(self.fft_demod, (self,2)) # Output unequalized signal ############ BLOCK OUTPUTS # ofdm_frame_acquisition (0,occupied carriers) # ofdm_frame_acquisition (1,flag) # .... Repeats for each input ########################## # Add additional channels for each radio output = 2 for p in range(1,self.rx_channels): print "ofdm_receiver: "+str(p) # Add channel filter object_name_cf = 'chan_filter_'+str(p) setattr(self, object_name_cf, filter.fft_filter_ccc(1, chan_coeffs) ) # Connect hier to channel filter self.connect((self,p), (getattr(self,object_name_cf), 0)) # Add Mixer object_name_sm = 'sigmix_'+str(p) setattr(self, object_name_sm, blocks.multiply_cc()) # Connect channel filter to mixer self.connect((getattr(self,object_name_cf), 0), (getattr(self,object_name_sm), 0)) # Connect nco to mixer self.connect( self.nco, (getattr(self,object_name_sm), 1) ) # Add ofdm sampler object_name_sp = 'sampler_'+str(p) # setattr(self, object_name_sp, copy.copy(self.sampler)) # not copiable setattr(self, object_name_sp, digital.ofdm_sampler(fft_length, fft_length+cp_length)) # Connect mixer to sampler self.connect((getattr(self,object_name_sm), 0), (getattr(self,object_name_sp), 0)) # Connect timing signal to sampler self.connect((self.ofdm_sync,1), (getattr(self,object_name_sp), 1)) # Add FFT object_name_fft = 'fft_'+str(p) # setattr(self, object_name_fft, copy.copy(self.fft_demod)) setattr(self, object_name_fft, gr_fft.fft_vcc(fft_length, True, win, True)) # Connect sampler to FFT self.connect((getattr(self,object_name_sp), 0), (getattr(self,object_name_fft), 0)) # Add frame acquistion object_name_fa = 'ofdm_frame_ac_'+str(p) setattr(self, object_name_fa, digital.ofdm_frame_acquisition(occupied_tones,fft_length,cp_length, ks[0])) # Connect FFT to frame acquistion self.connect((getattr(self,object_name_fft), 0), (getattr(self,object_name_fa), 0)) # Connect sampler to frame acquistion self.connect((getattr(self,object_name_sp), 1), (getattr(self,object_name_fa), 1)) # Add frame acquistion outputs to hier self.connect((getattr(self,object_name_fa), 0), (self, output)) output = output + 1 self.connect((getattr(self,object_name_fa), 1), (self, output)) output = output + 1 # ############# NULLS ############# # # Add Null sink for unused inputs # object_name_nb = 'null_sink_'+str(p) # setattr(self, object_name_nb, blocks.null_sink(gr.sizeof_gr_complex*1)) # # Connect # self.connect((self, p+1), (getattr(self,object_name_nb), 0)) if logging: self.connect(self.chan_filt, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) self.connect(self.fft_demod, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) self.connect(self.ofdm_frame_acq, blocks.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) self.connect((self.ofdm_frame_acq,1), blocks.file_sink(1, "ofdm_receiver-found_corr_b.dat")) self.connect(self.sampler, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) self.connect(self.sigmix, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) self.connect(self.nco, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))