def __init__(self): gr.top_block.__init__(self) self._nsamples = 1000000 self._audio_rate = 8000 # Set up N channels with their own baseband and IF frequencies self._N = 5 chspacing = 16000 freq = [10, 20, 30, 40, 50] f_lo = [0, 1*chspacing, -1*chspacing, 2*chspacing, -2*chspacing] self._if_rate = 4*self._N*self._audio_rate # Create a signal source and frequency modulate it self.sum = blocks.add_cc() for n in range(self._N): sig = analog.sig_source_f(self._audio_rate, analog.GR_SIN_WAVE, freq[n], 0.5) fm = fmtx(f_lo[n], self._audio_rate, self._if_rate) self.connect(sig, fm) self.connect(fm, (self.sum, n)) self.head = blocks.head(gr.sizeof_gr_complex, self._nsamples) self.snk_tx = blocks.vector_sink_c() self.channel = channels.channel_model(0.1) self.connect(self.sum, self.head, self.channel, self.snk_tx) # Design the channlizer self._M = 10 bw = chspacing / 2.0 t_bw = chspacing / 10.0 self._chan_rate = self._if_rate / self._M self._taps = filter.firdes.low_pass_2(1, self._if_rate, bw, t_bw, attenuation_dB=100, window=filter.firdes.WIN_BLACKMAN_hARRIS) tpc = math.ceil(float(len(self._taps)) / float(self._M)) print("Number of taps: ", len(self._taps)) print("Number of channels: ", self._M) print("Taps per channel: ", tpc) self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps) self.connect(self.channel, self.pfb) # Create a file sink for each of M output channels of the filter and connect it self.fmdet = list() self.squelch = list() self.snks = list() for i in range(self._M): self.fmdet.append(analog.nbfm_rx(self._audio_rate, self._chan_rate)) self.squelch.append(analog.standard_squelch(self._audio_rate*10)) self.snks.append(blocks.vector_sink_f()) self.connect((self.pfb, i), self.fmdet[i], self.squelch[i], self.snks[i])
def __init__(self): gr.top_block.__init__(self) self._nsamples = 1000000 self._audio_rate = 8000 # Set up N channels with their own baseband and IF frequencies self._N = 5 chspacing = 16000 freq = [10, 20, 30, 40, 50] f_lo = [0, 1*chspacing, -1*chspacing, 2*chspacing, -2*chspacing] self._if_rate = 4*self._N*self._audio_rate # Create a signal source and frequency modulate it self.sum = blocks.add_cc() for n in xrange(self._N): sig = analog.sig_source_f(self._audio_rate, analog.GR_SIN_WAVE, freq[n], 0.5) fm = fmtx(f_lo[n], self._audio_rate, self._if_rate) self.connect(sig, fm) self.connect(fm, (self.sum, n)) self.head = blocks.head(gr.sizeof_gr_complex, self._nsamples) self.snk_tx = blocks.vector_sink_c() self.channel = channels.channel_model(0.1) self.connect(self.sum, self.head, self.channel, self.snk_tx) # Design the channlizer self._M = 10 bw = chspacing/2.0 t_bw = chspacing/10.0 self._chan_rate = self._if_rate / self._M self._taps = filter.firdes.low_pass_2(1, self._if_rate, bw, t_bw, attenuation_dB=100, window=filter.firdes.WIN_BLACKMAN_hARRIS) tpc = math.ceil(float(len(self._taps)) / float(self._M)) print "Number of taps: ", len(self._taps) print "Number of channels: ", self._M print "Taps per channel: ", tpc self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps) self.connect(self.channel, self.pfb) # Create a file sink for each of M output channels of the filter and connect it self.fmdet = list() self.squelch = list() self.snks = list() for i in xrange(self._M): self.fmdet.append(analog.nbfm_rx(self._audio_rate, self._chan_rate)) self.squelch.append(analog.standard_squelch(self._audio_rate*10)) self.snks.append(blocks.vector_sink_f()) self.connect((self.pfb, i), self.fmdet[i], self.squelch[i], self.snks[i])
def update(self, rxcenter, txcenter, rxsps, txsps, fast=False): """ Updates the module by its parameters. Supports a full reconfiguration and a fast reconfiguration for only simple changes such as volume, squelch, frequency, and audiosps which can be changed without much computational expense. """ self.rxsps = rxsps self.txsps = txsps # self.freq, self.bw, self.bwdrop, self.gain, self.vol, self.isps, self.sq freq = self.freq.get_value() bw = self.bw.get_value() bwdrop = self.bwdrop.get_value() gain = self.gain.get_value() vol = self.vol.get_value() sq = self.sq.get_value() dev = self.dev.get_value() taps = filter.firdes.low_pass(gain, sps, bw, bwdrop, filter.firdes.WIN_BLACKMAN) # Turn it off to disconnect them before the variable contents # below are replaced. was_active = self.active self.off() self.shiftsrc = analog.sig_source_c(sps, analog.GR_COS_WAVE, -freq, 0.1, 0) self.shifter = blocks.multiply_cc() self.decfilter = filter.fir_filter_ccf(1, taps) self.fmdemod = analog.nbfm_rx( audio_rate=16000, quad_rate=sps, tau=float(tau) * 0.000000001, max_dev=dev, ) self.sqblock = analog.standard_squelch(isps) self.sqblock.set_threshold(float(sq) / 100.0) self.volblock = blocks.multiply_const_ff(float(vol) / 70.0) if was_active: self.on() else: self.off()
def __init__(self, args, spec, antenna, gain, audio_output): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature self.u = uhd.usrp_source(device_addr=args, io_type=uhd.io_type.COMPLEX_FLOAT32, num_channels=1) self.if_rate = 256e3 self.quad_rate = 64e3 self.audio_rate = 32e3 self.u.set_samp_rate(self.if_rate) dev_rate = self.u.get_samp_rate() # Create filter to get actual channel we want nfilts = 32 chan_coeffs = filter.firdes.low_pass(nfilts, # gain nfilts*dev_rate, # sampling rate 13e3, # low pass cutoff freq 4e3, # width of trans. band filter.firdes.WIN_HANN) # filter type rrate = self.quad_rate / dev_rate self.resamp = filter.pfb.arb_resampler_ccf(rrate, chan_coeffs, nfilts) # instantiate the guts of the single channel receiver self.fmrx = analog.nbfm_rx(self.audio_rate, self.quad_rate) # standard squelch block self.squelch = analog.standard_squelch(self.audio_rate) # audio gain / mute block self._audio_gain = blocks.multiply_const_ff(1.0) # sound card as final sink audio_sink = audio.sink(int(self.audio_rate), audio_output) # now wire it all together self.connect(self.u, self.resamp, self.fmrx, self.squelch, self._audio_gain, audio_sink) if gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() gain = float(g.start() + g.stop())/2.0 self.enabled = True self.set_gain(gain) v = self.volume_range() self.set_volume((v[0]+v[1])/2) s = self.squelch_range() self.set_squelch((s[0]+s[1])/2) # Set the subdevice spec if(spec): self.u.set_subdev_spec(spec, 0) # Set the antenna if(antenna): self.u.set_antenna(antenna, 0)
def __init__(self, args, spec, antenna, gain, audio_output): gr.hier_block2.__init__(self, "receive_path", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(0, 0, 0)) # Output signature self.u = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) # Set the subdevice spec if(spec): self.u.set_subdev_spec(spec, 0) # Set the antenna if(antenna): self.u.set_antenna(antenna, 0) self.if_rate = 256e3 self.quad_rate = 64e3 self.audio_rate = 32e3 self.u.set_samp_rate(self.if_rate) dev_rate = self.u.get_samp_rate() # Create filter to get actual channel we want nfilts = 32 chan_coeffs = filter.firdes.low_pass(nfilts, # gain nfilts*dev_rate, # sampling rate 8e3, # low pass cutoff freq 2e3, # width of trans. band filter.firdes.WIN_HANN) # filter type rrate = self.quad_rate / dev_rate self.resamp = filter.pfb.arb_resampler_ccf(rrate, chan_coeffs, nfilts) if USE_SIMPLE_SQUELCH: self.squelch = analog.simple_squelch_cc(20) else: self.squelch = analog.standard_squelch(self.audio_rate) # instantiate the guts of the single channel receiver self.fmrx = analog.nbfm_rx(self.audio_rate, self.quad_rate) # audio gain / mute block self._audio_gain = blocks.multiply_const_ff(1.0) # sound card as final sink audio_sink = audio.sink (int(self.audio_rate), audio_output) # now wire it all together if USE_SIMPLE_SQUELCH: self.connect (self.u, self.resamp, self.squelch, self.fmrx, self._audio_gain, audio_sink) else: self.connect (self.u, self.resamp, self.fmrx, self.squelch, self._audio_gain, audio_sink) if gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() gain = float(g.start()+g.stop())/2 self.set_gain(gain) v = self.volume_range() self.set_volume((v[0]+v[1])/2) s = self.squelch_range() self.set_squelch((s[0]+s[1])/2)
def update(self, rxcenter, txcenter, rxsps, txsps, fast=False): ModeShell.update(self, rxcenter, txcenter, rxsps, txsps, fast=fast) """ Updates the module by its parameters. Supports a full reconfiguration and a fast reconfiguration for only simple changes such as volume, squelch, frequency, and audiosps which can be changed without much computational expense. """ rxsps = float(rxsps) self.rxsps = rxsps txsps = float(txsps) self.txsps = txsps pre = [ 'tx_vol', 'tx_sq', 'tx_cnst_src', 'tx_ftc', 'tx_ssb_shifter_mul', 'tx_ssb_shifter', 'tx_lpf', 'tx_if0', 'tx_if0_mul', 'rx_if0', 'rx_if0_mul', 'rx_lpf', 'rx_cms', 'rx_vol', 'sqblock' ] for q in pre: setattr(self, q, None) freq = self.freq.get_value() tx_audio_mul = self.tx_audio_mul.get_value() tx_ssb_shifter_freq = self.ssb_shifter_freq.get_value() tx_cutoff_freq = self.cutoff_freq.get_value() tx_filter_gain = self.tx_filter_gain.get_value() tx_cutoff_width = self.cutoff_width.get_value() tx_sqval = self.qtx_sq.get_value() rx_output_gain = self.rx_output_gain.get_value() rx_cutoff_freq = self.cutoff_freq.get_value() rx_filter_gain = self.rx_filter_gain.get_value() rx_cutoff_width = self.cutoff_width.get_value() rx_sqval = self.qrx_sq.get_value() print 'rx_cutoff_freq:%s' % rx_cutoff_freq tx_loc_freq = freq - txcenter rx_loc_freq = freq - rxcenter print '@@@@@@@@@@ KEY CHANGED WAS %s' % self.key_changed if self.key_changed == 'txpwrpri': print '$$$$ RETURNING' return if self.key_changed == 'qtx_sq' and self.tx_sq is not None: self.tx_sq.set_threshold(tx_sqval / 100.0) return if self.key_changed == 'qrx_sq' and self.sqblock is not None: self.sqblock_sq.set_threshold(rx_sqval / 100.0) return if self.key_changed == 'freq': freq = self.freq.get_value() tx_loc_freq = freq - txcenter rx_loc_freq = freq - rxcenter if abs(tx_loc_freq) < txsps * 0.7 and self.tx_vol is not None: self.rxtxstatus.set_tx_status(True) self.tx_if0_mul.set_phase_inc(tx_loc_freq / txsps * math.pi * 2.0) if abs(rx_loc_freq) < txsps * 0.7 and self.rx_if0 is not None: self.rxtxstatus.set_rx_status(True) self.rx_if0_mul.set_phase_inc(rx_loc_freq / txsps * math.pi * 2.0) if self.rx_if0 is not None and self.tx_vol is not None: return if self.key_changed == 'ssb_shifter_freq' and self.tx_ssb_shifter is not None: self.tx_ssb_shifter_mul.set_phase_inc(tx_ssb_shifter_freq / 16000.0 * math.pi * 2.0) return if self.key_changed == 'cutoff_freq' or self.key_changed == 'cutoff_width': if self.tx_lpf: self.tx_lpf.set_taps( filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) if self.rx_lpf: self.rx_lpf.set_taps( filter.firdes.low_pass(int(rx_filter_gain), rxsps, rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return if self.key_changed == 'tx_filter_gain' and self.tx_lpf is not None: self.tx_lpf.set_taps( filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return if self.key_changed == 'rx_filter_gain' and self.rx_lpf is not None: self.rx_lpf.set_taps( filter.firdes.low_pass(int(rx_filter_gain), rxsps, rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return # Turn it off to disconnect them before the variable contents # below are replaced. was_active = self.active self.off() if abs(tx_loc_freq) > txsps * 0.75: self.tx_vol = None self.rxtxstatus.set_tx_status(False) else: self.tx_vol = blocks.multiply_const_ff(tx_audio_mul) self.tx_sq = analog.standard_squelch(audio_rate=16000) self.tx_sq.set_threshold(tx_sqval / 100.0) self.tx_cnst_src = analog.sig_source_f(int(16000), analog.GR_CONST_WAVE, 0, 0, 0) self.tx_ftc = blocks.float_to_complex() self.tx_ssb_shifter_mul = blocks.rotator_cc() self.tx_ssb_shifter_mul.set_phase_inc(tx_ssb_shifter_freq / 16000.0 * math.pi * 2.0) self.tx_lpf = filter.interp_fir_filter_ccf( int(txsps / 16000), filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) self.tx_if0_mul = blocks.rotator_cc() self.tx_if0_mul.set_phase_inc(tx_loc_freq / txsps * math.pi * 2.0) # Late failure is okay. Better false negative than RX is OFF. self.rxtxstatus.set_tx_status(True) if abs(rx_loc_freq) > rxsps * 0.75: self.rx_if0 = None self.rxtxstatus.set_rx_status(False) else: # Early failure is okay. Better false positive that TX is ON. self.rxtxstatus.set_rx_status(True) self.rx_if0_mul = blocks.rotator_cc() self.rx_if0_mul.set_phase_inc(-rx_loc_freq / rxsps * math.pi * 2.0) self.rx_lpf = filter.fir_filter_ccf( int(rxsps / 16000), filter.firdes.low_pass(int(rx_filter_gain), int(rxsps), rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_HAMMING, 6.76)) self.rx_cms = blocks.complex_to_mag_squared() self.rx_vol = blocks.multiply_const_ff(10.0**(rx_output_gain / 10.0)) self.sqblock = analog.standard_squelch(16000) self.sqblock.set_threshold(float(rx_sqval) / 100.0) self.rx_sigstr = gblocks.SignalStrengthCalculator(numpy.float32) self.chanover.set_audio_strength_query_func( self.rx_sigstr.get_value) if was_active: self.on() else: self.off()
def __init__(self, argv): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-a", "--args", type="string", default="", help="UHD device address args [default=%default]") parser.add_option("", "--dev", type="string", default=0, help="Device (rtl=0 or something") parser.add_option("-f", "--freqset", type="string", default="", help="Frequency set key=freq,key=freq,... in kHz") parser.add_option("-m", "--mode", type="string", default="fm", help="Mode (am or fm)") parser.add_option("-g", "--gain", type="eng_float", default=30.0, help="set gain in dB (default is maximum)") parser.add_option("-V", "--volume", type="eng_float", default=1.0, help="set volume (default is midpoint)") parser.add_option("-i", "--icecast", type="string", default="", help="Icecast host:port") parser.add_option("-p", "--icepw", type="string", default="127.0.0.1:8000", help="Icecast source password") parser.add_option( "-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if options.volume is None: options.volume = 0.8 self.vol = options.volume self.freqs = self.parse_freqset(options.freqset) self.freq_corr = 0 self.rf_gain = options.gain # around 20 self.if_gain = 7 self.bb_gain = 10.0 self.bandwidth = 2400000 self.channel_bw = 10000 freq_min = min(self.freqs.values()) freq_max = max(self.freqs.values()) print "Frequencies:" for k in self.freqs: print " %s: %.3f MHz" % (k, self.freqs[k] / 1000000.0) required_bw = freq_max - freq_min print "Required bandwidth: %.3f MHz" % (required_bw / 1000000.0) if required_bw > self.bandwidth: print "Required bandwidth %.3f MHz larger than maximum BW %.3f MHz" % ( required_bw / 1000000, self.bandwidth / 100000) return None # offset center frequency so that it's not on a monitored frequency self.center_freq = freq_min + (required_bw / 2) for f in self.freqs.values(): if abs(f - self.center_freq) < self.channel_bw: self.center_freq += self.channel_bw print "Center frequency: %.3f MHz" % self.center_freq print "" # build graph arg_s = options.dev #"rtl=%d" % options.dev u = self.u = osmosdr.source(args=arg_s) u.set_center_freq(self.center_freq, 0) u.set_freq_corr(self.freq_corr, 0) u.set_dc_offset_mode(0, 0) # 0-2: Off-Manual-Automatic u.set_iq_balance_mode(0, 0) # 0-2: Off-Manual-Automatic u.set_gain_mode(False, 0) # 0-1: Manual, Automatic u.set_gain(self.rf_gain, 0) u.set_if_gain(self.if_gain, 0) u.set_bb_gain(self.bb_gain, 0) u.set_antenna("all", 0) u.set_sample_rate(1024e3 * 2) u.set_bandwidth(self.bandwidth, 0) dev_rate = self.u.get_sample_rate() demod_rate = 64e3 audio_rate = 32e3 chanfilt_decim = int(dev_rate // demod_rate) audio_decim = int(demod_rate // audio_rate) print "Device rate %d, bandwidth %.3f MHz" % ( dev_rate, self.bandwidth / 1000000.0) print "Demod rate %d, audio rate %d" % (demod_rate, audio_rate) if options.mode == 'am': chan_filt_coeffs = filter.firdes.low_pass_2( 1, # gain dev_rate, # sampling rate 8e3, # passband cutoff 2e3, # transition bw 60) # stopband attenuation else: print "FM filter" chan_filt_coeffs = filter.firdes.low_pass_2( 1, # gain dev_rate, # sampling rate 16e3, # passband cutoff 3e3, # transition bw 60) # stopband attenuation audio_filt_coeffs = filter.firdes.low_pass_2( 1, # gain demod_rate, # sampling rate 7e3, # passband cutoff 2e3, # transition bw 60) # stopband attenuation demodulators = [] for k in self.freqs: f = self.freqs[k] print "Setting up %s: %.3f MHz" % (k, f / 1000000.0) if_freq = f - self.center_freq chan_filt = filter.freq_xlating_fir_filter_ccf( chanfilt_decim, chan_filt_coeffs, if_freq, dev_rate) agc = analog.agc_cc(0.1, 1, 1) if options.mode == 'am': demod = blocks.complex_to_mag() squelch = analog.standard_squelch(dev_rate / 10) sq_range = squelch.squelch_range() sq = (sq_range[0] + sq_range[1]) / 2 sq = 0.7 print "Squelch: range %.1f ... %.1f, using %.2f" % ( sq_range[0], sq_range[1], sq) squelch.set_threshold(sq) audio_filt = filter.fir_filter_fff(audio_decim, audio_filt_coeffs) self.connect(chan_filt, agc, demod, squelch, audio_filt) last_block = audio_filt else: print "FM demod" demod = analog.demod_20k0f3e_cf(demod_rate, audio_decim) squelch = analog.pwr_squelch_cc( -50.0, # Power threshold 125.0 / demod_rate, # Time constant int(demod_rate / 20), # 50ms rise/fall False) # Zero, not gate output self.connect(chan_filt, squelch, agc, demod) last_block = demod demodulators.append([chan_filt, last_block]) if options.icecast: # set up a file sink fname = self.setup_upstream_pipe(k, options) float_to_int = blocks.float_to_short(scale=7500.0) file_sink = blocks.file_sink(gr.sizeof_short, fname, append=True) self.connect(last_block, float_to_int, file_sink) self.adder = None if options.audio_output != "": self.volume_control = blocks.multiply_const_ff(self.vol) self.adder = blocks.add_ff(1) # sound card as final sink self.audio_sink = audio.sink(int(audio_rate), options.audio_output, False) # ok_to_block # now wire it all together ch = 0 for d in demodulators: self.connect(self.u, d[0]) if self.adder: self.connect(d[1], (self.adder, ch)) ch += 1 if self.adder: self.connect(self.adder, self.volume_control, self.audio_sink) if options.gain is None: g = self.u.get_gain_range() # if no gain was specified, use the mid gain options.gain = (g.start() + g.stop()) / 2.0
def __init__(self): gr.top_block.__init__(self, "Top Block") Qt.QWidget.__init__(self) self.setWindowTitle("Top Block") qtgui.util.check_set_qss() try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "top_block") self.restoreGeometry(self.settings.value("geometry").toByteArray()) ################################################## # Variables ################################################## self.center_sdr_hardware_f = center_sdr_hardware_f = 99e6 self.sdr_hardware_f_slider = sdr_hardware_f_slider = center_sdr_hardware_f self.low_pass_filter_cutoff_f = low_pass_filter_cutoff_f = 70e3 self.if_slider = if_slider = -1.50e6 self.volume_slider = volume_slider = 0.6 self.squelch_slider = squelch_slider = -60 self.samp_rate = samp_rate = 4.8e6 self.low_pass_trans_width_slider = low_pass_trans_width_slider = 20e3 self.low_pass_filter_cutoff_f_slider = low_pass_filter_cutoff_f_slider = low_pass_filter_cutoff_f self.curr_f_label = curr_f_label = sdr_hardware_f_slider - if_slider ################################################## # Blocks ################################################## self._volume_slider_range = Range(0.2, 3, 0.2, 0.6, 200) self._volume_slider_win = RangeWidget(self._volume_slider_range, self.set_volume_slider, 'Volume', "counter_slider", float) self.top_grid_layout.addWidget(self._volume_slider_win) self._squelch_slider_range = Range(-80, -30, 5, -60, 200) self._squelch_slider_win = RangeWidget(self._squelch_slider_range, self.set_squelch_slider, 'Squelch', "counter_slider", float) self.top_grid_layout.addWidget(self._squelch_slider_win) self._sdr_hardware_f_slider_range = Range(93e6, 106e6, 50e3, center_sdr_hardware_f, 200) self._sdr_hardware_f_slider_win = RangeWidget( self._sdr_hardware_f_slider_range, self.set_sdr_hardware_f_slider, 'SDR frequency', "counter_slider", float) self.top_grid_layout.addWidget(self._sdr_hardware_f_slider_win) self._low_pass_trans_width_slider_range = Range( 5e3, 50e3, 5e3, 20e3, 200) self._low_pass_trans_width_slider_win = RangeWidget( self._low_pass_trans_width_slider_range, self.set_low_pass_trans_width_slider, 'Filter trans width fr', "counter_slider", float) self.top_grid_layout.addWidget(self._low_pass_trans_width_slider_win) self._low_pass_filter_cutoff_f_slider_range = Range( low_pass_filter_cutoff_f - 40e3, low_pass_filter_cutoff_f + 40e3, 5e3, low_pass_filter_cutoff_f, 200) self._low_pass_filter_cutoff_f_slider_win = RangeWidget( self._low_pass_filter_cutoff_f_slider_range, self.set_low_pass_filter_cutoff_f_slider, 'Filter cutoff freq', "counter_slider", float) self.top_grid_layout.addWidget( self._low_pass_filter_cutoff_f_slider_win) self._if_slider_range = Range(-5e6, 5e6, 50e3, -1.50e6, 200) self._if_slider_win = RangeWidget(self._if_slider_range, self.set_if_slider, 'IF frequency', "counter_slider", float) self.top_grid_layout.addWidget(self._if_slider_win) self.qtgui_freq_sink_x_0_0_0 = qtgui.freq_sink_f( 1024, #size firdes.WIN_RECTANGULAR, #wintype sdr_hardware_f_slider - if_slider, #fc 0, #bw "FFT audio", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0_0_0.set_update_time(0.10) self.qtgui_freq_sink_x_0_0_0.set_y_axis(-140, 10) self.qtgui_freq_sink_x_0_0_0.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_0_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0_0_0.enable_autoscale(False) self.qtgui_freq_sink_x_0_0_0.enable_grid(False) self.qtgui_freq_sink_x_0_0_0.set_fft_average(0.2) self.qtgui_freq_sink_x_0_0_0.enable_axis_labels(True) self.qtgui_freq_sink_x_0_0_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0_0_0.disable_legend() if "float" == "float" or "float" == "msg_float": self.qtgui_freq_sink_x_0_0_0.set_plot_pos_half(not True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0_0_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0_0_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0_0_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0_0_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0_0_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_0_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0_0_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_0_0_win) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_RECTANGULAR, #wintype sdr_hardware_f_slider - if_slider, #fc 0, #bw "FFT before filter", #name 1 #number of inputs ) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-140, 10) self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(0.2) self.qtgui_freq_sink_x_0.enable_axis_labels(True) self.qtgui_freq_sink_x_0.enable_control_panel(False) if not True: self.qtgui_freq_sink_x_0.disable_legend() if "complex" == "float" or "complex" == "msg_float": self.qtgui_freq_sink_x_0.set_plot_pos_half(not True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in xrange(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win) self.osmosdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " + '') self.osmosdr_source_0.set_sample_rate(samp_rate) self.osmosdr_source_0.set_center_freq(sdr_hardware_f_slider, 0) self.osmosdr_source_0.set_freq_corr(0, 0) self.osmosdr_source_0.set_dc_offset_mode(0, 0) self.osmosdr_source_0.set_iq_balance_mode(0, 0) self.osmosdr_source_0.set_gain_mode(False, 0) self.osmosdr_source_0.set_gain(10, 0) self.osmosdr_source_0.set_if_gain(20, 0) self.osmosdr_source_0.set_bb_gain(30, 0) self.osmosdr_source_0.set_antenna('', 0) self.osmosdr_source_0.set_bandwidth(0, 0) self.low_pass_filter_0 = filter.fir_filter_ccf( 10, firdes.low_pass(1, samp_rate, low_pass_filter_cutoff_f_slider, low_pass_trans_width_slider, firdes.WIN_HAMMING, 6.76)) self._curr_f_label_tool_bar = Qt.QToolBar(self) if None: self._curr_f_label_formatter = None else: self._curr_f_label_formatter = lambda x: eng_notation.num_to_str(x) self._curr_f_label_tool_bar.addWidget( Qt.QLabel('Current Frequency' + ": ")) self._curr_f_label_label = Qt.QLabel( str(self._curr_f_label_formatter(self.curr_f_label))) self._curr_f_label_tool_bar.addWidget(self._curr_f_label_label) self.top_grid_layout.addWidget(self._curr_f_label_tool_bar) self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff( (volume_slider, )) self.audio_sink_0 = audio.sink(48000, '', True) self.analog_wfm_rcv_1 = analog.wfm_rcv( quad_rate=480e3, audio_decimation=10, ) self.analog_standard_squelch_0 = analog.standard_squelch( audio_rate=48e3) self.analog_standard_squelch_0.set_threshold(squelch_slider) self.analog_sig_source_x_1 = analog.sig_source_c( samp_rate, analog.GR_COS_WAVE, if_slider, 1, 0) ################################################## # Connections ################################################## self.connect((self.analog_sig_source_x_1, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.analog_standard_squelch_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.analog_wfm_rcv_1, 0), (self.analog_standard_squelch_0, 0)) self.connect((self.analog_wfm_rcv_1, 0), (self.qtgui_freq_sink_x_0_0_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.audio_sink_0, 0)) self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_1, 0)) self.connect((self.osmosdr_source_0, 0), (self.blocks_multiply_xx_0, 1)) self.connect((self.osmosdr_source_0, 0), (self.qtgui_freq_sink_x_0, 0))
def __init__(self, argv): gr.top_block.__init__(self) parser=OptionParser(option_class=eng_option) parser.add_option("-a", "--args", type="string", default="", help="UHD device address args [default=%default]") parser.add_option("", "--dev", type="string", default=0, help="Device (rtl=0 or something") parser.add_option("-f", "--freqset", type="string", default="", help="Frequency set key=freq,key=freq,... in kHz") parser.add_option("-m", "--mode", type="string", default="fm", help="Mode (am or fm)") parser.add_option("-g", "--gain", type="eng_float", default=30.0, help="set gain in dB (default is maximum)") parser.add_option("-V", "--volume", type="eng_float", default=1.0, help="set volume (default is midpoint)") parser.add_option("-i", "--icecast", type="string", default="", help="Icecast host:port") parser.add_option("-p", "--icepw", type="string", default="127.0.0.1:8000", help="Icecast source password") parser.add_option("-O", "--audio-output", type="string", default="", help="pcm device name. E.g., hw:0,0 or surround51 or /dev/dsp") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if options.volume is None: options.volume = 0.8 self.vol = options.volume self.freqs = self.parse_freqset(options.freqset) self.freq_corr = 0 self.rf_gain = options.gain # around 20 self.if_gain = 7 self.bb_gain = 10.0 self.bandwidth = 2400000 self.channel_bw = 10000 freq_min = min(self.freqs.values()) freq_max = max(self.freqs.values()) print "Frequencies:" for k in self.freqs: print " %s: %.3f MHz" % (k, self.freqs[k]/1000000.0) required_bw = freq_max - freq_min print "Required bandwidth: %.3f MHz" % (required_bw/1000000.0) if required_bw > self.bandwidth: print "Required bandwidth %.3f MHz larger than maximum BW %.3f MHz" % (required_bw/1000000, self.bandwidth/100000) return None # offset center frequency so that it's not on a monitored frequency self.center_freq = freq_min + (required_bw/2) for f in self.freqs.values(): if abs(f - self.center_freq) < self.channel_bw: self.center_freq += self.channel_bw print "Center frequency: %.3f MHz" % self.center_freq print "" # build graph arg_s = options.dev #"rtl=%d" % options.dev u = self.u = osmosdr.source(args=arg_s) u.set_center_freq(self.center_freq, 0) u.set_freq_corr(self.freq_corr, 0) u.set_dc_offset_mode(0, 0) # 0-2: Off-Manual-Automatic u.set_iq_balance_mode(0, 0) # 0-2: Off-Manual-Automatic u.set_gain_mode(False, 0) # 0-1: Manual, Automatic u.set_gain(self.rf_gain, 0) u.set_if_gain(self.if_gain, 0) u.set_bb_gain(self.bb_gain, 0) u.set_antenna("all", 0) u.set_sample_rate(1024e3*2) u.set_bandwidth(self.bandwidth, 0) dev_rate = self.u.get_sample_rate() demod_rate = 64e3 audio_rate = 32e3 chanfilt_decim = int(dev_rate // demod_rate) audio_decim = int(demod_rate // audio_rate) print "Device rate %d, bandwidth %.3f MHz" % (dev_rate, self.bandwidth / 1000000.0) print "Demod rate %d, audio rate %d" % (demod_rate, audio_rate) if options.mode == 'am': chan_filt_coeffs = filter.firdes.low_pass_2(1, # gain dev_rate, # sampling rate 8e3, # passband cutoff 2e3, # transition bw 60) # stopband attenuation else: print "FM filter" chan_filt_coeffs = filter.firdes.low_pass_2(1, # gain dev_rate, # sampling rate 16e3, # passband cutoff 3e3, # transition bw 60) # stopband attenuation audio_filt_coeffs = filter.firdes.low_pass_2(1, # gain demod_rate, # sampling rate 7e3, # passband cutoff 2e3, # transition bw 60) # stopband attenuation demodulators = [] for k in self.freqs: f = self.freqs[k] print "Setting up %s: %.3f MHz" % (k, f / 1000000.0) if_freq = f - self.center_freq chan_filt = filter.freq_xlating_fir_filter_ccf(chanfilt_decim, chan_filt_coeffs, if_freq, dev_rate) agc = analog.agc_cc(0.1, 1, 1) if options.mode == 'am': demod = blocks.complex_to_mag() squelch = analog.standard_squelch(dev_rate/10) sq_range = squelch.squelch_range() sq = (sq_range[0] + sq_range[1])/2 sq = 0.7 print "Squelch: range %.1f ... %.1f, using %.2f" % (sq_range[0], sq_range[1], sq) squelch.set_threshold(sq) audio_filt = filter.fir_filter_fff(audio_decim, audio_filt_coeffs) self.connect(chan_filt, agc, demod, squelch, audio_filt) last_block = audio_filt else: print "FM demod" demod = analog.demod_20k0f3e_cf(demod_rate, audio_decim) squelch = analog.pwr_squelch_cc(-50.0, # Power threshold 125.0/demod_rate, # Time constant int(demod_rate/20), # 50ms rise/fall False) # Zero, not gate output self.connect(chan_filt, squelch, agc, demod) last_block = demod demodulators.append([chan_filt, last_block]) if options.icecast: # set up a file sink fname = self.setup_upstream_pipe(k, options) float_to_int = blocks.float_to_short(scale=7500.0) file_sink = blocks.file_sink(gr.sizeof_short, fname, append=True) self.connect(last_block, float_to_int, file_sink) self.adder = None if options.audio_output != "": self.volume_control = blocks.multiply_const_ff(self.vol) self.adder = blocks.add_ff(1) # sound card as final sink self.audio_sink = audio.sink(int (audio_rate), options.audio_output, False) # ok_to_block # now wire it all together ch = 0 for d in demodulators: self.connect(self.u, d[0]) if self.adder: self.connect(d[1], (self.adder, ch)) ch += 1 if self.adder: self.connect(self.adder, self.volume_control, self.audio_sink) if options.gain is None: g = self.u.get_gain_range() # if no gain was specified, use the mid gain options.gain = (g.start() + g.stop())/2.0
def update(self, rxcenter, txcenter, rxsps, txsps, fast=False): ModeShell.update(self, rxcenter, txcenter, rxsps, txsps, fast=fast) """ Updates the module by its parameters. Supports a full reconfiguration and a fast reconfiguration for only simple changes such as volume, squelch, frequency, and audiosps which can be changed without much computational expense. """ rxsps = float(rxsps) self.rxsps = rxsps txsps = float(txsps) self.txsps = txsps pre = [ 'tx_vol', 'tx_sq', 'tx_cnst_src', 'tx_ftc', 'tx_ssb_shifter_mul', 'tx_ssb_shifter', 'tx_lpf', 'tx_if0', 'tx_if0_mul', 'rx_if0', 'rx_if0_mul', 'rx_lpf', 'rx_cms', 'rx_vol', 'sqblock' ] for q in pre: setattr(self, q, None) freq = self.freq.get_value() tx_audio_mul = self.tx_audio_mul.get_value() tx_ssb_shifter_freq = self.ssb_shifter_freq.get_value() tx_cutoff_freq = self.cutoff_freq.get_value() tx_filter_gain = self.tx_filter_gain.get_value() tx_cutoff_width = self.cutoff_width.get_value() tx_sqval = self.qtx_sq.get_value() rx_output_gain = self.rx_output_gain.get_value() rx_cutoff_freq = self.cutoff_freq.get_value() rx_filter_gain = self.rx_filter_gain.get_value() rx_cutoff_width = self.cutoff_width.get_value() rx_sqval = self.qrx_sq.get_value() print 'rx_cutoff_freq:%s' % rx_cutoff_freq tx_loc_freq = freq - txcenter rx_loc_freq = freq - rxcenter print '@@@@@@@@@@ KEY CHANGED WAS %s' % self.key_changed if self.key_changed == 'txpwrpri': print '$$$$ RETURNING' return if self.key_changed == 'qtx_sq' and self.tx_sq is not None: self.tx_sq.set_threshold(tx_sqval / 100.0) return if self.key_changed == 'qrx_sq' and self.sqblock is not None: self.sqblock_sq.set_threshold(rx_sqval / 100.0) return if self.key_changed == 'freq': freq = self.freq.get_value() tx_loc_freq = freq - txcenter rx_loc_freq = freq - rxcenter if abs(tx_loc_freq) < txsps * 0.7 and self.tx_vol is not None: self.rxtxstatus.set_tx_status(True) self.tx_if0_mul.set_phase_inc(tx_loc_freq / txsps * math.pi * 2.0) if abs(rx_loc_freq) < txsps * 0.7 and self.rx_if0 is not None: self.rxtxstatus.set_rx_status(True) self.rx_if0_mul.set_phase_inc(rx_loc_freq / txsps * math.pi * 2.0) if self.rx_if0 is not None and self.tx_vol is not None: return if self.key_changed == 'ssb_shifter_freq' and self.tx_ssb_shifter is not None: self.tx_ssb_shifter_mul.set_phase_inc (tx_ssb_shifter_freq / 16000.0 * math.pi * 2.0) return if self.key_changed == 'cutoff_freq' or self.key_changed == 'cutoff_width': if self.tx_lpf: self.tx_lpf.set_taps(filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) if self.rx_lpf: self.rx_lpf.set_taps(filter.firdes.low_pass(int(rx_filter_gain), rxsps, rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return if self.key_changed == 'tx_filter_gain' and self.tx_lpf is not None: self.tx_lpf.set_taps(filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return if self.key_changed == 'rx_filter_gain' and self.rx_lpf is not None: self.rx_lpf.set_taps(filter.firdes.low_pass(int(rx_filter_gain), rxsps, rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) return # Turn it off to disconnect them before the variable contents # below are replaced. was_active = self.active self.off() if abs(tx_loc_freq) > txsps * 0.75: self.tx_vol = None self.rxtxstatus.set_tx_status(False) else: self.tx_vol = blocks.multiply_const_ff(tx_audio_mul) self.tx_sq = analog.standard_squelch(audio_rate=16000) self.tx_sq.set_threshold(tx_sqval / 100.0) self.tx_cnst_src = analog.sig_source_f(int(16000), analog.GR_CONST_WAVE, 0, 0, 0) self.tx_ftc = blocks.float_to_complex() self.tx_ssb_shifter_mul = blocks.rotator_cc() self.tx_ssb_shifter_mul.set_phase_inc(tx_ssb_shifter_freq / 16000.0 * math.pi * 2.0) self.tx_lpf = filter.interp_fir_filter_ccf(int(txsps / 16000), filter.firdes.low_pass(int(tx_filter_gain), txsps, tx_cutoff_freq, tx_cutoff_width, filter.firdes.WIN_BLACKMAN, 6.76)) self.tx_if0_mul = blocks.rotator_cc() self.tx_if0_mul.set_phase_inc(tx_loc_freq / txsps * math.pi * 2.0) # Late failure is okay. Better false negative than RX is OFF. self.rxtxstatus.set_tx_status(True) if abs(rx_loc_freq) > rxsps * 0.75: self.rx_if0 = None self.rxtxstatus.set_rx_status(False) else: # Early failure is okay. Better false positive that TX is ON. self.rxtxstatus.set_rx_status(True) self.rx_if0_mul = blocks.rotator_cc() self.rx_if0_mul.set_phase_inc(-rx_loc_freq / rxsps * math.pi * 2.0) self.rx_lpf = filter.fir_filter_ccf(int(rxsps / 16000), filter.firdes.low_pass(int(rx_filter_gain), int(rxsps), rx_cutoff_freq, rx_cutoff_width, filter.firdes.WIN_HAMMING, 6.76)) self.rx_cms = blocks.complex_to_mag_squared() self.rx_vol = blocks.multiply_const_ff(10.0 ** (rx_output_gain / 10.0)) self.sqblock = analog.standard_squelch(16000) self.sqblock.set_threshold(float(rx_sqval) / 100.0) self.rx_sigstr = gblocks.SignalStrengthCalculator(numpy.float32) self.chanover.set_audio_strength_query_func(self.rx_sigstr.get_value) if was_active: self.on() else: self.off()